/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.rule.properties.factories;
import static net.sourceforge.pmd.PropertyDescriptorFields.DEFAULT_VALUE;
import static net.sourceforge.pmd.PropertyDescriptorFields.DELIMITER;
import static net.sourceforge.pmd.PropertyDescriptorFields.DESC;
import static net.sourceforge.pmd.PropertyDescriptorFields.LEGAL_PACKAGES;
import static net.sourceforge.pmd.PropertyDescriptorFields.MAX;
import static net.sourceforge.pmd.PropertyDescriptorFields.MIN;
import static net.sourceforge.pmd.PropertyDescriptorFields.NAME;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.sourceforge.pmd.PropertyDescriptor;
import net.sourceforge.pmd.PropertyDescriptorFactory;
import net.sourceforge.pmd.lang.rule.properties.AbstractProperty;
import net.sourceforge.pmd.util.CollectionUtil;
import net.sourceforge.pmd.util.StringUtil;
/**
*
* @author Brian Remedios
*
* @param <T>
*/
public class BasicPropertyDescriptorFactory<T> implements PropertyDescriptorFactory {
private final Class<?> valueType;
private final Map<String, Boolean> fieldTypesByKey;
protected static final Map<String, Boolean> CORE_FIELD_TYPES_BY_KEY = CollectionUtil.mapFrom(
new String[] { NAME, DESC, DEFAULT_VALUE, DELIMITER },
new Boolean[] { Boolean.TRUE, Boolean.TRUE, Boolean.TRUE, Boolean.FALSE });
public BasicPropertyDescriptorFactory(Class<?> theValueType) {
valueType = theValueType;
fieldTypesByKey = Collections.unmodifiableMap(CORE_FIELD_TYPES_BY_KEY);
}
// public interface WrapperBuilder<T> {
// T[] newArray(int size);
// T itemFrom(String txt);
// }
//
// protected WrapperBuilder intBuilder = new WrapperBuilder<Integer>() {
// public Integer[] newArray(int size) { return new Integer[size]; }
// public Integer itemFrom(String txt) { return Integer.parseInt(txt); }
// };
public BasicPropertyDescriptorFactory(Class<?> theValueType, Map<String, Boolean> additionalFieldTypesByKey) {
valueType = theValueType;
Map<String, Boolean> temp = new HashMap<>(CORE_FIELD_TYPES_BY_KEY.size() + additionalFieldTypesByKey.size());
temp.putAll(CORE_FIELD_TYPES_BY_KEY);
temp.putAll(additionalFieldTypesByKey);
fieldTypesByKey = Collections.unmodifiableMap(temp);
}
@Override
public Class<?> valueType() {
return valueType;
}
@Override
public PropertyDescriptor<?> createWith(Map<String, String> valuesById) {
throw new RuntimeException("Unimplemented createWith() method in subclass");
}
@Override
public Map<String, Boolean> expectedFields() {
return fieldTypesByKey;
}
protected String nameIn(Map<String, String> valuesById) {
return valuesById.get(NAME);
}
protected String descriptionIn(Map<String, String> valuesById) {
return valuesById.get(DESC);
}
protected String defaultValueIn(Map<String, String> valuesById) {
return valuesById.get(DEFAULT_VALUE);
}
protected String numericDefaultValueIn(Map<String, String> valuesById) {
String number = defaultValueIn(valuesById);
return StringUtil.isEmpty(number) ? "0" : number; // TODO is 0
// reasonable if
// undefined?
}
protected static String minValueIn(Map<String, String> valuesById) {
return valuesById.get(MIN);
}
protected static String maxValueIn(Map<String, String> valuesById) {
return valuesById.get(MAX);
}
// protected static T[] primitivesFrom(String text, WrapperBuilder<T>
// builder) {
//
// String[] values = text.split(","); // TODO
// List items = new ArrayList(values.length);
// for (String value : values) {
// try {
// Object newIten = builder.itemFrom(value);
// items.add(newIten);
// } catch (Exception ex) {
//
// }
// }
// return items.toArray(builder.newArray(items.size()));
// }
protected static Boolean[] booleanValuesIn(String booleanString, char delimiter) {
String[] values = StringUtil.substringsOf(booleanString, delimiter);
Boolean[] result = new Boolean[values.length];
for (int i = 0; i < values.length; i++) {
result[i] = Boolean.valueOf(values[i]);
}
return result;
}
protected static Character[] charsIn(String charString, char delimiter) {
String[] values = StringUtil.substringsOf(charString, delimiter);
Character[] chars = new Character[values.length];
for (int i = 0; i < values.length; i++) {
if (values.length != 1) {
throw new IllegalArgumentException("missing/ambiguous character value");
}
chars[i] = values[i].charAt(0);
}
return chars;
}
protected static Integer[] integersIn(String numberString, char delimiter) {
String[] values = StringUtil.substringsOf(numberString, delimiter);
List<Integer> ints = new ArrayList<>(values.length);
for (String value : values) {
try {
Integer newInt = Integer.parseInt(value);
ints.add(newInt);
} catch (Exception ex) {
}
}
return ints.toArray(new Integer[ints.size()]);
}
protected static Long[] longsIn(String numberString, char delimiter) {
String[] values = StringUtil.substringsOf(numberString, delimiter);
List<Long> longs = new ArrayList<>(values.length);
for (String value : values) {
try {
Long newLong = Long.parseLong(value);
longs.add(newLong);
} catch (Exception ex) {
}
}
return longs.toArray(new Long[longs.size()]);
}
protected static Float[] floatsIn(String numberString, char delimiter) {
String[] values = StringUtil.substringsOf(numberString, delimiter);
List<Float> floats = new ArrayList<>(values.length);
for (String value : values) {
try {
Float newFloat = Float.parseFloat(value);
floats.add(newFloat);
} catch (Exception ex) {
}
}
return floats.toArray(new Float[floats.size()]);
}
protected static Double[] doublesIn(String numberString, char delimiter) {
String[] values = StringUtil.substringsOf(numberString, delimiter);
List<Double> doubles = new ArrayList<>(values.length);
for (String value : values) {
try {
Double newDouble = Double.parseDouble(value);
doubles.add(newDouble);
} catch (Exception ex) {
}
}
return doubles.toArray(new Double[doubles.size()]);
}
protected static String[] labelsIn(Map<String, String> valuesById) {
return null; // TODO
}
protected static Object[] choicesIn(Map<String, String> valuesById) {
return null; // TODO
}
protected static int indexIn(Map<String, String> valuesById) {
return 0; // TODO
}
protected static int[] indiciesIn(Map<String, String> valuesById) {
return null; // TODO
}
protected static char delimiterIn(Map<String, String> valuesById) {
return delimiterIn(valuesById, AbstractProperty.DEFAULT_DELIMITER);
}
protected static char delimiterIn(Map<String, String> valuesById, char defaultDelimiter) {
String characterStr = "";
if (valuesById.containsKey(DELIMITER)) {
characterStr = valuesById.get(DELIMITER).trim();
}
if (characterStr.isEmpty()) {
return defaultDelimiter;
}
return characterStr.charAt(0);
}
protected static String[] minMaxFrom(Map<String, String> valuesById) {
String min = minValueIn(valuesById);
String max = maxValueIn(valuesById);
if (StringUtil.isEmpty(min) || StringUtil.isEmpty(max)) {
throw new RuntimeException("min and max values must be specified");
}
return new String[] { min, max };
}
protected static String[] legalPackageNamesIn(Map<String, String> valuesById, char delimiter) {
String names = valuesById.get(LEGAL_PACKAGES);
if (StringUtil.isEmpty(names)) {
return null;
}
return StringUtil.substringsOf(names, delimiter);
}
public static Map<String, Boolean> expectedFieldTypesWith(String[] otherKeys, Boolean[] otherValues) {
Map<String, Boolean> largerMap = new HashMap<>(otherKeys.length + CORE_FIELD_TYPES_BY_KEY.size());
largerMap.putAll(CORE_FIELD_TYPES_BY_KEY);
for (int i = 0; i < otherKeys.length; i++) {
largerMap.put(otherKeys[i], otherValues[i]);
}
return largerMap;
}
// protected static Map<String, PropertyDescriptorFactory>
// factoriesByTypeIdFrom(PropertyDescriptorFactory[] factories) {
// Map<String, PropertyDescriptorFactory> factoryMap = new HashMap<String,
// PropertyDescriptorFactory>(factories.length);
// for (PropertyDescriptorFactory factory : factories)
// factoryMap.put(factory.typeId(), factory);
// return factoryMap;
// }
//
}