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
62 if (!isSame(language, super.getLanguage()) || this.language != null) {
63 this.language = language;
64 super.setLanguage(language);
65 }
66 }
67
68 public LanguageVersion getOverriddenMinimumLanguageVersion() {
69 return minimumLanguageVersion;
70 }
71
72 @Override
73 public void setMinimumLanguageVersion(LanguageVersion minimumLanguageVersion) {
74
75
76 if (!isSame(minimumLanguageVersion, super.getMinimumLanguageVersion()) || this.minimumLanguageVersion != null) {
77 this.minimumLanguageVersion = minimumLanguageVersion;
78 super.setMinimumLanguageVersion(minimumLanguageVersion);
79 }
80 }
81
82 public LanguageVersion getOverriddenMaximumLanguageVersion() {
83 return maximumLanguageVersion;
84 }
85
86 @Override
87 public void setMaximumLanguageVersion(LanguageVersion maximumLanguageVersion) {
88
89
90 if (!isSame(maximumLanguageVersion, super.getMaximumLanguageVersion()) || this.maximumLanguageVersion != null) {
91 this.maximumLanguageVersion = maximumLanguageVersion;
92 super.setMaximumLanguageVersion(maximumLanguageVersion);
93 }
94 }
95
96 public Boolean isOverriddenDeprecated() {
97 return deprecated;
98 }
99
100 @Override
101 public boolean isDeprecated() {
102 return deprecated != null && deprecated.booleanValue();
103 }
104
105 @Override
106 public void setDeprecated(boolean deprecated) {
107
108
109 this.deprecated = deprecated ? deprecated : null;
110 }
111
112 public String getOverriddenName() {
113 return name;
114 }
115
116 public String getOriginalName() {
117 return super.getName();
118 }
119
120 @Override
121 public void setName(String name) {
122
123
124 if (!isSame(name, super.getName()) || this.name != null) {
125 this.name = name;
126 }
127 }
128
129 @Override
130 public String getName() {
131 if (this.name != null) {
132 return this.name;
133 }
134 return super.getName();
135 }
136
137 public String getOverriddenMessage() {
138 return message;
139 }
140
141 @Override
142 public void setMessage(String message) {
143
144
145 if (!isSame(message, super.getMessage()) || this.message != null) {
146 this.message = message;
147 super.setMessage(message);
148 }
149 }
150
151 public String getOverriddenDescription() {
152 return description;
153 }
154
155 @Override
156 public void setDescription(String description) {
157
158
159 if (!isSame(description, super.getDescription()) || this.description != null) {
160 this.description = description;
161 super.setDescription(description);
162 }
163 }
164
165 public List<String> getOverriddenExamples() {
166 return examples;
167 }
168
169 @Override
170 public void addExample(String example) {
171
172
173
174
175
176
177
178
179
180
181 if (!contains(super.getExamples(), example)) {
182 if (examples == null) {
183 examples = new ArrayList<String>(1);
184 }
185
186
187 examples.clear();
188 examples.add(example);
189 super.addExample(example);
190 }
191 }
192
193 public String getOverriddenExternalInfoUrl() {
194 return externalInfoUrl;
195 }
196
197 @Override
198 public void setExternalInfoUrl(String externalInfoUrl) {
199
200
201 if (!isSame(externalInfoUrl, super.getExternalInfoUrl()) || this.externalInfoUrl != null) {
202 this.externalInfoUrl = externalInfoUrl;
203 super.setExternalInfoUrl(externalInfoUrl);
204 }
205 }
206
207 public RulePriority getOverriddenPriority() {
208 return priority;
209 }
210
211 @Override
212 public void setPriority(RulePriority priority) {
213
214
215 if (priority != super.getPriority() || this.priority != null) {
216 this.priority = priority;
217 super.setPriority(priority);
218 }
219 }
220
221 public List<PropertyDescriptor<?>> getOverriddenPropertyDescriptors() {
222
223 return propertyDescriptors == null ? EMPTY_DESCRIPTORS : propertyDescriptors;
224 }
225
226 @Override
227 public void definePropertyDescriptor(PropertyDescriptor<?> propertyDescriptor) throws IllegalArgumentException {
228
229
230
231 super.definePropertyDescriptor(propertyDescriptor);
232 if (propertyDescriptors == null) {
233 propertyDescriptors = new ArrayList<PropertyDescriptor<?>>();
234 }
235 propertyDescriptors.add(propertyDescriptor);
236 }
237
238 public Map<PropertyDescriptor<?>, Object> getOverriddenPropertiesByPropertyDescriptor() {
239 return propertyValues;
240 }
241
242 @Override
243 public <T> void setProperty(PropertyDescriptor<T> propertyDescriptor, T value) {
244
245 if (!isSame(super.getProperty(propertyDescriptor), value)) {
246 if (propertyValues == null) {
247 propertyValues = new HashMap<PropertyDescriptor<?>, Object>();
248 }
249 propertyValues.put(propertyDescriptor, value);
250 super.setProperty(propertyDescriptor, value);
251 }
252 }
253
254 public RuleSetReference getRuleSetReference() {
255 return ruleSetReference;
256 }
257
258 public void setRuleSetReference(RuleSetReference ruleSetReference) {
259 this.ruleSetReference = ruleSetReference;
260 }
261
262 private static boolean isSame(String s1, String s2) {
263 return StringUtil.isSame(s1, s2, true, false, true);
264 }
265
266 @SuppressWarnings("PMD.CompareObjectsWithEquals")
267 private static boolean isSame(Object o1, Object o2) {
268 if (o1 instanceof Object[] && o2 instanceof Object[]) {
269 return isSame((Object[]) o1, (Object[]) o2);
270 }
271 return o1 == o2 || o1 != null && o2 != null && o1.equals(o2);
272 }
273
274 @SuppressWarnings("PMD.UnusedNullCheckInEquals")
275
276 private static boolean isSame(Object[] a1, Object[] a2) {
277 return a1 == a2 || a1 != null && a2 != null && Arrays.equals(a1, a2);
278 }
279
280 private static boolean contains(Collection<String> collection, String s1) {
281 for (String s2 : collection) {
282 if (isSame(s1, s2)) {
283 return true;
284 }
285 }
286 return false;
287 }
288
289 public boolean hasDescriptor(PropertyDescriptor<?> descriptor) {
290 return propertyDescriptors != null && propertyDescriptors.contains(descriptor)
291 || super.hasDescriptor(descriptor);
292 }
293
294 public boolean hasOverriddenProperty(PropertyDescriptor<?> descriptor) {
295 return propertyValues != null && propertyValues.containsKey(descriptor);
296 }
297
298 public boolean usesDefaultValues() {
299
300 List<PropertyDescriptor<?>> descriptors = getOverriddenPropertyDescriptors();
301 if (!descriptors.isEmpty()) {
302 return false;
303 }
304
305 for (PropertyDescriptor<?> desc : descriptors) {
306 if (!isSame(desc.defaultValue(), getProperty(desc))) {
307 return false;
308 }
309 }
310
311 if (!getRule().usesDefaultValues()) {
312 return false;
313 }
314
315 return true;
316 }
317
318 public void useDefaultValueFor(PropertyDescriptor<?> desc) {
319
320
321 getRule().useDefaultValueFor(desc);
322
323 if (propertyValues == null) {
324 return;
325 }
326
327 propertyValues.remove(desc);
328
329 if (propertyDescriptors != null) {
330 propertyDescriptors.remove(desc);
331 }
332 }
333 }