package org.ff4j.property; /* * #%L * ff4j-core * %% * Copyright (C) 2013 - 2015 Ff4J * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import java.io.Serializable; import java.lang.reflect.ParameterizedType; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import org.ff4j.property.util.PropertyJsonBean; import org.ff4j.utils.Util; /** * Abstraction of Property. * * @author Cedrick Lunven (@clunven) */ public abstract class Property < T > implements Serializable { /** serial. */ private static final long serialVersionUID = 4987351300418126366L; /** Some store do not allow property edition. */ protected boolean readOnly = false; /** Unique name for property. */ protected String name; /** Short description of the property. */ protected String description = null; /** Canonical name for JSON serialization. */ protected String type = getClass().getCanonicalName(); /** Current Value. */ protected T value; /** If value have a limited set of values. */ protected Set < T > fixedValues; /** * Default constructor. */ protected Property() { } /** * Constructor by property name. * * @param name * unique property name */ protected Property(String name) { Util.assertHasLength(name); this.name = name; } /** * Constructor with name and value as String. * * @param name * current name * @param value * current value */ protected Property(String name, String value) { this(name); this.value = fromString(value); } /** * Constructor with name , value and target available values * * @param name * current name * @param value * current value */ protected Property(String name, T value, Set < T > fixed) { this(name); this.value = value; this.fixedValues = fixed; if (fixedValues != null && !fixedValues.isEmpty() && !fixedValues.contains(value)) { throw new IllegalArgumentException("Invalid value corrects are " + fixedValues); } } /** * Constructor with name , value and target available values * * @param name * current name * @param value * current value */ protected Property(String name, T value, T... fixed) { this(name, value, new HashSet<T>(Arrays.asList(fixed))); } /** * Help XML parsing to realize downcastings. * * @param v * current value as String */ public void add2FixedValueFromString(String v) { add2FixedValue(fromString(v)); } /** * Add element to fixed values. * * @param value * current value */ public void add2FixedValue(T value) { if (fixedValues == null) { fixedValues = new HashSet<T>(); } fixedValues.add(value); } /** * Unmarshalling of value for serailized string expression. * * @param v * value represented as a serialized String * @return * target value */ public abstract T fromString(String v); /** * Check dynamically the class of the parameter T. * * @return * class of template T parameter * @throws Exception * error on reading type */ @SuppressWarnings({ "unchecked" }) public Class<T> parameterizedType() { ParameterizedType pt = (ParameterizedType) getClass().getGenericSuperclass(); return (Class<T>) pt.getActualTypeArguments()[0]; } /** * Serialized value as String * * @return * current value as a string or null */ public String asString() { if (value == null) { return null; } return value.toString(); } /** * Return value as int (if possible). * * @return * int value */ public int asInt() { return Integer.parseInt(asString()); } /** * Return value as double if possible. * * @return * int value */ public double asDouble() { return Double.parseDouble(asString()); } /** * Return value as boolean if possible. * * @return * boolea value */ public boolean asBoolean() { return Boolean.parseBoolean(asString()); } /** * Getter accessor for attribute 'value'. * * @return * current value of 'value' */ public T getValue() { return value; } /** * Setter accessor for attribute 'value'. * @param value * new value for 'value ' */ public void setValue(T value) { this.value = value; } /** * Load value from its string expression. * * @param value * current string value */ public void setValueFromString(String value) { this.value = fromString(value); } /** * Getter accessor for attribute 'name'. * * @return * current value of 'name' */ public String getName() { return name; } /** * Setter accessor for attribute 'name'. * @param name * new value for 'name ' */ public void setName(String name) { this.name = name; } /** * Getter accessor for attribute 'fixedValues'. * * @return * current value of 'fixedValues' */ public Set<T> getFixedValues() { return fixedValues; } /** * Setter accessor for attribute 'fixedValues'. * @param fixedValues * new value for 'fixedValues ' */ public void setFixedValues(Set<T> fixedValues) { this.fixedValues = fixedValues; } /** {@inheritDoc} */ @Override public String toString() { return toJson(); } /** {@inheritDoc} */ public String toJson() { return new PropertyJsonBean(this).asJson(); } /** * Getter accessor for attribute 'type'. * * @return * current value of 'type' */ public String getType() { return type; } /** * Setter accessor for attribute 'type'. * @param type * new value for 'type ' */ public void setType(String type) { this.type = type; } /** * Getter accessor for attribute 'description'. * * @return * current value of 'description' */ public String getDescription() { return description; } /** * Setter accessor for attribute 'description'. * @param description * new value for 'description ' */ public void setDescription(String description) { this.description = description; } /** * Getter accessor for attribute 'readOnly'. * * @return * current value of 'readOnly' */ public boolean isReadOnly() { return readOnly; } /** * Setter accessor for attribute 'readOnly'. * @param readOnly * new value for 'readOnly ' */ public void setReadOnly(boolean readOnly) { this.readOnly = readOnly; } }