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