From 578bbf8f7bcb0ff5d9522d19260f13e32662cb19 Mon Sep 17 00:00:00 2001
From: oowekyala
Date: Sun, 25 Jun 2017 17:40:16 +0200
Subject: [PATCH 01/53] Draft for the new API
---
.../sourceforge/pmd/PropertyDescriptor.java | 39 +-
.../AbstractMultiValueProperty.java | 202 ++++++++++
.../rule/properties/AbstractProperty.java | 365 +++---------------
.../AbstractSingleValueProperty.java | 121 ++++++
4 files changed, 406 insertions(+), 321 deletions(-)
create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java
create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java
index bd13191967..e1387bbe67 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java
@@ -12,10 +12,11 @@ import java.util.Map;
* descriptor instances are static and immutable they provide validation,
* serialization, and default values for any specific datatypes.
*
- * @author Brian Remedios
* @param type of the property's value
+ *
+ * @author Brian Remedios
*/
-public interface PropertyDescriptor extends Comparable> {
+public interface PropertyDescriptor extends Comparable> {
/**
* The name of the property without spaces as it serves as the key into the
* property map.
@@ -33,11 +34,12 @@ public interface PropertyDescriptor extends Comparable type();
+ Class> type();
/**
* Returns whether the property is multi-valued, i.e. an array of strings,
@@ -71,18 +73,18 @@ public interface PropertyDescriptor extends ComparableExample:
* name -> 0.0 description 1.0 minValue -> 2.0 maxValue -> 2.1
*
@@ -98,12 +100,13 @@ public interface PropertyDescriptor extends Comparable extends Comparable extends Comparable choices();
/**
* 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
+ * @param rule Rule
+ *
* @return String
*/
String propertyErrorFor(Rule rule);
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java
new file mode 100644
index 0000000000..4bd2d804b0
--- /dev/null
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java
@@ -0,0 +1,202 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+package net.sourceforge.pmd.lang.rule.properties;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import net.sourceforge.pmd.Rule;
+
+/**
+ * Multi valued property.
+ *
+ * @param The type of the individual values. The multiple values are wrapped into a list.
+ *
+ * @author Clément Fournier
+ */
+public abstract class AbstractMultiValueProperty extends AbstractProperty> {
+
+ /** The default value. */
+ protected final List defaultValue;
+
+
+ /**
+ * Creates a multi valued property using the default delimiter {@link #DEFAULT_DELIMITER}.
+ *
+ * @param theName Name of the property (must not be empty)
+ * @param theDescription Description (must not be empty)
+ * @param theDefault Default value
+ * @param theUIOrder UI order (must be positive or zero)
+ *
+ * @throws IllegalArgumentException If name or description are empty, or UI order is negative.
+ */
+ public AbstractMultiValueProperty(String theName, String theDescription, List theDefault, float theUIOrder) {
+ this(theName, theDescription, theDefault, theUIOrder, DEFAULT_DELIMITER);
+ }
+
+
+ /**
+ * Creates a multi valued property using another delimiter.
+ *
+ * @param theName Name of the property (must not be empty)
+ * @param theDescription Description (must not be empty)
+ * @param theDefault Default value
+ * @param theUIOrder UI order (must be positive or zero)
+ * @param delimiter The delimiter to use
+ *
+ * @throws IllegalArgumentException If name or description are empty, or UI order is negative.
+ */
+ public AbstractMultiValueProperty(String theName, String theDescription, List theDefault,
+ float theUIOrder, char delimiter) {
+
+ super(theName, theDescription, theUIOrder, delimiter);
+ defaultValue = theDefault;
+ }
+
+
+ /**
+ * Creates a multi valued property using the default delimiter {@link #DEFAULT_DELIMITER}.
+ *
+ * @param theName Name of the property (must not be empty)
+ * @param theDescription Description (must not be empty)
+ * @param theDefault Default value
+ * @param theUIOrder UI order (must be positive or zero)
+ *
+ * @throws IllegalArgumentException If name or description are empty, or UI order is negative.
+ */
+ protected AbstractMultiValueProperty(String theName, String theDescription, V[] theDefault, float theUIOrder) {
+ this(theName, theDescription, theDefault, theUIOrder, DEFAULT_DELIMITER);
+ }
+
+ /**
+ * Constructor for AbstractPMDProperty.
+ *
+ * @param theName Name of the property (must not be empty)
+ * @param theDescription Description (must not be empty)
+ * @param theDefault Default value
+ * @param theUIOrder UI order (must be positive or zero)
+ * @param delimiter The delimiter to separate multi values
+ *
+ * @throws IllegalArgumentException If name or description are empty, or UI order is negative.
+ */
+ protected AbstractMultiValueProperty(String theName, String theDescription, V[] theDefault,
+ float theUIOrder, char delimiter) {
+
+ this(theName, theDescription, Arrays.asList(theDefault), theUIOrder, delimiter);
+ }
+
+
+ @Override
+ public List defaultValue() {
+ return defaultValue;
+ }
+
+ /**
+ * Returns true if a default value is null.
+ *
+ * @return True if a default value is null
+ */
+ private boolean defaultHasNullValue() {
+ return defaultValue == null || defaultValue.contains(null);
+ }
+
+ @Override
+ public final boolean isMultiValue() {
+ return true;
+ }
+
+ @Override
+ public String asDelimitedString(List values, char delimiter) {
+ if (values == null) {
+ return "";
+ }
+
+ StringBuilder sb = new StringBuilder();
+ for (V value : values) {
+ sb.append(value == null ? "" : value.toString()).append(delimiter);
+ }
+ if (sb.length() > 0) {
+ sb.deleteCharAt(sb.length() - 1);
+ }
+
+ return sb.toString();
+ }
+
+
+ @Override
+ public String errorFor(List values) {
+
+ String err;
+ for (V value2 : values) {
+ err = valueErrorFor(value2);
+ if (err != null) {
+ return err;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Checks a single value for a "missing value" error.
+ *
+ * @param value Value to check
+ *
+ * @return A descriptive String of the error or null if there was none
+ */
+ protected String valueErrorFor(V value) {
+ return value != null || defaultHasNullValue() ? null : "missing value";
+ }
+
+ @Override
+ public Map> choices() {
+ return null;
+ }
+
+
+ /* This is the one overriden in PropertyDescriptor */
+ @Override
+ public String propertyErrorFor(Rule rule) {
+ List realValues = rule.getProperty(this);
+ if (realValues == null && !isRequired()) {
+ return null;
+ }
+ return errorFor(realValues);
+ }
+
+ /**
+ * Returns a string representation of the default value.
+ *
+ * @return A string representation of the default value.
+ */
+ protected String defaultAsString() {
+ return asDelimitedString(defaultValue(), multiValueDelimiter());
+ }
+
+ /**
+ * Parse a string and returns an instance of a value.
+ *
+ * @param toParse String to parse
+ *
+ * @return An instance of a value
+ */
+ protected abstract V createFrom(String toParse);
+
+ @Override
+ public List valueFrom(String valueString) throws IllegalArgumentException {
+ String[] strValues = valueString.split(Pattern.quote("" + multiValueDelimiter()));
+
+ List values = new ArrayList<>(strValues.length);
+ for (int i = 0; i < strValues.length; i++) {
+ values.add(createFrom(strValues[i]));
+ }
+
+ return values;
+ }
+
+}
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java
index 2bc1c8c037..9865aaa0b4 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractProperty.java
@@ -13,359 +13,150 @@ import java.util.Map;
import net.sourceforge.pmd.PropertyDescriptor;
import net.sourceforge.pmd.PropertyDescriptorFields;
-import net.sourceforge.pmd.Rule;
import net.sourceforge.pmd.util.StringUtil;
/**
+ * Abstract class for properties.
+ *
+ * @param The type of the values.
*
* @author Brian Remedios
- * @param
*/
public abstract class AbstractProperty implements PropertyDescriptor {
- private final String name;
- private final String description;
- private final T defaultValue;
- private final boolean isRequired;
- private final float uiOrder;
-
/**
* Default delimiter for multi properties. Note: Numeric properties usual
* use the {@value #DEFAULT_NUMERIC_DELIMITER}.
*/
public static final char DEFAULT_DELIMITER = '|';
+
/**
* Default delimiter for numeric properties.
*/
public static final char DEFAULT_NUMERIC_DELIMITER = ',';
+ private final String name;
+ private final String description;
+ private final boolean isRequired;
+ private final float uiOrder;
private char multiValueDelimiter = DEFAULT_DELIMITER;
- protected AbstractProperty(String theName, String theDescription, T theDefault, float theUIOrder) {
- this(theName, theDescription, theDefault, theUIOrder, DEFAULT_DELIMITER);
+
+ /**
+ * Creates an AbstractProperty using the default delimiter {@link #DEFAULT_DELIMITER}.
+ *
+ * @param theName Name of the property (must not be empty)
+ * @param theDescription Description (must not be empty)
+ * @param theUIOrder UI order (must be positive or zero)
+ *
+ * @throws IllegalArgumentException If name or description are empty, or UI order is negative.
+ */
+ protected AbstractProperty(String theName, String theDescription, float theUIOrder) {
+ this(theName, theDescription, theUIOrder, DEFAULT_DELIMITER);
}
/**
* Constructor for AbstractPMDProperty.
*
- * @param theName
- * String
- * @param theDescription
- * String
- * @param theDefault
- * Object
- * @param theUIOrder
- * float
- * @throws IllegalArgumentException
+ * @param theName Name of the property (must not be empty)
+ * @param theDescription Description (must not be empty)
+ * @param theUIOrder UI order (must be positive or zero)
+ * @param delimiter The delimiter to separate multi values
+ *
+ * @throws IllegalArgumentException If name or description are empty, or UI order is negative.
*/
- protected AbstractProperty(String theName, String theDescription, T theDefault, float theUIOrder, char delimiter) {
+ protected AbstractProperty(String theName, String theDescription,
+ float theUIOrder, char delimiter) {
+ if (theUIOrder < 0) {
+ throw new IllegalArgumentException("Property attribute 'UI order' cannot be null or blank");
+ }
+
name = checkNotEmpty(theName, NAME);
description = checkNotEmpty(theDescription, DESCRIPTION);
- defaultValue = theDefault;
isRequired = false; // TODO - do we need this?
- uiOrder = checkPositive(theUIOrder, "UI order");
+ uiOrder = theUIOrder;
multiValueDelimiter = delimiter;
}
- /**
- * @param arg
- * String
- * @param argId
- * String
- * @return String
- * @throws IllegalArgumentException
- */
- private static String checkNotEmpty(String arg, String argId) {
+ private static String checkNotEmpty(String arg, String argId) throws IllegalArgumentException {
if (StringUtil.isEmpty(arg)) {
throw new IllegalArgumentException("Property attribute '" + argId + "' cannot be null or blank");
}
-
return arg;
}
/**
- * @param arg
- * float
- * @param argId
- * String
- * @return float
- * @throws IllegalArgumentException
+ * Tests if two values are equal.
+ *
+ * @param value First value
+ * @param otherValue Object
+ *
+ * @return True if the two values are equal.
+ *
+ * @deprecated Never used in pmd's codebase + is just an alias for Object#equals.
*/
- private static float checkPositive(float arg, String argId) {
- if (arg < 0) {
- throw new IllegalArgumentException("Property attribute " + argId + "' must be zero or positive");
- }
- return arg;
+ @SuppressWarnings("PMD.CompareObjectsWithEquals")
+ public static boolean areEqual(Object value, Object otherValue) {
+ return value != null && value.equals(otherValue);
}
- /**
- * {@inheritDoc}
- */
- @Override
- public char multiValueDelimiter() {
- return multiValueDelimiter;
- }
- /**
- * {@inheritDoc}
- */
@Override
public String name() {
return name;
}
- /**
- * {@inheritDoc}
- */
@Override
public String description() {
return description;
}
- /**
- * {@inheritDoc}
- */
- @Override
- public T defaultValue() {
- return defaultValue;
- }
-
- /**
- * Method defaultHasNullValue.
- *
- * @return boolean
- */
- protected boolean defaultHasNullValue() {
-
- if (defaultValue == null) {
- return true;
- }
-
- if (isMultiValue() && isArray(defaultValue)) {
- Object[] defaults = (Object[]) defaultValue;
- for (Object default1 : defaults) {
- if (default1 == null) {
- return true;
- }
- }
- }
-
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean isMultiValue() {
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
@Override
public boolean isRequired() {
return isRequired;
}
- /**
- * {@inheritDoc}
- */
@Override
public float uiOrder() {
return uiOrder;
}
- /**
- * Return the value as a string that can be easily recognized and parsed
- * when we see it again.
- *
- * @param value
- * Object
- * @return String
- */
- protected String asString(Object value) {
- return value == null ? "" : value.toString();
+ @Override
+ public char multiValueDelimiter() {
+ return multiValueDelimiter;
}
- /**
- * {@inheritDoc}
- */
@Override
- public String asDelimitedString(T values) {
+ public final String asDelimitedString(T values) {
return asDelimitedString(values, multiValueDelimiter());
}
/**
* Return the specified values as a single string using the delimiter.
*
- * @param values
- * Object
- * @param delimiter
- * char
+ * @param values Values to format
+ * @param delimiter char
+ *
* @return String
- * @see net.sourceforge.pmd.PropertyDescriptor#asDelimitedString(Object)
+ *
+ * @see net.sourceforge.pmd.PropertyDescriptor#asDelimitedString(T)
*/
- public String asDelimitedString(T values, char delimiter) {
- if (values == null) {
- return "";
- }
+ public abstract String asDelimitedString(T values, char delimiter);
- if (values instanceof Object[]) {
- Object[] valueSet = (Object[]) values;
- if (valueSet.length == 0) {
- return "";
- }
- if (valueSet.length == 1) {
- return asString(valueSet[0]);
- }
-
- StringBuilder sb = new StringBuilder();
- sb.append(asString(valueSet[0]));
- for (int i = 1; i < valueSet.length; i++) {
- sb.append(delimiter);
- sb.append(asString(valueSet[i]));
- }
- return sb.toString();
- }
-
- return asString(values);
- }
-
- /**
- * {@inheritDoc}
- */
@Override
- public int compareTo(PropertyDescriptor> otherProperty) {
+ public final int compareTo(PropertyDescriptor> otherProperty) {
float otherOrder = otherProperty.uiOrder();
return (int) (otherOrder - uiOrder);
}
- /**
- * {@inheritDoc}
- */
- @Override
- public String errorFor(Object value) {
- String typeError = typeErrorFor(value);
- if (typeError != null) {
- return typeError;
- }
- return isMultiValue() ? valuesErrorFor(value) : valueErrorFor(value);
- }
-
- /**
- * @param value
- * Object
- * @return String
- */
- protected String valueErrorFor(Object value) {
-
- if (value == null) {
- if (defaultHasNullValue()) {
- return null;
- }
- return "missing value";
- }
- return null;
- }
-
- /**
- * @param value
- * Object
- * @return String
- */
- protected String valuesErrorFor(Object value) {
-
- if (!isArray(value)) {
- return "multiple values expected";
- }
-
- Object[] values = (Object[]) value;
-
- String err = null;
- for (Object value2 : values) {
- err = valueErrorFor(value2);
- if (err != null) {
- return err;
- }
- }
-
- return null;
- }
-
- /**
- * @param value
- * Object
- * @return boolean
- */
- protected static boolean isArray(Object value) {
- return value != null && value.getClass().getComponentType() != null;
- }
-
- /**
- * @param value
- * Object
- * @return String
- */
- protected String typeErrorFor(Object value) {
-
- if (value == null && !isRequired) {
- return null;
- }
-
- if (isMultiValue()) {
- if (!isArray(value)) {
- return "Value is not an array of type: " + type();
- }
-
- Class> arrayType = value.getClass().getComponentType();
- if (arrayType == null || !arrayType.isAssignableFrom(type().getComponentType())) {
- return "Value is not an array of type: " + type();
- }
- return null;
- }
-
- if (!type().isAssignableFrom(value.getClass())) {
- return value + " is not an instance of " + type();
- }
-
- return null;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String propertyErrorFor(Rule rule) {
- Object realValue = rule.getProperty(this);
- if (realValue == null && !isRequired()) {
- return null;
- }
- return errorFor(realValue);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Object[][] choices() {
- return null;
- }
-
- /**
- * {@inheritDoc}
- */
@Override
public int preferredRowCount() {
return 1;
}
- /**
- * {@inheritDoc}
- */
+
@Override
public boolean equals(Object obj) {
if (this == obj) {
@@ -380,58 +171,26 @@ public abstract class AbstractProperty implements PropertyDescriptor {
return false;
}
- /**
- * {@inheritDoc}
- */
@Override
public int hashCode() {
return name.hashCode();
}
- /**
- * {@inheritDoc}
- */
+
@Override
public String toString() {
return "[PropertyDescriptor: name=" + name() + ", type=" + type() + ", value=" + defaultValue() + "]";
}
/**
- * @return String
+ * Returns a string representation of the default value.
+ *
+ * @return A string representation of the default value.
*/
- protected String defaultAsString() {
- if (isMultiValue()) {
- return asDelimitedString(defaultValue(), multiValueDelimiter());
- } else {
- return defaultValue().toString();
- }
- }
-
- /**
- * @param value
- * Object
- * @param otherValue
- * Object
- * @return boolean
- */
- @SuppressWarnings("PMD.CompareObjectsWithEquals")
- public static final boolean areEqual(Object value, Object otherValue) {
- if (value == otherValue) {
- return true;
- }
- if (value == null) {
- return false;
- }
- if (otherValue == null) {
- return false;
- }
-
- return value.equals(otherValue);
- }
+ protected abstract String defaultAsString();
@Override
public Map attributeValuesById() {
-
Map values = new HashMap<>();
addAttributesTo(values);
return values;
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java
new file mode 100644
index 0000000000..897fe854e7
--- /dev/null
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java
@@ -0,0 +1,121 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+package net.sourceforge.pmd.lang.rule.properties;
+
+import java.util.Map;
+
+import net.sourceforge.pmd.Rule;
+
+/**
+ * Single value property.
+ *
+ * @param The type of the value.
+ *
+ * @author Clément Fournier
+ */
+public abstract class AbstractSingleValueProperty extends AbstractProperty {
+
+ /** Default value. */
+ protected T defaultValue;
+
+ /**
+ * Creates a single value property using the default delimiter {@link #DEFAULT_DELIMITER}.
+ *
+ * @param theName Name of the property (must not be empty)
+ * @param theDescription Description (must not be empty)
+ * @param theUIOrder UI order (must be positive or zero)
+ * @param theDefault Default value
+ *
+ * @throws IllegalArgumentException If name or description are empty, or UI order is negative.
+ */
+ protected AbstractSingleValueProperty(String theName, String theDescription, T theDefault, float theUIOrder) {
+ super(theName, theDescription, theUIOrder, DEFAULT_DELIMITER);
+
+ defaultValue = theDefault;
+ }
+
+
+ @Override
+ public final T defaultValue() {
+ return defaultValue;
+ }
+
+ /**
+ * Returns true if the default value is {@code null}.
+ *
+ * @return True if the default value is {@code null}.
+ */
+ private boolean defaultHasNullValue() {
+ return defaultValue == null;
+ }
+
+ @Override
+ public final boolean isMultiValue() {
+ return false;
+ }
+
+ @Override
+ public String asDelimitedString(T values, char delimiter) {
+ return values == null ? "" : values.toString();
+ }
+
+ @Override
+ public String propertyErrorFor(Rule rule) {
+ T realValue = rule.getProperty(this);
+ if (realValue == null && !isRequired()) {
+ return null;
+ }
+ return errorFor(realValue);
+ }
+
+ @Override
+ public String errorFor(T value) {
+ String typeError = typeErrorFor(value);
+ if (typeError != null) {
+ return typeError;
+ }
+ return valueErrorFor(value);
+ }
+
+ private String typeErrorFor(T value) { // TODO:cf consider subtypes!!
+
+ if (value != null && !type().isAssignableFrom(value.getClass())) {
+ return value + " is not an instance of " + type();
+ }
+
+ return null;
+ }
+
+ protected String valueErrorFor(T value) {
+ return value != null || defaultHasNullValue() ? null : "missing value";
+ }
+
+ @Override
+ protected final String defaultAsString() {
+ return defaultValue().toString();
+ }
+
+ @Override
+ public Map choices() {
+ return null;
+ }
+
+ /**
+ * Parse a string and returns an instance of a value.
+ *
+ * @param toParse String to parse
+ *
+ * @return An instance of a value
+ */
+ protected abstract T createFrom(String toParse);
+
+ // this is there to be symmetrical.
+
+ @Override
+ public final T valueFrom(String valueString) throws IllegalArgumentException {
+ return createFrom(valueString);
+ }
+
+}
From b2673b38b5553db85c360567fdf3d04321dcf771 Mon Sep 17 00:00:00 2001
From: oowekyala
Date: Sun, 25 Jun 2017 20:55:43 +0200
Subject: [PATCH 02/53] POC on boolean and enumerated properties
---
.../sourceforge/pmd/PropertyDescriptor.java | 4 +-
.../AbstractMultiValueProperty.java | 19 ++-
.../AbstractSingleValueProperty.java | 17 ++-
.../rule/properties/BooleanMultiProperty.java | 79 ++++------
.../lang/rule/properties/BooleanProperty.java | 59 +++-----
.../properties/EnumeratedMultiProperty.java | 135 +++++++-----------
.../rule/properties/EnumeratedProperty.java | 96 +++++++------
7 files changed, 178 insertions(+), 231 deletions(-)
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java
index e1387bbe67..b0091d98d5 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/PropertyDescriptor.java
@@ -5,6 +5,8 @@
package net.sourceforge.pmd;
import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
/**
* Property value descriptor that defines the use & requirements for setting
@@ -126,7 +128,7 @@ public interface PropertyDescriptor extends Comparable>
*
* @return Object[][]
*/
- Map choices();
+ Set> choices();
/**
* A convenience method that returns an error string if the rule holds onto
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java
index 4bd2d804b0..9e0aafdc4b 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractMultiValueProperty.java
@@ -7,7 +7,8 @@ package net.sourceforge.pmd.lang.rule.properties;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
import java.util.regex.Pattern;
import net.sourceforge.pmd.Rule;
@@ -52,7 +53,7 @@ public abstract class AbstractMultiValueProperty extends AbstractProperty theDefault,
- float theUIOrder, char delimiter) {
+ float theUIOrder, char delimiter) {
super(theName, theDescription, theUIOrder, delimiter);
defaultValue = theDefault;
@@ -69,7 +70,7 @@ public abstract class AbstractMultiValueProperty extends AbstractProperty extends AbstractProperty extends AbstractProperty values, char delimiter) {
if (values == null) {
@@ -118,7 +123,7 @@ public abstract class AbstractMultiValueProperty extends AbstractProperty 0) {
sb.deleteCharAt(sb.length() - 1);
@@ -154,7 +159,7 @@ public abstract class AbstractMultiValueProperty extends AbstractProperty> choices() {
+ public Set>> choices() {
return null;
}
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java
index 897fe854e7..c56e550716 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/AbstractSingleValueProperty.java
@@ -4,7 +4,8 @@
package net.sourceforge.pmd.lang.rule.properties;
-import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
import net.sourceforge.pmd.Rule;
@@ -56,6 +57,8 @@ public abstract class AbstractSingleValueProperty extends AbstractProperty
return false;
}
+
+
@Override
public String asDelimitedString(T values, char delimiter) {
return values == null ? "" : values.toString();
@@ -92,13 +95,17 @@ public abstract class AbstractSingleValueProperty extends AbstractProperty
return value != null || defaultHasNullValue() ? null : "missing value";
}
- @Override
- protected final String defaultAsString() {
- return defaultValue().toString();
+ protected String asString(T value) {
+ return value == null ? "" : value.toString();
}
@Override
- public Map choices() {
+ protected final String defaultAsString() {
+ return asString(defaultValue);
+ }
+
+ @Override
+ public Set> choices() {
return null;
}
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java
index b742e4cc4b..e598a65ed1 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanMultiProperty.java
@@ -4,6 +4,7 @@
package net.sourceforge.pmd.lang.rule.properties;
+import java.util.List;
import java.util.Map;
import net.sourceforge.pmd.PropertyDescriptorFactory;
@@ -14,79 +15,59 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto
*
* @author Brian Remedios
*/
-public class BooleanMultiProperty extends AbstractScalarProperty {
+public class BooleanMultiProperty extends AbstractMultiValueProperty {
- public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(
- String[].class) {
+ /**
+ * Factory.
+ */
+ public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(
+ Boolean.class) {
@Override
public BooleanMultiProperty createWith(Map valuesById) {
char delimiter = delimiterIn(valuesById);
return new BooleanMultiProperty(nameIn(valuesById), descriptionIn(valuesById),
- booleanValuesIn(defaultValueIn(valuesById), delimiter), 0f);
+ booleanValuesIn(defaultValueIn(valuesById), delimiter), 0f);
}
};
/**
* Constructor for BooleanMultiProperty that allows for multiple values.
*
- * @param theName
- * String
- * @param theDescription
- * String
- * @param defaultValues
- * Boolean[]
- * @param theUIOrder
- * float
+ * @param theName String
+ * @param theDescription String
+ * @param defaultValues Boolean[]
+ * @param theUIOrder float
*/
public BooleanMultiProperty(String theName, String theDescription, Boolean[] defaultValues, float theUIOrder) {
super(theName, theDescription, defaultValues, theUIOrder);
}
/**
- * @return Class
- * @see net.sourceforge.pmd.PropertyDescriptor#type()
- */
- @Override
- public Class type() {
- return Boolean[].class;
- }
-
- /**
- * @return boolean
- * @see net.sourceforge.pmd.PropertyDescriptor#isMultiValue()
- */
- @Override
- public boolean isMultiValue() {
- return true;
- }
-
- /**
- * Creates and returns a Boolean instance from a raw string
+ * Constructor for BooleanMultiProperty that allows for multiple values.
*
- * @param value
- * String
- * @return Object
+ * @param theName String
+ * @param theDescription String
+ * @param defaultValues Boolean[]
+ * @param theUIOrder float
*/
- @Override
- protected Object createFrom(String value) {
- return Boolean.valueOf(value);
+ public BooleanMultiProperty(String theName, String theDescription, List defaultValues, float theUIOrder) {
+ super(theName, theDescription, defaultValues, theUIOrder);
}
- /**
- * @param size
- * int
- * @return Object[]
- */
@Override
- protected Boolean[] arrayFor(int size) {
- return new Boolean[size];
+ protected Boolean createFrom(String toParse) {
+ return Boolean.valueOf(toParse);
}
- /**
- * @return String
- */
+
@Override
- protected String defaultAsString() {
- return asDelimitedString(defaultValue());
+ public Class type() {
+ return Boolean.class;
+ }
+
+
+ @Override
+ public List valueFrom(String propertyString) throws IllegalArgumentException {
+ return null;
}
}
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java
index 6a03a0fc93..b980ad6b97 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/BooleanProperty.java
@@ -14,77 +14,52 @@ import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescripto
*
* @author Brian Remedios
*/
-public class BooleanProperty extends AbstractScalarProperty {
+public class BooleanProperty extends AbstractSingleValueProperty {
- public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(
- Boolean.class) {
+ public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(
+ Boolean.class) {
@Override
public BooleanProperty createWith(Map valuesById) {
return new BooleanProperty(nameIn(valuesById), descriptionIn(valuesById),
- Boolean.valueOf(defaultValueIn(valuesById)), 0f);
+ Boolean.valueOf(defaultValueIn(valuesById)), 0f);
}
};
/**
* Constructor for BooleanProperty limited to a single value.
*
- * @param theName
- * String
- * @param theDescription
- * String
- * @param defaultValue
- * boolean
- * @param theUIOrder
- * float
+ * @param theName Name
+ * @param theDescription Description
+ * @param defaultValue Default value
+ * @param theUIOrder UI order
*/
- public BooleanProperty(String theName, String theDescription, Boolean defaultValue, float theUIOrder) {
- super(theName, theDescription, Boolean.valueOf(defaultValue), theUIOrder);
+ public BooleanProperty(String theName, String theDescription, boolean defaultValue, float theUIOrder) {
+ super(theName, theDescription, defaultValue, theUIOrder);
}
/**
* Constructor for BooleanProperty limited to a single value. Converts
* default argument string into a boolean.
*
- * @param theName
- * String
- * @param theDescription
- * String
- * @param defaultBoolStr
- * String
- * @param theUIOrder
- * float
+ * @param theName Name
+ * @param theDescription Description
+ * @param defaultBoolStr String representing the default value.
+ * @param theUIOrder UI order
*/
public BooleanProperty(String theName, String theDescription, String defaultBoolStr, float theUIOrder) {
this(theName, theDescription, Boolean.valueOf(defaultBoolStr), theUIOrder);
}
- /**
- * @return Class
- * @see net.sourceforge.pmd.PropertyDescriptor#type()
- */
+
@Override
public Class type() {
return Boolean.class;
}
- /**
- * @return String
- */
@Override
- protected String defaultAsString() {
- return Boolean.toString(defaultValue());
+ public Boolean createFrom(String propertyString) throws IllegalArgumentException {
+ return null;
}
- /**
- * Creates and returns a Boolean instance from a raw string
- *
- * @param value
- * String
- * @return Object
- */
- @Override
- protected Object createFrom(String value) {
- return Boolean.valueOf(value);
- }
}
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java
index a3dc611ea1..8f2e7cb031 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/properties/EnumeratedMultiProperty.java
@@ -4,12 +4,14 @@
package net.sourceforge.pmd.lang.rule.properties;
+import java.util.ArrayList;
import java.util.Enumeration;
+import java.util.List;
import java.util.Map;
import net.sourceforge.pmd.PropertyDescriptorFactory;
import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory;
-import net.sourceforge.pmd.util.StringUtil;
+import net.sourceforge.pmd.util.CollectionUtil;
/**
* Defines a datatype with a set of preset values of any type as held within a
@@ -17,118 +19,91 @@ import net.sourceforge.pmd.util.StringUtil;
* serve as keys to obtain the values. The choices() method provides the ordered
* selections to be used in an editor widget.
*
- * @author Brian Remedios
* @param
+ *
+ * @author Brian Remedios
*/
-public class EnumeratedMultiProperty extends AbstractEnumeratedProperty {
+public class EnumeratedMultiProperty extends AbstractMultiValueProperty {
- public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory(
- Enumeration[].class) {
+ public static final PropertyDescriptorFactory FACTORY
+ = new BasicPropertyDescriptorFactory(Enumeration.class) {
@Override
public EnumeratedMultiProperty createWith(Map valuesById) {
- return new EnumeratedMultiProperty(nameIn(valuesById), descriptionIn(valuesById), labelsIn(valuesById),
- choicesIn(valuesById), indiciesIn(valuesById), 0f);
+ return new EnumeratedMultiProperty<>(nameIn(valuesById), descriptionIn(valuesById), labelsIn(valuesById),
+ choicesIn(valuesById), indicesIn(valuesById), 0f);
}
};
+ protected Map choicesByLabel;
+ protected Map labelsByChoice;
+
+
/**
* Constructor for EnumeratedProperty.
*
- * @param theName
- * String
- * @param theDescription
- * String
- * @param theLabels
- * String[]
- * @param theChoices
- * E[]
- * @param choiceIndices
- * int[]
- * @param theUIOrder
- * float
+ * @param theName String
+ * @param theDescription String
+ * @param theLabels String[]
+ * @param theChoices E[]
+ * @param choiceIndices int[]
+ * @param theUIOrder float
+ *
* @throws IllegalArgumentException
*/
public EnumeratedMultiProperty(String theName, String theDescription, String[] theLabels, E[] theChoices,
- int[] choiceIndices, float theUIOrder) {
- super(theName, theDescription, theLabels, theChoices, choiceIndices, theUIOrder, true);
+ int[] choiceIndices, float theUIOrder) {
+ super(theName, theDescription, selection(choiceIndices, theChoices), theUIOrder);
+ choicesByLabel = CollectionUtil.mapFrom(theLabels, theChoices);
+ labelsByChoice = CollectionUtil.invertedMapFrom(choicesByLabel);
}
- /**
- * @return Class
- * @see net.sourceforge.pmd.PropertyDescriptor#type()
- */
- @Override
- public Class