1
2
3
4 package net.sourceforge.pmd.lang.rule;
5
6 import java.util.ArrayList;
7 import java.util.Arrays;
8 import java.util.Collection;
9 import java.util.HashMap;
10 import java.util.List;
11 import java.util.Map;
12
13 import net.sourceforge.pmd.PropertyDescriptor;
14 import net.sourceforge.pmd.Rule;
15 import net.sourceforge.pmd.RulePriority;
16 import net.sourceforge.pmd.RuleSetReference;
17 import net.sourceforge.pmd.lang.Language;
18 import net.sourceforge.pmd.lang.LanguageVersion;
19 import net.sourceforge.pmd.util.StringUtil;
20
21
22
23
24
25
26
27
28 public class RuleReference extends AbstractDelegateRule {
29
30 private Language language;
31 private LanguageVersion minimumLanguageVersion;
32 private LanguageVersion maximumLanguageVersion;
33 private Boolean deprecated;
34 private String name;
35 private List<PropertyDescriptor<?>> propertyDescriptors;
36 private Map<PropertyDescriptor<?>, Object> propertyValues;
37 private String message;
38 private String description;
39 private List<String> examples;
40 private String externalInfoUrl;
41 private RulePriority priority;
42 private RuleSetReference ruleSetReference;
43
44 private static final List<PropertyDescriptor<?>> EMPTY_DESCRIPTORS = new ArrayList<PropertyDescriptor<?>>(0);
45
46 public Language getOverriddenLanguage() {
47 return language;
48 }
49
50 public RuleReference() {
51 }
52
53 public RuleReference(Rule theRule, RuleSetReference theRuleSetReference) {
54 setRule(theRule);
55 ruleSetReference = theRuleSetReference;
56 }
57
58 @Override
59 public void setLanguage(Language language) {
60
61 if (!isSame(language, super.getLanguage()) || this.language != null) {
62 this.language = language;
63 super.setLanguage(language);
64 }
65 }
66
67 public LanguageVersion getOverriddenMinimumLanguageVersion() {
68 return minimumLanguageVersion;
69 }
70
71 @Override
72 public void setMinimumLanguageVersion(LanguageVersion minimumLanguageVersion) {
73
74 if (!isSame(minimumLanguageVersion, super.getMinimumLanguageVersion()) || this.minimumLanguageVersion != null) {
75 this.minimumLanguageVersion = minimumLanguageVersion;
76 super.setMinimumLanguageVersion(minimumLanguageVersion);
77 }
78 }
79
80 public LanguageVersion getOverriddenMaximumLanguageVersion() {
81 return maximumLanguageVersion;
82 }
83
84 @Override
85 public void setMaximumLanguageVersion(LanguageVersion maximumLanguageVersion) {
86
87 if (!isSame(maximumLanguageVersion, super.getMaximumLanguageVersion()) || this.maximumLanguageVersion != null) {
88 this.maximumLanguageVersion = maximumLanguageVersion;
89 super.setMaximumLanguageVersion(maximumLanguageVersion);
90 }
91 }
92
93 public Boolean isOverriddenDeprecated() {
94 return deprecated;
95 }
96
97 @Override
98 public boolean isDeprecated() {
99 return deprecated != null && deprecated.booleanValue();
100 }
101
102 @Override
103 public void setDeprecated(boolean deprecated) {
104
105
106 this.deprecated = deprecated ? deprecated : null;
107 }
108
109 public String getOverriddenName() {
110 return name;
111 }
112
113 @Override
114 public void setName(String name) {
115
116 if (!isSame(name, super.getName()) || this.name != null) {
117 this.name = name;
118 super.setName(name);
119 }
120 }
121
122 public String getOverriddenMessage() {
123 return message;
124 }
125
126 @Override
127 public void setMessage(String message) {
128
129 if (!isSame(message, super.getMessage()) || this.message != null) {
130 this.message = message;
131 super.setMessage(message);
132 }
133 }
134
135 public String getOverriddenDescription() {
136 return description;
137 }
138
139 @Override
140 public void setDescription(String description) {
141
142 if (!isSame(description, super.getDescription()) || this.description != null) {
143 this.description = description;
144 super.setDescription(description);
145 }
146 }
147
148 public List<String> getOverriddenExamples() {
149 return examples;
150 }
151
152 @Override
153 public void addExample(String example) {
154
155
156
157
158
159
160
161
162
163
164 if (!contains(super.getExamples(), example)) {
165 if (examples == null) {
166 examples = new ArrayList<String>(1);
167 }
168
169 examples.clear();
170 examples.add(example);
171 super.addExample(example);
172 }
173 }
174
175 public String getOverriddenExternalInfoUrl() {
176 return externalInfoUrl;
177 }
178
179 @Override
180 public void setExternalInfoUrl(String externalInfoUrl) {
181
182 if (!isSame(externalInfoUrl, super.getExternalInfoUrl()) || this.externalInfoUrl != null) {
183 this.externalInfoUrl = externalInfoUrl;
184 super.setExternalInfoUrl(externalInfoUrl);
185 }
186 }
187
188 public RulePriority getOverriddenPriority() {
189 return priority;
190 }
191
192 @Override
193 public void setPriority(RulePriority priority) {
194
195 if (priority != super.getPriority() || this.priority != null) {
196 this.priority = priority;
197 super.setPriority(priority);
198 }
199 }
200
201 public List<PropertyDescriptor<?>> getOverriddenPropertyDescriptors() {
202
203 return propertyDescriptors == null ?
204 EMPTY_DESCRIPTORS :
205 propertyDescriptors;
206 }
207
208 @Override
209 public void definePropertyDescriptor(PropertyDescriptor<?> propertyDescriptor) throws IllegalArgumentException {
210
211
212
213 super.definePropertyDescriptor(propertyDescriptor);
214 if (propertyDescriptors == null) {
215 propertyDescriptors = new ArrayList<PropertyDescriptor<?>>();
216 }
217 propertyDescriptors.add(propertyDescriptor);
218 }
219
220 public Map<PropertyDescriptor<?>, Object> getOverriddenPropertiesByPropertyDescriptor() {
221 return propertyValues;
222 }
223
224 @Override
225 public <T> void setProperty(PropertyDescriptor<T> propertyDescriptor, T value) {
226
227 if (!isSame(super.getProperty(propertyDescriptor), value)) {
228 if (propertyValues == null) {
229 propertyValues = new HashMap<PropertyDescriptor<?>, Object>();
230 }
231 propertyValues.put(propertyDescriptor, value);
232 super.setProperty(propertyDescriptor, value);
233 }
234 }
235
236 public RuleSetReference getRuleSetReference() {
237 return ruleSetReference;
238 }
239
240 public void setRuleSetReference(RuleSetReference ruleSetReference) {
241 this.ruleSetReference = ruleSetReference;
242 }
243
244 private static boolean isSame(String s1, String s2) {
245 return StringUtil.isSame(s1, s2, true, false, true);
246 }
247
248 @SuppressWarnings("PMD.CompareObjectsWithEquals")
249 private static boolean isSame(Object o1, Object o2) {
250 if (o1 instanceof Object[] && o2 instanceof Object[]) {
251 return isSame((Object[])o1, (Object[])o2);
252 }
253 return o1 == o2 || (o1 != null && o2 != null && o1.equals(o2));
254 }
255
256 @SuppressWarnings("PMD.UnusedNullCheckInEquals")
257 private static boolean isSame(Object[] a1, Object[] a2) {
258 return a1 == a2 || (a1 != null && a2 != null && Arrays.equals(a1, a2));
259 }
260
261 private static boolean contains(Collection<String> collection, String s1) {
262 for (String s2 : collection) {
263 if (isSame(s1, s2)) {
264 return true;
265 }
266 }
267 return false;
268 }
269
270 public boolean hasDescriptor(PropertyDescriptor<?> descriptor) {
271 return (propertyDescriptors != null && propertyDescriptors.contains(descriptor)) ||
272 super.hasDescriptor(descriptor);
273 }
274
275 public boolean hasOverriddenProperty(PropertyDescriptor<?> descriptor) {
276 return propertyValues != null && propertyValues.containsKey(descriptor);
277 }
278
279 public boolean usesDefaultValues() {
280
281 List<PropertyDescriptor<?>> descriptors = getOverriddenPropertyDescriptors();
282 if (!descriptors.isEmpty()) {
283 return false;
284 }
285
286 for (PropertyDescriptor<?> desc : descriptors) {
287 if (!isSame(desc.defaultValue(), getProperty(desc))) {
288 return false;
289 }
290 }
291
292 if (!getRule().usesDefaultValues()) {
293 return false;
294 }
295
296 return true;
297 }
298
299 public void useDefaultValueFor(PropertyDescriptor<?> desc) {
300
301
302 getRule().useDefaultValueFor(desc);
303
304 if (propertyValues == null) return;
305
306 propertyValues.remove(desc);
307
308 if (propertyDescriptors != null) {
309 propertyDescriptors.remove(desc);
310 }
311 }
312 }