Java tutorial
/** * 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.Collections; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; import net.sourceforge.pmd.MultiValuePropertyDescriptor; import net.sourceforge.pmd.PropertyDescriptorField; import net.sourceforge.pmd.Rule; /** * Multi-valued property. * * @param <V> The type of the individual values. The multiple values are wrapped into a list. * * @author Clment Fournier * @version 6.0.0 */ /* default */ abstract class AbstractMultiValueProperty<V> extends AbstractProperty<List<V>> implements MultiValuePropertyDescriptor<V> { /** The default value. */ private final List<V> defaultValue; private final char multiValueDelimiter; /** * 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. */ AbstractMultiValueProperty(String theName, String theDescription, List<V> theDefault, float theUIOrder, boolean isDefinedExternally) { this(theName, theDescription, theDefault, theUIOrder, DEFAULT_DELIMITER, isDefinedExternally); } /** * Creates a multi valued property using a custom 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 separate multiple values * * @throws IllegalArgumentException If name or description are empty, or UI order is negative. */ AbstractMultiValueProperty(String theName, String theDescription, List<V> theDefault, float theUIOrder, char delimiter, boolean isDefinedExternally) { super(theName, theDescription, theUIOrder, isDefinedExternally); defaultValue = Collections.unmodifiableList(theDefault); multiValueDelimiter = delimiter; } @Override public final boolean isMultiValue() { return true; } /* This is the one overriden in PropertyDescriptor */ @Override public String propertyErrorFor(Rule rule) { List<V> realValues = rule.getProperty(this); return realValues == null ? null : errorFor(realValues); } @Override public String errorFor(List<V> 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"; } private boolean defaultHasNullValue() { return defaultValue == null || defaultValue.contains(null); } /** * Returns a string representation of the default value. * * @return A string representation of the default value. */ protected String defaultAsString() { return asDelimitedString(defaultValue(), multiValueDelimiter()); } private String asDelimitedString(List<V> values, char delimiter) { if (values == null) { return ""; } StringBuilder sb = new StringBuilder(); for (V value : values) { sb.append(asString(value)).append(delimiter); } if (sb.length() > 0) { sb.deleteCharAt(sb.length() - 1); } return sb.toString(); } @Override public List<V> defaultValue() { return defaultValue; } @Override public char multiValueDelimiter() { return multiValueDelimiter; } /** * Returns a string representation of the value, even if it's null. * * @param value The value to describe * * @return A string representation of the value */ protected String asString(V value) { return value == null ? "" : value.toString(); } @Override public final String asDelimitedString(List<V> values) { return asDelimitedString(values, multiValueDelimiter()); } @Override public List<V> valueFrom(String valueString) throws IllegalArgumentException { if (StringUtils.isBlank(valueString)) { return Collections.emptyList(); } String[] strValues = valueString.split(Pattern.quote("" + multiValueDelimiter())); List<V> values = new ArrayList<>(strValues.length); for (String strValue : strValues) { values.add(createFrom(strValue)); } return values; } /** * Parse a string and returns an instance of a single value (not a list). * * @param toParse String to parse * * @return An instance of a value */ protected abstract V createFrom(String toParse); @Override protected void addAttributesTo(Map<PropertyDescriptorField, String> attributes) { super.addAttributesTo(attributes); attributes.put(PropertyDescriptorField.DELIMITER, Character.toString(multiValueDelimiter())); } }