001: package net.sourceforge.pmd;
002:
003: import java.util.ArrayList;
004: import java.util.Collection;
005: import java.util.List;
006: import java.util.Map;
007: import java.util.Properties;
008:
009: import net.sourceforge.pmd.util.StringUtil;
010:
011: /**
012: * This class represents a Rule which is a reference to Rule defined in another
013: * RuleSet. All details of the Rule are delegated to the underlying referenced
014: * Rule, but those operations which modify overridden aspects of the rule are
015: * explicitly tracked. Modification operations which set a value to the
016: * current underlying value do not override.
017: */
018: public class RuleReference extends AbstractDelegateRule {
019: private String name;
020: private Properties properties;
021: private String message;
022: private String description;
023: private List<String> examples;
024: private String externalInfoUrl;
025: private Integer priority;
026: private RuleSetReference ruleSetReference;
027:
028: public String getOverriddenName() {
029: return name;
030: }
031:
032: @Override
033: public void setName(String name) {
034: // Only override if different than current value, or if already overridden.
035: if (!isSame(name, super .getName()) || this .name != null) {
036: this .name = name;
037: super .setName(name);
038: }
039: }
040:
041: public Properties getOverriddenProperties() {
042: return properties;
043: }
044:
045: @Override
046: public void addProperty(String name, String property) {
047: // Only override if different than current value.
048: if (!super .hasProperty(name)
049: || !isSame(property, super .getStringProperty(name))) {
050: if (this .properties == null) {
051: this .properties = new Properties();
052: }
053: this .properties.put(name, property);
054: super .addProperty(name, property);
055: }
056: }
057:
058: @Override
059: public void addProperties(Properties properties) {
060: // Attempt override for each
061: for (Map.Entry<Object, Object> entry : properties.entrySet()) {
062: addProperty((String) entry.getKey(), (String) entry
063: .getValue());
064: }
065: }
066:
067: public String getOverriddenMessage() {
068: return message;
069: }
070:
071: @Override
072: public void setMessage(String message) {
073: // Only override if different than current value, or if already overridden.
074: if (!isSame(message, super .getMessage())
075: || this .message != null) {
076: this .message = message;
077: super .setMessage(message);
078: }
079: }
080:
081: public String getOverriddenDescription() {
082: return description;
083: }
084:
085: @Override
086: public void setDescription(String description) {
087: // Only override if different than current value, or if already overridden.
088: if (!isSame(description, super .getDescription())
089: || this .description != null) {
090: this .description = description;
091: super .setDescription(description);
092: }
093: }
094:
095: public List<String> getOverriddenExamples() {
096: return examples;
097: }
098:
099: @Override
100: public void addExample(String example) {
101: // TODO Meaningful override of examples is hard, because they are merely
102: // a list of strings. How does one indicate override of a particular
103: // value? Via index? Rule.setExample(int, String)? But the XML format
104: // does not provide a means of overriding by index, not unless you took
105: // the position in the XML file to indicate corresponding index to
106: // override. But that means you have to override starting from index 0.
107: // This would be so much easier if examples had to have names, like
108: // properties.
109:
110: // Only override if different than current values.
111: if (!contains(super .getExamples(), example)) {
112: if (this .examples == null) {
113: this .examples = new ArrayList<String>(1);
114: }
115: // TODO Fix later. To keep example overrides from being unbounded, we're only going to keep track of the last one.
116: this .examples.clear();
117: this .examples.add(example);
118: super .addExample(example);
119: }
120: }
121:
122: public String getOverriddenExternalInfoUrl() {
123: return externalInfoUrl;
124: }
125:
126: @Override
127: public void setExternalInfoUrl(String externalInfoUrl) {
128: // Only override if different than current value, or if already overridden.
129: if (!isSame(externalInfoUrl, super .getExternalInfoUrl())
130: || this .externalInfoUrl != null) {
131: this .externalInfoUrl = externalInfoUrl;
132: super .setExternalInfoUrl(externalInfoUrl);
133: }
134: }
135:
136: public Integer getOverriddenPriority() {
137: return priority;
138: }
139:
140: @Override
141: public void setPriority(int priority) {
142: // Only override if different than current value, or if already overridden.
143: if (priority != super .getPriority() || this .priority != null) {
144: this .priority = priority;
145: super .setPriority(priority);
146: }
147: }
148:
149: public RuleSetReference getRuleSetReference() {
150: return ruleSetReference;
151: }
152:
153: public void setRuleSetReference(RuleSetReference ruleSetReference) {
154: this .ruleSetReference = ruleSetReference;
155: }
156:
157: private static boolean isSame(String s1, String s2) {
158: return StringUtil.isSame(s1, s2, true, false, true);
159: }
160:
161: private static boolean contains(Collection<String> collection,
162: String s1) {
163: for (String s2 : collection) {
164: if (isSame(s1, s2)) {
165: return true;
166: }
167: }
168: return false;
169: }
170: }
|