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 }