View Javadoc

1   package net.sourceforge.pmd;
2   
3   import java.util.ArrayList;
4   import java.util.Collection;
5   import java.util.List;
6   import java.util.Map;
7   import java.util.Properties;
8   
9   import net.sourceforge.pmd.util.StringUtil;
10  
11  /**
12   * This class represents a Rule which is a reference to Rule defined in another
13   * RuleSet. All details of the Rule are delegated to the underlying referenced
14   * Rule, but those operations which modify overridden aspects of the rule are
15   * explicitly tracked.  Modification operations which set a value to the
16   * current underlying value do not override.
17   */
18  public class RuleReference extends AbstractDelegateRule {
19  	private String name;
20  	private Properties properties;
21  	private String message;
22  	private String description;
23  	private List<String> examples;
24  	private String externalInfoUrl;
25  	private Integer priority;
26  	private RuleSetReference ruleSetReference;
27  
28  	public String getOverriddenName() {
29  		return name;
30  	}
31  
32  	@Override
33  	public void setName(String name) {
34  		// Only override if different than current value, or if already overridden.
35  		if (!isSame(name, super.getName()) || this.name != null) {
36  			this.name = name;
37  			super.setName(name);
38  		}
39  	}
40  
41  	public Properties getOverriddenProperties() {
42  		return properties;
43  	}
44  
45  	@Override
46  	public void addProperty(String name, String property) {
47  		// Only override if different than current value.
48  		if (!super.hasProperty(name) || !isSame(property, super.getStringProperty(name))) {
49  			if (this.properties == null) {
50  				this.properties = new Properties();
51  			}
52  			this.properties.put(name, property);
53  			super.addProperty(name, property);
54  		}
55  	}
56  
57  	@Override
58  	public void addProperties(Properties properties) {
59  		// Attempt override for each
60  		for (Map.Entry<Object, Object> entry : properties.entrySet()) {
61  			addProperty((String)entry.getKey(), (String)entry.getValue());
62  		}
63  	}
64  
65  	public String getOverriddenMessage() {
66  		return message;
67  	}
68  
69  	@Override
70  	public void setMessage(String message) {
71  		// Only override if different than current value, or if already overridden.
72  		if (!isSame(message, super.getMessage()) || this.message != null) {
73  			this.message = message;
74  			super.setMessage(message);
75  		}
76  	}
77  
78  	public String getOverriddenDescription() {
79  		return description;
80  	}
81  
82  	@Override
83  	public void setDescription(String description) {
84  		// Only override if different than current value, or if already overridden.
85  		if (!isSame(description, super.getDescription()) || this.description != null) {
86  			this.description = description;
87  			super.setDescription(description);
88  		}
89  	}
90  
91  	public List<String> getOverriddenExamples() {
92  		return examples;
93  	}
94  
95  	@Override
96  	public void addExample(String example) {
97  		// TODO Meaningful override of examples is hard, because they are merely
98  		// a list of strings.  How does one indicate override of a particular
99  		// value?  Via index?  Rule.setExample(int, String)?  But the XML format
100 		// does not provide a means of overriding by index, not unless you took
101 		// the position in the XML file to indicate corresponding index to
102 		// override.  But that means you have to override starting from index 0.
103 		// This would be so much easier if examples had to have names, like
104 		// properties.
105 				
106 		// Only override if different than current values.
107 		if (!contains(super.getExamples(), example)) {
108 			if (this.examples == null) {
109 				this.examples = new ArrayList<String>(1);
110 			}
111 			// TODO Fix later. To keep example overrides from being unbounded, we're only going to keep track of the last one.
112 			this.examples.clear();
113 			this.examples.add(example);
114 			super.addExample(example);
115 		}
116 	}
117 
118 	public String getOverriddenExternalInfoUrl() {
119 		return externalInfoUrl;
120 	}
121 
122 	@Override
123 	public void setExternalInfoUrl(String externalInfoUrl) {
124 		// Only override if different than current value, or if already overridden.
125 		if (!isSame(externalInfoUrl, super.getExternalInfoUrl()) || this.externalInfoUrl != null) {
126 			this.externalInfoUrl = externalInfoUrl;
127 			super.setExternalInfoUrl(externalInfoUrl);
128 		}
129 	}
130 
131 	public Integer getOverriddenPriority() {
132 		return priority;
133 	}
134 
135 	@Override
136 	public void setPriority(int priority) {
137 		// Only override if different than current value, or if already overridden.
138 		if (priority != super.getPriority() || this.priority != null) {
139 			this.priority = priority;
140 			super.setPriority(priority);
141 		}
142 	}
143 
144 	public RuleSetReference getRuleSetReference() {
145 		return ruleSetReference;
146 	}
147 
148 	public void setRuleSetReference(RuleSetReference ruleSetReference) {
149 		this.ruleSetReference = ruleSetReference;
150 	}
151 
152 	private static boolean isSame(String s1, String s2) {
153 		return StringUtil.isSame(s1, s2, true, false, true);
154 	}
155 
156 	private static boolean contains(Collection<String> collection, String s1) {
157 		for (String s2 : collection) {
158 			if (isSame(s1, s2)) {
159 				return true;
160 			}
161 		}
162 		return false;
163 	}
164 }