Fix initialisation bug

This commit is contained in:
oowekyala
2017-07-15 16:36:11 +02:00
parent 278e857bf6
commit 35dee58bc8
17 changed files with 141 additions and 146 deletions

View File

@ -4,7 +4,7 @@
package net.sourceforge.pmd;
import static net.sourceforge.pmd.PropertyDescriptor.CORE_FIELD_TYPES_BY_KEY;
import static net.sourceforge.pmd.PropertyDescriptor.CORE_EXPECTED_FIELDS;
import static net.sourceforge.pmd.PropertyDescriptorField.DEFAULT_VALUE;
import static net.sourceforge.pmd.PropertyDescriptorField.DELIMITER;
import static net.sourceforge.pmd.PropertyDescriptorField.DESCRIPTION;
@ -19,6 +19,8 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import net.sourceforge.pmd.util.StringUtil;
/**
@ -30,26 +32,18 @@ import net.sourceforge.pmd.util.StringUtil;
*/
public abstract class AbstractPropertyDescriptorFactory<T> implements PropertyDescriptorFactory<T> {
static {
System.err.println(CORE_FIELD_TYPES_BY_KEY);
}
private final Class<?> valueType;
/**
* Denote the identifiers of the expected fields paired with booleans
* denoting whether they are required (non-null) or not.
* denoting whether they are required or not.
*/
private final Map<PropertyDescriptorField, Boolean> expectedFields;
public AbstractPropertyDescriptorFactory(Class<?> theValueType) {
valueType = theValueType;
expectedFields = CORE_FIELD_TYPES_BY_KEY;
expectedFields = CORE_EXPECTED_FIELDS;
}
@ -57,12 +51,12 @@ public abstract class AbstractPropertyDescriptorFactory<T> implements PropertyDe
valueType = theValueType;
if (additionalFieldTypesByKey == null) {
expectedFields = CORE_FIELD_TYPES_BY_KEY;
expectedFields = CORE_EXPECTED_FIELDS;
return;
}
Map<PropertyDescriptorField, Boolean> temp
= new HashMap<>(CORE_FIELD_TYPES_BY_KEY.size() + additionalFieldTypesByKey.size());
temp.putAll(CORE_FIELD_TYPES_BY_KEY);
= new HashMap<>(CORE_EXPECTED_FIELDS.size() + additionalFieldTypesByKey.size());
temp.putAll(CORE_EXPECTED_FIELDS);
temp.putAll(additionalFieldTypesByKey);
expectedFields = Collections.unmodifiableMap(temp);
@ -116,7 +110,7 @@ public abstract class AbstractPropertyDescriptorFactory<T> implements PropertyDe
*/
protected String defaultValueIn(Map<PropertyDescriptorField, String> valuesById) {
String deft = valuesById.get(DEFAULT_VALUE);
if (StringUtil.isEmpty(deft)) {
if (isValueMissing(deft)) {
throw new RuntimeException("Default value was null, empty, or missing");
}
return deft;
@ -125,7 +119,7 @@ public abstract class AbstractPropertyDescriptorFactory<T> implements PropertyDe
@Override
public final PropertyDescriptor<T> createWith(Map<PropertyDescriptorField, String> valuesById) {
// checkRequiredFields(valuesById);
checkRequiredFields(valuesById);
return createWith(valuesById, false);
}
@ -133,7 +127,7 @@ public abstract class AbstractPropertyDescriptorFactory<T> implements PropertyDe
/** Checks whether all required fields are present in the map. */
private void checkRequiredFields(Map<PropertyDescriptorField, String> valuesById) {
for (Entry<PropertyDescriptorField, Boolean> entry : expectedFields.entrySet()) {
if (entry.getValue() && StringUtil.isEmpty(valuesById.get(entry.getKey()))) {
if (entry.getValue() && isValueMissing(valuesById.get(entry.getKey()))) {
throw new RuntimeException("Missing required value for key: " + entry.getKey());
}
}
@ -249,7 +243,7 @@ public abstract class AbstractPropertyDescriptorFactory<T> implements PropertyDe
characterStr = valuesById.get(DELIMITER).trim();
}
if (StringUtil.isEmpty(characterStr)) {
if (StringUtils.isBlank(characterStr)) {
return defaultDelimiter;
}
@ -272,7 +266,7 @@ public abstract class AbstractPropertyDescriptorFactory<T> implements PropertyDe
protected static String[] minMaxFrom(Map<PropertyDescriptorField, String> valuesById) {
String min = minValueIn(valuesById);
String max = maxValueIn(valuesById);
if (StringUtil.isEmpty(min) || StringUtil.isEmpty(max)) {
if (StringUtils.isBlank(min) || StringUtils.isBlank(max)) {
throw new RuntimeException("min and max values must be specified");
}
return new String[] {min, max};
@ -291,7 +285,7 @@ public abstract class AbstractPropertyDescriptorFactory<T> implements PropertyDe
protected static String[] legalPackageNamesIn(Map<PropertyDescriptorField, String> valuesById, char delimiter) {
String names = valuesById.get(LEGAL_PACKAGES);
if (StringUtil.isEmpty(names)) {
if (StringUtils.isBlank(names)) {
return null;
}
return StringUtil.substringsOf(names, delimiter);
@ -299,18 +293,19 @@ public abstract class AbstractPropertyDescriptorFactory<T> implements PropertyDe
/**
* Returns a map describing which fields are required to build an
* 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
* @param otherValues
* @param otherKeys Additional keys
* @param otherValues Whether the corresponding keys are required or not
*
* @return
* @return The complete map of expected fields.
*/
public static Map<PropertyDescriptorField, Boolean> expectedFieldTypesWith(PropertyDescriptorField[] otherKeys,
static Map<PropertyDescriptorField, Boolean> expectedFieldTypesWith(PropertyDescriptorField[] otherKeys,
Boolean[] otherValues) {
Map<PropertyDescriptorField, Boolean> largerMap = new HashMap<>(
otherKeys.length + CORE_FIELD_TYPES_BY_KEY.size());
largerMap.putAll(CORE_FIELD_TYPES_BY_KEY);
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]);
}

View File

@ -7,8 +7,10 @@ package net.sourceforge.pmd;
import java.util.List;
/**
* Specializes property descriptors for single 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 the interface {@link PropertyDescriptor}.
* 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
* components of the list (not the type of the list). Notice that for implementors, the type parameter of this interface
* is <i>not</i> the same as the type parameter of {@link PropertyDescriptor} they inherit!
*
* @param <V> The type of value this descriptor works with. This is the type of the list's component.
*

View File

@ -9,7 +9,7 @@ import static net.sourceforge.pmd.PropertyDescriptorField.MIN;
import java.util.Map;
import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil;
import net.sourceforge.pmd.lang.rule.properties.ExpectedFieldsBuilder;
/**
* Defines a descriptor type whose instance values are required to lie within
@ -22,7 +22,7 @@ import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil;
public interface NumericPropertyDescriptor<T> extends PropertyDescriptor<T> {
Map<PropertyDescriptorField, Boolean> NUMBER_FIELD_TYPES_BY_KEY
= PropertyDescriptorUtil.expectedFields().put(MIN, true).put(MAX, true).get();
= ExpectedFieldsBuilder.instance().put(MIN, true).put(MAX, true).build();
/**

View File

@ -11,7 +11,7 @@ import static net.sourceforge.pmd.PropertyDescriptorField.NAME;
import java.util.Map;
import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil.ExpectedFieldsBuilder;
import net.sourceforge.pmd.lang.rule.properties.ExpectedFieldsBuilder;
/**
* Property value descriptor that defines the use &amp; requirements for setting
@ -35,13 +35,13 @@ import net.sourceforge.pmd.lang.rule.properties.PropertyDescriptorUtil.ExpectedF
public interface PropertyDescriptor<T> extends Comparable<PropertyDescriptor<?>> {
/** Default expected fields. Unmodifiable. */
Map<PropertyDescriptorField, Boolean> CORE_FIELD_TYPES_BY_KEY
= (new ExpectedFieldsBuilder())
Map<PropertyDescriptorField, Boolean> CORE_EXPECTED_FIELDS
= ExpectedFieldsBuilder.instance()
.put(NAME, true)
.put(DESCRIPTION, true)
.put(DEFAULT_VALUE, true)
.put(DELIMITER, false)
.get();
.build();
/**

View File

@ -16,6 +16,8 @@ import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.lang3.StringUtils;
import net.sourceforge.pmd.benchmark.Benchmark;
import net.sourceforge.pmd.benchmark.Benchmarker;
import net.sourceforge.pmd.cache.ChecksumAware;
@ -179,7 +181,7 @@ public class RuleSet implements ChecksumAware {
* @return The same builder, for a fluid programming interface
*/
public RuleSetBuilder addRuleByReference(final String ruleSetFileName, final Rule rule) {
if (StringUtil.isEmpty(ruleSetFileName)) {
if (StringUtils.isBlank(ruleSetFileName)) {
throw new RuntimeException(
"Adding a rule by reference is not allowed with an empty rule set file name.");
}
@ -246,7 +248,7 @@ public class RuleSet implements ChecksumAware {
*/
public RuleSetBuilder addRuleSetByReference(final RuleSet ruleSet, final boolean allRules,
final String... excludes) {
if (StringUtil.isEmpty(ruleSet.getFileName())) {
if (StringUtils.isBlank(ruleSet.getFileName())) {
throw new RuntimeException(
"Adding a rule by reference is not allowed with an empty rule set file name.");
}

View File

@ -4,6 +4,8 @@
package net.sourceforge.pmd;
import static net.sourceforge.pmd.PropertyDescriptorField.DEFAULT_VALUE;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
@ -23,6 +25,7 @@ import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@ -414,7 +417,7 @@ public class RuleSetFactory {
String ref = ruleElement.getAttribute("ref");
if (ref.endsWith("xml")) {
parseRuleSetReferenceNode(ruleSetReferenceId, ruleSetBuilder, ruleElement, ref);
} else if (StringUtil.isEmpty(ref)) {
} else if (StringUtils.isBlank(ref)) {
parseSingleRuleNode(ruleSetReferenceId, ruleSetBuilder, ruleNode);
} else {
parseRuleReferenceNode(ruleSetReferenceId, ruleSetBuilder, ruleNode, ref, withDeprecatedRuleReferences);
@ -812,13 +815,13 @@ public class RuleSetFactory {
Element propertyElement = (Element) propertyNode;
String typeId = propertyElement.getAttribute(PropertyDescriptorField.TYPE.attributeName());
String strValue = propertyElement.getAttribute(PropertyDescriptorField.DEFAULT_VALUE.attributeName());
if (StringUtil.isEmpty(strValue)) {
String strValue = propertyElement.getAttribute(DEFAULT_VALUE.attributeName());
if (StringUtils.isBlank(strValue)) {
strValue = valueFrom(propertyElement);
}
// Setting of existing property, or defining a new property?
if (StringUtil.isEmpty(typeId)) {
if (StringUtils.isBlank(typeId)) {
String name = propertyElement.getAttribute(PropertyDescriptorField.NAME.attributeName());
PropertyDescriptor<?> propertyDescriptor = rule.getPropertyDescriptor(name);
@ -842,9 +845,19 @@ public class RuleSetFactory {
// 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);
}
if (StringUtils.isBlank(values.get(DEFAULT_VALUE))) {
NodeList children = propertyElement.getElementsByTagName(DEFAULT_VALUE.attributeName());
if (children.getLength() == 1) {
values.put(DEFAULT_VALUE, children.item(0).getTextContent());
} else {
throw new RuntimeException("No value defined!");
}
}
// casting is not pretty but prevents the interface from having this method
PropertyDescriptor<?> desc = ((AbstractPropertyDescriptorFactory) pdFactory).createExternalWith(values);

View File

@ -408,7 +408,7 @@ public class RuleSetReferenceId {
*/
public InputStream getInputStream(ClassLoader classLoader) throws RuleSetNotFoundException {
if (externalRuleSetReferenceId == null) {
InputStream in = StringUtil.isEmpty(ruleSetFileName) ? null
InputStream in = StringUtils.isBlank(ruleSetFileName) ? null
: ResourceLoader.loadResourceAsStream(ruleSetFileName, classLoader);
if (in == null) {
throw new RuleSetNotFoundException("Can't find resource '" + ruleSetFileName + "' for rule '" + ruleName

View File

@ -9,6 +9,8 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import net.sourceforge.pmd.PropertyDescriptorFactory;
import net.sourceforge.pmd.PropertyDescriptorField;
import net.sourceforge.pmd.lang.rule.properties.ValueParser.Companion;
@ -28,7 +30,7 @@ public final class CharacterMultiProperty extends AbstractMultiValueProperty<Cha
@Override
protected boolean isValueMissing(String value) {
return StringUtil.isMissing(value);
return StringUtils.isEmpty(value);
}
@Override

View File

@ -8,6 +8,8 @@ import static net.sourceforge.pmd.lang.rule.properties.ValueParser.CHARACTER_PAR
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import net.sourceforge.pmd.PropertyDescriptorFactory;
import net.sourceforge.pmd.PropertyDescriptorField;
import net.sourceforge.pmd.util.StringUtil;
@ -25,7 +27,7 @@ public final class CharacterProperty extends AbstractSingleValueProperty<Charact
@Override
protected boolean isValueMissing(String value) {
return StringUtil.isMissing(value);
return StringUtils.isEmpty(value);
}
@Override

View File

@ -21,18 +21,18 @@ import net.sourceforge.pmd.PropertyDescriptorField;
*/
public final class DoubleProperty extends AbstractNumericProperty<Double> {
/** Factory. */
public static final PropertyDescriptorFactory<Double> FACTORY // @formatter:off
= new SingleValuePropertyDescriptorFactory<Double>(Double.class, NUMBER_FIELD_TYPES_BY_KEY) {
@Override
public DoubleProperty createWith(Map<PropertyDescriptorField, String> valuesById,
boolean isDefinedExternally) {
final String[] minMax = minMaxFrom(valuesById);
System.out.println(Arrays.asList(minMax));
return new DoubleProperty(nameIn(valuesById),
descriptionIn(valuesById),
DOUBLE_PARSER.valueOf(minMax[0]),
DOUBLE_PARSER.valueOf(minMax[1]),
DOUBLE_PARSER.valueOf(defaultValueIn(valuesById)),
doubleFrom(minMax[0]),
doubleFrom(minMax[1]),
doubleFrom(defaultValueIn(valuesById)),
0f,
isDefinedExternally);
}
@ -73,8 +73,8 @@ public final class DoubleProperty extends AbstractNumericProperty<Double> {
*
* @return Parsed Double
*/
public static Double doubleFrom(String numberString) {
return Double.valueOf(numberString);
private static Double doubleFrom(String numberString) {
return DOUBLE_PARSER.valueOf(numberString);
}

View File

@ -0,0 +1,59 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.rule.properties;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import net.sourceforge.pmd.PropertyDescriptorField;
/** Builder for an expected fields map. */
public final class ExpectedFieldsBuilder {
private final Map<PropertyDescriptorField, Boolean> 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<PropertyDescriptorField, Boolean> 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();
}
}

View File

@ -92,4 +92,6 @@ public final class FloatProperty extends AbstractNumericProperty<Float> {
protected Float createFrom(String value) {
return FLOAT_PARSER.valueOf(value);
}
}

View File

@ -19,6 +19,7 @@ import net.sourceforge.pmd.PropertyDescriptorField;
*/
public final class IntegerProperty extends AbstractNumericProperty<Integer> {
/** Factory. */
public static final PropertyDescriptorFactory<Integer> FACTORY // @formatter:off
= new SingleValuePropertyDescriptorFactory<Integer>(Integer.class, NUMBER_FIELD_TYPES_BY_KEY) {
@ -36,11 +37,6 @@ public final class IntegerProperty extends AbstractNumericProperty<Integer> {
}; // @formatter:on
static {
System.err.println(FACTORY);
}
/**
* Constructor that limits itself to a single value within the specified limits.
*

View File

@ -9,7 +9,6 @@ import java.util.HashMap;
import java.util.Map;
import net.sourceforge.pmd.PropertyDescriptorFactory;
import net.sourceforge.pmd.PropertyDescriptorField;
/**
* Utility class allowing to find the factory of a specific type of descriptor. That's used to define descriptors in
@ -24,7 +23,6 @@ public final class PropertyDescriptorUtil {
static {
Map<String, PropertyDescriptorFactory<?>> temp = new HashMap<>(18);
temp.put("Boolean", BooleanProperty.FACTORY);
temp.put("List<Boolean>", BooleanMultiProperty.FACTORY);
@ -33,6 +31,7 @@ public final class PropertyDescriptorUtil {
temp.put("Character", CharacterProperty.FACTORY);
temp.put("List<Character>", CharacterMultiProperty.FACTORY);
temp.put("Integer", IntegerProperty.FACTORY);
temp.put("List<Integer>", IntegerMultiProperty.FACTORY);
temp.put("Long", LongProperty.FACTORY);
@ -41,7 +40,6 @@ public final class PropertyDescriptorUtil {
temp.put("List<Float>", FloatMultiProperty.FACTORY);
temp.put("Double", DoubleProperty.FACTORY);
temp.put("List<Double>", DoubleMultiProperty.FACTORY);
// temp.put("Enum", EnumeratedProperty.FACTORY); // TODO:cf implement that
// temp.put("List<Enum>", EnumeratedMultiProperty.FACTORY);
@ -90,52 +88,4 @@ public final class PropertyDescriptorUtil {
}
/**
* Gets a builder for a required fields map.
*
* @return A builder
*
* @see ExpectedFieldsBuilder
*/
public static ExpectedFieldsBuilder expectedFields() {
return new ExpectedFieldsBuilder();
}
/** Builder for an expected fields map. */
public static final class ExpectedFieldsBuilder {
Map<PropertyDescriptorField, Boolean> requiredFields = new HashMap<>();
public 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<PropertyDescriptorField, Boolean> get() {
return Collections.unmodifiableMap(requiredFields);
}
}
}

View File

@ -10,6 +10,8 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import net.sourceforge.pmd.PropertyDescriptorFactory;
import net.sourceforge.pmd.PropertyDescriptorField;
import net.sourceforge.pmd.lang.rule.properties.ValueParser.Companion;
@ -30,7 +32,7 @@ public final class StringMultiProperty extends AbstractMultiValueProperty<String
@Override
protected boolean isValueMissing(String value) {
return StringUtil.isMissing(value);
return StringUtils.isEmpty(value);
}
@Override

View File

@ -6,6 +6,8 @@ package net.sourceforge.pmd.lang.rule.properties;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import net.sourceforge.pmd.PropertyDescriptorFactory;
import net.sourceforge.pmd.PropertyDescriptorField;
import net.sourceforge.pmd.util.StringUtil;
@ -24,7 +26,7 @@ public final class StringProperty extends AbstractSingleValueProperty<String> {
@Override
protected boolean isValueMissing(String value) {
return StringUtil.isMissing(value);
return StringUtils.isEmpty(value);
}
@Override

View File

@ -8,6 +8,8 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
/**
* A number of String-specific utility methods for use by PMD or its IDE
* plugins.
@ -100,14 +102,14 @@ public final class StringUtil {
/**
* Returns true if the value arg is either null, empty, or full of
* whitespace characters. More efficient that calling
* (string).trim().length() == 0
* (string).trim().length() == 0.
*
* @param value
* @param value String to test
*
* @return <code>true</code> if the value is empty, <code>false</code> otherwise.
*/
public static boolean isEmpty(String value) {
return isMissing(value) || nullSafeIsBlank(value);
return StringUtils.isBlank(value);
}
@ -119,41 +121,7 @@ public final class StringUtil {
* @return True if the argument is null or the empty string
*/
public static boolean isMissing(String value) {
if (value == null || "".equals(value)) {
return true;
}
return false;
}
/** Argument must not be null. */
private static boolean nullSafeIsBlank(String value) {
for (int i = 0; i < value.length(); i++) {
if (!Character.isWhitespace(value.charAt(i))) {
return false;
}
}
return true;
}
/**
* Returns true if the argument is null or entirely composed of whitespace characters.
*
* @param value String to test
*
* @return True if the argument is null or entirely composed of whitespace characters.
*/
public static boolean isBlank(String value) {
if (value == null) {
return true;
}
return nullSafeIsBlank(value);
return StringUtils.isEmpty(value);
}