Move towards java7 compat
This commit is contained in:
@ -16,6 +16,8 @@ import net.sourceforge.pmd.lang.apex.metrics.api.ApexOperationMetricKey;
|
|||||||
import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule;
|
import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule;
|
||||||
import net.sourceforge.pmd.lang.metrics.ResultOption;
|
import net.sourceforge.pmd.lang.metrics.ResultOption;
|
||||||
import net.sourceforge.pmd.properties.IntegerProperty;
|
import net.sourceforge.pmd.properties.IntegerProperty;
|
||||||
|
import net.sourceforge.pmd.properties.newframework.PropertyDescriptor;
|
||||||
|
import net.sourceforge.pmd.properties.newframework.PropertyFactory;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,8 +27,8 @@ import net.sourceforge.pmd.properties.IntegerProperty;
|
|||||||
*/
|
*/
|
||||||
public class CyclomaticComplexityRule extends AbstractApexRule {
|
public class CyclomaticComplexityRule extends AbstractApexRule {
|
||||||
|
|
||||||
private static final IntegerProperty CLASS_LEVEL_DESCRIPTOR
|
private static final PropertyDescriptor<Integer> CLASS_LEVEL_DESCRIPTOR
|
||||||
= IntegerProperty.named("classReportLevel")
|
= PropertyFactory.intProperty("classReportLevel")
|
||||||
.desc("Total class complexity reporting threshold")
|
.desc("Total class complexity reporting threshold")
|
||||||
.range(1, 200)
|
.range(1, 200)
|
||||||
.defaultValue(40)
|
.defaultValue(40)
|
||||||
|
@ -14,8 +14,9 @@ import java.util.stream.Collectors;
|
|||||||
* @author Clément Fournier
|
* @author Clément Fournier
|
||||||
* @since 6.7.0
|
* @since 6.7.0
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractPropertyDescriptor<T> implements PropertyDescriptor<T> {
|
abstract class AbstractGenericPropertyDescriptor<T> implements PropertyDescriptor<T> {
|
||||||
|
|
||||||
|
protected final T defaultValue;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final String description;
|
private final String description;
|
||||||
private final float uiOrder;
|
private final float uiOrder;
|
||||||
@ -23,13 +24,16 @@ public abstract class AbstractPropertyDescriptor<T> implements PropertyDescripto
|
|||||||
private final Class<?> type;
|
private final Class<?> type;
|
||||||
|
|
||||||
|
|
||||||
protected AbstractPropertyDescriptor(String name,
|
protected AbstractGenericPropertyDescriptor(String name,
|
||||||
String description,
|
String description,
|
||||||
float uiOrder,
|
float uiOrder,
|
||||||
Set<PropertyValidator<T>> validators, Class<?> type) {
|
T defaultValue,
|
||||||
|
Set<PropertyValidator<T>> validators,
|
||||||
|
Class<?> type) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.uiOrder = uiOrder;
|
this.uiOrder = uiOrder;
|
||||||
|
this.defaultValue = defaultValue;
|
||||||
this.validators = validators;
|
this.validators = validators;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
@ -53,6 +57,12 @@ public abstract class AbstractPropertyDescriptor<T> implements PropertyDescripto
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T getDefaultValue() {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getErrorMessagesFor(T value) {
|
public List<String> getErrorMessagesFor(T value) {
|
||||||
return validators.stream()
|
return validators.stream()
|
@ -1,76 +0,0 @@
|
|||||||
/**
|
|
||||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.sourceforge.pmd.properties.newframework;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Clément Fournier
|
|
||||||
* @since 6.7.0
|
|
||||||
*/
|
|
||||||
public abstract class AbstractMultiValuePropertyBuilder<B extends AbstractPropertyBuilder<B, List<V>>, V> extends AbstractPropertyBuilder<B, List<V>> {
|
|
||||||
private final Set<PropertyValidator<V>> componentValidators = new LinkedHashSet<>();
|
|
||||||
private final Function<String, V> parser;
|
|
||||||
private final Class<V> type;
|
|
||||||
|
|
||||||
private List<V> defaultValues;
|
|
||||||
|
|
||||||
|
|
||||||
AbstractMultiValuePropertyBuilder(String name, Function<String, V> parser, Class<V> type) {
|
|
||||||
super(name);
|
|
||||||
this.parser = parser;
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify a default value.
|
|
||||||
*
|
|
||||||
* @param val List of values
|
|
||||||
*
|
|
||||||
* @return The same builder
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public B defaultValues(Collection<? extends V> val) {
|
|
||||||
this.defaultValues = new ArrayList<>(val);
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify default values.
|
|
||||||
*
|
|
||||||
* @param val List of values
|
|
||||||
*
|
|
||||||
* @return The same builder
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public B defaultValues(V... val) {
|
|
||||||
this.defaultValues = Arrays.asList(val);
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PropertyDescriptor<List<V>> build() {
|
|
||||||
return new MultiValuePropertyDescriptor<>(
|
|
||||||
name,
|
|
||||||
description,
|
|
||||||
uiOrder,
|
|
||||||
defaultValues,
|
|
||||||
validators,
|
|
||||||
componentValidators,
|
|
||||||
parser,
|
|
||||||
type
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,27 +4,40 @@
|
|||||||
|
|
||||||
package net.sourceforge.pmd.properties.newframework;
|
package net.sourceforge.pmd.properties.newframework;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Function;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import net.sourceforge.pmd.properties.ValueParser;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Base class for generic property builders.
|
||||||
|
*
|
||||||
|
* @param <B> Concrete type of this builder instance
|
||||||
|
* @param <T> Type of values the property handles
|
||||||
|
*
|
||||||
* @author Clément Fournier
|
* @author Clément Fournier
|
||||||
* @since 6.7.0
|
* @since 6.7.0
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractPropertyBuilder<B extends AbstractPropertyBuilder<B, T>, T> {
|
public abstract class AbstractPropertyBuilder<B extends AbstractPropertyBuilder<B, T>, T> {
|
||||||
private static final Pattern NAME_PATTERN = Pattern.compile("[a-zA-Z][\\w-]*");
|
private static final Pattern NAME_PATTERN = Pattern.compile("[a-zA-Z][\\w-]*");
|
||||||
protected final Set<PropertyValidator<T>> validators = new LinkedHashSet<>();
|
private final Set<PropertyValidator<T>> validators = new LinkedHashSet<>();
|
||||||
protected String name;
|
private String name;
|
||||||
protected String description;
|
private String description;
|
||||||
protected float uiOrder = 0f;
|
private float uiOrder = 0f;
|
||||||
|
private T defaultValue;
|
||||||
|
|
||||||
|
|
||||||
public AbstractPropertyBuilder(String name) {
|
AbstractPropertyBuilder(String name) {
|
||||||
|
|
||||||
if (StringUtils.isBlank(name)) {
|
if (StringUtils.isBlank(name)) {
|
||||||
throw new IllegalArgumentException("Name must be provided");
|
throw new IllegalArgumentException("Name must be provided");
|
||||||
} else if (!NAME_PATTERN.matcher(name).matches()) {
|
} else if (!NAME_PATTERN.matcher(name).matches()) {
|
||||||
@ -34,6 +47,26 @@ public abstract class AbstractPropertyBuilder<B extends AbstractPropertyBuilder<
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Set<PropertyValidator<T>> getValidators() {
|
||||||
|
return validators;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float getUiOrder() {
|
||||||
|
return uiOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
T getDefaultValue() {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the description of the property.
|
* Specify the description of the property.
|
||||||
*
|
*
|
||||||
@ -66,8 +99,22 @@ public abstract class AbstractPropertyBuilder<B extends AbstractPropertyBuilder<
|
|||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected B addValidator(Predicate<T> pred, String errorMessage) {
|
B addValidator(PropertyValidator<T> validator) {
|
||||||
validators.add(PropertyValidator.fromPredicate(pred, errorMessage));
|
validators.add(validator);
|
||||||
|
return (B) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify a default value.
|
||||||
|
*
|
||||||
|
* @param val Value
|
||||||
|
*
|
||||||
|
* @return The same builder
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public B defaultValue(T val) {
|
||||||
|
this.defaultValue = val;
|
||||||
return (B) this;
|
return (B) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,4 +135,117 @@ public abstract class AbstractPropertyBuilder<B extends AbstractPropertyBuilder<
|
|||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder for a generic single-value property.
|
||||||
|
*
|
||||||
|
* <p>This class is abstract because the B type parameter
|
||||||
|
* prevents it to be instantiated anyway. That type parameter
|
||||||
|
* is of use to more refined concrete subclasses.
|
||||||
|
*
|
||||||
|
* @param <B> Concrete type of this builder instance
|
||||||
|
* @param <T> Type of values the property handles
|
||||||
|
*
|
||||||
|
* @author Clément Fournier
|
||||||
|
* @since 6.7.0
|
||||||
|
*/
|
||||||
|
public abstract static class GenericPropertyBuilder<B extends GenericPropertyBuilder<B, T>, T> extends AbstractPropertyBuilder<B, T> {
|
||||||
|
|
||||||
|
|
||||||
|
private final ValueParser<T> parser;
|
||||||
|
private final Class<T> type;
|
||||||
|
|
||||||
|
|
||||||
|
GenericPropertyBuilder(String name, ValueParser<T> parser, Class<T> type) {
|
||||||
|
super(name);
|
||||||
|
this.parser = parser;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PropertyDescriptor<T> build() {
|
||||||
|
return new GenericPropertyDescriptor<>(
|
||||||
|
getName(),
|
||||||
|
getDescription(),
|
||||||
|
getUiOrder(),
|
||||||
|
getDefaultValue(),
|
||||||
|
getValidators(),
|
||||||
|
parser,
|
||||||
|
type
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder for a generic multi-value property.
|
||||||
|
*
|
||||||
|
* <p>This class is abstract because the B type parameter
|
||||||
|
* prevents it to be instantiated anyway. That type parameter
|
||||||
|
* is of use to more refined concrete subclasses.
|
||||||
|
*
|
||||||
|
* @param <B> Concrete type of this builder instance
|
||||||
|
* @param <V> Type of values the property handles. This is the component type of the list
|
||||||
|
*
|
||||||
|
* @author Clément Fournier
|
||||||
|
* @since 6.7.0
|
||||||
|
*/
|
||||||
|
public abstract static class AbstractGenericMultiPropertyBuilder<B extends AbstractPropertyBuilder<B, List<V>>, V> extends AbstractPropertyBuilder<B, List<V>> {
|
||||||
|
private final Set<PropertyValidator<V>> componentValidators = new LinkedHashSet<>();
|
||||||
|
private final Function<String, V> parser;
|
||||||
|
private final Class<V> type;
|
||||||
|
|
||||||
|
|
||||||
|
AbstractGenericMultiPropertyBuilder(String name, Function<String, V> parser, Class<V> type) {
|
||||||
|
super(name);
|
||||||
|
this.parser = parser;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify a default value.
|
||||||
|
*
|
||||||
|
* @param val List of values
|
||||||
|
*
|
||||||
|
* @return The same builder
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public B defaultValues(Collection<? extends V> val) {
|
||||||
|
super.defaultValue(new ArrayList<>(val));
|
||||||
|
return (B) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify default values.
|
||||||
|
*
|
||||||
|
* @param val List of values
|
||||||
|
*
|
||||||
|
* @return The same builder
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public B defaultValues(V... val) {
|
||||||
|
super.defaultValue(Arrays.asList(val));
|
||||||
|
return (B) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PropertyDescriptor<List<V>> build() {
|
||||||
|
return new GenericMultiValuePropertyDescriptor<>(
|
||||||
|
getName(),
|
||||||
|
getDescription(),
|
||||||
|
getUiOrder(),
|
||||||
|
getDefaultValue(),
|
||||||
|
getValidators(),
|
||||||
|
componentValidators,
|
||||||
|
parser,
|
||||||
|
type
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
/**
|
|
||||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.sourceforge.pmd.properties.newframework;
|
|
||||||
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Clément Fournier
|
|
||||||
* @since 6.7.0
|
|
||||||
*/
|
|
||||||
public abstract class AbstractSingleValuePropertyBuilder<B extends AbstractSingleValuePropertyBuilder<B, T>, T> extends AbstractPropertyBuilder<B, T> {
|
|
||||||
|
|
||||||
|
|
||||||
private final Function<String, T> parser;
|
|
||||||
private final Class<T> type;
|
|
||||||
|
|
||||||
private T defaultValue;
|
|
||||||
|
|
||||||
|
|
||||||
AbstractSingleValuePropertyBuilder(String name, Function<String, T> parser, Class<T> type) {
|
|
||||||
super(name);
|
|
||||||
this.parser = parser;
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PropertyDescriptor<T> build() {
|
|
||||||
return new SingleValuePropertyDescriptor<>(
|
|
||||||
name,
|
|
||||||
description,
|
|
||||||
uiOrder,
|
|
||||||
defaultValue,
|
|
||||||
validators,
|
|
||||||
parser,
|
|
||||||
type
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify a default value.
|
|
||||||
*
|
|
||||||
* @param val Value
|
|
||||||
*
|
|
||||||
* @return The same builder
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public B defaultValue(T val) {
|
|
||||||
this.defaultValue = val;
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the name of the property to be built.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
package net.sourceforge.pmd.properties.newframework;
|
package net.sourceforge.pmd.properties.newframework;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -15,22 +16,20 @@ import java.util.stream.Collectors;
|
|||||||
* @author Clément Fournier
|
* @author Clément Fournier
|
||||||
* @since 6.7.0
|
* @since 6.7.0
|
||||||
*/
|
*/
|
||||||
final class MultiValuePropertyDescriptor<V> extends AbstractPropertyDescriptor<List<V>> {
|
final class GenericMultiValuePropertyDescriptor<V> extends AbstractGenericPropertyDescriptor<List<V>> {
|
||||||
|
|
||||||
|
|
||||||
private final List<V> defaultValue;
|
|
||||||
private final Set<PropertyValidator<V>> componentValidators;
|
private final Set<PropertyValidator<V>> componentValidators;
|
||||||
private final Function<String, V> parser;
|
private final Function<String, V> parser;
|
||||||
|
|
||||||
|
|
||||||
MultiValuePropertyDescriptor(String name, String description, float uiOrder,
|
GenericMultiValuePropertyDescriptor(String name, String description, float uiOrder,
|
||||||
List<V> defaultValue,
|
List<V> defaultValue,
|
||||||
Set<PropertyValidator<List<V>>> listValidators,
|
Set<PropertyValidator<List<V>>> listValidators,
|
||||||
Set<PropertyValidator<V>> componentValidators,
|
Set<PropertyValidator<V>> componentValidators,
|
||||||
Function<String, V> parser,
|
Function<String, V> parser,
|
||||||
Class<V> type) {
|
Class<V> type) {
|
||||||
super(name, description, uiOrder, listValidators, type);
|
super(name, description, uiOrder, defaultValue, listValidators, type);
|
||||||
this.defaultValue = defaultValue;
|
|
||||||
this.componentValidators = componentValidators;
|
this.componentValidators = componentValidators;
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
}
|
}
|
||||||
@ -44,7 +43,7 @@ final class MultiValuePropertyDescriptor<V> extends AbstractPropertyDescriptor<L
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<V> getDefaultValue() {
|
public List<V> getDefaultValue() {
|
||||||
return defaultValue;
|
return Collections.unmodifiableList(defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sourceforge.pmd.properties.newframework;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.sourceforge.pmd.properties.ValueParser;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Clément Fournier
|
||||||
|
* @since 6.7.0
|
||||||
|
*/
|
||||||
|
final class GenericPropertyDescriptor<T> extends AbstractGenericPropertyDescriptor<T> {
|
||||||
|
|
||||||
|
|
||||||
|
private final ValueParser<T> parser;
|
||||||
|
|
||||||
|
|
||||||
|
GenericPropertyDescriptor(String name,
|
||||||
|
String description,
|
||||||
|
float uiOrder,
|
||||||
|
T defaultValue,
|
||||||
|
Set<PropertyValidator<T>> validators,
|
||||||
|
ValueParser<T> parser,
|
||||||
|
Class<T> type) {
|
||||||
|
super(name, description, uiOrder, defaultValue, validators, type);
|
||||||
|
this.parser = parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isMultiValue() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T valueFrom(List<String> valuesList) throws IllegalArgumentException {
|
||||||
|
if (valuesList.size() != 1) {
|
||||||
|
throw new IllegalArgumentException("This property can only handle a single value, but " + valuesList.size() + " was supplied");
|
||||||
|
}
|
||||||
|
|
||||||
|
return parser.valueOf(valuesList.get(0));
|
||||||
|
}
|
||||||
|
}
|
@ -4,10 +4,11 @@
|
|||||||
|
|
||||||
package net.sourceforge.pmd.properties.newframework;
|
package net.sourceforge.pmd.properties.newframework;
|
||||||
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.EnumUtils;
|
import org.apache.commons.lang3.EnumUtils;
|
||||||
|
|
||||||
|
import net.sourceforge.pmd.properties.ValueParser;
|
||||||
|
import net.sourceforge.pmd.properties.newframework.AbstractPropertyBuilder.GenericPropertyBuilder;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Clément Fournier
|
* @author Clément Fournier
|
||||||
@ -20,38 +21,42 @@ public final class PropertyFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static <T extends Enum<T>> T enumConstantFromEnum(Class<T> enumClass, String name) {
|
||||||
|
return EnumUtils.getEnumList(enumClass).stream()
|
||||||
|
.filter(e -> e.name().equalsIgnoreCase(name))
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow(() -> new IllegalArgumentException("The name '" + name + "' doesn't correspond to any constant in the enum '" + enumClass.getName() + "'"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static NumericPropertyBuilder<Integer> intProperty(String name) {
|
public static NumericPropertyBuilder<Integer> intProperty(String name) {
|
||||||
return new NumericPropertyBuilder<>(name, Integer::valueOf, Integer.class);
|
return new NumericPropertyBuilder<>(name, Integer::valueOf, Integer.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO need a way to document the possible values
|
|
||||||
public static <T extends Enum<T>> GenericPBuilder<T> enumProperty(String name, Class<T> enumClass) {
|
public static <T extends Enum<T>> GenericPBuilder<T> enumProperty(String name, Class<T> enumClass) {
|
||||||
return new GenericPBuilder<>(name, s ->
|
return new GenericPBuilder<>(name, s -> enumConstantFromEnum(enumClass, s), enumClass);
|
||||||
EnumUtils.getEnumList(enumClass).stream()
|
|
||||||
.filter(e -> e.name().equalsIgnoreCase(s))
|
|
||||||
.findFirst()
|
|
||||||
.orElseThrow(() -> new IllegalArgumentException("The name '" + s + "' doesn't correspond to any constant in the enum '" + enumClass.getName() + "'"))
|
|
||||||
, enumClass);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// removes the other type parameter
|
// removes the other type parameter
|
||||||
public static class GenericPBuilder<T> extends AbstractSingleValuePropertyBuilder<GenericPBuilder<T>, T> {
|
public static class GenericPBuilder<T> extends GenericPropertyBuilder<GenericPBuilder<T>, T> {
|
||||||
|
|
||||||
GenericPBuilder(String name, Function<String, T> parser, Class<T> type) {
|
GenericPBuilder(String name, ValueParser<T> parser, Class<T> type) {
|
||||||
super(name, parser, type);
|
super(name, parser, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class NumericPropertyBuilder<N extends Number> extends AbstractSingleValuePropertyBuilder<NumericPropertyBuilder<N>, N> {
|
public static class NumericPropertyBuilder<N extends Number> extends GenericPropertyBuilder<NumericPropertyBuilder<N>, N> {
|
||||||
|
|
||||||
NumericPropertyBuilder(String name, Function<String, N> parser, Class<N> type) {
|
NumericPropertyBuilder(String name, ValueParser<N> parser, Class<N> type) {
|
||||||
super(name, parser, type);
|
super(name, parser, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public NumericPropertyBuilder<N> requirePositive() {
|
// TODO rename
|
||||||
return addValidator(n -> n.intValue() > 0, "Expected a positive number");
|
public NumericPropertyBuilder<N> range(N min, N max) {
|
||||||
|
return addValidator(Validators.rangeValidator(min, max));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,22 +5,42 @@
|
|||||||
package net.sourceforge.pmd.properties.newframework;
|
package net.sourceforge.pmd.properties.newframework;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Validates the value of a property.
|
||||||
|
*
|
||||||
|
* @param <T> Type of value to handle
|
||||||
|
*
|
||||||
* @author Clément Fournier
|
* @author Clément Fournier
|
||||||
* @since 6.7.0
|
* @since 6.7.0
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
|
||||||
public interface PropertyValidator<T> {
|
public interface PropertyValidator<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a diagnostic message if the value
|
||||||
|
* has a problem. Otherwise returns an empty
|
||||||
|
* optional.
|
||||||
|
*
|
||||||
|
* @param value The value to validate
|
||||||
|
*
|
||||||
|
* @return An optional diagnostic message
|
||||||
|
*/
|
||||||
Optional<String> validate(T value);
|
Optional<String> validate(T value);
|
||||||
|
|
||||||
|
|
||||||
static <U> PropertyValidator<U> fromPredicate(Predicate<U> pred, String failureMessage) {
|
/**
|
||||||
return u -> pred.test(u) ? Optional.empty() : Optional.of(failureMessage);
|
* Returns a description of the constraint
|
||||||
}
|
* imposed by this validator on the values.
|
||||||
|
* E.g. "The value should be positive", or
|
||||||
|
* "The value should be one of A | B | C."
|
||||||
|
*
|
||||||
|
* @return A description of the constraint
|
||||||
|
*/
|
||||||
|
String getConstraintDescription();
|
||||||
|
|
||||||
|
|
||||||
|
// TODO Java 8 move PropertyFactory#fromPredicate here
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
/**
|
|
||||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.sourceforge.pmd.properties.newframework;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Clément Fournier
|
|
||||||
* @since 6.7.0
|
|
||||||
*/
|
|
||||||
final class SingleValuePropertyDescriptor<T> extends AbstractPropertyDescriptor<T> {
|
|
||||||
|
|
||||||
|
|
||||||
private final T defaultValue;
|
|
||||||
private final Function<String, T> parser;
|
|
||||||
|
|
||||||
|
|
||||||
SingleValuePropertyDescriptor(String name, String description, float uiOrder,
|
|
||||||
T defaultValue,
|
|
||||||
Set<PropertyValidator<T>> validators,
|
|
||||||
Function<String, T> parser,
|
|
||||||
Class<T> type) {
|
|
||||||
super(name, description, uiOrder, validators, type);
|
|
||||||
this.defaultValue = defaultValue;
|
|
||||||
this.parser = parser;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isMultiValue() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T getDefaultValue() {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T valueFrom(List<String> valuesList) throws IllegalArgumentException {
|
|
||||||
if (valuesList.size() != 1) {
|
|
||||||
throw new IllegalArgumentException("This property can only handle a single value, but " + valuesList.size() + " was supplied");
|
|
||||||
}
|
|
||||||
|
|
||||||
return parser.apply(valuesList.get(0));
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,70 @@
|
|||||||
|
/**
|
||||||
|
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sourceforge.pmd.properties.newframework;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transitional class to make up for the absence of lambdas until we move to Java 8.
|
||||||
|
*
|
||||||
|
* @author Clément Fournier
|
||||||
|
* @since 6.7.0
|
||||||
|
*/
|
||||||
|
final class Validators {
|
||||||
|
|
||||||
|
private Validators() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static <T extends Number> PropertyValidator<T> rangeValidator(T min, T max) {
|
||||||
|
return fromPredicate(new Predicate<T>() {
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
|
return min.doubleValue() < t.doubleValue() && max.doubleValue() > t.doubleValue();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Should be between " + min + " and " + max
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds a new validator from a predicate,
|
||||||
|
* and documentation messages.
|
||||||
|
*
|
||||||
|
* @param pred The predicate. If it returns
|
||||||
|
* false on a value, then the
|
||||||
|
* value is deemed to have a
|
||||||
|
* problem and the failureMessage
|
||||||
|
* will be transmitted.
|
||||||
|
* @param constraintDescription Description of the constraint,
|
||||||
|
* see {@link PropertyValidator#getConstraintDescription()}.
|
||||||
|
* @param <U> Type of value to validate
|
||||||
|
*
|
||||||
|
* @return A new validator
|
||||||
|
*/
|
||||||
|
private static <U> PropertyValidator<U> fromPredicate(Predicate<U> pred, String constraintDescription) {
|
||||||
|
return new PropertyValidator<U>() {
|
||||||
|
@Override
|
||||||
|
public Optional<String> validate(U value) {
|
||||||
|
return pred.test(value) ? Optional.empty() : Optional.of("Constraint violated on value '" + value + "' (" + constraintDescription + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getConstraintDescription() {
|
||||||
|
return constraintDescription;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Until we have Java 8
|
||||||
|
interface Predicate<T> {
|
||||||
|
boolean test(T t);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user