blob: 21ab70f630dbf79667ef8063463ce98c4a75a23a [file] [log] [blame]
/********************************************************************************
* 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);
}
}
}