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.factories;
5   
6   import static net.sourceforge.pmd.PropertyDescriptorFields.DEFAULT_VALUE;
7   import static net.sourceforge.pmd.PropertyDescriptorFields.DELIMITER;
8   import static net.sourceforge.pmd.PropertyDescriptorFields.DESC;
9   import static net.sourceforge.pmd.PropertyDescriptorFields.LEGAL_PACKAGES;
10  import static net.sourceforge.pmd.PropertyDescriptorFields.MAX;
11  import static net.sourceforge.pmd.PropertyDescriptorFields.MIN;
12  import static net.sourceforge.pmd.PropertyDescriptorFields.NAME;
13  
14  import java.util.ArrayList;
15  import java.util.Collections;
16  import java.util.HashMap;
17  import java.util.List;
18  import java.util.Map;
19  
20  import net.sourceforge.pmd.PropertyDescriptor;
21  import net.sourceforge.pmd.PropertyDescriptorFactory;
22  import net.sourceforge.pmd.lang.rule.properties.AbstractProperty;
23  import net.sourceforge.pmd.util.CollectionUtil;
24  import net.sourceforge.pmd.util.StringUtil;
25  
26  /**
27   * 
28   * @author Brian Remedios
29   *
30   * @param <T>
31   */
32  public class BasicPropertyDescriptorFactory<T> implements PropertyDescriptorFactory {
33  
34      private final Class<?> valueType;
35      private final Map<String, Boolean> fieldTypesByKey;
36  
37      protected static final Map<String, Boolean> CORE_FIELD_TYPES_BY_KEY = CollectionUtil
38              .mapFrom(new String[] { NAME, DESC, DEFAULT_VALUE, DELIMITER }, new Boolean[] { Boolean.TRUE, Boolean.TRUE,
39                      Boolean.TRUE, Boolean.FALSE });
40  
41      public BasicPropertyDescriptorFactory(Class<?> theValueType) {
42          valueType = theValueType;
43          fieldTypesByKey = Collections.unmodifiableMap(CORE_FIELD_TYPES_BY_KEY);
44      }
45  
46      // public interface WrapperBuilder<T> {
47      // T[] newArray(int size);
48      // T itemFrom(String txt);
49      // }
50      //
51      // protected WrapperBuilder intBuilder = new WrapperBuilder<Integer>() {
52      // public Integer[] newArray(int size) { return new Integer[size]; }
53      // public Integer itemFrom(String txt) { return Integer.parseInt(txt); }
54      // };
55  
56      public BasicPropertyDescriptorFactory(Class<?> theValueType, Map<String, Boolean> additionalFieldTypesByKey) {
57  
58          valueType = theValueType;
59          Map<String, Boolean> temp = new HashMap<>(CORE_FIELD_TYPES_BY_KEY.size()
60                  + additionalFieldTypesByKey.size());
61          temp.putAll(CORE_FIELD_TYPES_BY_KEY);
62          temp.putAll(additionalFieldTypesByKey);
63  
64          fieldTypesByKey = Collections.unmodifiableMap(temp);
65      }
66  
67      public Class<?> valueType() {
68          return valueType;
69      }
70  
71      public PropertyDescriptor<?> createWith(Map<String, String> valuesById) {
72          throw new RuntimeException("Unimplemented createWith() method in subclass");
73      }
74  
75      public Map<String, Boolean> expectedFields() {
76          return fieldTypesByKey;
77      }
78  
79      protected String nameIn(Map<String, String> valuesById) {
80          return valuesById.get(NAME);
81      }
82  
83      protected String descriptionIn(Map<String, String> valuesById) {
84          return valuesById.get(DESC);
85      }
86  
87      protected String defaultValueIn(Map<String, String> valuesById) {
88          return valuesById.get(DEFAULT_VALUE);
89      }
90  
91      protected String numericDefaultValueIn(Map<String, String> valuesById) {
92          String number = defaultValueIn(valuesById);
93          return StringUtil.isEmpty(number) ? "0" : number; // TODO is 0
94                                                            // reasonable if
95                                                            // undefined?
96      }
97  
98      protected static String minValueIn(Map<String, String> valuesById) {
99          return valuesById.get(MIN);
100     }
101 
102     protected static String maxValueIn(Map<String, String> valuesById) {
103         return valuesById.get(MAX);
104     }
105 
106     // protected static T[] primitivesFrom(String text, WrapperBuilder<T>
107     // builder) {
108     //
109     // String[] values = text.split(","); // TODO
110     // List items = new ArrayList(values.length);
111     // for (String value : values) {
112     // try {
113     // Object newIten = builder.itemFrom(value);
114     // items.add(newIten);
115     // } catch (Exception ex) {
116     //
117     // }
118     // }
119     // return items.toArray(builder.newArray(items.size()));
120     // }
121 
122     protected static Boolean[] booleanValuesIn(String booleanString, char delimiter) {
123         String[] values = StringUtil.substringsOf(booleanString, delimiter);
124         Boolean[] result = new Boolean[values.length];
125         for (int i = 0; i < values.length; i++) {
126             result[i] = Boolean.valueOf(values[i]);
127         }
128         return result;
129     }
130 
131     protected static Character[] charsIn(String charString, char delimiter) {
132         String[] values = StringUtil.substringsOf(charString, delimiter);
133         Character[] chars = new Character[values.length];
134 
135         for (int i = 0; i < values.length; i++) {
136             if (values.length != 1) {
137                 throw new IllegalArgumentException("missing/ambiguous character value");
138             }
139             chars[i] = values[i].charAt(0);
140         }
141         return chars;
142     }
143 
144     protected static Integer[] integersIn(String numberString, char delimiter) {
145         String[] values = StringUtil.substringsOf(numberString, delimiter);
146         List<Integer> ints = new ArrayList<>(values.length);
147         for (String value : values) {
148             try {
149                 Integer newInt = Integer.parseInt(value);
150                 ints.add(newInt);
151             } catch (Exception ex) {
152 
153             }
154         }
155         return ints.toArray(new Integer[ints.size()]);
156     }
157 
158     protected static Long[] longsIn(String numberString, char delimiter) {
159         String[] values = StringUtil.substringsOf(numberString, delimiter);
160         List<Long> longs = new ArrayList<>(values.length);
161         for (String value : values) {
162             try {
163                 Long newLong = Long.parseLong(value);
164                 longs.add(newLong);
165             } catch (Exception ex) {
166 
167             }
168         }
169         return longs.toArray(new Long[longs.size()]);
170     }
171 
172     protected static Float[] floatsIn(String numberString, char delimiter) {
173         String[] values = StringUtil.substringsOf(numberString, delimiter);
174         List<Float> floats = new ArrayList<>(values.length);
175         for (String value : values) {
176             try {
177                 Float newFloat = Float.parseFloat(value);
178                 floats.add(newFloat);
179             } catch (Exception ex) {
180 
181             }
182         }
183         return floats.toArray(new Float[floats.size()]);
184     }
185 
186     protected static Double[] doublesIn(String numberString, char delimiter) {
187         String[] values = StringUtil.substringsOf(numberString, delimiter);
188         List<Double> doubles = new ArrayList<>(values.length);
189         for (String value : values) {
190             try {
191                 Double newDouble = Double.parseDouble(value);
192                 doubles.add(newDouble);
193             } catch (Exception ex) {
194 
195             }
196         }
197         return doubles.toArray(new Double[doubles.size()]);
198     }
199 
200     protected static String[] labelsIn(Map<String, String> valuesById) {
201         return null; // TODO
202     }
203 
204     protected static Object[] choicesIn(Map<String, String> valuesById) {
205         return null; // TODO
206     }
207 
208     protected static int indexIn(Map<String, String> valuesById) {
209         return 0; // TODO
210     }
211 
212     protected static int[] indiciesIn(Map<String, String> valuesById) {
213         return null; // TODO
214     }
215 
216     protected static char delimiterIn(Map<String, String> valuesById) {
217         return delimiterIn(valuesById, AbstractProperty.DEFAULT_DELIMITER);
218     }
219 
220     protected static char delimiterIn(Map<String, String> valuesById, char defaultDelimiter) {
221         String characterStr = "";
222         if (valuesById.containsKey(DELIMITER)) {
223             characterStr = valuesById.get(DELIMITER).trim();
224         }
225         if (characterStr.isEmpty()) {
226             return defaultDelimiter;
227         }
228         return characterStr.charAt(0);
229     }
230 
231     protected static String[] minMaxFrom(Map<String, String> valuesById) {
232         String min = minValueIn(valuesById);
233         String max = maxValueIn(valuesById);
234         if (StringUtil.isEmpty(min) || StringUtil.isEmpty(max)) {
235             throw new RuntimeException("min and max values must be specified");
236         }
237         return new String[] { min, max };
238     }
239 
240     protected static String[] legalPackageNamesIn(Map<String, String> valuesById, char delimiter) {
241         String names = valuesById.get(LEGAL_PACKAGES);
242         if (StringUtil.isEmpty(names)) {
243             return null;
244         }
245         return StringUtil.substringsOf(names, delimiter);
246     }
247 
248     public static Map<String, Boolean> expectedFieldTypesWith(String[] otherKeys, Boolean[] otherValues) {
249         Map<String, Boolean> largerMap = new HashMap<>(otherKeys.length + CORE_FIELD_TYPES_BY_KEY.size());
250         largerMap.putAll(CORE_FIELD_TYPES_BY_KEY);
251         for (int i = 0; i < otherKeys.length; i++) {
252             largerMap.put(otherKeys[i], otherValues[i]);
253         }
254         return largerMap;
255     }
256 
257     // protected static Map<String, PropertyDescriptorFactory>
258     // factoriesByTypeIdFrom(PropertyDescriptorFactory[] factories) {
259     // Map<String, PropertyDescriptorFactory> factoryMap = new HashMap<String,
260     // PropertyDescriptorFactory>(factories.length);
261     // for (PropertyDescriptorFactory factory : factories)
262     // factoryMap.put(factory.typeId(), factory);
263     // return factoryMap;
264     // }
265     //
266 }