diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 0b5f0bbe17..b4bd8836ff 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -423,6 +423,7 @@ a warning will now be produced suggesting users to adopt it for better performan * [#661](https://github.com/pmd/pmd/pull/661): \[apex] avoid hardcoding id's - [Jan Aertgeerts](https://github.com/JAertgeerts) * [#666](https://github.com/pmd/pmd/pull/666): \[java] Add DoNotExtendJavaLangThrowable rule - [Robert Painsi](https://github.com/robertpainsi) * [#668](https://github.com/pmd/pmd/pull/668): \[core] Fix javadoc warnings on pmd-core - [Clément Fournier](https://github.com/oowekyala) +* [#669](https://github.com/pmd/pmd/pull/669): \[core] Builder pattern for properties - [Clément Fournier](https://github.com/oowekyala) * [#675](https://github.com/pmd/pmd/pull/675): \[java] Fix in Java grammar: Try with final resource node error - [Gonzalo Ibars Ingman](https://github.com/gibarsin) * [#679](https://github.com/pmd/pmd/pull/679): \[core] Token scheme generalization - [Gonzalo Ibars Ingman](https://github.com/gibarsin) * [#694](https://github.com/pmd/pmd/pull/694): \[core] Add minor fixes to root pom - [Matias Comercio](https://github.com/MatiasComercio) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/AvoidDeeplyNestedIfStmtsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/AvoidDeeplyNestedIfStmtsRule.java index 38cf6d115f..7dc9db738f 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/AvoidDeeplyNestedIfStmtsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/AvoidDeeplyNestedIfStmtsRule.java @@ -14,8 +14,10 @@ public class AvoidDeeplyNestedIfStmtsRule extends AbstractApexRule { private int depth; private int depthLimit; - private static final IntegerProperty PROBLEM_DEPTH_DESCRIPTOR = new IntegerProperty("problemDepth", - "The if statement depth reporting threshold", 1, 25, 3, 1.0f); + private static final IntegerProperty PROBLEM_DEPTH_DESCRIPTOR + = IntegerProperty.named("problemDepth") + .desc("The if statement depth reporting threshold") + .range(1, 25).defaultValue(3).uiOrder(1.0f).build(); public AvoidDeeplyNestedIfStmtsRule() { definePropertyDescriptor(PROBLEM_DEPTH_DESCRIPTOR); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/StdCyclomaticComplexityRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/StdCyclomaticComplexityRule.java index 0a7d632fee..fbafac2d59 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/StdCyclomaticComplexityRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/StdCyclomaticComplexityRule.java @@ -37,8 +37,10 @@ import net.sourceforge.pmd.properties.IntegerProperty; */ public class StdCyclomaticComplexityRule extends AbstractApexRule { - public static final IntegerProperty REPORT_LEVEL_DESCRIPTOR = new IntegerProperty("reportLevel", - "Cyclomatic Complexity reporting threshold", 1, 30, 10, 1.0f); + public static final IntegerProperty REPORT_LEVEL_DESCRIPTOR + = IntegerProperty.named("reportLevel") + .desc("Cyclomatic Complexity reporting threshold") + .range(1, 30).defaultValue(10).uiOrder(1.0f).build(); public static final BooleanProperty SHOW_CLASSES_COMPLEXITY_DESCRIPTOR = new BooleanProperty( "showClassesComplexity", "Add class average violations to the report", true, 2.0f); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index 0c6563add0..228a4ee3ee 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -26,8 +26,10 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.lang3.StringUtils; +import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; @@ -40,11 +42,10 @@ import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.rule.MockRule; import net.sourceforge.pmd.lang.rule.RuleReference; import net.sourceforge.pmd.lang.rule.XPathRule; -import net.sourceforge.pmd.properties.AbstractPropertyDescriptorFactory; import net.sourceforge.pmd.properties.PropertyDescriptor; -import net.sourceforge.pmd.properties.PropertyDescriptorFactory; import net.sourceforge.pmd.properties.PropertyDescriptorField; import net.sourceforge.pmd.properties.PropertyDescriptorUtil; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorExternalBuilder; import net.sourceforge.pmd.util.ResourceLoader; /** @@ -872,20 +873,18 @@ public class RuleSetFactory { return; } - PropertyDescriptorFactory pdFactory = PropertyDescriptorUtil.factoryFor(typeId); + PropertyDescriptorExternalBuilder pdFactory = PropertyDescriptorUtil.factoryFor(typeId); if (pdFactory == null) { throw new RuntimeException("No property descriptor factory for type: " + typeId); } - Set valueKeys = pdFactory.expectableFields(); - Map values = new HashMap<>(valueKeys.size()); + Map values = new HashMap<>(); + NamedNodeMap atts = propertyElement.getAttributes(); // populate a map of values for an individual descriptor - for (PropertyDescriptorField field : valueKeys) { - String valueStr = propertyElement.getAttribute(field.attributeName()); - if (valueStr != null) { - values.put(field, valueStr); - } + for (int i = 0; i < atts.getLength(); i++) { + Attr a = (Attr) atts.item(i); + values.put(PropertyDescriptorField.getConstant(a.getName()), a.getValue()); } if (StringUtils.isBlank(values.get(DEFAULT_VALUE))) { @@ -898,7 +897,7 @@ public class RuleSetFactory { } // casting is not pretty but prevents the interface from having this method - PropertyDescriptor desc = ((AbstractPropertyDescriptorFactory) pdFactory).createExternalWith(values); + PropertyDescriptor desc = pdFactory.build(values); rule.definePropertyDescriptor(desc); setValue(rule, desc, strValue); 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 beee1b098b..5697db3f00 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java @@ -9,7 +9,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; - import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.FactoryConfigurationError; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/MockRule.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/MockRule.java index f363ba3e03..a4501f9d39 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/MockRule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/MockRule.java @@ -23,7 +23,7 @@ public class MockRule extends AbstractRule { public MockRule() { super(); setLanguage(LanguageRegistry.getLanguage("Dummy")); - definePropertyDescriptor(new IntegerProperty("testIntProperty", "testIntProperty", 0, 100, 1, 0)); + definePropertyDescriptor(IntegerProperty.named("testIntProperty").desc("testIntProperty").range(0, 100).defaultValue(1).uiOrder(0).build()); } public MockRule(String name, String description, String message, String ruleSetName, RulePriority priority) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractMultiNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractMultiNumericProperty.java index 2d9bd655bd..e6ed065287 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractMultiNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractMultiNumericProperty.java @@ -9,16 +9,18 @@ import java.util.Map; import net.sourceforge.pmd.properties.modules.NumericPropertyModule; + /** * Base class for multi-valued numeric properties. * * @param The type of number * * @author Brian Remedios + * @author Clément Fournier * @version Refactored June 2017 (6.0.0) */ /* default */ abstract class AbstractMultiNumericProperty extends AbstractMultiValueProperty - implements NumericPropertyDescriptor> { + implements NumericPropertyDescriptor> { private final NumericPropertyModule module; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractMultiPackagedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractMultiPackagedProperty.java index a39cf3a7b4..a9183adcae 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractMultiPackagedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractMultiPackagedProperty.java @@ -9,16 +9,18 @@ import java.util.Map; import net.sourceforge.pmd.properties.modules.PackagedPropertyModule; + /** * Multi-valued property restricting the type of its values to some packages. * * @param The type of the values * * @author Brian Remedios + * @author Clément Fournier * @version Refactored June 2017 (6.0.0) */ /* default */ abstract class AbstractMultiPackagedProperty extends AbstractMultiValueProperty - implements PackagedPropertyDescriptor> { + implements PackagedPropertyDescriptor> { protected final PackagedPropertyModule module; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractMultiValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractMultiValueProperty.java index f016f17c3c..1f4e7a362d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractMultiValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractMultiValueProperty.java @@ -14,6 +14,7 @@ import org.apache.commons.lang3.StringUtils; import net.sourceforge.pmd.Rule; + /** * Multi-valued property. * @@ -23,7 +24,7 @@ import net.sourceforge.pmd.Rule; * @version 6.0.0 */ /* default */ abstract class AbstractMultiValueProperty extends AbstractProperty> - implements MultiValuePropertyDescriptor { + implements MultiValuePropertyDescriptor { /** The default value. */ diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractNumericProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractNumericProperty.java index d942e02d60..2b5afaa6ae 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractNumericProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractNumericProperty.java @@ -8,17 +8,18 @@ import java.util.Map; import net.sourceforge.pmd.properties.modules.NumericPropertyModule; + /** - * Maintains a pair of boundary limit values between which all values managed by - * the subclasses must fit. + * Maintains a pair of boundary limit values between which all values managed by the subclasses must fit. * * @param The type of value. * * @author Brian Remedios + * @author Clément Fournier * @version Refactored June 2017 (6.0.0) */ /* default */ abstract class AbstractNumericProperty extends AbstractSingleValueProperty - implements NumericPropertyDescriptor { + implements NumericPropertyDescriptor { private final NumericPropertyModule module; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractPackagedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractPackagedProperty.java index d9aafbff69..3d498026a1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractPackagedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractPackagedProperty.java @@ -8,17 +8,19 @@ import java.util.Map; import net.sourceforge.pmd.properties.modules.PackagedPropertyModule; + /** - * Property which restricts the type of its values to some packages. If - * the legalPackageNames value is set to null then no restrictions are made. + * Property which restricts the type of its values to some packages. If the legalPackageNames value is set to null then + * no restrictions are made. * * @param The type of the values * * @author Brian Remedios + * @author Clément Fournier * @version Refactored June 2017 (6.0.0) */ /* default */ abstract class AbstractPackagedProperty extends AbstractSingleValueProperty - implements PackagedPropertyDescriptor { + implements PackagedPropertyDescriptor { protected final PackagedPropertyModule module; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractProperty.java index 2b1650b651..935d8e4b66 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractProperty.java @@ -13,12 +13,14 @@ import java.util.Map; import org.apache.commons.lang3.StringUtils; + /** * Abstract class for properties. * * @param The type of the property's value. This is a list type for multi-valued properties * * @author Brian Remedios + * @author Clément Fournier * @version Refactored June 2017 (6.0.0) */ /* default */ abstract class AbstractProperty implements PropertyDescriptor { @@ -50,14 +52,6 @@ import org.apache.commons.lang3.StringUtils; } - private static String checkNotEmpty(String arg, PropertyDescriptorField argId) throws IllegalArgumentException { - if (StringUtils.isBlank(arg)) { - throw new IllegalArgumentException("Property attribute '" + argId + "' cannot be null or blank"); - } - return arg; - } - - @Override public String description() { return description; @@ -107,8 +101,8 @@ import org.apache.commons.lang3.StringUtils; @Override public String toString() { return "[PropertyDescriptor: name=" + name() + "," - + " type=" + (isMultiValue() ? "List<" + type() + ">" : type()) + "," - + " value=" + defaultValue() + "]"; + + " type=" + (isMultiValue() ? "List<" + type() + ">" : type()) + "," + + " value=" + defaultValue() + "]"; } @@ -127,8 +121,8 @@ import org.apache.commons.lang3.StringUtils; /** - * Adds this property's attributes to the map. Subclasses can override this to add more - * {@link PropertyDescriptorField}. + * Adds this property's attributes to the map. Subclasses can override this to add more {@link + * PropertyDescriptorField}. * * @param attributes The map to fill */ @@ -153,4 +147,12 @@ import org.apache.commons.lang3.StringUtils; } + private static String checkNotEmpty(String arg, PropertyDescriptorField argId) throws IllegalArgumentException { + if (StringUtils.isBlank(arg)) { + throw new IllegalArgumentException("Property attribute '" + argId + "' cannot be null or blank"); + } + return arg; + } + + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorFactory.java deleted file mode 100755 index e4fb024153..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractPropertyDescriptorFactory.java +++ /dev/null @@ -1,312 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.properties; - -import static net.sourceforge.pmd.properties.PropertyDescriptor.CORE_EXPECTED_FIELDS; -import static net.sourceforge.pmd.properties.PropertyDescriptorField.DEFAULT_VALUE; -import static net.sourceforge.pmd.properties.PropertyDescriptorField.DELIMITER; -import static net.sourceforge.pmd.properties.PropertyDescriptorField.DESCRIPTION; -import static net.sourceforge.pmd.properties.PropertyDescriptorField.LEGAL_PACKAGES; -import static net.sourceforge.pmd.properties.PropertyDescriptorField.MAX; -import static net.sourceforge.pmd.properties.PropertyDescriptorField.MIN; -import static net.sourceforge.pmd.properties.PropertyDescriptorField.NAME; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import org.apache.commons.lang3.StringUtils; - -/** - * Basic implementation of a property descriptor factory. - * - * @param The type of values property descriptor returned by this factory. This can be a list. - * - * @author Brian Remedios - */ -public abstract class AbstractPropertyDescriptorFactory implements PropertyDescriptorFactory { - - private final Class valueType; - - /** - * Denote the identifiers of the expected fields paired with booleans - * denoting whether they are required or not. - */ - private final Map expectedFields; - - - public AbstractPropertyDescriptorFactory(Class theValueType) { - valueType = theValueType; - expectedFields = CORE_EXPECTED_FIELDS; - } - - - public AbstractPropertyDescriptorFactory(Class theValueType, Map additionalFieldTypesByKey) { - - valueType = theValueType; - if (additionalFieldTypesByKey == null) { - expectedFields = CORE_EXPECTED_FIELDS; - return; - } - Map temp - = new HashMap<>(CORE_EXPECTED_FIELDS.size() + additionalFieldTypesByKey.size()); - temp.putAll(CORE_EXPECTED_FIELDS); - temp.putAll(additionalFieldTypesByKey); - - expectedFields = Collections.unmodifiableMap(temp); - } - - - @Override - public Class valueType() { - return valueType; - } - - - @Override - public Set expectableFields() { - return Collections.unmodifiableSet(expectedFields.keySet()); - } - - - /** - * Retrieves the name of the descriptor from the map. - * - * @param valuesById Map of attributes - * - * @return The name, which is null if none is specified - */ - protected String nameIn(Map valuesById) { - return valuesById.get(NAME); - } - - - /** - * Retrieves the description from the map. - * - * @param valuesById Map of attributes - * - * @return The description, which is null if none is specified - */ - protected String descriptionIn(Map valuesById) { - return valuesById.get(DESCRIPTION); - } - - - /** - * Retrieves the default value from the map. - * - * @param valuesById Map of attributes - * - * @return The default value - * - * @throws RuntimeException if the default value is null, empty, or missing - */ - protected String defaultValueIn(Map valuesById) { - String deft = valuesById.get(DEFAULT_VALUE); - if (isValueMissing(deft)) { - throw new RuntimeException("Default value was null, empty, or missing"); - } - return deft; - } - - - @Override - public final PropertyDescriptor createWith(Map valuesById) { - checkRequiredFields(valuesById); - return createWith(valuesById, false); - } - - - /** Checks whether all required fields are present in the map. */ - private void checkRequiredFields(Map valuesById) { - for (Entry entry : expectedFields.entrySet()) { - if (entry.getValue() && isValueMissing(valuesById.get(entry.getKey()))) { - throw new RuntimeException("Missing required value for key: " + entry.getKey()); - } - } - } - - - /** - * Creates a new property descriptor specifying whether the descriptor is externally defined or not. This is - * meant to be implemented by subclasses. - * - * @param valuesById The map of values - * @param isExternallyDefined Whether the descriptor is externally defined - * - * @return A new and initialized {@link PropertyDescriptor} - */ - protected abstract PropertyDescriptor createWith(Map valuesById, boolean isExternallyDefined); - - - /** - * Checks if the value is considered as missing or not. Some properties support whitespace values, hence the - * check. By default this does not support it. The factory can override this method to change the predicate. - * - * @param value The value to check - * - * @return True if the value must be considered missing, false otherwise - */ - protected boolean isValueMissing(String value) { - return StringUtils.isBlank(value); - } - - - /** - * Creates a new property descriptor which was defined externally. - * - * @param valuesById The map of values - * - * @return A new and initialized {@link PropertyDescriptor} - * - * @see PropertyDescriptor#isDefinedExternally() - */ - public final PropertyDescriptor createExternalWith(Map valuesById) { - checkRequiredFields(valuesById); - return createWith(valuesById, true); - } - - - /** - * Gets the labels for enumerated properties, returns a string array of length 0 if none are specified. - * - * @param valuesById Map of attributes - * - * @return An array containing the labels - */ - protected static String[] labelsIn(Map valuesById) { - return StringUtils.split(valuesById.get(PropertyDescriptorField.LABELS), - MultiValuePropertyDescriptor.DEFAULT_DELIMITER); - } - - - // For enumerated properties - protected static Object[] choicesIn(Map valuesById) { - throw new UnsupportedOperationException(); // TODO: find a way to extract an arbitrary object from a string - // Maybe reason enough to only allow enums... - } - - - // For enumerated properties - protected static int indexIn(Map valuesById) { - throw new UnsupportedOperationException(); // TODO - } - - - // For enumerated properties - protected static Class classIn(Map valuesById) { - throw new UnsupportedOperationException(); // TODO - } - - - // For enumerated properties - protected static int[] indicesIn(Map valuesById) { - throw new UnsupportedOperationException(); // TODO - } - - - /** - * Finds the delimiter in the map, taking {@link MultiValuePropertyDescriptor#DEFAULT_DELIMITER} if none is - * mentioned. - * - * @param valuesById Map of attributes - * - * @return The delimiter or the default - */ - protected static char delimiterIn(Map valuesById) { - return delimiterIn(valuesById, MultiValuePropertyDescriptor.DEFAULT_DELIMITER); - } - - - /** - * Finds the delimiter in the map, taking the specified default delimiter if none is specified. - * - * @param valuesById Map of attributes - * @param defaultDelimiter The default delimiter to take - * - * @return The delimiter or the default - * - * @throws RuntimeException If the delimiter is present but is more than 1 character - */ - protected static char delimiterIn(Map valuesById, char defaultDelimiter) { - String characterStr = ""; - if (valuesById.containsKey(DELIMITER)) { - characterStr = valuesById.get(DELIMITER).trim(); - } - - if (StringUtils.isBlank(characterStr)) { - return defaultDelimiter; - } - - if (characterStr.length() != 1) { - throw new RuntimeException("Ambiguous delimiter character, must have length 1: \"" + characterStr + "\""); - } - return characterStr.charAt(0); - } - - - /** - * Retrieves the minimum and maximum values from the map. - * - * @param valuesById Map of attributes - * - * @return An array of 2 string, min at the left, max at the right - * - * @throws RuntimeException If one of them is missing - */ - protected static String[] minMaxFrom(Map valuesById) { - String min = minValueIn(valuesById); - String max = maxValueIn(valuesById); - if (StringUtils.isBlank(min) || StringUtils.isBlank(max)) { - throw new RuntimeException("min and max values must be specified"); - } - return new String[] {min, max}; - } - - - private static String minValueIn(Map valuesById) { - return valuesById.get(MIN); - } - - - private static String maxValueIn(Map valuesById) { - return valuesById.get(MAX); - } - - - protected static String[] legalPackageNamesIn(Map valuesById, char delimiter) { - String names = valuesById.get(LEGAL_PACKAGES); - if (StringUtils.isBlank(names)) { - return null; - } - return StringUtils.split(names, delimiter); - } - - - /** - * Returns a map describing which fields are required to build a property using this factory. The parameters are - * added to the {@link PropertyDescriptor#CORE_EXPECTED_FIELDS}, which are required for all descriptors. - * - * @param otherKeys Additional keys - * @param otherValues Whether the corresponding keys are required or not - * - * @return The complete map of expected fields. - */ - static Map expectedFieldTypesWith(PropertyDescriptorField[] otherKeys, - Boolean[] otherValues) { - Map largerMap = new HashMap<>( - otherKeys.length + CORE_EXPECTED_FIELDS.size()); - largerMap.putAll(CORE_EXPECTED_FIELDS); - for (int i = 0; i < otherKeys.length; i++) { - largerMap.put(otherKeys[i], otherValues[i]); - } - return largerMap; - } - - -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractPropertySource.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractPropertySource.java index 318ec1ca2b..f465861fb8 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractPropertySource.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractPropertySource.java @@ -15,9 +15,9 @@ import java.util.Set; import net.sourceforge.pmd.util.CollectionUtil; + /** - * Base class for objects which can be configured through properties. Rules and - * Reports are such objects. + * Base class for objects which can be configured through properties. Rules and Reports are such objects. * * @author Brian Remedios */ @@ -61,7 +61,7 @@ public abstract class AbstractPropertySource implements PropertySource { for (PropertyDescriptor descriptor : propertyDescriptors) { if (descriptor.name().equals(propertyDescriptor.name())) { throw new IllegalArgumentException("There is already a PropertyDescriptor with name '" - + propertyDescriptor.name() + "' defined on Rule " + getName() + "."); + + propertyDescriptor.name() + "' defined on Rule " + getName() + "."); } } propertyDescriptors.add(propertyDescriptor); @@ -71,8 +71,7 @@ public abstract class AbstractPropertySource implements PropertySource { /** - * Gets the name of the property source. This is e.g. the rule name or the - * report name. + * Gets the name of the property source. This is e.g. the rule name or the report name. * * @return the name */ @@ -147,7 +146,7 @@ public abstract class AbstractPropertySource implements PropertySource { private void checkValidPropertyDescriptor(PropertyDescriptor propertyDescriptor) { if (!propertyDescriptors.contains(propertyDescriptor)) { throw new IllegalArgumentException( - "Property descriptor not defined for Rule " + getName() + ": " + propertyDescriptor); + "Property descriptor not defined for Rule " + getName() + ": " + propertyDescriptor); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractSingleValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractSingleValueProperty.java index 40effa179c..6c294d798e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractSingleValueProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/AbstractSingleValueProperty.java @@ -6,6 +6,7 @@ package net.sourceforge.pmd.properties; import net.sourceforge.pmd.Rule; + /** * Single value property. * @@ -14,7 +15,7 @@ import net.sourceforge.pmd.Rule; * @author Clément Fournier */ /* default */ abstract class AbstractSingleValueProperty extends AbstractProperty - implements SingleValuePropertyDescriptor { + implements SingleValuePropertyDescriptor { /** Default value. */ private T defaultValue; @@ -85,12 +86,10 @@ import net.sourceforge.pmd.Rule; } - private String typeErrorFor(T value) { // TODO:cf consider subtypes? - + private String typeErrorFor(T value) { if (value != null && !type().isAssignableFrom(value.getClass())) { return value + " is not an instance of " + type(); } - return null; } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/BooleanMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/BooleanMultiProperty.java index a7f3fc69a8..bb13cac575 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/BooleanMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/BooleanMultiProperty.java @@ -8,7 +8,10 @@ import static net.sourceforge.pmd.properties.ValueParserConstants.BOOLEAN_PARSER import java.util.Arrays; import java.util.List; -import java.util.Map; + +import net.sourceforge.pmd.properties.builders.MultiValuePropertyBuilder; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper; + /** * Defines a property type that supports multiple Boolean values. @@ -17,20 +20,6 @@ import java.util.Map; */ public final class BooleanMultiProperty extends AbstractMultiValueProperty { - /** Factory. */ - public static final PropertyDescriptorFactory> FACTORY // @formatter:off - = new MultiValuePropertyDescriptorFactory(Boolean.class) { - @Override - public BooleanMultiProperty createWith(Map valuesById, boolean isDefinedExternally) { - char delimiter = delimiterIn(valuesById); - return new BooleanMultiProperty(nameIn(valuesById), - descriptionIn(valuesById), - ValueParserConstants.parsePrimitives(defaultValueIn(valuesById), delimiter, BOOLEAN_PARSER), - 0f, - isDefinedExternally); - } - }; // @formatter:on - /** * Constructor using an array of defaults. @@ -76,4 +65,32 @@ public final class BooleanMultiProperty extends AbstractMultiValueProperty extractor() { + return new PropertyDescriptorBuilderConversionWrapper.MultiValue(Boolean.class, ValueParserConstants.BOOLEAN_PARSER) { + @Override + protected BooleanMultiPBuilder newBuilder(String name) { + return new BooleanMultiPBuilder(name); + } + }; + } + + + public static BooleanMultiPBuilder named(String name) { + return new BooleanMultiPBuilder(name); + } + + + public static final class BooleanMultiPBuilder extends MultiValuePropertyBuilder { + private BooleanMultiPBuilder(String name) { + super(name); + } + + + @Override + public BooleanMultiProperty build() { + return new BooleanMultiProperty(this.name, this.description, this.defaultValues, this.uiOrder, isDefinedInXML); + } + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/BooleanProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/BooleanProperty.java index 78876146fb..acac8d414a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/BooleanProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/BooleanProperty.java @@ -6,7 +6,9 @@ package net.sourceforge.pmd.properties; import static net.sourceforge.pmd.properties.ValueParserConstants.BOOLEAN_PARSER; -import java.util.Map; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper; +import net.sourceforge.pmd.properties.builders.SingleValuePropertyBuilder; + /** * Defines a property type that supports single Boolean values. @@ -16,23 +18,8 @@ import java.util.Map; */ public final class BooleanProperty extends AbstractSingleValueProperty { - /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new SingleValuePropertyDescriptorFactory(Boolean.class) { - @Override - public BooleanProperty createWith(Map valuesById, boolean isDefinedExternally) { - return new BooleanProperty(nameIn(valuesById), - descriptionIn(valuesById), - BOOLEAN_PARSER.valueOf(defaultValueIn(valuesById)), - 0f, - isDefinedExternally); - } - }; // @formatter:on - - /** - * Constructor for BooleanProperty limited to a single value. Converts - * default argument string into a boolean. + * Constructor for BooleanProperty limited to a single value. Converts default argument string into a boolean. * * @param theName Name * @param theDescription Description @@ -75,4 +62,33 @@ public final class BooleanProperty extends AbstractSingleValueProperty public Boolean createFrom(String propertyString) throws IllegalArgumentException { return BOOLEAN_PARSER.valueOf(propertyString); } + + + static PropertyDescriptorBuilderConversionWrapper.SingleValue extractor() { + return new PropertyDescriptorBuilderConversionWrapper.SingleValue(Boolean.class, ValueParserConstants.BOOLEAN_PARSER) { + @Override + protected BooleanPBuilder newBuilder(String name) { + return new BooleanPBuilder(name); + } + }; + } + + + public static BooleanPBuilder named(String name) { + return new BooleanPBuilder(name); + } + + + public static final class BooleanPBuilder extends SingleValuePropertyBuilder { + private BooleanPBuilder(String name) { + super(name); + } + + + @Override + public BooleanProperty build() { + return new BooleanProperty(this.name, this.description, this.defaultValue, this.uiOrder, this.isDefinedInXML); + } + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/CharacterMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/CharacterMultiProperty.java index 1eb0e2c252..e94c3840e8 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/CharacterMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/CharacterMultiProperty.java @@ -7,10 +7,13 @@ package net.sourceforge.pmd.properties; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Map; import org.apache.commons.lang3.StringUtils; +import net.sourceforge.pmd.properties.builders.MultiValuePropertyBuilder; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper; + + /** * Multi-valued character property. * @@ -19,27 +22,6 @@ import org.apache.commons.lang3.StringUtils; */ public final class CharacterMultiProperty extends AbstractMultiValueProperty { - /** Factory. */ - public static final PropertyDescriptorFactory> FACTORY // @formatter:off - = new MultiValuePropertyDescriptorFactory(Character.class) { - - @Override - protected boolean isValueMissing(String value) { - return StringUtils.isEmpty(value); - } - - @Override - public CharacterMultiProperty createWith(Map valuesById, boolean isDefinedExternally) { - char delimiter = delimiterIn(valuesById); - return new CharacterMultiProperty(nameIn(valuesById), - descriptionIn(valuesById), - ValueParserConstants.parsePrimitives(defaultValueIn(valuesById), delimiter, ValueParserConstants.CHARACTER_PARSER), - 0.0f, - delimiter, - isDefinedExternally); - } - }; // @formatter:on - /** * Constructor using an array of defaults. @@ -111,4 +93,33 @@ public final class CharacterMultiProperty extends AbstractMultiValueProperty extractor() { + return new PropertyDescriptorBuilderConversionWrapper.MultiValue(Character.class, ValueParserConstants.CHARACTER_PARSER) { + @Override + protected CharacterMultiPBuilder newBuilder(String name) { + return new CharacterMultiPBuilder(name); + } + }; + } + + + public static CharacterMultiPBuilder named(String name) { + return new CharacterMultiPBuilder(name); + } + + + public static final class CharacterMultiPBuilder extends MultiValuePropertyBuilder { + private CharacterMultiPBuilder(String name) { + super(name); + } + + + @Override + public CharacterMultiProperty build() { + return new CharacterMultiProperty(this.name, this.description, this.defaultValues, this.uiOrder, multiValueDelimiter, isDefinedInXML); + } + } + + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/CharacterProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/CharacterProperty.java index d91b65a3ce..ba90f2b3f3 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/CharacterProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/CharacterProperty.java @@ -6,9 +6,9 @@ package net.sourceforge.pmd.properties; import static net.sourceforge.pmd.properties.ValueParserConstants.CHARACTER_PARSER; -import java.util.Map; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper; +import net.sourceforge.pmd.properties.builders.SingleValuePropertyBuilder; -import org.apache.commons.lang3.StringUtils; /** * Defines a property type that supports single Character values. @@ -18,26 +18,6 @@ import org.apache.commons.lang3.StringUtils; */ public final class CharacterProperty extends AbstractSingleValueProperty { - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new SingleValuePropertyDescriptorFactory(Character.class) { - - @Override - protected boolean isValueMissing(String value) { - return StringUtils.isEmpty(value); - } - - @Override - public CharacterProperty createWith(Map valuesById, boolean isDefinedExternally) { - return new CharacterProperty(nameIn(valuesById), - descriptionIn(valuesById), - defaultValueIn(valuesById) == null ? null - : defaultValueIn(valuesById).charAt(0), - 0f, - isDefinedExternally); - } - }; // @formatter:on - - /** * Constructor for CharacterProperty. * @@ -60,20 +40,6 @@ public final class CharacterProperty extends AbstractSingleValueProperty extractor() { + return new PropertyDescriptorBuilderConversionWrapper.SingleValue(Character.class, ValueParserConstants.CHARACTER_PARSER) { + @Override + protected CharacterPBuilder newBuilder(String name) { + return new CharacterPBuilder(name); + } + }; + } + + + public static CharacterPBuilder named(String name) { + return new CharacterPBuilder(name); + } + + + public static final class CharacterPBuilder extends SingleValuePropertyBuilder { + private CharacterPBuilder(String name) { + super(name); + } + + + @Override + public CharacterProperty build() { + return new CharacterProperty(this.name, this.description, this.defaultValue, this.uiOrder, isDefinedInXML); + } + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/DoubleMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/DoubleMultiProperty.java index 4b6004e132..5bfabaf259 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/DoubleMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/DoubleMultiProperty.java @@ -4,11 +4,12 @@ package net.sourceforge.pmd.properties; -import static net.sourceforge.pmd.properties.ValueParserConstants.DOUBLE_PARSER; - import java.util.Arrays; import java.util.List; -import java.util.Map; + +import net.sourceforge.pmd.properties.builders.MultiNumericPropertyBuilder; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper; + /** * Multi-valued double property. @@ -18,27 +19,6 @@ import java.util.Map; */ public final class DoubleMultiProperty extends AbstractMultiNumericProperty { - /** Factory. */ - public static final PropertyDescriptorFactory> FACTORY // @formatter:off - = new MultiValuePropertyDescriptorFactory(Double.class, NUMBER_FIELD_TYPES_BY_KEY) { - @Override - public DoubleMultiProperty createWith(Map valuesById, boolean isDefinedExternally) { - String[] minMax = minMaxFrom(valuesById); - char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); - List defaultValues - = ValueParserConstants.parsePrimitives(defaultValueIn(valuesById), delimiter, DOUBLE_PARSER); - - return new DoubleMultiProperty(nameIn(valuesById), - descriptionIn(valuesById), - DOUBLE_PARSER.valueOf(minMax[0]), - DOUBLE_PARSER.valueOf(minMax[1]), - defaultValues, - 0f, - isDefinedExternally); - } - }; // @formatter:on - - /** * Constructor using an array of defaults. * @@ -93,4 +73,32 @@ public final class DoubleMultiProperty extends AbstractMultiNumericProperty extractor() { + return new PropertyDescriptorBuilderConversionWrapper.MultiValue.Numeric(Double.class, ValueParserConstants.DOUBLE_PARSER) { + @Override + protected DoubleMultiPBuilder newBuilder(String name) { + return new DoubleMultiPBuilder(name); + } + }; + } + + + public static DoubleMultiPBuilder named(String name) { + return new DoubleMultiPBuilder(name); + } + + + public static final class DoubleMultiPBuilder extends MultiNumericPropertyBuilder { + private DoubleMultiPBuilder(String name) { + super(name); + } + + + @Override + public DoubleMultiProperty build() { + return new DoubleMultiProperty(name, description, lowerLimit, upperLimit, defaultValues, uiOrder, isDefinedInXML); + } + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/DoubleProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/DoubleProperty.java index 1bddf4169a..ce635c4366 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/DoubleProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/DoubleProperty.java @@ -6,34 +6,18 @@ package net.sourceforge.pmd.properties; import static net.sourceforge.pmd.properties.ValueParserConstants.DOUBLE_PARSER; -import java.util.Map; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper; +import net.sourceforge.pmd.properties.builders.SingleNumericPropertyBuilder; + /** - * Defines a property type that support single double-type property values - * within an upper and lower boundary. + * Defines a property type that support single double-type property values within an upper and lower boundary. * * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ public final class DoubleProperty extends AbstractNumericProperty { - /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new SingleValuePropertyDescriptorFactory(Double.class, NUMBER_FIELD_TYPES_BY_KEY) { - @Override - public DoubleProperty createWith(Map valuesById, - boolean isDefinedExternally) { - final String[] minMax = minMaxFrom(valuesById); - return new DoubleProperty(nameIn(valuesById), - descriptionIn(valuesById), - doubleFrom(minMax[0]), - doubleFrom(minMax[1]), - doubleFrom(defaultValueIn(valuesById)), - 0f, - isDefinedExternally); - } - }; // @formatter:on - /** * Constructor for DoubleProperty that limits itself to a single value within the specified limits. Converts string @@ -62,18 +46,6 @@ public final class DoubleProperty extends AbstractNumericProperty { } - /** - * Parses a String into a Double. - * - * @param numberString String to parse - * - * @return Parsed Double - */ - private static Double doubleFrom(String numberString) { - return DOUBLE_PARSER.valueOf(numberString); - } - - /** * Constructor that limits itself to a single value within the specified limits. * @@ -102,4 +74,45 @@ public final class DoubleProperty extends AbstractNumericProperty { protected Double createFrom(String value) { return doubleFrom(value); } + + + /** + * Parses a String into a Double. + * + * @param numberString String to parse + * + * @return Parsed Double + */ + private static Double doubleFrom(String numberString) { + return DOUBLE_PARSER.valueOf(numberString); + } + + + static PropertyDescriptorBuilderConversionWrapper.SingleValue.Numeric extractor() { + return new PropertyDescriptorBuilderConversionWrapper.SingleValue.Numeric(Double.class, ValueParserConstants.DOUBLE_PARSER) { + @Override + protected DoublePBuilder newBuilder(String name) { + return new DoublePBuilder(name); + } + }; + } + + + public static DoublePBuilder named(String name) { + return new DoublePBuilder(name); + } + + + public static final class DoublePBuilder extends SingleNumericPropertyBuilder { + private DoublePBuilder(String name) { + super(name); + } + + + @Override + public DoubleProperty build() { + return new DoubleProperty(name, description, lowerLimit, upperLimit, defaultValue, uiOrder, isDefinedInXML); + } + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/EnumeratedMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/EnumeratedMultiProperty.java index 06ea880080..fd4ed5530b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/EnumeratedMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/EnumeratedMultiProperty.java @@ -8,9 +8,11 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import net.sourceforge.pmd.properties.builders.MultiValuePropertyBuilder; import net.sourceforge.pmd.properties.modules.EnumeratedPropertyModule; import net.sourceforge.pmd.util.CollectionUtil; + /** * Multi-valued property which can take only a fixed set of values of any type, then selected via String labels. The * mappings method returns the set of mappings between the labels and their values. @@ -24,21 +26,6 @@ import net.sourceforge.pmd.util.CollectionUtil; public final class EnumeratedMultiProperty extends AbstractMultiValueProperty implements EnumeratedPropertyDescriptor> { - /** Factory. */ - public static final PropertyDescriptorFactory> FACTORY // @formatter:off - = new MultiValuePropertyDescriptorFactory(Object.class) { // TODO:cf is Object the right type? - @Override - public EnumeratedMultiProperty createWith(Map valuesById, boolean isDefinedExternally) { - Object[] choices = choicesIn(valuesById); - return new EnumeratedMultiProperty<>(nameIn(valuesById), - descriptionIn(valuesById), - CollectionUtil.mapFrom(labelsIn(valuesById), choices), - selection(indicesIn(valuesById), choices), - classIn(valuesById), - 0f, - isDefinedExternally); - } - }; // @formatter:on private final EnumeratedPropertyModule module; @@ -56,13 +43,13 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty * @param theUIOrder UI order * * @deprecated Use {@link #EnumeratedMultiProperty(String, String, Map, List, Class, float)}. Will be removed in - * 7.0.0 + * 7.0.0 */ @Deprecated public EnumeratedMultiProperty(String theName, String theDescription, String[] theLabels, E[] theChoices, int[] choiceIndices, Class valueType, float theUIOrder) { this(theName, theDescription, CollectionUtil.mapFrom(theLabels, theChoices), - selection(choiceIndices, theChoices), valueType, theUIOrder, false); + selection(choiceIndices, theChoices), valueType, theUIOrder, false); } @@ -78,13 +65,13 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty * @param theUIOrder UI order * * @deprecated Use {@link #EnumeratedMultiProperty(String, String, Map, List, Class, float)}. Will be removed in - * 7.0.0 + * 7.0.0 */ @Deprecated public EnumeratedMultiProperty(String theName, String theDescription, String[] theLabels, E[] theChoices, int[] choiceIndices, float theUIOrder) { this(theName, theDescription, CollectionUtil.mapFrom(theLabels, theChoices), - selection(choiceIndices, theChoices), null, theUIOrder, false); + selection(choiceIndices, theChoices), null, theUIOrder, false); } @@ -168,4 +155,44 @@ public final class EnumeratedMultiProperty extends AbstractMultiValueProperty return selected; } + + public static EnumMultiPBuilder named(String name) { + return new EnumMultiPBuilder<>(name); + } + + + public static final class EnumMultiPBuilder extends MultiValuePropertyBuilder> { + + private Class valueType; + private Map mappings; + + + private EnumMultiPBuilder(String name) { + super(name); + } + + public EnumMultiPBuilder type(Class type) { + this.valueType = type; + return this; + } + + /** + * Sets the key-value mappings. + * + * @param map A map of label to value + * + * @return The same builder + */ + public EnumMultiPBuilder mappings(Map map) { + this.mappings = map; + return this; + } + + + @Override + public EnumeratedMultiProperty build() { + return new EnumeratedMultiProperty<>(this.name, this.description, mappings, this.defaultValues, valueType, this.uiOrder, isDefinedInXML); + } + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/EnumeratedProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/EnumeratedProperty.java index ccaab99d77..f60fb8e5b0 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/EnumeratedProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/EnumeratedProperty.java @@ -4,12 +4,13 @@ package net.sourceforge.pmd.properties; -import java.util.Enumeration; import java.util.Map; +import net.sourceforge.pmd.properties.builders.SingleValuePropertyBuilder; import net.sourceforge.pmd.properties.modules.EnumeratedPropertyModule; import net.sourceforge.pmd.util.CollectionUtil; + /** * Property which can take only a fixed set of values of any type, then selected via String labels. The mappings method * returns the set of mappings between the labels and their values. @@ -23,26 +24,7 @@ import net.sourceforge.pmd.util.CollectionUtil; * @version Refactored June 2017 (6.0.0) */ public final class EnumeratedProperty extends AbstractSingleValueProperty - implements EnumeratedPropertyDescriptor { - - /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new SingleValuePropertyDescriptorFactory(Enumeration.class) { // TODO:cf Enumeration? Object? - - @Override - public EnumeratedProperty createWith(Map valuesById, boolean isDefinedExternally) { - Map labelsToChoices = CollectionUtil.mapFrom(labelsIn(valuesById), // this is not implemented - choicesIn(valuesById)); // ditto - return new EnumeratedProperty<>(nameIn(valuesById), - descriptionIn(valuesById), - labelsToChoices, - choicesIn(valuesById)[indexIn(valuesById)], - classIn(valuesById), - 0f, - isDefinedExternally); - } - }; // @formatter:on - + implements EnumeratedPropertyDescriptor { private final EnumeratedPropertyModule module; @@ -65,7 +47,7 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty public EnumeratedProperty(String theName, String theDescription, String[] theLabels, E[] theChoices, int defaultIndex, Class valueType, float theUIOrder) { this(theName, theDescription, CollectionUtil.mapFrom(theLabels, theChoices), - theChoices[defaultIndex], valueType, theUIOrder, false); + theChoices[defaultIndex], valueType, theUIOrder, false); } @@ -86,7 +68,7 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty public EnumeratedProperty(String theName, String theDescription, String[] theLabels, E[] theChoices, int defaultIndex, float theUIOrder) { this(theName, theDescription, CollectionUtil.mapFrom(theLabels, theChoices), - theChoices[defaultIndex], null, theUIOrder, false); + theChoices[defaultIndex], null, theUIOrder, false); } @@ -146,4 +128,35 @@ public final class EnumeratedProperty extends AbstractSingleValueProperty } + public static EnumPBuilder named(String name) { + return new EnumPBuilder<>(name); + } + + public static final class EnumPBuilder extends SingleValuePropertyBuilder> { + + private Class valueType; + private Map mappings; + + + private EnumPBuilder(String name) { + super(name); + } + + public EnumPBuilder type(Class type) { + this.valueType = type; + return this; + } + + public EnumPBuilder mappings(Map map) { + this.mappings = map; + return this; + } + + + @Override + public EnumeratedProperty build() { + return new EnumeratedProperty<>(this.name, this.description, mappings, this.defaultValue, valueType, this.uiOrder, isDefinedInXML); + } + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/EnumeratedPropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/EnumeratedPropertyDescriptor.java index 9a4b4a36be..0736db2c4d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/EnumeratedPropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/EnumeratedPropertyDescriptor.java @@ -6,6 +6,7 @@ package net.sourceforge.pmd.properties; import java.util.Map; + /** * Interface defining an enumerated property descriptor. * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/ExpectedFieldsBuilder.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/ExpectedFieldsBuilder.java deleted file mode 100644 index f5dac458c4..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/ExpectedFieldsBuilder.java +++ /dev/null @@ -1,57 +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; - -/** Builder for an expected fields map. */ -public final class ExpectedFieldsBuilder { - - private final Map requiredFields = new HashMap<>(); - - - private ExpectedFieldsBuilder() { - - } - - - /** - * Adds a mapping of field/ required to the map. - * - * @param field The field to expect - * @param isRequired Whether it's required or not - * - * @return This instance, so that we have a fluent interface - */ - public ExpectedFieldsBuilder put(PropertyDescriptorField field, boolean isRequired) { - requiredFields.put(field, isRequired); - return this; - } - - - /** - * Gets an immutable map containing the fields we've put here. - * - * @return The map of field/ isRequired mappings - */ - public Map build() { - return Collections.unmodifiableMap(requiredFields); - } - - - /** - * Gets a builder for a required fields map. - * - * @return A builder - * - * @see ExpectedFieldsBuilder - */ - public static ExpectedFieldsBuilder instance() { - return new ExpectedFieldsBuilder(); - } - -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/FileProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/FileProperty.java index d8d7bc7611..5720929625 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/FileProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/FileProperty.java @@ -5,10 +5,13 @@ package net.sourceforge.pmd.properties; import java.io.File; -import java.util.Map; import org.apache.commons.lang3.StringUtils; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper; +import net.sourceforge.pmd.properties.builders.SinglePackagedPropertyBuilder; + + /** * Property taking a File object as its value. * @@ -17,19 +20,6 @@ import org.apache.commons.lang3.StringUtils; */ public final class FileProperty extends AbstractSingleValueProperty { - /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new SingleValuePropertyDescriptorFactory(File.class) { - @Override - public FileProperty createWith(Map valuesById, boolean isDefinedExternally) { - return new FileProperty(nameIn(valuesById), - descriptionIn(valuesById), - null, - 0f, - isDefinedExternally); - } - }; // @formatter:on - /** * Constructor for file property. @@ -60,4 +50,34 @@ public final class FileProperty extends AbstractSingleValueProperty { public File createFrom(String propertyString) { return StringUtils.isBlank(propertyString) ? null : new File(propertyString); } + + + static PropertyDescriptorBuilderConversionWrapper.SingleValue extractor() { + return new PropertyDescriptorBuilderConversionWrapper.SingleValue(File.class, ValueParserConstants.FILE_PARSER) { + @Override + protected FilePBuilder newBuilder(String name) { + return new FilePBuilder(name); + } + }; + } + + + public static FilePBuilder named(String name) { + return new FilePBuilder(name); + } + + + public static final class FilePBuilder extends SinglePackagedPropertyBuilder { + private FilePBuilder(String name) { + super(name); + } + + + @Override + public FileProperty build() { + return new FileProperty(name, description, defaultValue, uiOrder, isDefinedInXML); + } + } + + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/FloatMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/FloatMultiProperty.java index d0d199afbe..4c06a0f107 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/FloatMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/FloatMultiProperty.java @@ -4,11 +4,12 @@ package net.sourceforge.pmd.properties; -import static net.sourceforge.pmd.properties.ValueParserConstants.FLOAT_PARSER; - import java.util.Arrays; import java.util.List; -import java.util.Map; + +import net.sourceforge.pmd.properties.builders.MultiNumericPropertyBuilder; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper; + /** * Multi-valued float property. @@ -18,25 +19,6 @@ import java.util.Map; */ public final class FloatMultiProperty extends AbstractMultiNumericProperty { - /** Factory. */ - public static final PropertyDescriptorFactory> FACTORY // @formatter:off - = new MultiValuePropertyDescriptorFactory(Float.class, NUMBER_FIELD_TYPES_BY_KEY) { - @Override - public FloatMultiProperty createWith(Map valuesById, - boolean isDefinedExternally) { - String[] minMax = minMaxFrom(valuesById); - char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); - List defaultValues = ValueParserConstants.parsePrimitives(defaultValueIn(valuesById), delimiter, FLOAT_PARSER); - return new FloatMultiProperty(nameIn(valuesById), - descriptionIn(valuesById), - FLOAT_PARSER.valueOf(minMax[0]), - FLOAT_PARSER.valueOf(minMax[1]), - defaultValues, - 0f, - isDefinedExternally); - } - }; // @formatter:on - /** * Constructor using an array of defaults. @@ -91,4 +73,34 @@ public final class FloatMultiProperty extends AbstractMultiNumericProperty extractor() { + return new PropertyDescriptorBuilderConversionWrapper.MultiValue.Numeric(Float.class, ValueParserConstants.FLOAT_PARSER) { + @Override + protected FloatMultiPBuilder newBuilder(String name) { + return new FloatMultiPBuilder(name); + } + }; + } + + + public static FloatMultiPBuilder named(String name) { + return new FloatMultiPBuilder(name); + } + + + public static final class FloatMultiPBuilder extends MultiNumericPropertyBuilder { + private FloatMultiPBuilder(String name) { + super(name); + } + + + @Override + public FloatMultiProperty build() { + return new FloatMultiProperty(name, description, lowerLimit, upperLimit, defaultValues, uiOrder, isDefinedInXML); + } + } + + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/FloatProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/FloatProperty.java index 6657a04c09..a3ce5de9a1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/FloatProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/FloatProperty.java @@ -6,32 +6,17 @@ package net.sourceforge.pmd.properties; import static net.sourceforge.pmd.properties.ValueParserConstants.FLOAT_PARSER; -import java.util.Map; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper; +import net.sourceforge.pmd.properties.builders.SingleNumericPropertyBuilder; + /** - * Defines a property type that supports single float property values within an - * upper and lower boundary. + * Defines a property type that supports single float property values within an upper and lower boundary. * * @author Brian Remedios */ public final class FloatProperty extends AbstractNumericProperty { - /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new SingleValuePropertyDescriptorFactory(Float.class, NUMBER_FIELD_TYPES_BY_KEY) { - @Override - public FloatProperty createWith(Map valuesById, boolean isDefinedExternally) { - final String[] minMax = minMaxFrom(valuesById); - return new FloatProperty(nameIn(valuesById), - descriptionIn(valuesById), - FLOAT_PARSER.valueOf(minMax[0]), - FLOAT_PARSER.valueOf(minMax[1]), - FLOAT_PARSER.valueOf(defaultValueIn(valuesById)), - 0f, - isDefinedExternally); - } - }; // @formatter:on - /** * Constructor for FloatProperty that limits itself to a single value within the specified limits. Converts string @@ -50,7 +35,7 @@ public final class FloatProperty extends AbstractNumericProperty { public FloatProperty(String theName, String theDescription, String minStr, String maxStr, String defaultStr, float theUIOrder) { this(theName, theDescription, FLOAT_PARSER.valueOf(minStr), - FLOAT_PARSER.valueOf(maxStr), FLOAT_PARSER.valueOf(defaultStr), theUIOrder, false); + FLOAT_PARSER.valueOf(maxStr), FLOAT_PARSER.valueOf(defaultStr), theUIOrder, false); } @@ -91,4 +76,32 @@ public final class FloatProperty extends AbstractNumericProperty { } + static PropertyDescriptorBuilderConversionWrapper.SingleValue.Numeric extractor() { + return new PropertyDescriptorBuilderConversionWrapper.SingleValue.Numeric(Float.class, ValueParserConstants.FLOAT_PARSER) { + @Override + protected FloatPBuilder newBuilder(String name) { + return new FloatPBuilder(name); + } + }; + } + + + public static FloatPBuilder named(String name) { + return new FloatPBuilder(name); + } + + + public static final class FloatPBuilder extends SingleNumericPropertyBuilder { + private FloatPBuilder(String name) { + super(name); + } + + + @Override + public FloatProperty build() { + return new FloatProperty(name, description, lowerLimit, upperLimit, defaultValue, uiOrder, isDefinedInXML); + } + } + + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/IntegerMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/IntegerMultiProperty.java index 55b3d963dc..3aa5781651 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/IntegerMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/IntegerMultiProperty.java @@ -4,11 +4,12 @@ package net.sourceforge.pmd.properties; -import static net.sourceforge.pmd.properties.ValueParserConstants.INTEGER_PARSER; - import java.util.Arrays; import java.util.List; -import java.util.Map; + +import net.sourceforge.pmd.properties.builders.MultiNumericPropertyBuilder; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper; + /** * Multi-valued integer property. @@ -18,25 +19,6 @@ import java.util.Map; */ public final class IntegerMultiProperty extends AbstractMultiNumericProperty { - /** Factory. */ - public static final PropertyDescriptorFactory> FACTORY // @formatter:off - = new MultiValuePropertyDescriptorFactory(Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { - @Override - public IntegerMultiProperty createWith(Map valuesById, boolean - isDefinedExternally) { - String[] minMax = minMaxFrom(valuesById); - char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); - List defaultValues = ValueParserConstants.parsePrimitives(defaultValueIn(valuesById), delimiter, INTEGER_PARSER); - return new IntegerMultiProperty(nameIn(valuesById), - descriptionIn(valuesById), - INTEGER_PARSER.valueOf(minMax[0]), - INTEGER_PARSER.valueOf(minMax[1]), - defaultValues, - 0f, - isDefinedExternally); - } - }; // @formatter:on - /** * Constructor using an array of defaults. @@ -93,4 +75,32 @@ public final class IntegerMultiProperty extends AbstractMultiNumericProperty extractor() { + return new PropertyDescriptorBuilderConversionWrapper.MultiValue.Numeric(Integer.class, ValueParserConstants.INTEGER_PARSER) { + @Override + protected IntegerMultiPBuilder newBuilder(String name) { + return new IntegerMultiPBuilder(name); + } + }; + } + + + public static IntegerMultiPBuilder named(String name) { + return new IntegerMultiPBuilder(name); + } + + + public static final class IntegerMultiPBuilder extends MultiNumericPropertyBuilder { + private IntegerMultiPBuilder(String name) { + super(name); + } + + + @Override + public IntegerMultiProperty build() { + return new IntegerMultiProperty(name, description, lowerLimit, upperLimit, defaultValues, uiOrder, isDefinedInXML); + } + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/IntegerProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/IntegerProperty.java index ade84c258b..6508fa3fbe 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/IntegerProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/IntegerProperty.java @@ -6,33 +6,17 @@ package net.sourceforge.pmd.properties; import static net.sourceforge.pmd.properties.ValueParserConstants.INTEGER_PARSER; -import java.util.Map; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper; +import net.sourceforge.pmd.properties.builders.SingleNumericPropertyBuilder; + /** - * Defines a datatype that supports single Integer property values within an - * upper and lower boundary. + * Defines a datatype that supports single Integer property values within an upper and lower boundary. * * @author Brian Remedios */ public final class IntegerProperty extends AbstractNumericProperty { - /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new SingleValuePropertyDescriptorFactory(Integer.class, NUMBER_FIELD_TYPES_BY_KEY) { - - @Override - public IntegerProperty createWith(Map valuesById, boolean isDefinedExternally) { - final String[] minMax = minMaxFrom(valuesById); - return new IntegerProperty(nameIn(valuesById), - descriptionIn(valuesById), - INTEGER_PARSER.valueOf(minMax[0]), - INTEGER_PARSER.valueOf(minMax[1]), - INTEGER_PARSER.valueOf(defaultValueIn(valuesById)), - 0f, - isDefinedExternally); - } - }; // @formatter:on - /** * Constructor that limits itself to a single value within the specified limits. @@ -71,4 +55,31 @@ public final class IntegerProperty extends AbstractNumericProperty { } + static PropertyDescriptorBuilderConversionWrapper.SingleValue.Numeric extractor() { + return new PropertyDescriptorBuilderConversionWrapper.SingleValue.Numeric(Integer.class, ValueParserConstants.INTEGER_PARSER) { + @Override + protected IntegerPBuilder newBuilder(String name) { + return new IntegerPBuilder(name); + } + }; + } + + + public static IntegerPBuilder named(String name) { + return new IntegerPBuilder(name); + } + + + public static final class IntegerPBuilder extends SingleNumericPropertyBuilder { + private IntegerPBuilder(String name) { + super(name); + } + + + @Override + public IntegerProperty build() { + return new IntegerProperty(name, description, lowerLimit, upperLimit, defaultValue, uiOrder, isDefinedInXML); + } + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/LongMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/LongMultiProperty.java index c0409b8107..bd872407f5 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/LongMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/LongMultiProperty.java @@ -4,11 +4,12 @@ package net.sourceforge.pmd.properties; -import static net.sourceforge.pmd.properties.ValueParserConstants.LONG_PARSER; - import java.util.Arrays; import java.util.List; -import java.util.Map; + +import net.sourceforge.pmd.properties.builders.MultiNumericPropertyBuilder; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper; + /** * Multi-valued long property. @@ -18,24 +19,6 @@ import java.util.Map; */ public final class LongMultiProperty extends AbstractMultiNumericProperty { - /** Factory. */ - public static final PropertyDescriptorFactory> FACTORY // @formatter:off - = new MultiValuePropertyDescriptorFactory(Long.class, NUMBER_FIELD_TYPES_BY_KEY) { - @Override - public LongMultiProperty createWith(Map valuesById, boolean isDefinedExternally) { - String[] minMax = minMaxFrom(valuesById); - char delimiter = delimiterIn(valuesById, DEFAULT_NUMERIC_DELIMITER); - List defaultValues = ValueParserConstants.parsePrimitives(defaultValueIn(valuesById), delimiter, LONG_PARSER); - return new LongMultiProperty(nameIn(valuesById), - descriptionIn(valuesById), - LONG_PARSER.valueOf(minMax[0]), - LONG_PARSER.valueOf(minMax[1]), - defaultValues, - 0f, - isDefinedExternally); - } - }; // @formatter:on - /** * Constructor using an array of defaults. @@ -91,4 +74,36 @@ public final class LongMultiProperty extends AbstractMultiNumericProperty return Long.valueOf(value); } + + static PropertyDescriptorBuilderConversionWrapper.MultiValue.Numeric extractor() { + return new PropertyDescriptorBuilderConversionWrapper.MultiValue.Numeric(Long.class, ValueParserConstants.LONG_PARSER) { + @Override + protected LongMultiPBuilder newBuilder(String name) { + return new LongMultiPBuilder(name); + } + }; + } + + + public static LongMultiPBuilder named(String name) { + return new LongMultiPBuilder(name); + } + + + private static final class LongMultiPBuilder + extends MultiNumericPropertyBuilder { + + protected LongMultiPBuilder(String name) { + super(name); + } + + + @Override + public LongMultiProperty build() { + return new LongMultiProperty(name, description, lowerLimit, upperLimit, + defaultValues, uiOrder, isDefinedInXML); + } + } + + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/LongProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/LongProperty.java index 63f02ea542..020dc50f3e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/LongProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/LongProperty.java @@ -4,35 +4,19 @@ package net.sourceforge.pmd.properties; -import static net.sourceforge.pmd.properties.ValueParserConstants.LONG_PARSER; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper; +import net.sourceforge.pmd.properties.builders.SingleNumericPropertyBuilder; -import java.util.Map; /** * Single valued long property. * * @author Brian Remedios + * @author Clément Fournier * @version Refactored June 2017 (6.0.0) */ public final class LongProperty extends AbstractNumericProperty { - /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new SingleValuePropertyDescriptorFactory(Long.class, NUMBER_FIELD_TYPES_BY_KEY) { - @Override - public LongProperty createWith(Map valuesById, boolean isDefinedExternally) { - final String[] minMax = minMaxFrom(valuesById); - return new LongProperty(nameIn(valuesById), - descriptionIn(valuesById), - LONG_PARSER.valueOf(minMax[0]), - LONG_PARSER.valueOf(minMax[1]), - LONG_PARSER.valueOf(defaultValueIn(valuesById)), - 0f, - isDefinedExternally); - } - }; - // @formatter:on - /** * Constructor for LongProperty that limits itself to a single value within the specified limits. Converts string @@ -51,7 +35,7 @@ public final class LongProperty extends AbstractNumericProperty { public LongProperty(String theName, String theDescription, String minStr, String maxStr, String defaultStr, float theUIOrder) { this(theName, theDescription, Long.valueOf(minStr), Long.valueOf(maxStr), - Long.valueOf(defaultStr), theUIOrder, false); + Long.valueOf(defaultStr), theUIOrder, false); } @@ -90,4 +74,32 @@ public final class LongProperty extends AbstractNumericProperty { return Long.valueOf(toParse); } + + static PropertyDescriptorBuilderConversionWrapper.SingleValue.Numeric extractor() { + return new PropertyDescriptorBuilderConversionWrapper.SingleValue.Numeric(Long.class, ValueParserConstants.LONG_PARSER) { + @Override + protected LongPBuilder newBuilder(String name) { + return new LongPBuilder(name); + } + }; + } + + + public static LongPBuilder named(String name) { + return new LongPBuilder(name); + } + + + public static final class LongPBuilder extends SingleNumericPropertyBuilder { + private LongPBuilder(String name) { + super(name); + } + + + @Override + public LongProperty build() { + return new LongProperty(name, description, lowerLimit, upperLimit, defaultValue, uiOrder, isDefinedInXML); + } + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/MethodMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/MethodMultiProperty.java index 68c11a5936..bac24a7efb 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/MethodMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/MethodMultiProperty.java @@ -9,39 +9,23 @@ import static net.sourceforge.pmd.properties.ValueParserConstants.METHOD_PARSER; import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; -import java.util.Map; +import net.sourceforge.pmd.properties.builders.MultiPackagedPropertyBuilder; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper; import net.sourceforge.pmd.properties.modules.MethodPropertyModule; + /** - * Defines a property type that can specify multiple methods to use as part of a - * rule. + * Defines a property type that can specify multiple methods to use as part of a rule. * - * Rule developers can limit the rules to those within designated packages per - * the 'legalPackages' argument in the constructor which can be an array of - * partial package names, i.e., ["java.lang", "com.mycompany" ]. + * Rule developers can limit the rules to those within designated packages per the 'legalPackages' argument in the + * constructor which can be an array of partial package names, i.e., ["java.lang", "com.mycompany" ]. * * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ public final class MethodMultiProperty extends AbstractMultiPackagedProperty { - /** Factory. */ - public static final PropertyDescriptorFactory> FACTORY // @formatter:off - = new MultiValuePropertyDescriptorFactory(Method.class, PACKAGED_FIELD_TYPES_BY_KEY) { - @Override - public MethodMultiProperty createWith(Map valuesById, boolean isDefinedExternally) { - char delimiter = delimiterIn(valuesById, MULTI_VALUE_DELIMITER); - return new MethodMultiProperty(nameIn(valuesById), - descriptionIn(valuesById), - methodsFrom(defaultValueIn(valuesById)), - legalPackageNamesIn(valuesById, delimiter), - 0f, - isDefinedExternally); - } - - }; // @formatter:on - /** * Constructor for MethodMultiProperty using an array of defaults. @@ -79,7 +63,7 @@ public final class MethodMultiProperty extends AbstractMultiPackagedProperty theDefaults, String[] legalPackageNames, float theUIOrder, boolean isDefinedExternally) { super(theName, theDescription, theDefaults, theUIOrder, isDefinedExternally, - new MethodPropertyModule(legalPackageNames, theDefaults)); + new MethodPropertyModule(legalPackageNames, theDefaults)); } @@ -98,14 +82,9 @@ public final class MethodMultiProperty extends AbstractMultiPackagedProperty methodsFrom(String valueString) { - return ValueParserConstants.parsePrimitives(valueString, MULTI_VALUE_DELIMITER, METHOD_PARSER); + methodsFrom(methodDefaults), + legalPackageNames, theUIOrder, + false); } @@ -131,4 +110,38 @@ public final class MethodMultiProperty extends AbstractMultiPackagedProperty valueFrom(String valueString) throws IllegalArgumentException { return methodsFrom(valueString); } + + + private static List methodsFrom(String valueString) { + return ValueParserConstants.parsePrimitives(valueString, MULTI_VALUE_DELIMITER, METHOD_PARSER); + } + + + static PropertyDescriptorBuilderConversionWrapper.MultiValue.Packaged extractor() { + return new PropertyDescriptorBuilderConversionWrapper.MultiValue.Packaged(Method.class, ValueParserConstants.METHOD_PARSER) { + @Override + protected MethodMultiPBuilder newBuilder(String name) { + return new MethodMultiPBuilder(name); + } + }; + } + + + public static MethodMultiPBuilder named(String name) { + return new MethodMultiPBuilder(name); + } + + + public static final class MethodMultiPBuilder extends MultiPackagedPropertyBuilder { + private MethodMultiPBuilder(String name) { + super(name); + } + + + @Override + public MethodMultiProperty build() { + return new MethodMultiProperty(name, description, defaultValues, legalPackageNames, uiOrder, isDefinedInXML); + } + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/MethodProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/MethodProperty.java index fe92aa88fc..66cc0bed81 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/MethodProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/MethodProperty.java @@ -9,38 +9,23 @@ import static net.sourceforge.pmd.properties.ValueParserConstants.METHOD_PARSER; import java.lang.reflect.Method; import java.util.Collections; -import java.util.Map; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper; +import net.sourceforge.pmd.properties.builders.SinglePackagedPropertyBuilder; import net.sourceforge.pmd.properties.modules.MethodPropertyModule; + /** - * Defines a property type that can specify a single method to use as part of a - * rule. + * Defines a property type that can specify a single method to use as part of a rule. * - *

Rule developers can limit the rules to those within designated packages per - * the 'legalPackages' argument in the constructor which can be an array of - * partial package names, i.e., ["java.lang", "com.mycompany" ].

+ *

Rule developers can limit the rules to those within designated packages per the 'legalPackages' argument in the + * constructor which can be an array of partial package names, i.e., ["java.lang", "com.mycompany" ].

* * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ public final class MethodProperty extends AbstractPackagedProperty { - /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new SingleValuePropertyDescriptorFactory(Method.class, PACKAGED_FIELD_TYPES_BY_KEY) { - @Override - public MethodProperty createWith(Map valuesById, boolean isDefinedExternally) { - char delimiter = delimiterIn(valuesById); - return new MethodProperty(nameIn(valuesById), - descriptionIn(valuesById), - METHOD_PARSER.valueOf(defaultValueIn(valuesById)), - legalPackageNamesIn(valuesById, delimiter), - 0f, - isDefinedExternally); - } - }; // @formatter:on - /** * Constructor for MethodProperty. @@ -61,7 +46,7 @@ public final class MethodProperty extends AbstractPackagedProperty { private MethodProperty(String theName, String theDescription, Method theDefault, String[] legalPackageNames, float theUIOrder, boolean isDefinedExternally) { super(theName, theDescription, theDefault, theUIOrder, isDefinedExternally, - new MethodPropertyModule(legalPackageNames, Collections.singletonList(theDefault))); + new MethodPropertyModule(legalPackageNames, Collections.singletonList(theDefault))); } @@ -79,7 +64,7 @@ public final class MethodProperty extends AbstractPackagedProperty { public MethodProperty(String theName, String theDescription, String defaultMethodStr, String[] legalPackageNames, float theUIOrder) { this(theName, theDescription, METHOD_PARSER.valueOf(defaultMethodStr), - legalPackageNames, theUIOrder, false); + legalPackageNames, theUIOrder, false); } @@ -101,4 +86,32 @@ public final class MethodProperty extends AbstractPackagedProperty { } + static PropertyDescriptorBuilderConversionWrapper.SingleValue.Packaged extractor() { + return new PropertyDescriptorBuilderConversionWrapper.SingleValue.Packaged(Method.class, ValueParserConstants.METHOD_PARSER) { + @Override + protected MethodPBuilder newBuilder(String name) { + return new MethodPBuilder(name); + } + }; + } + + + public static MethodPBuilder named(String name) { + return new MethodPBuilder(name); + } + + + public static final class MethodPBuilder extends SinglePackagedPropertyBuilder { + private MethodPBuilder(String name) { + super(name); + } + + + @Override + public MethodProperty build() { + return new MethodProperty(name, description, defaultValue, legalPackageNames, uiOrder, isDefinedInXML); + } + } + + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/MultiValuePropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/MultiValuePropertyDescriptor.java index 4d047a0b14..6d70fd44a7 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/MultiValuePropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/MultiValuePropertyDescriptor.java @@ -6,6 +6,7 @@ package net.sourceforge.pmd.properties; import java.util.List; + /** * Specializes property descriptors for multi valued descriptors. For this type of property, the return value of the * {@link #type()} method must be the class literal of the type parameter of this interface, which is the type of the diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/MultiValuePropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/MultiValuePropertyDescriptorFactory.java deleted file mode 100644 index 08693bd610..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/MultiValuePropertyDescriptorFactory.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.properties; - -import java.util.List; -import java.util.Map; - -/** - * Concrete implementation of a property descriptor factory for multi valued properties. - * - * @param Type of the property - * - * @author Clément Fournier - * @since 6.0.0 - */ -public abstract class MultiValuePropertyDescriptorFactory extends AbstractPropertyDescriptorFactory> { - - public MultiValuePropertyDescriptorFactory(Class theValueType) { - super(theValueType); - } - - - public MultiValuePropertyDescriptorFactory(Class theValueType, - Map additionalFieldTypesByKey) { - super(theValueType, additionalFieldTypesByKey); - } - - - @Override - protected abstract MultiValuePropertyDescriptor createWith(Map valuesById, - boolean isDefinedExternally); - - - @Override - public boolean isMultiValue() { - return true; - } -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/NumericPropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/NumericPropertyDescriptor.java index 82cac5e9d5..99959662a9 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/NumericPropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/NumericPropertyDescriptor.java @@ -4,25 +4,16 @@ package net.sourceforge.pmd.properties; -import static net.sourceforge.pmd.properties.PropertyDescriptorField.MAX; -import static net.sourceforge.pmd.properties.PropertyDescriptorField.MIN; - -import java.util.Map; - /** - * Defines a descriptor type whose instance values are required to lie within - * specified upper and lower limits. + * Defines a descriptor type whose instance values are required to lie within specified upper and lower limits. * * @param type of the property value * * @author Brian Remedios + * @author Clément Fournier */ public interface NumericPropertyDescriptor extends PropertyDescriptor { - Map NUMBER_FIELD_TYPES_BY_KEY - = ExpectedFieldsBuilder.instance().put(MIN, true).put(MAX, true).build(); - - /** * Returns the maximum value that instances of the property can have. * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/PackagedPropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/PackagedPropertyDescriptor.java index a58d21e4e0..bfc42fc402 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/PackagedPropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/PackagedPropertyDescriptor.java @@ -4,10 +4,6 @@ package net.sourceforge.pmd.properties; -import static net.sourceforge.pmd.properties.PropertyDescriptorField.LEGAL_PACKAGES; - -import java.util.Map; - /** * Defines a property descriptor type whose values can be described by qualified names and thus restricted to only some * packages. These typically use values such as {@link Class} and {@link java.lang.reflect.Method}. @@ -18,11 +14,6 @@ import java.util.Map; */ public interface PackagedPropertyDescriptor extends PropertyDescriptor { - /** Required additional fields. */ - Map PACKAGED_FIELD_TYPES_BY_KEY - = AbstractPropertyDescriptorFactory.expectedFieldTypesWith(new PropertyDescriptorField[] {LEGAL_PACKAGES}, - new Boolean[] {false}); - /** Delimiter used to separate package names. */ char PACKAGE_NAME_DELIMITER = ' '; /** Delimiter used to separate multiple values if this descriptor is multi valued. */ diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyDescriptor.java index d154888eb8..09d501e01c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyDescriptor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyDescriptor.java @@ -4,50 +4,33 @@ package net.sourceforge.pmd.properties; -import static net.sourceforge.pmd.properties.PropertyDescriptorField.DEFAULT_VALUE; -import static net.sourceforge.pmd.properties.PropertyDescriptorField.DELIMITER; -import static net.sourceforge.pmd.properties.PropertyDescriptorField.DESCRIPTION; -import static net.sourceforge.pmd.properties.PropertyDescriptorField.NAME; - import java.util.Map; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleSetWriter; + /** - * Property value descriptor that defines the use & requirements for setting - * property values for use within PMD and any associated GUIs. While concrete - * descriptor instances are static and immutable they provide validation, + * Property value descriptor that defines the use & requirements for setting property values for use within PMD and + * any associated GUIs. While concrete descriptor instances are static and immutable they provide validation, * serialization, and default values for any specific datatypes. * - *

This interface is primarily specialized according to whether the property is - * multi-valued or single-valued, see {@link SingleValuePropertyDescriptor} and - * {@link MultiValuePropertyDescriptor}. + *

This interface is primarily specialized according to whether the property is multi-valued or single-valued, see + * {@link SingleValuePropertyDescriptor} and {@link MultiValuePropertyDescriptor}. * - *

Several interfaces further specialize the behaviour of descriptors to accommodate - * specific types of descriptors, see {@link NumericPropertyDescriptor} and - * {@link EnumeratedPropertyDescriptor}. + *

Several interfaces further specialize the behaviour of descriptors to accommodate specific types of descriptors, + * see {@link NumericPropertyDescriptor} and {@link EnumeratedPropertyDescriptor}. * * @param type of the property's value. This is a list type for multi-valued properties. * * @author Brian Remedios + * @author Clément Fournier * @version Refactored June 2017 (6.0.0) */ public interface PropertyDescriptor extends Comparable> { - /** Default expected fields. Unmodifiable. */ - Map CORE_EXPECTED_FIELDS - = ExpectedFieldsBuilder.instance() - .put(NAME, true) - .put(DESCRIPTION, true) - .put(DEFAULT_VALUE, true) - .put(DELIMITER, false) - .build(); - - /** - * The name of the property without spaces as it serves as the key into the - * property map. + * The name of the property without spaces as it serves as the key into the property map. * * @return String */ @@ -55,8 +38,7 @@ public interface PropertyDescriptor extends Comparable> /** - * Describes the property and the role it plays within the rule it is - * specified for. Could be used in a tooltip. + * Describes the property and the role it plays within the rule it is specified for. Could be used in a tooltip. * * @return String */ @@ -64,8 +46,8 @@ public interface PropertyDescriptor extends Comparable> /** - * Denotes the value datatype. For multi value properties, this is not the - * List class but the list's component class. + * Denotes the value datatype. For multi value properties, this is not the List class but the list's component + * class. * * @return Class literal of the value type */ @@ -75,10 +57,9 @@ public interface PropertyDescriptor extends Comparable> /** * Returns whether the property is multi-valued, i.e. an array of strings, * - *

As unary property rule properties will return a value of one, you must - * use the get/setProperty accessors when working with the actual values. - * When working with multi-value properties then the get/setProperties - * accessors must be used.

+ *

As unary property rule properties will return a value of one, you must use the get/setProperty accessors when + * working with the actual values. When working with multi-value properties then the get/setProperties accessors + * must be used.

* * @return boolean */ @@ -86,8 +67,7 @@ public interface PropertyDescriptor extends Comparable> /** - * Default value to use when the user hasn't specified one or when they wish - * to revert to a known-good state. + * Default value to use when the user hasn't specified one or when they wish to revert to a known-good state. * * @return Object */ @@ -95,8 +75,8 @@ public interface PropertyDescriptor extends Comparable> /** - * Validation function that returns a diagnostic error message for a sample - * property value. Returns null if the value is acceptable. + * Validation function that returns a diagnostic error message for a sample property value. Returns null if the + * value is acceptable. * * @param value The value to check. * @@ -106,15 +86,12 @@ public interface PropertyDescriptor extends Comparable> /** - * Denotes the relative order the property field should occupy if we are - * using an auto-generated UI to display and edit property values. If the - * value returned has a non-zero fractional part then this is can be used to - * place adjacent fields on the same row. + * Denotes the relative order the property field should occupy if we are using an auto-generated UI to display and + * edit property values. If the value returned has a non-zero fractional part then this is can be used to place + * adjacent fields on the same row. * - *

Example:
- * name -> 0.0 description 1.0 minValue -> 2.0 maxValue -> 2.1 - *

- * ..would have their fields placed like:
+ *

Example:
name -> 0.0 description 1.0 minValue -> 2.0 maxValue -> 2.1

..would have their + * fields placed like:
* * name: [ ] description: [ ] minimum: [ ] maximum: [ ] * @@ -129,15 +106,13 @@ public interface PropertyDescriptor extends Comparable> * @param propertyString The string to parse * * @return The value represented by the string - * * @throws IllegalArgumentException if the given string cannot be parsed */ T valueFrom(String propertyString) throws IllegalArgumentException; /** - * Formats the object onto a string suitable for storage within the property - * map. + * Formats the object onto a string suitable for storage within the property map. * * @param value Object * @@ -147,8 +122,8 @@ public interface PropertyDescriptor extends Comparable> /** - * A convenience method that returns an error string if the rule holds onto - * a property value that has a problem. Returns null otherwise. + * A convenience method that returns an error string if the rule holds onto a property value that has a problem. + * Returns null otherwise. * * @param rule Rule * @@ -158,9 +133,8 @@ public interface PropertyDescriptor extends Comparable> /** - * If the datatype is a String then return the preferred number of rows to - * allocate in the text widget, returns a value of one for all other types. - * Useful for multi-line XPATH editors. + * If the datatype is a String then return the preferred number of rows to allocate in the text widget, returns a + * value of one for all other types. Useful for multi-line XPATH editors. * * @return int */ @@ -168,8 +142,7 @@ public interface PropertyDescriptor extends Comparable> /** - * Returns a map representing all the property attributes of the receiver in - * string form. + * Returns a map representing all the property attributes of the receiver in string form. * * @return map */ @@ -177,10 +150,9 @@ public interface PropertyDescriptor extends Comparable> /** - * True if this descriptor was defined in the ruleset xml. This precision is - * necessary for the {@link RuleSetWriter} to write out the property correctly: - * if it was defined externally, then its definition must be written out, otherwise - * only its value. + * True if this descriptor was defined in the ruleset xml. This precision is necessary for the {@link RuleSetWriter} + * to write out the property correctly: if it was defined externally, then its definition must be written out, + * otherwise only its value. * * @return True if the descriptor was defined in xml */ diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyDescriptorFactory.java deleted file mode 100755 index a21517322e..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyDescriptorFactory.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.properties; - -import java.util.Map; -import java.util.Set; - -/** - * A factory to create {@link PropertyDescriptor}s based on a map of values. - * - * @param The type of values property descriptor returned by this factory. This can be a list. - * - * @author Brian Remedios - * @version Refactored July 2017 (6.0.0) - */ -public interface PropertyDescriptorFactory { - - /** - * The type of the value of the {@link PropertyDescriptor} created by this - * factory. - * - * @return The type of the value. - */ - Class valueType(); - - - /** - * Returns true if the built property descriptor is multi-valued. - * - * @return True if the built property descriptor is multi-valued. - */ - boolean isMultiValue(); - - - /** - * Denote the identifiers of all fields that contribute to building - * this descriptor. Control of the required fields is performed - * inside the factory. - * - * @return A set of field identifiers - */ - Set expectableFields(); - - - /** - * Create a property descriptor of the appropriate type using the values - * provided. - * - * @param valuesById the map of values - * - * @return A new and initialized {@link PropertyDescriptor} - */ - PropertyDescriptor createWith(Map valuesById); -} 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 268db660f5..e6ea6468d2 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 @@ -4,11 +4,14 @@ package net.sourceforge.pmd.properties; +import java.util.Objects; + import net.sourceforge.pmd.RuleSetFactory; + /** - * Field names for parsing the properties out of the ruleset xml files. These are intended to be used as the keys to - * a map of fields to values. Most property descriptors can be built directly from such a map using their factory. + * Field names for parsing the properties out of the ruleset xml files. These are intended to be used as the keys to a + * map of fields to values. Most property descriptors can be built directly from such a map using their factory. * * @author Brian Remedios * @see RuleSetFactory @@ -22,6 +25,8 @@ public enum PropertyDescriptorField { NAME("name"), /** The description of the property. */ DESCRIPTION("description"), + /** The UI order. */ + UI_ORDER("uiOrder"), /** The default value. */ DEFAULT_VALUE("value"), /** For multi-valued properties, this defines the delimiter of the single values. */ @@ -30,10 +35,7 @@ public enum PropertyDescriptorField { MIN("min"), /** The maximum allowed value for numeric properties. */ MAX("max"), - /** - * To limit the range of valid values, package names. - * @see PackagedPropertyDescriptor - */ + /** To limit the range of valid values, package names. */ LEGAL_PACKAGES("legalPackages"), /** Labels for enumerated properties. */ LABELS("labels"), @@ -65,4 +67,14 @@ public enum PropertyDescriptorField { return attributeName(); } + + public static PropertyDescriptorField getConstant(String name) { + for (PropertyDescriptorField f : values()) { + if (Objects.equals(f.attributeName, name)) { + return f; + } + } + return null; + } + } 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 old mode 100755 new mode 100644 index afc0dea3f6..33717da7a0 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyDescriptorUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertyDescriptorUtil.java @@ -8,51 +8,53 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; -/** - * Utility class allowing to find the factory of a specific type of descriptor. That's used to define descriptors in - * the xml, eg for xpath rules. - * - * @author Brian Remedios - */ -public final class PropertyDescriptorUtil { +import net.sourceforge.pmd.properties.builders.PropertyDescriptorExternalBuilder; - private static final Map> DESCRIPTOR_FACTORIES_BY_TYPE; + +/** + * @author Clément Fournier + * @since 6.0.0 + */ +public class PropertyDescriptorUtil { + + private static final Map> DESCRIPTOR_FACTORIES_BY_TYPE; static { - Map> temp = new HashMap<>(18); - temp.put("Boolean", BooleanProperty.FACTORY); - temp.put("List", BooleanMultiProperty.FACTORY); + Map> temp = new HashMap<>(18); + temp.put("Boolean", BooleanProperty.extractor()); + temp.put("List", BooleanMultiProperty.extractor()); - temp.put("String", StringProperty.FACTORY); - temp.put("List", StringMultiProperty.FACTORY); - temp.put("Character", CharacterProperty.FACTORY); - temp.put("List", CharacterMultiProperty.FACTORY); + temp.put("String", StringProperty.extractor()); + temp.put("List", StringMultiProperty.extractor()); + temp.put("Character", CharacterProperty.extractor()); + temp.put("List", CharacterMultiProperty.extractor()); - temp.put("Integer", IntegerProperty.FACTORY); - temp.put("List", IntegerMultiProperty.FACTORY); - temp.put("Long", LongProperty.FACTORY); - temp.put("List", LongMultiProperty.FACTORY); - temp.put("Float", FloatProperty.FACTORY); - temp.put("List", FloatMultiProperty.FACTORY); - temp.put("Double", DoubleProperty.FACTORY); - temp.put("List", DoubleMultiProperty.FACTORY); + temp.put("Integer", IntegerProperty.extractor()); + temp.put("List", IntegerMultiProperty.extractor()); + temp.put("Long", LongProperty.extractor()); + temp.put("List", LongMultiProperty.extractor()); + temp.put("Float", FloatProperty.extractor()); + temp.put("List", FloatMultiProperty.extractor()); + temp.put("Double", DoubleProperty.extractor()); + temp.put("List", DoubleMultiProperty.extractor()); // temp.put("Enum", EnumeratedProperty.FACTORY); // TODO:cf implement that // temp.put("List", EnumeratedMultiProperty.FACTORY); - temp.put("Class", TypeProperty.FACTORY); - temp.put("List", TypeMultiProperty.FACTORY); - temp.put("Method", MethodProperty.FACTORY); - temp.put("List", MethodMultiProperty.FACTORY); + temp.put("Class", TypeProperty.extractor()); + temp.put("List", TypeMultiProperty.extractor()); + temp.put("Method", MethodProperty.extractor()); + temp.put("List", MethodMultiProperty.extractor()); - temp.put("File", FileProperty.FACTORY); + temp.put("File", FileProperty.extractor()); DESCRIPTOR_FACTORIES_BY_TYPE = Collections.unmodifiableMap(temp); } - private PropertyDescriptorUtil() { } + private PropertyDescriptorUtil() { + } /** @@ -62,7 +64,7 @@ public final class PropertyDescriptorUtil { * * @return The factory used to build new instances of a descriptor */ - public static PropertyDescriptorFactory factoryFor(String typeId) { + public static PropertyDescriptorExternalBuilder factoryFor(String typeId) { return DESCRIPTOR_FACTORIES_BY_TYPE.get(typeId); } @@ -77,7 +79,7 @@ public final class PropertyDescriptorUtil { */ public static String typeIdFor(Class valueType, boolean multiValue) { - for (Map.Entry> entry : DESCRIPTOR_FACTORIES_BY_TYPE.entrySet()) { + for (Map.Entry> entry : DESCRIPTOR_FACTORIES_BY_TYPE.entrySet()) { if (entry.getValue().valueType() == valueType && entry.getValue().isMultiValue() == multiValue) { return entry.getKey(); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertySource.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertySource.java index 2f7af354d0..e235e0d74c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertySource.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/PropertySource.java @@ -8,9 +8,9 @@ import java.util.List; import java.util.Map; import java.util.Set; + /** - * Any entity that manages a list of properties is a {@link PropertySource}. - * These are e.g. Rules and Renderers. + * Any entity that manages a list of properties is a {@link PropertySource}. These are e.g. Rules and Renderers. * * @author Brian Remedios */ @@ -37,8 +37,7 @@ public interface PropertySource { /** - * Get the PropertyDescriptors for all defined properties. The properties - * are returned sorted by UI order. + * Get the PropertyDescriptors for all defined properties. The properties are returned sorted by UI order. * * @return The PropertyDescriptors in UI order. */ @@ -77,8 +76,7 @@ public interface PropertySource { /** - * Returns all the current property values for the receiver or an immutable - * empty map if none are specified. + * Returns all the current property values for the receiver or an immutable empty map if none are specified. * * @return all current property values or a empty map. */ @@ -104,8 +102,7 @@ public interface PropertySource { /** - * Clears out any user-specified value for the property allowing it to use - * the default value in the descriptor. + * Clears out any user-specified value for the property allowing it to use the default value in the descriptor. * * @param desc the property to clear out */ @@ -113,9 +110,8 @@ public interface PropertySource { /** - * Return the properties that are effectively ignored due to the - * configuration of the rule and values held by other properties. This can - * be used to disable corresponding widgets in a UI. + * Return the properties that are effectively ignored due to the configuration of the rule and values held by other + * properties. This can be used to disable corresponding widgets in a UI. * * @return the properties that are ignored */ @@ -123,9 +119,8 @@ public interface PropertySource { /** - * Returns a description of why the receiver may be dysfunctional. Usually - * due to missing property values or some kind of conflict between values. - * Returns null if the receiver is ok. + * Returns a description of why the receiver may be dysfunctional. Usually due to missing property values or some + * kind of conflict between values. Returns null if the receiver is ok. * * @return String */ diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/SingleValuePropertyDescriptorFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/SingleValuePropertyDescriptorFactory.java deleted file mode 100644 index 78967158ef..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/SingleValuePropertyDescriptorFactory.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.properties; - -import java.util.Map; - -/** - * Concrete implementation of a property descriptor factory for single valued properties. - * - * @param Type of the property - * - * @author Clément Fournier - * @since 6.0.0 - */ -public abstract class SingleValuePropertyDescriptorFactory extends AbstractPropertyDescriptorFactory { - - /* default */ SingleValuePropertyDescriptorFactory(Class theValueType) { - super(theValueType); - } - - - /* default */ SingleValuePropertyDescriptorFactory(Class theValueType, - Map additionalFieldTypesByKey) { - super(theValueType, additionalFieldTypesByKey); - } - - - @Override - public abstract SingleValuePropertyDescriptor createWith(Map valuesById, - boolean isDefinedExternally); - - - @Override - public final boolean isMultiValue() { - return false; - } -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/StringMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/StringMultiProperty.java index 4e6f945708..538c0abc20 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/StringMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/StringMultiProperty.java @@ -4,44 +4,24 @@ package net.sourceforge.pmd.properties; -import static net.sourceforge.pmd.properties.ValueParserConstants.STRING_PARSER; - import java.util.Arrays; import java.util.List; -import java.util.Map; import org.apache.commons.lang3.StringUtils; +import net.sourceforge.pmd.properties.builders.MultiValuePropertyBuilder; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper; + + /** - * Defines a datatype that supports multiple String values. Note that all - * strings must be filtered by the delimiter character. + * Defines a datatype that supports multiple String values. Note that all strings must be filtered by the delimiter + * character. * * @author Brian Remedios * @version Refactored June 2017 (6.0.0) */ public final class StringMultiProperty extends AbstractMultiValueProperty { - /** Factory. */ - public static final PropertyDescriptorFactory> FACTORY // @formatter:off - = new MultiValuePropertyDescriptorFactory(String.class) { - - @Override - protected boolean isValueMissing(String value) { - return StringUtils.isEmpty(value); - } - - @Override - public StringMultiProperty createWith(Map valuesById, boolean isDefinedExternally) { - char delimiter = delimiterIn(valuesById); - return new StringMultiProperty(nameIn(valuesById), - descriptionIn(valuesById), - ValueParserConstants.parsePrimitives(defaultValueIn(valuesById), delimiter, STRING_PARSER), - 0.0f, - delimiter, - isDefinedExternally); - } - }; // @formatter:on - /** * Constructor using an array of defaults. @@ -88,28 +68,6 @@ public final class StringMultiProperty extends AbstractMultiValueProperty defaultValue, char delim) { - - if (defaultValue == null) { - return; - } - - for (String aDefaultValue : defaultValue) { - if (aDefaultValue.indexOf(delim) >= 0) { - throw new IllegalArgumentException("Cannot include the delimiter in the set of defaults"); - } - } - } - - @Override public Class type() { return String.class; @@ -155,4 +113,54 @@ public final class StringMultiProperty extends AbstractMultiValueProperty defaultValue, char delim) { + + if (defaultValue == null) { + return; + } + + for (String aDefaultValue : defaultValue) { + if (aDefaultValue.indexOf(delim) >= 0) { + throw new IllegalArgumentException("Cannot include the delimiter in the set of defaults"); + } + } + } + + + static PropertyDescriptorBuilderConversionWrapper.MultiValue extractor() { + return new PropertyDescriptorBuilderConversionWrapper.MultiValue(String.class, ValueParserConstants.STRING_PARSER) { + @Override + protected StringMultiPBuilder newBuilder(String name) { + return new StringMultiPBuilder(name); + } + }; + } + + + public static StringMultiPBuilder named(String name) { + return new StringMultiPBuilder(name); + } + + + public static final class StringMultiPBuilder extends MultiValuePropertyBuilder { + private StringMultiPBuilder(String name) { + super(name); + } + + + @Override + public StringMultiProperty build() { + return new StringMultiProperty(this.name, this.description, this.defaultValues, this.uiOrder, this.multiValueDelimiter, isDefinedInXML); + } + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/StringProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/StringProperty.java index 6b751fdfcc..0fe2652845 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/StringProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/StringProperty.java @@ -4,9 +4,9 @@ package net.sourceforge.pmd.properties; -import java.util.Map; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper; +import net.sourceforge.pmd.properties.builders.SingleValuePropertyBuilder; -import org.apache.commons.lang3.StringUtils; /** * Defines a datatype that supports single String values. @@ -16,26 +16,6 @@ import org.apache.commons.lang3.StringUtils; */ public final class StringProperty extends AbstractSingleValueProperty { - /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new SingleValuePropertyDescriptorFactory(String.class) { - - @Override - protected boolean isValueMissing(String value) { - return StringUtils.isEmpty(value); - } - - @Override - public StringProperty createWith(Map valuesById, boolean isDefinedExternally) { - return new StringProperty(nameIn(valuesById), - descriptionIn(valuesById), - defaultValueIn(valuesById), - 0f, - isDefinedExternally); - } - }; // @formatter:on - - /** * Constructor. * @@ -66,4 +46,32 @@ public final class StringProperty extends AbstractSingleValueProperty { public String createFrom(String valueString) { return valueString; } + + + static PropertyDescriptorBuilderConversionWrapper.SingleValue extractor() { + return new PropertyDescriptorBuilderConversionWrapper.SingleValue(String.class, ValueParserConstants.STRING_PARSER) { + @Override + protected StringPBuilder newBuilder(String name) { + return new StringPBuilder(name); + } + }; + } + + + public static StringPBuilder named(String name) { + return new StringPBuilder(name); + } + + + public static final class StringPBuilder extends SingleValuePropertyBuilder { + private StringPBuilder(String name) { + super(name); + } + + + @Override + public StringProperty build() { + return new StringProperty(this.name, this.description, this.defaultValue, this.uiOrder, isDefinedInXML); + } + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/TypeMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/TypeMultiProperty.java index aa832efff9..5e53397e4a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/TypeMultiProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/TypeMultiProperty.java @@ -5,13 +5,14 @@ package net.sourceforge.pmd.properties; import java.util.List; -import java.util.Map; +import net.sourceforge.pmd.properties.builders.MultiPackagedPropertyBuilder; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper; import net.sourceforge.pmd.properties.modules.TypePropertyModule; + /** - * Defines a property that supports multiple class types, even for primitive - * values! + * Defines a property that supports multiple class types, even for primitive values! * * TODO - untested for array types * @@ -19,20 +20,6 @@ import net.sourceforge.pmd.properties.modules.TypePropertyModule; */ public final class TypeMultiProperty extends AbstractMultiPackagedProperty { - /** Factory. */ - public static final PropertyDescriptorFactory> FACTORY // @formatter:off - = new MultiValuePropertyDescriptorFactory(Class.class, PACKAGED_FIELD_TYPES_BY_KEY) { - @Override - public TypeMultiProperty createWith(Map valuesById, boolean isDefinedExternally) { - char delimiter = delimiterIn(valuesById); - return new TypeMultiProperty(nameIn(valuesById), - descriptionIn(valuesById), - defaultValueIn(valuesById), - legalPackageNamesIn(valuesById, delimiter), - 0f); - } - }; // @formatter:on - /** * Constructor for TypeProperty. @@ -56,7 +43,7 @@ public final class TypeMultiProperty extends AbstractMultiPackagedProperty theTypeDefaults, String[] legalPackageNames, float theUIOrder, boolean isDefinedExternally) { super(theName, theDescription, theTypeDefaults, theUIOrder, isDefinedExternally, - new TypePropertyModule(legalPackageNames, theTypeDefaults)); + new TypePropertyModule(legalPackageNames, theTypeDefaults)); } @@ -74,17 +61,12 @@ public final class TypeMultiProperty extends AbstractMultiPackagedProperty typesFrom(String valueString) { - return ValueParserConstants.parsePrimitives(valueString, MULTI_VALUE_DELIMITER, ValueParserConstants.CLASS_PARSER); - } - - @Override public Class type() { return Class.class; @@ -107,4 +89,38 @@ public final class TypeMultiProperty extends AbstractMultiPackagedProperty valueFrom(String valueString) { return typesFrom(valueString); } + + + private static List typesFrom(String valueString) { + return ValueParserConstants.parsePrimitives(valueString, MULTI_VALUE_DELIMITER, ValueParserConstants.CLASS_PARSER); + } + + + public static PropertyDescriptorBuilderConversionWrapper.MultiValue.Packaged extractor() { + return new PropertyDescriptorBuilderConversionWrapper.MultiValue.Packaged(Class.class, ValueParserConstants.CLASS_PARSER) { + @Override + protected TypeMultiPBuilder newBuilder(String name) { + return new TypeMultiPBuilder(name); + } + }; + } + + + public static TypeMultiPBuilder named(String name) { + return new TypeMultiPBuilder(name); + } + + + public static final class TypeMultiPBuilder extends MultiPackagedPropertyBuilder { + + private TypeMultiPBuilder(String name) { + super(name); + } + + + @Override + public TypeMultiProperty build() { + return new TypeMultiProperty(name, description, defaultValues, legalPackageNames, uiOrder, isDefinedInXML); + } + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/TypeProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/TypeProperty.java index fc5d577297..a7d2ef2898 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/TypeProperty.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/TypeProperty.java @@ -5,13 +5,14 @@ package net.sourceforge.pmd.properties; import java.util.Collections; -import java.util.Map; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper; +import net.sourceforge.pmd.properties.builders.SinglePackagedPropertyBuilder; import net.sourceforge.pmd.properties.modules.TypePropertyModule; + /** - * Defines a property that supports single class types, even for primitive - * values! + * Defines a property that supports single class types, even for primitive values! * * TODO - untested for array types * @@ -19,22 +20,6 @@ import net.sourceforge.pmd.properties.modules.TypePropertyModule; */ public final class TypeProperty extends AbstractPackagedProperty { - /** Factory. */ - public static final PropertyDescriptorFactory FACTORY // @formatter:off - = new SingleValuePropertyDescriptorFactory(Class.class, PACKAGED_FIELD_TYPES_BY_KEY) { - @Override - public TypeProperty createWith(Map valuesById, boolean isDefinedExternally) { - char delimiter = delimiterIn(valuesById); - return new TypeProperty(nameIn(valuesById), - descriptionIn(valuesById), - ValueParserConstants.CLASS_PARSER.valueOf(defaultValueIn(valuesById)), - legalPackageNamesIn(valuesById, delimiter), - 0f, - isDefinedExternally); - } - }; // @formatter:on - - /** * Constructor for TypeProperty using a string as default value. * @@ -57,7 +42,7 @@ public final class TypeProperty extends AbstractPackagedProperty { private TypeProperty(String theName, String theDescription, Class theDefault, String[] legalPackageNames, float theUIOrder, boolean isDefinedExternally) { super(theName, theDescription, theDefault, theUIOrder, isDefinedExternally, - new TypePropertyModule(legalPackageNames, Collections.singletonList(theDefault))); + new TypePropertyModule(legalPackageNames, Collections.singletonList(theDefault))); } @@ -92,4 +77,33 @@ public final class TypeProperty extends AbstractPackagedProperty { public Class createFrom(String valueString) { return ValueParserConstants.CLASS_PARSER.valueOf(valueString); } + + + static PropertyDescriptorBuilderConversionWrapper.SingleValue.Packaged extractor() { + return new PropertyDescriptorBuilderConversionWrapper.SingleValue.Packaged(Class.class, ValueParserConstants.CLASS_PARSER) { + @Override + protected TypePBuilder newBuilder(String name) { + return new TypePBuilder(name); + } + }; + } + + + public static TypePBuilder named(String name) { + return new TypePBuilder(name); + } + + + public static final class TypePBuilder extends SinglePackagedPropertyBuilder { + private TypePBuilder(String name) { + super(name); + } + + + @Override + public TypeProperty build() { + return new TypeProperty(name, description, defaultValue, legalPackageNames, uiOrder, isDefinedInXML); + } + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/ValueParser.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/ValueParser.java index 4224006c6c..4ce4acdcad 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/ValueParser.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/ValueParser.java @@ -18,7 +18,6 @@ public interface ValueParser { * @param value The string to parse * * @return The primitive found - * * @throws IllegalArgumentException if the value couldn't be parsed */ U valueOf(String value) throws IllegalArgumentException; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/ValueParserConstants.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/ValueParserConstants.java index c7a426c212..59ad3a1f3d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/ValueParserConstants.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/ValueParserConstants.java @@ -9,6 +9,7 @@ import static net.sourceforge.pmd.properties.modules.MethodPropertyModule.CLASS_ import static net.sourceforge.pmd.properties.modules.MethodPropertyModule.METHOD_ARG_DELIMITER; import static net.sourceforge.pmd.properties.modules.MethodPropertyModule.METHOD_GROUP_DELIMITERS; +import java.io.File; import java.lang.reflect.Array; import java.lang.reflect.Method; import java.util.ArrayList; @@ -18,105 +19,16 @@ import org.apache.commons.lang3.StringUtils; import net.sourceforge.pmd.util.ClassUtil; + /** * @author Clément Fournier * @since 6.0.0 */ -//TODO: make package-private when we move everything to n.s.pmd.properties public final class ValueParserConstants { - /** Extracts characters. */ - static final ValueParser CHARACTER_PARSER = new ValueParser() { - @Override - public Character valueOf(String value) { - if (value == null || value.length() != 1) { - throw new IllegalArgumentException("missing/ambiguous character value"); - } - return value.charAt(0); - } - }; - - - /** Extracts strings. That's a dummy used to return a list in StringMultiProperty. */ - static final ValueParser STRING_PARSER = new ValueParser() { - @Override - public String valueOf(String value) { - return value; - } - }; - - - /** Extracts integers. */ - static final ValueParser INTEGER_PARSER = new ValueParser() { - @Override - public Integer valueOf(String value) { - return Integer.valueOf(value); - } - }; - - - /** Extracts booleans. */ - static final ValueParser BOOLEAN_PARSER = new ValueParser() { - @Override - public Boolean valueOf(String value) { - return Boolean.valueOf(value); - } - }; - - - /** Extracts floats. */ - static final ValueParser FLOAT_PARSER = new ValueParser() { - @Override - public Float valueOf(String value) { - return Float.valueOf(value); - } - }; - - - /** Extracts longs. */ - static final ValueParser LONG_PARSER = new ValueParser() { - @Override - public Long valueOf(String value) { - return Long.valueOf(value); - } - }; - - - /** Extracts doubles. */ - static final ValueParser DOUBLE_PARSER = new ValueParser() { - @Override - public Double valueOf(String value) { - return Double.valueOf(value); - } - }; - - - /** Extract classes. */ - static final ValueParser CLASS_PARSER = new ValueParser() { - @Override - public Class valueOf(String value) throws IllegalArgumentException { - if (StringUtils.isBlank(value)) { - return null; - } - - Class cls = ClassUtil.getTypeFor(value); - if (cls != null) { - return cls; - } - - try { - return Class.forName(value); - } catch (ClassNotFoundException ex) { - throw new IllegalArgumentException(value); - } - } - }; - - /** Extracts methods. */ - // TODO: make package-private when we move everything to n.s.pmd.properties - public static final ValueParser METHOD_PARSER = new ValueParser() { + static final ValueParser METHOD_PARSER = new ValueParser() { @Override public Method valueOf(String value) throws IllegalArgumentException { return methodFrom(value, CLASS_METHOD_DELIMITER, METHOD_ARG_DELIMITER); @@ -223,6 +135,86 @@ public final class ValueParserConstants { } }; + /** Extracts characters. */ + static final ValueParser CHARACTER_PARSER = new ValueParser() { + @Override + public Character valueOf(String value) { + if (value == null || value.length() != 1) { + throw new IllegalArgumentException("missing/ambiguous character value"); + } + return value.charAt(0); + } + }; + /** Extracts strings. That's a dummy used to return a list in StringMultiProperty. */ + static final ValueParser STRING_PARSER = new ValueParser() { + @Override + public String valueOf(String value) { + return value; + } + }; + /** Extracts integers. */ + static final ValueParser INTEGER_PARSER = new ValueParser() { + @Override + public Integer valueOf(String value) { + return Integer.valueOf(value); + } + }; + /** Extracts booleans. */ + static final ValueParser BOOLEAN_PARSER = new ValueParser() { + @Override + public Boolean valueOf(String value) { + return Boolean.valueOf(value); + } + }; + /** Extracts floats. */ + static final ValueParser FLOAT_PARSER = new ValueParser() { + @Override + public Float valueOf(String value) { + return Float.valueOf(value); + } + }; + /** Extracts longs. */ + static final ValueParser LONG_PARSER = new ValueParser() { + @Override + public Long valueOf(String value) { + return Long.valueOf(value); + } + }; + /** Extracts doubles. */ + static final ValueParser DOUBLE_PARSER = new ValueParser() { + @Override + public Double valueOf(String value) { + return Double.valueOf(value); + } + }; + /** Extracts files */ + static final ValueParser FILE_PARSER = new ValueParser() { + @Override + public File valueOf(String value) throws IllegalArgumentException { + return new File(value); + } + }; + + /** Extract classes. */ + static final ValueParser CLASS_PARSER = new ValueParser() { + @Override + public Class valueOf(String value) throws IllegalArgumentException { + if (StringUtils.isBlank(value)) { + return null; + } + + Class cls = ClassUtil.getTypeFor(value); + if (cls != null) { + return cls; + } + + try { + return Class.forName(value); + } catch (ClassNotFoundException ex) { + throw new IllegalArgumentException(value); + } + } + }; private ValueParserConstants() { @@ -230,6 +222,25 @@ public final class ValueParserConstants { } + /** + * Returns a value parser parsing lists of values of type U. + * + * @param parser Parser used to parse a single value + * @param delimiter Char delimiting values + * @param Element type of the target list + * + * @return A list of values + */ + public static ValueParser> multi(final ValueParser parser, final char delimiter) { + return new ValueParser>() { + @Override + public List valueOf(String value) throws IllegalArgumentException { + return parsePrimitives(value, delimiter, parser); + } + }; + } + + /** * Parses a string into a list of values of type {@literal }. * @@ -242,7 +253,7 @@ public final class ValueParserConstants { */ // FUTURE 1.8 : use java.util.function.Function in place of ValueParser, // replace ValueParser constants with static functions - public static List parsePrimitives(String toParse, char delimiter, ValueParser extractor) { + static List parsePrimitives(String toParse, char delimiter, ValueParser extractor) { String[] values = StringUtils.split(toParse, delimiter); List result = new ArrayList<>(); for (String s : values) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/MultiNumericPropertyBuilder.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/MultiNumericPropertyBuilder.java new file mode 100644 index 0000000000..9a8585f640 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/MultiNumericPropertyBuilder.java @@ -0,0 +1,45 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.properties.builders; + +import net.sourceforge.pmd.properties.MultiValuePropertyDescriptor; + + +/** + * For multi-value numeric properties. + * + * @param Element type of the list + * @param Concrete type of the underlying builder + */ +public abstract class MultiNumericPropertyBuilder> + extends MultiValuePropertyBuilder { + + + protected V lowerLimit; + protected V upperLimit; + + + protected MultiNumericPropertyBuilder(String name) { + super(name); + multiValueDelimiter = MultiValuePropertyDescriptor.DEFAULT_NUMERIC_DELIMITER; + } + + + /** + * Specify the range of acceptable values. + * + * @param min Lower bound + * @param max Upper bound + * + * @return The same builder + */ + @SuppressWarnings("unchecked") + public T range(V min, V max) { + this.lowerLimit = min; + this.upperLimit = max; + return (T) this; + } + +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/MultiPackagedPropertyBuilder.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/MultiPackagedPropertyBuilder.java new file mode 100644 index 0000000000..aad9f61895 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/MultiPackagedPropertyBuilder.java @@ -0,0 +1,33 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.properties.builders; + +import java.util.Arrays; + + +/** + * @author Clément Fournier + * @since 6.0.0 + */ +public abstract class MultiPackagedPropertyBuilder> + extends MultiValuePropertyBuilder { + + protected String[] legalPackageNames; + + + protected MultiPackagedPropertyBuilder(String name) { + super(name); + } + + + @SuppressWarnings("unchecked") + public T legalPackages(String[] packs) { + if (packs != null) { + this.legalPackageNames = Arrays.copyOf(packs, packs.length); + } + return (T) this; + } + +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/MultiValuePropertyBuilder.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/MultiValuePropertyBuilder.java new file mode 100644 index 0000000000..e3be94eac2 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/MultiValuePropertyBuilder.java @@ -0,0 +1,72 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.properties.builders; + +import java.util.Arrays; +import java.util.List; + +import net.sourceforge.pmd.properties.MultiValuePropertyDescriptor; + + +/** + * For multi-value properties. + * + * @param Element type of the list + * @param Concrete type of the underlying builder + */ +public abstract class MultiValuePropertyBuilder> + extends PropertyDescriptorBuilder, T> { + + protected List defaultValues; + protected char multiValueDelimiter = MultiValuePropertyDescriptor.DEFAULT_DELIMITER; + + + protected MultiValuePropertyBuilder(String name) { + super(name); + } + + + /** + * Specify a default value. + * + * @param val List of values + * + * @return The same builder + */ + @SuppressWarnings("unchecked") + public T defaultValues(List val) { + this.defaultValues = val; + return (T) this; + } + + + /** + * Specify default values. + * + * @param val List of values + * + * @return The same builder + */ + @SuppressWarnings("unchecked") + public T defaultValues(V... val) { + this.defaultValues = Arrays.asList(val); + return (T) this; + } + + + /** + * Specify a delimiter character. By default it's {@link MultiValuePropertyDescriptor#DEFAULT_DELIMITER}, or {@link + * MultiValuePropertyDescriptor#DEFAULT_NUMERIC_DELIMITER} for numeric properties. + * + * @param delim Delimiter + * + * @return The same builder + */ + @SuppressWarnings("unchecked") + public T delim(char delim) { + this.multiValueDelimiter = delim; + return (T) this; + } +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/PropertyDescriptorBuilder.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/PropertyDescriptorBuilder.java new file mode 100644 index 0000000000..dc0cb5b4a4 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/PropertyDescriptorBuilder.java @@ -0,0 +1,78 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.properties.builders; + +import org.apache.commons.lang3.StringUtils; + +import net.sourceforge.pmd.properties.PropertyDescriptor; + + +/** + * Base class for property builders. + * + * @param Value type of the built descriptor + * @param Concrete type of this builder instance. Removes code duplication at the expense of a few unchecked casts. + * Everything goes well if this parameter's value is correctly set. + * + * @author Clément Fournier + * @since 6.0.0 + */ +public abstract class PropertyDescriptorBuilder> { + + protected String name; + protected String description; + protected float uiOrder = 0f; + protected boolean isDefinedInXML = false; + + + protected PropertyDescriptorBuilder(String name) { + if (StringUtils.isBlank(name)) { + throw new IllegalArgumentException("Name must be provided"); + } + this.name = name; + } + + + /** + * Specify the description of the property. + * + * @param desc The description + * + * @return The same builder + */ + @SuppressWarnings("unchecked") + public T desc(String desc) { + if (StringUtils.isBlank(desc)) { + throw new IllegalArgumentException("Description must be provided"); + } + this.description = desc; + return (T) this; + } + + + /** + * Specify the UI order of the property. + * + * @param f The UI order + * + * @return The same builder + */ + @SuppressWarnings("unchecked") + public T uiOrder(float f) { + this.uiOrder = f; + return (T) this; + } + + + /** + * Builds the descriptor and returns it. + * + * @return The built descriptor + * @throws IllegalArgumentException if parameters are incorrect + */ + public abstract PropertyDescriptor build(); + + +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/PropertyDescriptorBuilderConversionWrapper.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/PropertyDescriptorBuilderConversionWrapper.java new file mode 100644 index 0000000000..88eaf0b7c2 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/PropertyDescriptorBuilderConversionWrapper.java @@ -0,0 +1,257 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.properties.builders; + + +import static net.sourceforge.pmd.properties.PropertyDescriptorField.DELIMITER; +import static net.sourceforge.pmd.properties.PropertyDescriptorField.LEGAL_PACKAGES; + +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; + +import net.sourceforge.pmd.properties.MultiValuePropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyDescriptorField; +import net.sourceforge.pmd.properties.ValueParser; +import net.sourceforge.pmd.properties.ValueParserConstants; + + +/** + * Wraps a property builder and maps its inputs from strings to the target types of the descriptor. + * + * @param Value type of the descriptor + * @param Concrete type of the underlying builder + * + * @author Clément Fournier + * @since 6.0.0 + */ +public abstract class PropertyDescriptorBuilderConversionWrapper> + implements PropertyDescriptorExternalBuilder { + + private final Class valueType; + + + protected PropertyDescriptorBuilderConversionWrapper(Class valueType) { + this.valueType = valueType; + } + + + /** Populates the builder with extracted fields. To be overridden. */ + protected void populate(T builder, Map fields) { + builder.desc(fields.get(PropertyDescriptorField.DESCRIPTION)); + if (fields.containsKey(PropertyDescriptorField.UI_ORDER)) { + builder.uiOrder(Float.parseFloat(fields.get(PropertyDescriptorField.UI_ORDER))); + } + } + + + public abstract boolean isMultiValue(); + + + public Class valueType() { + return valueType; + } + + + protected abstract T newBuilder(String name); // FUTURE 1.8: use a Supplier constructor parameter + + + @Override + public PropertyDescriptor build(Map fields) { + T builder = newBuilder(fields.get(PropertyDescriptorField.NAME)); + populate(builder, fields); + builder.isDefinedInXML = true; + return builder.build(); + } + + + protected static String[] legalPackageNamesIn(Map valuesById, char delimiter) { + String names = valuesById.get(LEGAL_PACKAGES); + return StringUtils.isBlank(names) ? null : StringUtils.split(names, delimiter); + } + + + private static char delimiterIn(Map valuesById, char defalt) { + String characterStr = ""; + if (valuesById.containsKey(DELIMITER)) { + characterStr = valuesById.get(DELIMITER).trim(); + } + + if (StringUtils.isBlank(characterStr)) { + return defalt; + } + + if (characterStr.length() != 1) { + throw new RuntimeException("Ambiguous delimiter character, must have length 1: \"" + characterStr + "\""); + } + return characterStr.charAt(0); + } + + + /** + * For multi-value properties. + * + * @param Element type of the list + * @param Concrete type of the underlying builder + */ + public abstract static class MultiValue> + extends PropertyDescriptorBuilderConversionWrapper, T> { + + protected final ValueParser parser; + + + protected MultiValue(Class valueType, ValueParser parser) { + super(valueType); + this.parser = parser; + } + + + @Override + protected void populate(T builder, Map fields) { + super.populate(builder, fields); + char delim = delimiterIn(fields, builder.multiValueDelimiter); + builder.delim(delim).defaultValues(ValueParserConstants.multi(parser, delim) + .valueOf(fields.get(PropertyDescriptorField.DEFAULT_VALUE))); + } + + + @Override + public boolean isMultiValue() { + return true; + } + + + /** + * For multi-value numeric properties. + * + * @param Element type of the list + * @param Concrete type of the underlying builder + */ + public abstract static class Numeric> + extends MultiValue { + + protected Numeric(Class valueType, ValueParser parser) { + super(valueType, parser); + } + + + @Override + protected void populate(T builder, Map fields) { + super.populate(builder, fields); + V min = parser.valueOf(fields.get(PropertyDescriptorField.MIN)); + V max = parser.valueOf(fields.get(PropertyDescriptorField.MAX)); + builder.range(min, max); + } + } + + + /** + * For single-value packaged properties. + * + * @param Element type of the list + * @param Concrete type of the underlying builder + */ + public abstract static class Packaged> + extends MultiValue { + + protected Packaged(Class valueType, ValueParser parser) { + super(valueType, parser); + } + + + @Override + protected void populate(T builder, Map fields) { + super.populate(builder, fields); + builder.legalPackages(legalPackageNamesIn(fields, PropertyDescriptorBuilderConversionWrapper.delimiterIn(fields, + MultiValuePropertyDescriptor.DEFAULT_DELIMITER))); + } + } + + } + + + /** + * For single-value properties. + * + * @param Value type of the property + * @param Concrete type of the underlying builder + */ + public abstract static class SingleValue> + extends PropertyDescriptorBuilderConversionWrapper { + + protected final ValueParser parser; + + + protected SingleValue(Class valueType, ValueParser parser) { + super(valueType); + this.parser = parser; + } + + + @Override + protected void populate(T builder, Map fields) { + super.populate(builder, fields); + builder.defaultValue(parser.valueOf(fields.get(PropertyDescriptorField.DEFAULT_VALUE))); + } + + + @Override + public boolean isMultiValue() { + return false; + } + + + /** + * For single-value numeric properties. + * + * @param Element type of the list + * @param Concrete type of the underlying builder + */ + public abstract static class Numeric> + extends SingleValue { + + protected Numeric(Class valueType, ValueParser parser) { + super(valueType, parser); + } + + + @Override + protected void populate(T builder, Map fields) { + super.populate(builder, fields); + V min = parser.valueOf(fields.get(PropertyDescriptorField.MIN)); + V max = parser.valueOf(fields.get(PropertyDescriptorField.MAX)); + builder.range(min, max); + } + } + + + /** + * For single-value packaged properties. + * + * @param Element type of the list + * @param Concrete type of the underlying builder + */ + public abstract static class Packaged> + extends SingleValue { + + protected Packaged(Class valueType, ValueParser parser) { + super(valueType, parser); + } + + + @Override + protected void populate(T builder, Map fields) { + super.populate(builder, fields); + builder.legalPackageNames(legalPackageNamesIn(fields, PropertyDescriptorBuilderConversionWrapper.delimiterIn(fields, + MultiValuePropertyDescriptor.DEFAULT_DELIMITER))); + } + } + + + } + +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/PropertyDescriptorExternalBuilder.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/PropertyDescriptorExternalBuilder.java new file mode 100644 index 0000000000..16ded67141 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/PropertyDescriptorExternalBuilder.java @@ -0,0 +1,48 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.properties.builders; + +import java.util.Map; + +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyDescriptorField; + + +/** + * Builds properties from a map of key value pairs, eg extracted from an XML element. + * + * @param The type of values. + * + * @author Clément Fournier + * @since 6.0.0 + */ +public interface PropertyDescriptorExternalBuilder { + + + /** + * Whether this descriptor is multi-valued. + * + * @return True if this descriptor is multi-valued + */ + boolean isMultiValue(); + + + /** + * Type of the values of the descriptor, or component type if this descriptor is multi-valued. + * + * @return Type of the values + */ + Class valueType(); + + + /** + * Builds a descriptor. The descriptor returned is tagged as built externally. + * + * @param fields Key value pairs + * + * @return A builder + */ + PropertyDescriptor build(Map fields); +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/SingleNumericPropertyBuilder.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/SingleNumericPropertyBuilder.java new file mode 100644 index 0000000000..4e4d450aed --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/SingleNumericPropertyBuilder.java @@ -0,0 +1,39 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.properties.builders; + +/** + * @author Clément Fournier + * @since 6.0.0 + */ +public abstract class SingleNumericPropertyBuilder> + extends SingleValuePropertyBuilder { + + + protected V lowerLimit; + protected V upperLimit; + + + public SingleNumericPropertyBuilder(String name) { + super(name); + } + + + /** + * Specify the range of acceptable values. + * + * @param min Lower bound + * @param max Upper bound + * + * @return The same builder + */ + @SuppressWarnings("unchecked") + public T range(V min, V max) { + this.lowerLimit = min; + this.upperLimit = max; + return (T) this; + } + +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/SinglePackagedPropertyBuilder.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/SinglePackagedPropertyBuilder.java new file mode 100644 index 0000000000..3fb0b755bf --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/SinglePackagedPropertyBuilder.java @@ -0,0 +1,33 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.properties.builders; + +import java.util.Arrays; + + +/** + * @author Clément Fournier + * @since 6.0.0 + */ +public abstract class SinglePackagedPropertyBuilder> + extends SingleValuePropertyBuilder { + + protected String[] legalPackageNames; + + + public SinglePackagedPropertyBuilder(String name) { + super(name); + } + + + @SuppressWarnings("unchecked") + public T legalPackageNames(String[] packs) { + if (packs != null) { + this.legalPackageNames = Arrays.copyOf(packs, packs.length); + } + return (T) this; + } + +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/SingleValuePropertyBuilder.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/SingleValuePropertyBuilder.java new file mode 100644 index 0000000000..4c8edbf11b --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/builders/SingleValuePropertyBuilder.java @@ -0,0 +1,38 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.properties.builders; + +/** + * For single-value property descriptors. + * + * @param Value type of the built descriptor + * @param Concrete type of this builder instance. + */ +public abstract class SingleValuePropertyBuilder> + extends PropertyDescriptorBuilder { + + protected E defaultValue; + + + protected SingleValuePropertyBuilder(String name) { + super(name); + } + + + /** + * Specify a default value. + * + * @param val Value + * + * @return The same builder + */ + @SuppressWarnings("unchecked") + public T defaultValue(E val) { + this.defaultValue = val; + return (T) this; + } + + +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/modules/EnumeratedPropertyModule.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/modules/EnumeratedPropertyModule.java index f1c7d8afe3..ff78fa232b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/modules/EnumeratedPropertyModule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/modules/EnumeratedPropertyModule.java @@ -9,6 +9,7 @@ import java.util.Map; import net.sourceforge.pmd.util.CollectionUtil; + /** * Factorises common functionality for enumerated properties. * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/modules/MethodPropertyModule.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/modules/MethodPropertyModule.java index 2dbd0afe6f..c2b1019055 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/modules/MethodPropertyModule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/modules/MethodPropertyModule.java @@ -10,6 +10,7 @@ import java.util.Map; import net.sourceforge.pmd.util.ClassUtil; + /** * Factorises common functionality for method properties. * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/modules/NumericPropertyModule.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/modules/NumericPropertyModule.java index 46c5455738..b1602f83ef 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/modules/NumericPropertyModule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/modules/NumericPropertyModule.java @@ -11,6 +11,7 @@ import java.util.Map; import net.sourceforge.pmd.properties.PropertyDescriptorField; + /** * Common utilities for implementations of numeric property descriptors. * @@ -61,19 +62,6 @@ public class NumericPropertyModule { } - /** - * Returns a string representing the range defined by the two bounds. - * - * @param low Lower bound - * @param up Upper bound - * - * @return String - */ - private static String rangeString(Number low, Number up) { - return "(" + low + " -> " + up + ")"; - } - - public T getLowerLimit() { return lowerLimit; } @@ -90,4 +78,17 @@ public class NumericPropertyModule { } + /** + * Returns a string representing the range defined by the two bounds. + * + * @param low Lower bound + * @param up Upper bound + * + * @return String + */ + private static String rangeString(Number low, Number up) { + return "(" + low + " -> " + up + ")"; + } + + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/modules/PackagedPropertyModule.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/modules/PackagedPropertyModule.java index 06bf77db14..a9c29a0ea6 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/modules/PackagedPropertyModule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/modules/PackagedPropertyModule.java @@ -18,6 +18,7 @@ import org.apache.commons.lang3.StringUtils; import net.sourceforge.pmd.properties.PropertyDescriptorField; + /** * Factorises common functionality for packaged properties. * @@ -55,7 +56,7 @@ public abstract class PackagedPropertyModule { for (String name : legalNamePrefixes) { if (name == null) { throw new IllegalArgumentException("Null is not allowed in the legal package names:" - + Arrays.toString(legalNamePrefixes)); + + Arrays.toString(legalNamePrefixes)); } else if (!PACKAGE_NAME_PATTERN.matcher(name).matches()) { throw new IllegalArgumentException("One name is not a package: '" + name + "'"); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/properties/modules/TypePropertyModule.java b/pmd-core/src/main/java/net/sourceforge/pmd/properties/modules/TypePropertyModule.java index 0758b86c20..183357552e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/properties/modules/TypePropertyModule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/properties/modules/TypePropertyModule.java @@ -6,6 +6,7 @@ package net.sourceforge.pmd.properties.modules; import java.util.List; + /** * Factorises common functionality for type properties. * diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/AbstractRuleTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/AbstractRuleTest.java index 7fd8b2e4c2..999488418d 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/AbstractRuleTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/AbstractRuleTest.java @@ -96,7 +96,7 @@ public class AbstractRuleTest { @Test public void testRuleWithVariableInMessage() { MyRule r = new MyRule(); - r.definePropertyDescriptor(new IntegerProperty("testInt", "description", 0, 100, 10, 0)); + r.definePropertyDescriptor(IntegerProperty.named("testInt").desc("description").range(0, 100).defaultValue(10).uiOrder(0).build()); r.setMessage("Message ${packageName} ${className} ${methodName} ${variableName} ${testInt} ${noSuchProperty}"); RuleContext ctx = new RuleContext(); ctx.setLanguageVersion(LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getDefaultVersion()); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractNumericPropertyDescriptorTester.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractNumericPropertyDescriptorTester.java index aae68e3015..8cf7e90b43 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractNumericPropertyDescriptorTester.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractNumericPropertyDescriptorTester.java @@ -33,7 +33,7 @@ public abstract class AbstractNumericPropertyDescriptorTester extends Abstrac public void testMissingMinThreshold() { Map attributes = getPropertyDescriptorValues(); attributes.remove(PropertyDescriptorField.MIN); - getSingleFactory().createWith(attributes); + getSingleFactory().build(attributes); } @@ -50,7 +50,7 @@ public abstract class AbstractNumericPropertyDescriptorTester extends Abstrac public void testMissingMaxThreshold() { Map attributes = getPropertyDescriptorValues(); attributes.remove(PropertyDescriptorField.MAX); - getSingleFactory().createWith(attributes); + getSingleFactory().build(attributes); } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPackagedPropertyDescriptorTester.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPackagedPropertyDescriptorTester.java index cec27a06b7..7190685b38 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPackagedPropertyDescriptorTester.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/AbstractPackagedPropertyDescriptorTester.java @@ -22,8 +22,8 @@ public abstract class AbstractPackagedPropertyDescriptorTester extends Abstra public void testMissingPackageNames() { Map attributes = getPropertyDescriptorValues(); attributes.remove(PropertyDescriptorField.LEGAL_PACKAGES); - getMultiFactory().createWith(attributes); // no exception, null is ok - getSingleFactory().createWith(attributes); + getMultiFactory().build(attributes); // no exception, null is ok + getSingleFactory().build(attributes); } 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 dceaf101f3..c5e9cd7e8a 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 @@ -18,10 +18,12 @@ import java.util.Map; import org.junit.Test; +import net.sourceforge.pmd.properties.builders.PropertyDescriptorExternalBuilder; + + /** - * Base functionality for all concrete subclasses that evaluate type-specific - * property descriptors. Checks for error conditions during construction, error - * value detection, serialization, etc. + * Base functionality for all concrete subclasses that evaluate type-specific property descriptors. Checks for error + * conditions during construction, error value detection, serialization, etc. * * @author Brian Remedios */ @@ -47,20 +49,19 @@ public abstract class AbstractPropertyDescriptorTester { @Test public void testFactorySingleValue() { - PropertyDescriptor prop = getSingleFactory().createWith(getPropertyDescriptorValues()); + PropertyDescriptor prop = getSingleFactory().build(getPropertyDescriptorValues()); T originalValue = createValue(); T value = prop.valueFrom( - originalValue instanceof Class ? ((Class) originalValue).getName() : String.valueOf(originalValue)); + originalValue instanceof Class ? ((Class) originalValue).getName() : String.valueOf(originalValue)); String asDelimitedString = prop.asDelimitedString(value); Object value2 = prop.valueFrom(asDelimitedString); assertEquals(value, value2); } - @SuppressWarnings("unchecked") - protected final PropertyDescriptorFactory getSingleFactory() { - return (PropertyDescriptorFactory) PropertyDescriptorUtil.factoryFor(typeName); + protected final PropertyDescriptorExternalBuilder getSingleFactory() { + return (PropertyDescriptorExternalBuilder) PropertyDescriptorUtil.factoryFor(typeName); } @@ -83,8 +84,8 @@ public abstract class AbstractPropertyDescriptorTester { @Test public void testFactoryMultiValueDefaultDelimiter() { - PropertyDescriptorFactory> multiFactory = getMultiFactory(); - PropertyDescriptor> prop = multiFactory.createWith(getPropertyDescriptorValues()); + PropertyDescriptorExternalBuilder> multiFactory = getMultiFactory(); + PropertyDescriptor> prop = multiFactory.build(getPropertyDescriptorValues()); List originalValue = createMultipleValues(MULTI_VALUE_COUNT); String asDelimitedString = prop.asDelimitedString(originalValue); List value2 = prop.valueFrom(asDelimitedString); @@ -93,8 +94,8 @@ public abstract class AbstractPropertyDescriptorTester { @SuppressWarnings("unchecked") - protected final PropertyDescriptorFactory> getMultiFactory() { - return (PropertyDescriptorFactory>) PropertyDescriptorUtil.factoryFor("List<" + typeName + ">"); + protected final PropertyDescriptorExternalBuilder> getMultiFactory() { + return (PropertyDescriptorExternalBuilder>) PropertyDescriptorUtil.factoryFor("List<" + typeName + ">"); } @@ -110,12 +111,12 @@ public abstract class AbstractPropertyDescriptorTester { @Test public void testFactoryMultiValueCustomDelimiter() { - PropertyDescriptorFactory> multiFactory = getMultiFactory(); + PropertyDescriptorExternalBuilder> multiFactory = getMultiFactory(); Map valuesById = getPropertyDescriptorValues(); String customDelimiter = "ä"; assertFalse(ALL_CHARS.contains(customDelimiter)); valuesById.put(PropertyDescriptorField.DELIMITER, customDelimiter); - PropertyDescriptor> prop = multiFactory.createWith(valuesById); + PropertyDescriptor> prop = multiFactory.build(valuesById); List originalValue = createMultipleValues(MULTI_VALUE_COUNT); String asDelimitedString = prop.asDelimitedString(originalValue); List value2 = prop.valueFrom(asDelimitedString); @@ -149,8 +150,8 @@ public abstract class AbstractPropertyDescriptorTester { /** - * Attempt to create a property with faulty configuration values. This - * method should throw an IllegalArgumentException if done correctly. + * Attempt to create a property with faulty configuration values. This method should throw an + * IllegalArgumentException if done correctly. * * @return PropertyDescriptor */ @@ -219,8 +220,7 @@ public abstract class AbstractPropertyDescriptorTester { /** - * Return a value(s) that is known to be faulty per the general scope of the - * descriptor. + * Return a value(s) that is known to be faulty per the general scope of the descriptor. * * @return Object */ @@ -346,7 +346,6 @@ public abstract class AbstractPropertyDescriptorTester { * Method randomChoice. * * @param items Object[] - * * @return Object */ public static T randomChoice(T[] items) { @@ -359,7 +358,6 @@ public abstract class AbstractPropertyDescriptorTester { * * @param chars char[] * @param removeChar char - * * @return char[] */ protected static final char[] filter(char[] chars, char removeChar) { diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/NonRuleWithAllPropertyTypes.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/NonRuleWithAllPropertyTypes.java index 9c4b4205c4..cc93b240e3 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/NonRuleWithAllPropertyTypes.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/NonRuleWithAllPropertyTypes.java @@ -34,8 +34,7 @@ public class NonRuleWithAllPropertyTypes extends AbstractRule { public static final StringProperty SINGLE_STR = new StringProperty("singleStr", "String value", "hello world", 3.0f); public static final StringMultiProperty MULTI_STR = new StringMultiProperty("multiStr", "Multiple string values", new String[] {"hello", "world"}, 5.0f, '|'); - public static final IntegerProperty SINGLE_INT = new IntegerProperty("singleInt", "Single integer value", 1, 10, 8, - 3.0f); + public static final IntegerProperty SINGLE_INT = IntegerProperty.named("singleInt").desc("Single integer value").range(1, 10).defaultValue(8).uiOrder(3.0f).build(); public static final IntegerMultiProperty MULTI_INT = new IntegerMultiProperty("multiInt", "Multiple integer values", 0, 10, new Integer[] {1, 2, 3, 4}, 5.0f); public static final LongProperty SINGLE_LONG = new LongProperty("singleLong", "Single long value", 1L, 10L, 8L, diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/rule/CyclomaticComplexityRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/rule/CyclomaticComplexityRule.java index 9cc50b70a4..48c272929c 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/rule/CyclomaticComplexityRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/rule/CyclomaticComplexityRule.java @@ -29,11 +29,15 @@ import net.sourceforge.pmd.properties.IntegerProperty; */ public class CyclomaticComplexityRule extends AbstractJavaMetricsRule { - private static final IntegerProperty CLASS_LEVEL_DESCRIPTOR = new IntegerProperty( - "classReportLevel", "Total class complexity reporting threshold", 1, 600, 80, 1.0f); + private static final IntegerProperty CLASS_LEVEL_DESCRIPTOR + = IntegerProperty.named("classReportLevel") + .desc("Total class complexity reporting threshold") + .range(1, 600).defaultValue(80).uiOrder(1.0f).build(); - private static final IntegerProperty METHOD_LEVEL_DESCRIPTOR = new IntegerProperty( - "methodReportLevel", "Cyclomatic complexity reporting threshold", 1, 50, 10, 1.0f); + private static final IntegerProperty METHOD_LEVEL_DESCRIPTOR + = IntegerProperty.named("methodReportLevel") + .desc("Cyclomatic complexity reporting threshold") + .range(1, 50).defaultValue(10).uiOrder(1.0f).build(); private static final Map OPTION_MAP; @@ -45,9 +49,12 @@ public class CyclomaticComplexityRule extends AbstractJavaMetricsRule { } - private static final EnumeratedMultiProperty CYCLO_OPTIONS_DESCRIPTOR = new EnumeratedMultiProperty<>( - "cycloOptions", "Choose options for the computation of Cyclo", - OPTION_MAP, Collections.emptyList(), CycloOption.class, 3.0f); + private static final EnumeratedMultiProperty CYCLO_OPTIONS_DESCRIPTOR + = EnumeratedMultiProperty.named("cycloOptions").type(CycloOption.class) + .desc("Choose options for the computation of Cyclo") + .mappings(OPTION_MAP) + .defaultValues(Collections.emptyList()) + .uiOrder(3.0f).build(); private int methodReportLevel; private int classReportLevel; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/AvoidUsingOctalValuesRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/AvoidUsingOctalValuesRule.java index cd1fdf5864..929818c530 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/AvoidUsingOctalValuesRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/AvoidUsingOctalValuesRule.java @@ -16,8 +16,11 @@ public class AvoidUsingOctalValuesRule extends AbstractJavaRule { public static final Pattern STRICT_OCTAL_PATTERN = Pattern.compile("0[0-7]+[lL]?"); - private static final BooleanProperty STRICT_METHODS_DESCRIPTOR = new BooleanProperty("strict", - "Detect violations between 00 and 07", false, 1.0f); + private static final BooleanProperty STRICT_METHODS_DESCRIPTOR = BooleanProperty.named("strict") + .desc("Detect violations between 00 and 07") + .defaultValue(false) + .uiOrder(1.0f).build(); + public AvoidUsingOctalValuesRule() { definePropertyDescriptor(STRICT_METHODS_DESCRIPTOR); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codesize/StdCyclomaticComplexityRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codesize/StdCyclomaticComplexityRule.java index dde262300d..45d699d5b2 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codesize/StdCyclomaticComplexityRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codesize/StdCyclomaticComplexityRule.java @@ -39,8 +39,10 @@ import net.sourceforge.pmd.properties.IntegerProperty; */ public class StdCyclomaticComplexityRule extends AbstractJavaRule { - public static final IntegerProperty REPORT_LEVEL_DESCRIPTOR = new IntegerProperty("reportLevel", - "Cyclomatic Complexity reporting threshold", 1, 30, 10, 1.0f); + public static final IntegerProperty REPORT_LEVEL_DESCRIPTOR + = IntegerProperty.named("reportLevel") + .desc("Cyclomatic Complexity reporting threshold") + .range(1, 30).defaultValue(10).uiOrder(1.0f).build(); public static final BooleanProperty SHOW_CLASSES_COMPLEXITY_DESCRIPTOR = new BooleanProperty( "showClassesComplexity", "Add class average violations to the report", true, 2.0f); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/comments/CommentSizeRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/comments/CommentSizeRule.java index eeeb7cdd0d..31fb327688 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/comments/CommentSizeRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/comments/CommentSizeRule.java @@ -21,9 +21,15 @@ import net.sourceforge.pmd.util.StringUtil; */ public class CommentSizeRule extends AbstractCommentRule { - public static final IntegerProperty MAX_LINES = new IntegerProperty("maxLines", "Maximum lines", 2, 200, 6, 2.0f); - public static final IntegerProperty MAX_LINE_LENGTH = new IntegerProperty("maxLineLength", "Maximum line length", 1, - 200, 80, 2.0f); + public static final IntegerProperty MAX_LINES + = IntegerProperty.named("maxLines") + .desc("Maximum lines") + .range(2, 200).defaultValue(6).uiOrder(2.0f).build(); + + public static final IntegerProperty MAX_LINE_LENGTH + = IntegerProperty.named("maxLineLength") + .desc("Maximum line length") + .range(1, 200).defaultValue(80).uiOrder(2.0f).build(); private static final String CR = "\n"; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/controversial/DataflowAnomalyAnalysisRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/controversial/DataflowAnomalyAnalysisRule.java index 4308a72cb5..bc2dc11cab 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/controversial/DataflowAnomalyAnalysisRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/controversial/DataflowAnomalyAnalysisRule.java @@ -29,17 +29,23 @@ import net.sourceforge.pmd.properties.IntegerProperty; * @author Sven Jacob */ public class DataflowAnomalyAnalysisRule extends AbstractJavaRule implements Executable { + private static final IntegerProperty MAX_PATH_DESCRIPTOR + = IntegerProperty.named("maxPaths") + .desc("Maximum number of checked paths per method. A lower value will increase the performance of the rule but may decrease anomalies found.") + .range(100, 8000) + .defaultValue(1000) + .uiOrder(1.0f).build(); + private static final IntegerProperty MAX_VIOLATIONS_DESCRIPTOR + = IntegerProperty.named("maxViolations") + .desc("Maximum number of anomalies per class") + .range(1, 2000) + .defaultValue(100) + .uiOrder(2.0f).build(); private RuleContext rc; private List daaRuleViolations; private int maxRuleViolations; private int currentRuleViolationCount; - private static final IntegerProperty MAX_PATH_DESCRIPTOR = new IntegerProperty("maxPaths", - "Maximum number of checked paths per method. A lower value will increase the performance of the rule but may decrease anomalies found.", - 100, 8000, 1000, 1.0f); - - private static final IntegerProperty MAX_VIOLATIONS_DESCRIPTOR = new IntegerProperty("maxViolations", - "Maximum number of anomalies per class", 1, 2000, 100, 2.0f); private static class Usage { public int accessType; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/coupling/CouplingBetweenObjectsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/coupling/CouplingBetweenObjectsRule.java index 00124a484a..ba9daa44f2 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/coupling/CouplingBetweenObjectsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/coupling/CouplingBetweenObjectsRule.java @@ -36,8 +36,10 @@ public class CouplingBetweenObjectsRule extends AbstractJavaRule { private int couplingCount; private Set typesFoundSoFar; - private static final IntegerProperty THRESHOLD_DESCRIPTOR = new IntegerProperty("threshold", - "Unique type reporting threshold", 2, 100, 20, 1.0f); + private static final IntegerProperty THRESHOLD_DESCRIPTOR + = IntegerProperty.named("threshold") + .desc("Unique type reporting threshold") + .range(2, 100).defaultValue(20).uiOrder(1.0f).build(); public CouplingBetweenObjectsRule() { definePropertyDescriptor(THRESHOLD_DESCRIPTOR); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/AvoidDeeplyNestedIfStmtsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/AvoidDeeplyNestedIfStmtsRule.java index 973b6a56aa..d7d4580da5 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/AvoidDeeplyNestedIfStmtsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/AvoidDeeplyNestedIfStmtsRule.java @@ -14,8 +14,10 @@ public class AvoidDeeplyNestedIfStmtsRule extends AbstractJavaRule { private int depth; private int depthLimit; - private static final IntegerProperty PROBLEM_DEPTH_DESCRIPTOR = new IntegerProperty("problemDepth", - "The if statement depth reporting threshold", 1, 25, 3, 1.0f); + private static final IntegerProperty PROBLEM_DEPTH_DESCRIPTOR + = IntegerProperty.named("problemDepth") + .desc("The if statement depth reporting threshold") + .range(1, 25).defaultValue(3).uiOrder(1.0f).build(); public AvoidDeeplyNestedIfStmtsRule() { definePropertyDescriptor(PROBLEM_DEPTH_DESCRIPTOR); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/AvoidDuplicateLiteralsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/AvoidDuplicateLiteralsRule.java index c5f31cf4a6..092ac83c71 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/AvoidDuplicateLiteralsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/AvoidDuplicateLiteralsRule.java @@ -33,8 +33,10 @@ import net.sourceforge.pmd.properties.StringProperty; public class AvoidDuplicateLiteralsRule extends AbstractJavaRule { - public static final IntegerProperty THRESHOLD_DESCRIPTOR = new IntegerProperty("maxDuplicateLiterals", - "Max duplicate literals", 1, 20, 4, 1.0f); + public static final IntegerProperty THRESHOLD_DESCRIPTOR + = IntegerProperty.named("maxDuplicateLiterals") + .desc("Max duplicate literals") + .range(1, 20).defaultValue(4).uiOrder(1.0f).build(); public static final IntegerProperty MINIMUM_LENGTH_DESCRIPTOR = new IntegerProperty("minimumLength", "Minimum string length to check", 1, Integer.MAX_VALUE, 3, 1.5f); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/ConsecutiveLiteralAppendsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/ConsecutiveLiteralAppendsRule.java index 52c86a8836..56e67f1d22 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/ConsecutiveLiteralAppendsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/ConsecutiveLiteralAppendsRule.java @@ -71,8 +71,10 @@ public class ConsecutiveLiteralAppendsRule extends AbstractJavaRule { BLOCK_PARENTS.add(ASTMethodDeclaration.class); } - private static final IntegerProperty THRESHOLD_DESCRIPTOR = new IntegerProperty("threshold", - "Max consecutive appends", 1, 10, 1, 1.0f); + private static final IntegerProperty THRESHOLD_DESCRIPTOR + = IntegerProperty.named("threshold") + .desc("Max consecutive appends") + .range(1, 10).defaultValue(1).uiOrder(1.0f).build(); private int threshold = 1; diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/design/CyclomaticComplexityRule.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/design/CyclomaticComplexityRule.java index 6192477798..fe23505c62 100644 --- a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/design/CyclomaticComplexityRule.java +++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/design/CyclomaticComplexityRule.java @@ -43,8 +43,10 @@ public class CyclomaticComplexityRule extends AbstractPLSQLRule { private static final Logger LOGGER = Logger.getLogger(CyclomaticComplexityRule.class.getName()); private static final String CLASS_NAME = CyclomaticComplexityRule.class.getName(); - public static final IntegerProperty REPORT_LEVEL_DESCRIPTOR = new IntegerProperty("reportLevel", - "Cyclomatic Complexity reporting threshold", 1, 30, 10, 1.0f); + public static final IntegerProperty REPORT_LEVEL_DESCRIPTOR + = IntegerProperty.named("reportLevel") + .desc("Cyclomatic Complexity reporting threshold") + .range(1, 30).defaultValue(10).uiOrder(1.0f).build(); public static final BooleanProperty SHOW_CLASSES_COMPLEXITY_DESCRIPTOR = new BooleanProperty( "showClassesComplexity", "Add class average violations to the report", true, 2.0f); diff --git a/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/design/AvoidDeeplyNestedIfStmtsRule.java b/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/design/AvoidDeeplyNestedIfStmtsRule.java index 3c01a3ace0..281dc1442b 100644 --- a/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/design/AvoidDeeplyNestedIfStmtsRule.java +++ b/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/design/AvoidDeeplyNestedIfStmtsRule.java @@ -16,8 +16,10 @@ public class AvoidDeeplyNestedIfStmtsRule extends AbstractVmRule { private int depth; private int depthLimit; - private static final IntegerProperty PROBLEM_DEPTH_DESCRIPTOR = new IntegerProperty("problemDepth", - "The if statement depth reporting threshold", 1, 25, 3, 1.0f); + private static final IntegerProperty PROBLEM_DEPTH_DESCRIPTOR + = IntegerProperty.named("problemDepth") + .desc("The if statement depth reporting threshold") + .range(1, 25).defaultValue(3).uiOrder(1.0f).build(); public AvoidDeeplyNestedIfStmtsRule() { definePropertyDescriptor(PROBLEM_DEPTH_DESCRIPTOR);