From a0ba221dbc57e6d6b1ee3b9cee4ae33647de9aac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Tue, 28 Nov 2017 19:39:54 +0100 Subject: [PATCH] Convert PropertyDescriptorUtil to an enum and enrich its interface refs #763 --- .../net/sourceforge/pmd/RuleSetWriter.java | 4 +- .../properties/PropertyDescriptorField.java | 2 +- .../properties/PropertyDescriptorUtil.java | 101 ---------- .../pmd/properties/PropertyTypeId.java | 174 ++++++++++++++++++ .../sourceforge/pmd/rules/RuleFactory.java | 4 +- .../AbstractPropertyDescriptorTester.java | 4 +- 6 files changed, 181 insertions(+), 108 deletions(-) delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyDescriptorUtil.java create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyTypeId.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java index 856ce4549f0..00811006275 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java @@ -34,7 +34,7 @@ import net.sourceforge.pmd.lang.rule.XPathRule; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertyDescriptorField; -import net.sourceforge.pmd.properties.PropertyDescriptorUtil; +import net.sourceforge.pmd.properties.PropertyTypeId; /** * This class represents a way to serialize a RuleSet to an XML configuration @@ -348,7 +348,7 @@ private Element createPropertyDefinitionElementBR(PropertyDescriptor property final Element propertyElement = createPropertyValueElement(propertyDescriptor, propertyDescriptor.defaultValue()); propertyElement.setAttribute(PropertyDescriptorField.TYPE.attributeName(), - PropertyDescriptorUtil.typeIdFor(propertyDescriptor.type(), + PropertyTypeId.typeIdFor(propertyDescriptor.type(), propertyDescriptor.isMultiValue())); Map propertyValuesById = propertyDescriptor.attributeValuesById(); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyDescriptorField.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyDescriptorField.java index e6ea6468d2b..e1d3f1dd09c 100755 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyDescriptorField.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyDescriptorField.java @@ -15,7 +15,7 @@ * * @author Brian Remedios * @see RuleSetFactory - * @see PropertyDescriptorUtil + * @see PropertyTypeId */ public enum PropertyDescriptorField { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyDescriptorUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyDescriptorUtil.java deleted file mode 100644 index c55f80765ef..00000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyDescriptorUtil.java +++ /dev/null @@ -1,101 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.properties; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import net.sourceforge.pmd.properties.builders.PropertyDescriptorExternalBuilder; - - -/** - * @author Clément Fournier - * @since 6.0.0 - */ -// TODO make an enum -public class PropertyDescriptorUtil { - - private static final Map> DESCRIPTOR_FACTORIES_BY_TYPE; - - - static { - Map> temp = new HashMap<>(16); - temp.put("Boolean", BooleanProperty.extractor()); - temp.put("List[Boolean]", BooleanMultiProperty.extractor()); - - temp.put("String", StringProperty.extractor()); - temp.put("List[String]", StringMultiProperty.extractor()); - temp.put("Character", CharacterProperty.extractor()); - temp.put("List[Character]", CharacterMultiProperty.extractor()); - - temp.put("Integer", IntegerProperty.extractor()); - temp.put("List[Integer]", IntegerMultiProperty.extractor()); - temp.put("Long", LongProperty.extractor()); - temp.put("List[Long]", LongMultiProperty.extractor()); - temp.put("Float", FloatProperty.extractor()); - temp.put("List[Float]", FloatMultiProperty.extractor()); - temp.put("Double", DoubleProperty.extractor()); - temp.put("List[Double]", DoubleMultiProperty.extractor()); - // temp.put("Enum", EnumeratedProperty.FACTORY); // TODO:cf we need new syntax in the xml to support that - // temp.put("List[Enum]", EnumeratedMultiProperty.FACTORY); - - temp.put("Class", TypeProperty.extractor()); - temp.put("List[Class]", TypeMultiProperty.extractor()); - - // temp.put("Method", MethodProperty.extractor()); // hidden, see #762 - // temp.put("List[Method]", MethodMultiProperty.extractor()); // ditto - // temp.put("File", FileProperty.extractor()); // ditto - - DESCRIPTOR_FACTORIES_BY_TYPE = Collections.unmodifiableMap(temp); - } - - - private PropertyDescriptorUtil() { - } - - - /** - * Returns the full mappings from type ids to extractors. - * - * @return The full mapping. - */ - public static Map> typeIdsToExtractors() { - return DESCRIPTOR_FACTORIES_BY_TYPE; - } - - - /** - * Gets the factory for the descriptor identified by the string id. - * - * @param typeId The identifier of the type - * - * @return The factory used to build new instances of a descriptor - */ - public static PropertyDescriptorExternalBuilder factoryFor(String typeId) { - return DESCRIPTOR_FACTORIES_BY_TYPE.get(typeId); - } - - - /** - * Gets the string representation of this type, as it should be given when defining a descriptor in the xml. - * - * @param valueType The type to look for - * @param multiValue Whether the descriptor is multivalued or not - * - * @return The type id - */ - public static String typeIdFor(Class valueType, boolean multiValue) { - - for (Map.Entry> entry : DESCRIPTOR_FACTORIES_BY_TYPE.entrySet()) { - if (entry.getValue().valueType() == valueType && entry.getValue().isMultiValue() == multiValue) { - return entry.getKey(); - } - } - return null; - } - - -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyTypeId.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyTypeId.java new file mode 100644 index 00000000000..2668c7fed7e --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyTypeId.java @@ -0,0 +1,174 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.properties; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorExternalBuilder; + + +/** + * Enumerates the properties that can be built from the XML. Defining a property in + * the XML requires the {@code type} attribute, and the mapping between the values of + * this attribute and the concrete property that is built is encoded in the constants + * of this enum. + * + * @author Clément Fournier + * @see PropertyDescriptorExternalBuilder + * @since 6.0.0 + */ +public enum PropertyTypeId { + BOOLEAN("Boolean", BooleanProperty.extractor()), + BOOLEAN_LIST("List[Boolean]", BooleanMultiProperty.extractor()), + + STRING("String", StringProperty.extractor()), + STRING_LIST("List[String]", StringMultiProperty.extractor()), + CHARACTER("Character", CharacterProperty.extractor()), + CHARACTER_LIST("List[Character]", CharacterMultiProperty.extractor()), + + INTEGER("Integer", IntegerProperty.extractor()), + INTEGER_LIST("List[Integer]", IntegerMultiProperty.extractor()), + LONG("Long", LongProperty.extractor()), + LONG_LIST("List[Long]", LongMultiProperty.extractor()), + FLOAT("Float", FloatProperty.extractor()), + FLOAT_LIST("List[Float]", FloatMultiProperty.extractor()), + DOUBLE("Double", DoubleProperty.extractor()), + DOUBLE_LIST("List[Double]", DoubleMultiProperty.extractor()), + // ENUM("Enum", EnumeratedProperty.FACTORY), // TODO:cf we need new syntax in the xml to support that + // ENUM_LIST("List[Enum]", EnumeratedMultiProperty.FACTORY), + + CLASS("Class", TypeProperty.extractor()), + CLASS_LIST("List[Class]", TypeMultiProperty.extractor()); + + + private static final Map> DESCRIPTOR_FACTORIES_BY_TYPE; + private final String typeId; + private final PropertyDescriptorExternalBuilder factory; + + static { + Map> temp = new HashMap<>(); + for (PropertyTypeId id : values()) { + temp.put(id.typeId, id.factory); + } + DESCRIPTOR_FACTORIES_BY_TYPE = Collections.unmodifiableMap(temp); + } + + + PropertyTypeId(String id, PropertyDescriptorExternalBuilder factory) { + this.typeId = id; + this.factory = factory; + } + + + /** + * Gets the value of the type attribute represented by this constant. + * + * @return The type id + */ + public String getTypeId() { + return typeId; + } + + + /** + * Gets the factory associated to the type id, that can build the + * property from strings extracted from the XML. + * + * @return The factory + */ + public PropertyDescriptorExternalBuilder getFactory() { + return factory; + } + + + /** + * Returns true if the property corresponding to this factory is numeric, + * which means it can be safely cast to a {@link NumericPropertyDescriptor}. + * + * @return whether the property is numeric + */ + public boolean isPropertyNumeric() { + return factory instanceof PropertyDescriptorBuilderConversionWrapper.SingleValue.Numeric + || factory instanceof PropertyDescriptorBuilderConversionWrapper.MultiValue.Numeric; + } + + + /** + * Returns true if the property corresponding to this factory is packaged, + * which means it can be safely cast to a {@link PackagedPropertyDescriptor}. + * + * @return whether the property is packaged + */ + public boolean isPropertyPackaged() { + return factory instanceof PropertyDescriptorBuilderConversionWrapper.SingleValue.Packaged + || factory instanceof PropertyDescriptorBuilderConversionWrapper.MultiValue.Packaged; + } + + + /** + * Returns true if the property corresponding to this factory takes + * lists of values as its value. + * + * @return whether the property is multivalue + */ + public boolean isPropertyMultivalue() { + return factory.isMultiValue(); + } + + + /** + * Returns the value type of the property corresponding to this factory. + * This is the component type of the list if the property is multivalued. + * + * @return The value type of the property + */ + public Class propertyValueType() { + return factory.valueType(); + } + + + /** + * Returns the full mappings from type ids to factory. + * + * @return The full mapping. + */ + public static Map> typeIdsToExtractors() { + return DESCRIPTOR_FACTORIES_BY_TYPE; + } + + + /** + * Gets the factory for the descriptor identified by the string id. + * + * @param typeId The identifier of the type + * + * @return The factory used to build new instances of a descriptor + */ + public static PropertyDescriptorExternalBuilder factoryFor(String typeId) { + return DESCRIPTOR_FACTORIES_BY_TYPE.get(typeId); + } + + + /** + * Gets the string representation of this type, as it should be given + * when defining a descriptor in the xml. + * + * @param valueType The type to look for + * @param multiValue Whether the descriptor is multivalued or not + * + * @return The type id + */ + public static String typeIdFor(Class valueType, boolean multiValue) { + for (Map.Entry> entry : DESCRIPTOR_FACTORIES_BY_TYPE.entrySet()) { + if (entry.getValue().valueType() == valueType && entry.getValue().isMultiValue() == multiValue) { + return entry.getKey(); + } + } + return null; + } +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/rules/RuleFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/rules/RuleFactory.java index 84ce6b95d49..bdca4f45a23 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/rules/RuleFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/rules/RuleFactory.java @@ -28,7 +28,7 @@ import net.sourceforge.pmd.lang.rule.RuleReference; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertyDescriptorField; -import net.sourceforge.pmd.properties.PropertyDescriptorUtil; +import net.sourceforge.pmd.properties.PropertyTypeId; import net.sourceforge.pmd.properties.builders.PropertyDescriptorExternalBuilder; @@ -304,7 +304,7 @@ private static boolean isPropertyDefinition(Element node) { private static PropertyDescriptor parsePropertyDefinition(Element propertyElement) { String typeId = propertyElement.getAttribute(PropertyDescriptorField.TYPE.attributeName()); - PropertyDescriptorExternalBuilder pdFactory = PropertyDescriptorUtil.factoryFor(typeId); + PropertyDescriptorExternalBuilder pdFactory = PropertyTypeId.factoryFor(typeId); if (pdFactory == null) { throw new IllegalArgumentException("No property descriptor factory for type: " + typeId); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java index b0c56663ae8..cbf11c0743d 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorTester.java @@ -61,7 +61,7 @@ public void testFactorySingleValue() { @SuppressWarnings("unchecked") protected final PropertyDescriptorExternalBuilder getSingleFactory() { - return (PropertyDescriptorExternalBuilder) PropertyDescriptorUtil.factoryFor(typeName); + return (PropertyDescriptorExternalBuilder) PropertyTypeId.factoryFor(typeName); } @@ -95,7 +95,7 @@ public void testFactoryMultiValueDefaultDelimiter() { @SuppressWarnings("unchecked") protected final PropertyDescriptorExternalBuilder> getMultiFactory() { - return (PropertyDescriptorExternalBuilder>) PropertyDescriptorUtil.factoryFor("List[" + typeName + "]"); + return (PropertyDescriptorExternalBuilder>) PropertyTypeId.factoryFor("List[" + typeName + "]"); }