View Javadoc
1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.lang.rule.properties;
5   
6   import static net.sourceforge.pmd.PropertyDescriptorFields.MAX;
7   import static net.sourceforge.pmd.PropertyDescriptorFields.MIN;
8   
9   import java.util.Map;
10  
11  import net.sourceforge.pmd.NumericPropertyDescriptor;
12  import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory;
13  
14  /**
15   * Maintains a pair of boundary limit values between which all values managed by
16   * the subclasses must fit.
17   * 
18   * @author Brian Remedios
19   * @param <T>
20   */
21  public abstract class AbstractNumericProperty<T> extends AbstractScalarProperty<T> implements
22          NumericPropertyDescriptor<T> {
23  
24      private Number lowerLimit;
25      private Number upperLimit;
26  
27      public static final Map<String, Boolean> NUMBER_FIELD_TYPES_BY_KEY = BasicPropertyDescriptorFactory
28              .expectedFieldTypesWith(new String[] { MIN, MAX }, new Boolean[] { Boolean.TRUE, Boolean.TRUE });
29  
30      /**
31       * 
32       * @param theName
33       * @param theDescription
34       * @param lower
35       * @param upper
36       * @param theDefault
37       * @param theUIOrder
38       * @throws IllegalArgumentException
39       */
40      protected AbstractNumericProperty(String theName, String theDescription, Number lower, Number upper, T theDefault,
41              float theUIOrder) {
42          super(theName, theDescription, theDefault, theUIOrder);
43  
44          if (lower.doubleValue() > upper.doubleValue()) {
45              throw new IllegalArgumentException("Lower limit cannot be greater than the upper limit");
46          }
47  
48          lowerLimit = lower;
49          upperLimit = upper;
50      }
51  
52      /**
53       * Returns the minimum value that instances of the property can have
54       * 
55       * @return The minimum value.
56       * @see net.sourceforge.pmd.NumericPropertyDescriptor#lowerLimit()
57       */
58      public Number lowerLimit() {
59          return lowerLimit;
60      }
61  
62      /**
63       * @return String
64       */
65      protected String defaultAsString() {
66          return defaultValue().toString();
67      }
68  
69      /**
70       * Returns the maximum value that instances of the property can have
71       * 
72       * @return The maximum value.
73       * @see net.sourceforge.pmd.NumericPropertyDescriptor#upperLimit()
74       */
75      public Number upperLimit() {
76          return upperLimit;
77      }
78  
79      /**
80       * @return String
81       */
82      public String rangeString() {
83          StringBuilder sb = new StringBuilder().append('(').append(lowerLimit).append(" -> ").append(upperLimit)
84                  .append(')');
85          return sb.toString();
86      }
87  
88      /**
89       * Returns a string describing any error the value may have when
90       * characterized by the receiver.
91       * 
92       * @param value Object
93       * @return String
94       */
95      protected String valueErrorFor(Object value) {
96  
97          double number = ((Number) value).doubleValue();
98  
99          if (number > upperLimit.doubleValue() || number < lowerLimit.doubleValue()) {
100             return value + " is out of range " + rangeString();
101         }
102 
103         return null;
104     }
105 
106     /**
107      * Method addAttributesTo.
108      * 
109      * @param attributes Map<String,String>
110      */
111     protected void addAttributesTo(Map<String, String> attributes) {
112         super.addAttributesTo(attributes);
113 
114         attributes.put(MIN, lowerLimit.toString());
115         attributes.put(MAX, upperLimit.toString());
116     }
117 }