| /******************************************************************************** |
| * Copyright (c) 2015-2019 Contributors to the Eclipse Foundation |
| * |
| * See the NOTICE file(s) distributed with this work for additional |
| * information regarding copyright ownership. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| ********************************************************************************/ |
| |
| package org.eclipse.mdm.api.base.model; |
| |
| import java.time.LocalDateTime; |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.Optional; |
| import java.util.function.Function; |
| |
| import org.eclipse.mdm.api.base.adapter.Core; |
| |
| /** |
| * Implementation of an abstract parameter which holds a value with one of the |
| * supported {@link ValueType}s listed below. The value is internally stored in |
| * its {@code String} representation. Any modeled entity with such a use case |
| * should extends this class. API consumers should never use this class in any |
| * way, instead the implementations of this class have to be used. |
| * |
| * <ul> |
| * <li>{@link ValueType#STRING}</li> |
| * <li>{@link ValueType#DATE}</li> |
| * <li>{@link ValueType#BOOLEAN}</li> |
| * <li>{@link ValueType#BYTE}</li> |
| * <li>{@link ValueType#SHORT}</li> |
| * <li>{@link ValueType#INTEGER}</li> |
| * <li>{@link ValueType#LONG}</li> |
| * <li>{@link ValueType#FLOAT}</li> |
| * <li>{@link ValueType#DOUBLE}</li> |
| * <li>{@link ValueType#FLOAT_COMPLEX}</li> |
| * <li>{@link ValueType#DOUBLE_COMPLEX}</li> |
| * </ul> |
| * |
| * @since 1.0.0 |
| * @author Viktor Stoehr, Gigatronik Ingolstadt GmbH |
| * @author Sebastian Dirsch, Gigatronik Ingolstadt GmbH |
| * @see #getVirtualValue() |
| * @see #setObjectValue(Object, Unit) |
| * @see #setStringValue(String) |
| * @see #setDateValue(LocalDateTime) |
| * @see #setBooleanValue(Boolean) |
| * @see #setByteValue(Byte, Unit) |
| * @see #setShortValue(Short, Unit) |
| * @see #setIntegerValue(Integer, Unit) |
| * @see #setLongValue(Long, Unit) |
| * @see #setFloatValue(Float, Unit) |
| * @see #setDoubleValue(Double, Unit) |
| * @see #setFloatComplexValue(FloatComplex, Unit) |
| * @see #setDoubleComplexValue(DoubleComplex, Unit) |
| */ |
| public abstract class BaseParameter extends BaseEntity implements Deletable { |
| |
| private static final Map<ScalarType, Function<String, Object>> SCALARTYPE_FUNCTION_MAP = new HashMap<>(); |
| // ====================================================================== |
| // Instance variables |
| // ====================================================================== |
| |
| private final String attrScalarType; |
| private final String attrValue; |
| |
| static { |
| SCALARTYPE_FUNCTION_MAP.put(ScalarType.STRING, v -> v); |
| SCALARTYPE_FUNCTION_MAP.put(ScalarType.DATE, v -> LocalDateTime.parse(v, Value.LOCAL_DATE_TIME_FORMATTER)); |
| SCALARTYPE_FUNCTION_MAP.put(ScalarType.BOOLEAN, Boolean::valueOf); |
| SCALARTYPE_FUNCTION_MAP.put(ScalarType.BYTE, Byte::valueOf); |
| SCALARTYPE_FUNCTION_MAP.put(ScalarType.SHORT, Short::valueOf); |
| SCALARTYPE_FUNCTION_MAP.put(ScalarType.INTEGER, Integer::valueOf); |
| SCALARTYPE_FUNCTION_MAP.put(ScalarType.LONG, Long::valueOf); |
| SCALARTYPE_FUNCTION_MAP.put(ScalarType.FLOAT, Float::valueOf); |
| SCALARTYPE_FUNCTION_MAP.put(ScalarType.DOUBLE, Double::valueOf); |
| SCALARTYPE_FUNCTION_MAP.put(ScalarType.FLOAT_COMPLEX, FloatComplex::valueOf); |
| SCALARTYPE_FUNCTION_MAP.put(ScalarType.DOUBLE_COMPLEX, DoubleComplex::valueOf); |
| } |
| // ====================================================================== |
| // Constructors |
| // ====================================================================== |
| |
| /** |
| * Constructor. |
| * |
| * @param attrScalarType Name of the {@link ScalarType} attribute. |
| * @param attrValue Name of the {@code String} value attribute. |
| * @param core The {@link Core}. |
| */ |
| protected BaseParameter(String attrScalarType, String attrValue, Core core) { |
| super(core); |
| this.attrScalarType = attrScalarType; |
| this.attrValue = attrValue; |
| } |
| |
| // ====================================================================== |
| // Public methods |
| // ====================================================================== |
| |
| /** |
| * Creates a virtual representation of this parameter's value. This is done by |
| * converting the internally stored {@code String} value to type specified by |
| * this parameter's {@link ValueType} (the allowed types are listed below). The |
| * name of the returned virtual {@link Value} is the name of this parameter. |
| * |
| * <ul> |
| * <li>{@link ValueType#STRING}</li> |
| * <li>{@link ValueType#DATE}</li> |
| * <li>{@link ValueType#BOOLEAN}</li> |
| * <li>{@link ValueType#BYTE}</li> |
| * <li>{@link ValueType#SHORT}</li> |
| * <li>{@link ValueType#INTEGER}</li> |
| * <li>{@link ValueType#LONG}</li> |
| * <li>{@link ValueType#FLOAT}</li> |
| * <li>{@link ValueType#DOUBLE}</li> |
| * <li>{@link ValueType#FLOAT_COMPLEX}</li> |
| * <li>{@link ValueType#DOUBLE_COMPLEX}</li> |
| * </ul> |
| * |
| * <p> |
| * <b>Note:</b> The returned value is a virtual one and hence intended for |
| * displaying purposes only. To change this parameter's value one of its |
| * {@code setXYValue} methods has to be used. |
| * |
| * @return The created {@code Value} with the converted value is returned. |
| */ |
| public Value getVirtualValue() { |
| ScalarType scalarType = getScalarType(); |
| Function<String, Object> typeConverter = SCALARTYPE_FUNCTION_MAP.get(scalarType); |
| |
| if (typeConverter == null) { |
| return ValueType.UNKNOWN.create(getName()); |
| } |
| |
| Value parameterValue = getParameterValue(); |
| Object value = parameterValue.isValid() ? typeConverter.apply(parameterValue.extract()) : null; |
| return scalarType.toSingleValueType().create(getName(), getUnitName(), parameterValue.isValid(), value); |
| } |
| |
| /** |
| * Takes given value and determines its type. Finally value and the optional |
| * {@code Unit} are passed to the corresponding {@code setXYValue(XY)} method as |
| * listed below. The value is allowed to be an instance of the following types: |
| * {@code String}, {@code LocalDateTime}, {@code Boolean}, {@code Byte}, |
| * {@code Short}, {@code Integer}, {@code Long}, {@code Float}, {@code Double}, |
| * {@code FloatComplex} and {@code DoubleComplex}. |
| * |
| * <p> |
| * <b>Note:</b> If the given value is an instance of {@code String}, {@code |
| * LocalDateTime} or a {@code Boolean}, then the given unit is ignored. |
| * |
| * @param value The new value for this parameter is not allowed to be null. |
| * @param unit The optionally related {@code Unit}. |
| * @throws IllegalArgumentException Thrown if the given value is not supported. |
| * @see #setStringValue(String) |
| * @see #setDateValue(LocalDateTime) |
| * @see #setBooleanValue(Boolean) |
| * @see #setByteValue(Byte, Unit) |
| * @see #setShortValue(Short, Unit) |
| * @see #setIntegerValue(Integer, Unit) |
| * @see #setLongValue(Long, Unit) |
| * @see #setFloatValue(Float, Unit) |
| * @see #setDoubleValue(Double, Unit) |
| * @see #setFloatComplexValue(FloatComplex, Unit) |
| * @see #setDoubleComplexValue(DoubleComplex, Unit) |
| */ |
| public void setObjectValue(Object value, Unit unit) { |
| if (value instanceof String) { |
| setStringValue((String) value); |
| } else if (value instanceof LocalDateTime) { |
| setDateValue((LocalDateTime) value); |
| } else if (value instanceof Boolean) { |
| setBooleanValue((Boolean) value); |
| } else if (value instanceof Byte) { |
| setByteValue((Byte) value, unit); |
| } else if (value instanceof Short) { |
| setShortValue((Short) value, unit); |
| } else if (value instanceof Integer) { |
| setIntegerValue((Integer) value, unit); |
| } else if (value instanceof Long) { |
| setLongValue((Long) value, unit); |
| } else if (value instanceof Float) { |
| setFloatValue((Float) value, unit); |
| } else if (value instanceof Double) { |
| setDoubleValue((Double) value, unit); |
| } else if (value instanceof FloatComplex) { |
| setFloatComplexValue((FloatComplex) value, unit); |
| } else if (value instanceof DoubleComplex) { |
| setDoubleComplexValue((DoubleComplex) value, unit); |
| } else { |
| throw new IllegalArgumentException( |
| "Value '" + value + "' of type '" + value.getClass().getSimpleName() + "' is not supported."); |
| } |
| } |
| |
| /** |
| * Replaces current value with given {@code String} value. Any existing relation |
| * to a {@link Unit} will be removed. |
| * |
| * @param value The new value for this parameter. |
| */ |
| public void setStringValue(String value) { |
| setScalarType(ScalarType.STRING); |
| getParameterValue().set(value); |
| setUnit(null); |
| } |
| |
| /** |
| * Replaces current value with the {@code String} representation of given |
| * {@code LocalDateTime}. Any existing relation to a {@link Unit} will be |
| * removed. |
| * |
| * @param value The new value for this parameter. |
| */ |
| public void setDateValue(LocalDateTime value) { |
| setScalarType(ScalarType.DATE); |
| getParameterValue().set(value.format(Value.LOCAL_DATE_TIME_FORMATTER)); |
| setUnit(null); |
| } |
| |
| /** |
| * Replaces current value with the {@code String} representation of given |
| * {@code Boolean}. Any existing relation to a {@link Unit} will be removed. |
| * |
| * @param value The new value for this parameter. |
| */ |
| public void setBooleanValue(Boolean value) { |
| setScalarType(ScalarType.BOOLEAN); |
| getParameterValue().set(value.toString()); |
| setUnit(null); |
| } |
| |
| /** |
| * Replaces current value with the {@code String} representation of given |
| * {@code Byte}. Any existing relation to a {@link Unit} will be replaced with |
| * the given one. |
| * |
| * @param value The new value for this parameter. |
| * @param unit The relation to a unit is optional. |
| */ |
| public void setByteValue(Byte value, Unit unit) { |
| setScalarType(ScalarType.BYTE); |
| getParameterValue().set(value.toString()); |
| setUnit(unit); |
| } |
| |
| /** |
| * Replaces current value with the {@code String} representation of given |
| * {@code Short}. Any existing relation to a {@link Unit} will be replaced with |
| * the given one. |
| * |
| * @param value The new value for this parameter. |
| * @param unit The relation to a unit is optional. |
| */ |
| public void setShortValue(Short value, Unit unit) { |
| setScalarType(ScalarType.SHORT); |
| getParameterValue().set(value.toString()); |
| setUnit(unit); |
| } |
| |
| /** |
| * Replaces current value with the {@code String} representation of given |
| * {@code Integer}. Any existing relation to a {@link Unit} will be replaced |
| * with the given one. |
| * |
| * @param value The new value for this parameter. |
| * @param unit The relation to a unit is optional. |
| */ |
| public void setIntegerValue(Integer value, Unit unit) { |
| setScalarType(ScalarType.INTEGER); |
| getParameterValue().set(value.toString()); |
| setUnit(unit); |
| } |
| |
| /** |
| * Replaces current value with the {@code String} representation of given |
| * {@code Long}. Any existing relation to a {@link Unit} will be replaced with |
| * the given one. |
| * |
| * @param value The new value for this parameter. |
| * @param unit The relation to a unit is optional. |
| */ |
| public void setLongValue(Long value, Unit unit) { |
| setScalarType(ScalarType.LONG); |
| getParameterValue().set(value.toString()); |
| setUnit(unit); |
| } |
| |
| /** |
| * Replaces current value with the {@code String} representation of given |
| * {@code Float}. Any existing relation to a {@link Unit} will be replaced with |
| * the given one. |
| * |
| * @param value The new value for this parameter. |
| * @param unit The relation to a unit is optional. |
| */ |
| public void setFloatValue(Float value, Unit unit) { |
| setScalarType(ScalarType.FLOAT); |
| getParameterValue().set(value.toString()); |
| setUnit(unit); |
| } |
| |
| /** |
| * Replaces current value with the {@code String} representation of given |
| * {@code Double}. Any existing relation to a {@link Unit} will be replaced with |
| * the given one. |
| * |
| * @param value The new value for this parameter. |
| * @param unit The relation to a unit is optional. |
| */ |
| public void setDoubleValue(Double value, Unit unit) { |
| setScalarType(ScalarType.DOUBLE); |
| getParameterValue().set(value.toString()); |
| setUnit(unit); |
| } |
| |
| /** |
| * Replaces current value with the {@code String} representation of given |
| * {@code FloatComplex}. Any existing relation to a {@link Unit} will be |
| * replaced with the given one. |
| * |
| * @param value The new value for this parameter. |
| * @param unit The relation to a unit is optional. |
| */ |
| public void setFloatComplexValue(FloatComplex value, Unit unit) { |
| setScalarType(ScalarType.FLOAT_COMPLEX); |
| getParameterValue().set(value.toString()); |
| setUnit(unit); |
| } |
| |
| /** |
| * Replaces current value with the {@code String} representation of given |
| * {@code DoubleComplex}. Any existing relation to a {@link Unit} will be |
| * replaced with the given one. |
| * |
| * @param value The new value for this parameter. |
| * @param unit The relation to a unit is optional. |
| */ |
| public void setDoubleComplexValue(DoubleComplex value, Unit unit) { |
| setScalarType(ScalarType.DOUBLE_COMPLEX); |
| getParameterValue().set(value.toString()); |
| setUnit(unit); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public String toString() { |
| StringBuilder sb = new StringBuilder(getClass().getSimpleName()).append("(Name = ").append(getName()); |
| |
| sb.append(", Value = "); |
| Value parameterValue = getParameterValue(); |
| if (parameterValue.isValid()) { |
| sb.append((String) getParameterValue().extract()); |
| } |
| |
| Optional<Unit> unit = getUnit(); |
| if (unit.isPresent()) { |
| sb.append(" [").append(unit.get().getName()).append(']'); |
| } |
| |
| return sb.append(')').toString(); |
| } |
| |
| // ====================================================================== |
| // Private methods |
| // ====================================================================== |
| |
| /** |
| * Returns the {@link Value} of this parameter. |
| * |
| * @return This parameter's {@code Value} is returned. |
| */ |
| private Value getParameterValue() { |
| return getValue(attrValue); |
| } |
| |
| /** |
| * Returns the scalar value type of this parameter. |
| * |
| * @return This parameter's scalar type is returned. |
| */ |
| private ScalarType getScalarType() { |
| return getValue(attrScalarType).extract(); |
| } |
| |
| /** |
| * Sets new scalar type for this parameter. |
| * |
| * @param scalarType The new {@code ScalarType}. |
| */ |
| private void setScalarType(ScalarType scalarType) { |
| getValue(attrScalarType).set(scalarType); |
| } |
| |
| /** |
| * Returns the name of the related {@link Unit}. If no {@code Unit} is related, |
| * an empty {@code String} is returned instead. |
| * |
| * @return The name of the related {@code Unit} is returned or an empty |
| * {@code String}. |
| */ |
| private String getUnitName() { |
| Optional<Unit> unit = getUnit(); |
| if (unit.isPresent()) { |
| return unit.get().getName(); |
| } |
| |
| return ""; |
| } |
| |
| /** |
| * Returns an optionally related {@link Unit}. |
| * |
| * @return The returned {@code Optional} is empty if no {@code Unit} is related. |
| */ |
| private Optional<Unit> getUnit() { |
| return Optional.ofNullable(getCore().getMutableStore().get(Unit.class)); |
| } |
| |
| /** |
| * Replaces current {@link Unit} relation with the given one, if the {@code |
| * Optional} is not empty. Otherwise any current relations is removed. |
| * |
| * @param unit The new {@code Unit} may be {@code null}. |
| */ |
| private void setUnit(Unit unit) { |
| if (unit == null) { |
| getCore().getMutableStore().remove(Unit.class); |
| } else { |
| getCore().getMutableStore().set(unit); |
| } |
| } |
| |
| } |