/**
* Copyright (c) 2014-2017 by the respective copyright holders.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.config.core;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
/**
* The {@link ConfigDescriptionParameter} class contains the description of a
* concrete configuration parameter. Such parameter descriptions are collected
* within the {@link ConfigDescription} and can be retrieved from the {@link ConfigDescriptionRegistry}.
*
* @author Michael Grammling - Initial Contribution
* @author Alex Tugarev - Added options, filter criteria, and more parameter
* attributes
* @author Chris Jackson - Added groupId, limitToOptions, advanced,
* multipleLimit, verify attributes
* @author Christoph Knauf - Added default constructor, changed Boolean
* getter to return primitive types
* @author Thomas Höfer - Added unit
*/
public class ConfigDescriptionParameter {
/**
* The {@link Type} defines an enumeration of all supported data types a
* configuration parameter can take.
*
* @author Michael Grammling - Initial Contribution
*/
public enum Type {
/**
* The data type for a UTF8 text value.
*/
TEXT,
/**
* The data type for a signed integer value in the range of [ {@link Integer#MIN_VALUE},
* {@link Integer#MAX_VALUE}].
*/
INTEGER,
/**
* The data type for a signed floating point value (IEEE 754) in the
* range of [{@link Float#MIN_VALUE}, {@link Float#MAX_VALUE}].
*/
DECIMAL,
/**
* The data type for a boolean ({@code true} or {@code false}).
*/
BOOLEAN;
}
private String name;
private Type type;
private String groupName;
private BigDecimal min;
private BigDecimal max;
private BigDecimal step;
private String pattern;
private boolean required = false;
private boolean readOnly = false;
private boolean multiple = false;
private Integer multipleLimit;
private String unit;
private String unitLabel;
private String context;
private String defaultValue;
private String label;
private String description;
private List<ParameterOption> options = new ArrayList<ParameterOption>();
private List<FilterCriteria> filterCriteria = new ArrayList<FilterCriteria>();
private boolean limitToOptions = false;
private boolean advanced = false;
private boolean verify = false;
private static final Set<String> UNITS = Collections
.unmodifiableSet(new HashSet<String>(Arrays.asList("A", "cd", "K", "kg", "m", "mol", "s", "g", "rad", "sr",
"Hz", "N", "Pa", "J", "W", "C", "V", "F", "Ω", "S", "Wb", "T", "H", "Cel", "lm", "lx", "Bq", "Gy",
"Sv", "kat", "m/s2", "m2v", "m3", "kph", "%", "l", "min", "h", "d", "week", "y")));
/**
* Default constructor.
*
*/
public ConfigDescriptionParameter() {
}
/**
* Creates a new instance of this class with the specified parameters.
*
* @param name
* the name of the configuration parameter (must neither be null
* nor empty)
* @param type
* the data type of the configuration parameter (must not be
* null)
*
* @throws IllegalArgumentException
* if the name is null or empty, or the type is null
*/
public ConfigDescriptionParameter(String name, Type type) throws IllegalArgumentException {
this(name, type, null, null, null, null, false, false, false, null, null, null, null, null, null, null, false,
true, null, null, null, false);
}
/**
* Creates a new instance of this class with the specified parameters.
*
* @param name
* the name of the configuration parameter (must neither be null
* nor empty)
* @param type
* the data type of the configuration parameter (nullable)
* @param minimum
* the minimal value for numeric types, or the minimal length of
* strings, or the minimal number of selected options (nullable)
* @param maximum
* the maximal value for numeric types, or the maximal length of
* strings, or the maximal number of selected options (nullable)
* @param stepsize
* the value granularity for a numeric value (nullable)
* @param pattern
* the regular expression for a text type (nullable)
* @param required
* specifies whether the value is required
* @param readOnly
* specifies whether the value is read-only
* @param multiple
* specifies whether multiple selections of options are allowed
* @param context
* the context of the configuration parameter (can be null or
* empty)
* @param defaultValue
* the default value of the configuration parameter (can be null)
* @param label
* a human readable label for the configuration parameter (can be
* null or empty)
* @param description
* a human readable description for the configuration parameter
* (can be null or empty)
* @param filterCriteria
* a list of filter criteria for values of a dynamic selection
* list (nullable)
* @param options
* a list of element definitions of a static selection list
* (nullable)
* @param groupName
* a string used to group parameters together into logical blocks
* so that the UI can display them together
* @param advanced
* specifies if this is an advanced parameter. An advanced
* parameter can be hidden in the UI to focus the user on
* important configuration
* @param limitToOptions
* specifies that the users input is limited to the options list.
* When set to true without options, this should have no affect.
* When set to true with options, the user can only select the
* options from the list When set to false with options, the user
* can enter values other than those in the list
* @param multipleLimit
* specifies the maximum number of options that can be selected
* when multiple is true
* @param unit
* specifies the unit of measurements for the configuration parameter (nullable)
* @param unitLabel
* specifies the unit label for the configuration parameter. This attribute can also be used to provide
* natural language units as iterations, runs, etc.
*
* @throws IllegalArgumentException
* <ul>
* <li>if the name is null or empty, or the type is null</li>
* <li>if a unit or a unit label is provided for a parameter having type text or boolean</li>
* <li>if an invalid unit was given (cp.
* https://www.eclipse.org/smarthome/documentation/development/bindings/xml-reference.html for the list
* of valid units)</li>
* </ul>
*/
ConfigDescriptionParameter(String name, Type type, BigDecimal minimum, BigDecimal maximum, BigDecimal stepsize,
String pattern, Boolean required, Boolean readOnly, Boolean multiple, String context, String defaultValue,
String label, String description, List<ParameterOption> options, List<FilterCriteria> filterCriteria,
String groupName, Boolean advanced, Boolean limitToOptions, Integer multipleLimit, String unit,
String unitLabel, Boolean verify) throws IllegalArgumentException {
if ((name == null) || (name.isEmpty())) {
throw new IllegalArgumentException("The name must neither be null nor empty!");
}
if (type == null) {
throw new IllegalArgumentException("The type must not be null!");
}
if ((type == Type.TEXT || type == Type.BOOLEAN) && (unit != null || unitLabel != null)) {
throw new IllegalArgumentException(
"Unit or unit label must only be set for integer or decimal configuration parameters");
}
if (unit != null && !UNITS.contains(unit)) {
throw new IllegalArgumentException("The given unit is invalid.");
}
this.name = name;
this.type = type;
this.groupName = groupName;
this.min = minimum;
this.max = maximum;
this.step = stepsize;
this.pattern = pattern;
this.context = context;
this.defaultValue = defaultValue;
this.label = label;
this.description = description;
this.multipleLimit = multipleLimit;
this.unit = unit;
this.unitLabel = unitLabel;
if (verify != null) {
this.verify = verify;
}
if (readOnly != null) {
this.readOnly = readOnly;
}
if (multiple != null) {
this.multiple = multiple;
}
if (advanced != null) {
this.advanced = advanced;
}
if (required != null) {
this.required = required;
}
if (limitToOptions != null) {
this.limitToOptions = limitToOptions;
}
if (options != null) {
this.options = Collections.unmodifiableList(options);
} else {
this.options = Collections.unmodifiableList(new LinkedList<ParameterOption>());
}
if (filterCriteria != null) {
this.filterCriteria = Collections.unmodifiableList(filterCriteria);
} else {
this.filterCriteria = Collections.unmodifiableList(new LinkedList<FilterCriteria>());
}
}
/**
* Returns the name of the configuration parameter.
*
* @return the name of the configuration parameter (neither null, nor empty)
*/
public String getName() {
return this.name;
}
/**
* Returns the data type of the configuration parameter.
*
* @return the data type of the configuration parameter (not null)
*/
public Type getType() {
return this.type;
}
/**
* @return the minimal value for numeric types, or the minimal length of
* strings, or the minimal number of selected options (nullable)
*/
public BigDecimal getMinimum() {
return min;
}
/**
* @return the maximal value for numeric types, or the maximal length of
* strings, or the maximal number of selected options (nullable)
*/
public BigDecimal getMaximum() {
return max;
}
/**
* @return the value granularity for a numeric value (nullable)
*/
public BigDecimal getStepSize() {
return step;
}
/**
* @return the regular expression for a text type (nullable)
*/
public String getPattern() {
return pattern;
}
/**
* @return true if the value is required, otherwise false.
*/
public Boolean isReadOnly() {
return readOnly;
}
/**
* @return true if multiple selections of options are allowed, otherwise
* false.
*/
public Boolean isMultiple() {
return multiple;
}
/**
* @return the maximum number of options that can be selected from the options list
*/
public Integer getMultipleLimit() {
return multipleLimit;
}
/**
* Returns the context of the configuration parameter.
* <p>
* The context defines an enumeration of some specific context a configuration parameter can take. A context is
* usually used for specific input validation or user interfaces.
* <p>
* <b>Valid values:</b>
*
* <pre>
* network-address, password, password-create,
* color, date, datetime, email, month, week, time, tel, url,
* item, thing, group, tag, service
* </pre>
*
* @return the context of the configuration parameter (could be null or
* empty)
*/
public String getContext() {
return this.context;
}
/**
* Returns {@code true} if the configuration parameter has to be set,
* otherwise {@code false}.
*
* @return true if the configuration parameter has to be set, otherwise
* false
*/
public boolean isRequired() {
return this.required;
}
/**
* Returns the default value of the configuration parameter.
*
* @return the default value of the configuration parameter (could be null)
*/
public String getDefault() {
return this.defaultValue;
}
/**
* Returns a human readable label for the configuration parameter.
*
* @return a human readable label for the configuration parameter (could be
* null or empty)
*/
public String getLabel() {
return this.label;
}
/**
* Returns a the group for this configuration parameter.
*
* @return a group for the configuration parameter (could be null or empty)
*/
public String getGroupName() {
return this.groupName;
}
/**
* Returns true is the value for this parameter must be limited to the
* values in the options list.
*
* @return true if the value is limited to the options list
*/
public boolean getLimitToOptions() {
return this.limitToOptions;
}
/**
* Returns true is the parameter is considered an advanced option.
*
* @return true if the value is an advanced option
*/
public boolean isAdvanced() {
return this.advanced;
}
/**
* Returns a human readable description for the configuration parameter.
*
* @return a human readable description for the configuration parameter
* (could be null or empty)
*/
public String getDescription() {
return this.description;
}
/**
* Returns a static selection list for the value of this parameter.
*
* @return static selection list for the value of this parameter
*/
public List<ParameterOption> getOptions() {
return this.options;
}
/**
* Returns a list of filter criteria for a dynamically created selection
* list.
* <p>
* The clients should consider the relation between the filter criteria and the parameter's context.
*
* @return list of filter criteria for a dynamically created selection list
*/
public List<FilterCriteria> getFilterCriteria() {
return this.filterCriteria;
}
/**
* Returns the unit of measurements of this parameter.
*
* @return the unit of measurements of this parameter (could be null)
*/
public String getUnit() {
return unit;
}
/**
* Returns the unit label of this parameter.
*
* @return the unit label of this parameter (could be null)
*/
public String getUnitLabel() {
return unitLabel;
}
/**
* Returns the verify flag for this parameter. Verify parameters are considered dangerous and the user should be
* alerted with an "Are you sure" flag in the UI.
*
* @return true if the parameter requires verification in the UI
*/
public Boolean isVerifyable() {
return verify;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(this.getClass().getSimpleName());
sb.append(" [name=");
sb.append(name);
sb.append(", ");
sb.append("type=");
sb.append(type);
if (groupName != null) {
sb.append(", ");
sb.append("groupName=");
sb.append(groupName);
}
if (min != null) {
sb.append(", ");
sb.append("min=");
sb.append(min);
}
if (max != null) {
sb.append(", ");
sb.append("max=");
sb.append(max);
}
if (step != null) {
sb.append(", ");
sb.append("step=");
sb.append(step);
}
if (pattern != null) {
sb.append(", ");
sb.append("pattern=");
sb.append(pattern);
}
sb.append(", ");
sb.append("readOnly=");
sb.append(readOnly);
sb.append(", ");
sb.append("required=");
sb.append(required);
sb.append(", ");
sb.append("verify=");
sb.append(verify);
sb.append(", ");
sb.append("multiple=");
sb.append(multiple);
sb.append(", ");
sb.append("multipleLimit=");
sb.append(multipleLimit);
if (context != null) {
sb.append(", ");
sb.append("context=");
sb.append(context);
}
if (label != null) {
sb.append(", ");
sb.append("label=");
sb.append(label);
}
if (description != null) {
sb.append(", ");
sb.append("description=");
sb.append(description);
}
if (defaultValue != null) {
sb.append(", ");
sb.append("defaultValue=");
sb.append(defaultValue);
}
if (unit != null) {
sb.append(", ");
sb.append("unit=");
sb.append(unit);
}
if (unitLabel != null) {
sb.append(", ");
sb.append("unitLabel=");
sb.append(unitLabel);
}
sb.append("]");
return sb.toString();
}
}