/**
* Copyright (C) 2010-14 diirt developers. See COPYRIGHT.TXT
* All rights reserved. Use is subject to license terms. See LICENSE.TXT
*/
package org.diirt.datasource.vtype;
import org.diirt.vtype.VStatistics;
import org.diirt.vtype.Time;
import org.diirt.vtype.VMultiDouble;
import org.diirt.vtype.VInt;
import org.diirt.vtype.VFloat;
import org.diirt.vtype.VTable;
import org.diirt.vtype.VFloatArray;
import org.diirt.vtype.VDouble;
import org.diirt.vtype.VStringArray;
import org.diirt.vtype.VNumberArray;
import org.diirt.vtype.VString;
import org.diirt.vtype.VEnum;
import org.diirt.vtype.VByteArray;
import org.diirt.vtype.VNumber;
import org.diirt.vtype.ValueFormat;
import org.diirt.vtype.VByte;
import org.diirt.vtype.VDoubleArray;
import org.diirt.vtype.VShort;
import org.diirt.vtype.VIntArray;
import org.diirt.vtype.VShortArray;
import org.diirt.vtype.ValueUtil;
import org.diirt.vtype.VType;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static org.diirt.datasource.ExpressionLanguage.*;
import org.diirt.datasource.LatestValueCollector;
import org.diirt.datasource.ReadFunction;
import org.diirt.datasource.WriteFunction;
import static org.diirt.vtype.ValueFactory.*;
import org.diirt.datasource.expression.ChannelExpression;
import org.diirt.datasource.expression.ChannelExpressionList;
import org.diirt.datasource.expression.DesiredRateExpression;
import org.diirt.datasource.expression.DesiredRateExpressionImpl;
import org.diirt.datasource.expression.DesiredRateExpressionList;
import org.diirt.datasource.expression.DesiredRateExpressionListImpl;
import org.diirt.datasource.expression.DesiredRateReadWriteExpression;
import org.diirt.datasource.expression.DesiredRateReadWriteExpressionImpl;
import org.diirt.datasource.expression.Expressions;
import org.diirt.datasource.expression.SourceRateExpression;
import org.diirt.datasource.expression.SourceRateExpressionList;
import org.diirt.datasource.expression.WriteExpression;
import org.diirt.datasource.expression.WriteExpressionImpl;
import org.diirt.util.array.ArrayByte;
import org.diirt.util.array.ArrayDouble;
import org.diirt.util.array.ArrayFloat;
import org.diirt.util.array.ArrayInt;
import org.diirt.util.array.ArrayShort;
import org.diirt.util.array.ListDouble;
import org.diirt.util.array.ListInt;
import org.diirt.util.array.ListNumber;
import org.diirt.util.time.TimeDuration;
/**
* PVManager expression language support for value types.
*
* @author carcassi
*/
public class ExpressionLanguage {
private ExpressionLanguage() {}
static {
// Add support for value types.
DataTypeSupport.install();
}
//
// Channel expressions
//
/**
* A channel with the given name that returns any of the value types.
*
* @param name the channel name; can't be null
* @return an expression representing the channel
*/
public static ChannelExpression<VType, Object> vType(String name) {
return channel(name, VType.class, Object.class);
}
/**
* A list of channels with the given names that return any of the value types.
*
* @param names the channel names; can't be null
* @return a list of expressions representing the channels
*/
public static ChannelExpressionList<VType, Object> vTypes(Collection<String> names) {
return channels(names, VType.class, Object.class);
}
/**
* A channel with the given name of type VNumber.
*
* @param name the channel name; can't be null
* @return an expression representing the channel
*/
public static ChannelExpression<VNumber, Number> vNumber(String name) {
return channel(name, VNumber.class, Number.class);
}
/**
* A list of channels with the given names, all of type VNumber.
*
* @param names the channel names; can't be null
* @return a list of expressions representing the channels
*/
public static ChannelExpressionList<VNumber, Number> vNumbers(Collection<String> names) {
return channels(names, VNumber.class, Number.class);
}
/**
* A channel with the given name of type VDouble.
*
* @param name the channel name; can't be null
* @return an expression representing the channel
*/
public static ChannelExpression<VDouble, Double> vDouble(String name) {
return channel(name, VDouble.class, Double.class);
}
/**
* A channel with the given name of type VFloat.
*
* @param name the channel name; can't be null
* @return an expression representing the channel
*/
public static ChannelExpression<VFloat, Float> vFloat(String name) {
return channel(name, VFloat.class, Float.class);
}
/**
* A channel with the given name of type VInt.
*
* @param name the channel name; can't be null
* @return an expression representing the channel
*/
public static ChannelExpression<VInt, Integer> vInt(String name) {
return channel(name, VInt.class, Integer.class);
}
/**
* A channel with the given name of type VShort.
*
* @param name the channel name; can't be null
* @return an expression representing the channel
*/
public static ChannelExpression<VShort, Short> vShort(String name) {
return channel(name, VShort.class, Short.class);
}
/**
* A channel with the given name of type VByte.
*
* @param name the channel name; can't be null
* @return an expression representing the channel
*/
public static ChannelExpression<VByte, Byte> vByte(String name) {
return channel(name, VByte.class, Byte.class);
}
/**
* A channel with the given name of type VNumberArray.
*
* @param name the channel name; can't be null
* @return an expression representing the channel
*/
public static ChannelExpression<VNumberArray, ListNumber> vNumberArray(String name) {
return channel(name, VNumberArray.class, ListNumber.class);
}
/**
* Transforms a list of numeric scalar into an array.
*
* @param expressions a list of numeric expressions
* @return a new numeric array expression
*/
public static DesiredRateExpression<VNumberArray>
vNumberArrayOf(DesiredRateExpressionList<? extends VNumber> expressions) {
// TODO - there should be a common function to extract the list of functions
List<ReadFunction<? extends VNumber>> functions = new ArrayList<ReadFunction<? extends VNumber>>();
for (DesiredRateExpression<? extends VNumber> expression : expressions.getDesiredRateExpressions()) {
functions.add(expression.getFunction());
}
VNumbersToVNumberArrayConverter converter =
new VNumbersToVNumberArrayConverter(functions);
return new DesiredRateExpressionImpl<VNumberArray>(expressions, converter, "numberArrayOf");
}
/**
* A channel with the given name of type VFloatArray.
*
* @param name the channel name; can't be null
* @return an expression representing the channel
*/
public static ChannelExpression<VFloatArray, ArrayFloat> vFloatArray(String name) {
return channel(name, VFloatArray.class, ArrayFloat.class);
}
/**
* A channel with the given name of type VDoubleArray.
*
* @param name the channel name; can't be null
* @return an expression representing the channel
*/
public static ChannelExpression<VDoubleArray, ArrayDouble> vDoubleArray(String name) {
return channel(name, VDoubleArray.class, ArrayDouble.class);
}
/**
* A channel with the given name of type VByteArray.
*
* @param name the channel name; can't be null
* @return an expression representing the channel
*/
public static ChannelExpression<VByteArray, ArrayByte> vByteArray(String name) {
return channel(name, VByteArray.class, ArrayByte.class);
}
/**
* A channel with the given name of type VShortArray.
*
* @param name the channel name; can't be null
* @return an expression representing the channel
*/
public static ChannelExpression<VShortArray, ArrayShort> vShortArray(String name) {
return channel(name, VShortArray.class, ArrayShort.class);
}
/**
* A channel with the given name of type VIntArray.
*
* @param name the channel name; can't be null
* @return an expression representing the channel
*/
public static ChannelExpression<VIntArray, ArrayInt> vIntArray(String name) {
return channel(name, VIntArray.class, ArrayInt.class);
}
/**
* A channel with the given name of type VString.
*
* @param name the channel name; can't be null
* @return an expression representing the channel
*/
public static ChannelExpression<VString, String> vString(String name) {
return channel(name, VString.class, String.class);
}
/**
* A channel with the given name of type VStringArray.
*
* @param name the channel name; can't be null
* @return an expression representing the channel
*/
@SuppressWarnings("unchecked")
public static ChannelExpression<VStringArray, List<String>> vStringArray(String name) {
return (ChannelExpression<VStringArray, List<String>>) (ChannelExpression) channel(name, VStringArray.class, List.class);
}
/**
* A channel with the given name of type VEnum.
*
* @param name the channel name; can't be null
* @return an expression representing the channel
*/
public static ChannelExpression<VEnum, Integer> vEnum(String name) {
return channel(name, VEnum.class, Integer.class);
}
/**
* A list of channels with the given names, all of type VDouble.
*
* @param names the channel names; can't be null
* @return a list of expressions representing the channels
*/
public static ChannelExpressionList<VDouble, Double> vDoubles(Collection<String> names) {
return channels(names, VDouble.class, Double.class);
}
//
// Constant expressions
//
/**
* A constant representing a string. Alarm will be none and timestamp now.
*
* @param value the constant value
* @return a string expression
*/
public static DesiredRateExpression<VString> vConst(String value) {
return constant(newVString(value, alarmNone(), timeNow()), value);
}
/**
* A constant representing a double. Alarm will be none, timestamp now
* and no display information.
*
* @param value the constant value
* @return a double expression
*/
public static DesiredRateExpression<VDouble> vConst(double value) {
return constant(newVDouble(value, alarmNone(), timeNow(), displayNone()), Double.toString(value));
}
/**
* A constant representing an int. Alarm will be none, timestamp now
* and no display information.
*
* @param value the constant value
* @return an int expression
*/
public static DesiredRateExpression<VInt> vConst(int value) {
return constant(newVInt(value, alarmNone(), timeNow(), displayNone()), Integer.toString(value));
}
/**
* A constant representing a double array. Alarm will be none, timestamp now
* and no display information.
*
* @param values the constant values
* @return a double array expression
*/
public static DesiredRateExpression<VDoubleArray> vConst(double... values) {
return constant(newVDoubleArray(new ArrayDouble(values), alarmNone(), timeNow(), displayNone()));
}
/**
* A constant representing a double array. Alarm will be none, timestamp now
* and no display information.
*
* @param values the constant values
* @return a double array expression
*/
public static DesiredRateExpression<VDoubleArray> vConst(ListDouble values) {
return constant(newVDoubleArray(values, alarmNone(), timeNow(), displayNone()));
}
/**
* A constant representing an int array. Alarm will be none, timestamp now
* and no display information.
*
* @param values the constant values
* @return an int array expression
*/
public static DesiredRateExpression<VIntArray> vConst(int... values) {
return constant(newVIntArray(new ArrayInt(values), alarmNone(), timeNow(), displayNone()));
}
/**
* A constant representing an int array. Alarm will be none, timestamp now
* and no display information.
*
* @param values the constant values
* @return an int array expression
*/
public static DesiredRateExpression<VIntArray> vConst(ListInt values) {
return constant(newVIntArray(values, alarmNone(), timeNow(), displayNone()));
}
/**
* A list of constant expressions of type VDouble.
*
* @param values the list of constants
* @return a list of double expression
*/
public static DesiredRateExpressionList<VDouble> vDoubleConstants(List<Double> values) {
DesiredRateExpressionList<VDouble> list = new DesiredRateExpressionListImpl<VDouble>();
for (Double value : values) {
list.and(constant(newVDouble(value, alarmNone(), timeNow(), displayNone())));
}
return list;
}
/**
* A list of constant expressions of type VDouble.
*
* @param values the list of constants
* @return a list of int expression
*/
public static DesiredRateExpressionList<VInt> vIntConstants(List<Integer> values) {
DesiredRateExpressionList<VInt> list = new DesiredRateExpressionListImpl<VInt>();
for (Integer value : values) {
list.and(constant(newVInt(value, alarmNone(), timeNow(), displayNone())));
}
return list;
}
/**
* A list of constant expressions of type VString.
*
* @param values the list of constants
* @return a list of string expression
*/
public static DesiredRateExpressionList<VString> vStringConstants(List<String> values) {
DesiredRateExpressionList<VString> list = new DesiredRateExpressionListImpl<VString>();
for (String value : values) {
list.and(constant(newVString(value, alarmNone(), timeNow())));
}
return list;
}
/**
* An expression that formats the given expression to a string using the
* given format.
*
* @param expression the expression to format
* @param valueFormat the format to use for the conversion
* @return an expression with the string representation of the argument
*/
public static DesiredRateExpression<VString> vStringOf(DesiredRateExpression<? extends VType> expression, ValueFormat valueFormat) {
return new DesiredRateExpressionImpl<>(expression, new VStringOfFunction(expression.getFunction(), valueFormat), expression.getName());
}
/**
* An expression that formats the given expression to a string using the
* default format.
*
* @param expression the expression to format
* @return an expression with the string representation of the argument
*/
public static DesiredRateExpression<VString> vStringOf(DesiredRateExpression<? extends VType> expression) {
return new DesiredRateExpressionImpl<>(expression, new VStringOfFunction(expression.getFunction(), ValueUtil.getDefaultValueFormat()), expression.getName());
}
/**
* An expression that formats the given expression to a string using the
* default format.
*
* @param expression the expression to format
* @return an expression with the string representation of the argument
*/
public static DesiredRateReadWriteExpression<VString, String> vStringOf(DesiredRateReadWriteExpression<? extends VType, ? extends Object> expression) {
return vStringOf(expression, ValueUtil.getDefaultValueFormat());
}
/**
* An expression that formats the given expression to a string using the
* given format.
*
* @param expression the expression to format
* @param valueFormat the format to use for the conversion
* @return an expression with the string representation of the argument
*/
public static DesiredRateReadWriteExpression<VString, String> vStringOf(DesiredRateReadWriteExpression<? extends VType, ? extends Object> expression,
ValueFormat valueFormat) {
LatestValueCollector<VType> forward = new LatestValueCollector<>();
DesiredRateExpression<VString> readExp = new DesiredRateExpressionImpl<>(expression,
new VStringOfFunction(expression.getFunction(), valueFormat, forward)
, expression.getName());
@SuppressWarnings("unchecked")
WriteFunction<Object> writeFunction = (WriteFunction<Object>) (WriteFunction) expression.getWriteFunction();
WriteExpression<String> writeExp = new WriteExpressionImpl<>(expression,
new VStringOfWriteFunction(forward, valueFormat, writeFunction), expression.getName());
return new DesiredRateReadWriteExpressionImpl<>(readExp, writeExp);
}
/**
* Aggregates the sample at the scan rate and takes the average.
*
* @param doublePv the expression to take the average of; can't be null
* @return an expression representing the average of the expression
*/
public static DesiredRateExpression<VDouble> averageOf(SourceRateExpression<VDouble> doublePv) {
DesiredRateExpression<List<VDouble>> queue = newValuesOf(doublePv);
return new DesiredRateExpressionImpl<VDouble>(queue,
new AverageAggregator(queue.getFunction()), "avg(" + doublePv.getName() + ")");
}
/**
* Aggregates the sample at the scan rate and calculates statistical information.
*
* @param doublePv the expression to calculate the statistics information on; can't be null
* @return an expression representing the statistical information of the expression
*/
public static DesiredRateExpression<VStatistics> statisticsOf(SourceRateExpression<VDouble> doublePv) {
DesiredRateExpression<List<VDouble>> queue = newValuesOf(doublePv);
return new DesiredRateExpressionImpl<VStatistics>(queue,
new StatisticsDoubleAggregator(queue.getFunction()), "stats(" + doublePv.getName() + ")");
}
/**
* Applies {@link #statisticsOf(org.diirt.datasource.expression.SourceRateExpression) } to all
* arguments.
*
* @param doubleExpressions a list of double expressions
* @return a list of statistical expressions
*/
public static DesiredRateExpressionList<VStatistics> statisticsOf(SourceRateExpressionList<VDouble> doubleExpressions) {
DesiredRateExpressionList<VStatistics> expressions = new DesiredRateExpressionListImpl<VStatistics>();
for (SourceRateExpression<VDouble> doubleExpression : doubleExpressions.getSourceRateExpressions()) {
expressions.and(statisticsOf(doubleExpression));
}
return expressions;
}
/**
* A synchronized array from the given expression.
*
* @param tolerance maximum time difference between samples
* @param expressions the expressions from which to reconstruct the array
* @return an expression for the array
*/
public static DesiredRateExpression<VMultiDouble>
synchronizedArrayOf(Duration tolerance, SourceRateExpressionList<VDouble> expressions) {
return synchronizedArrayOf(tolerance, tolerance.multipliedBy(10), expressions);
}
/**
* A synchronized array from the given expression.
*
* @param tolerance maximum time difference between samples in the
* reconstructed array
* @param cacheDepth maximum time difference between samples in the caches
* used to reconstruct the array
* @param expressions the expressions from which to reconstruct the array
* @return an expression for the array
*/
public static DesiredRateExpression<VMultiDouble>
synchronizedArrayOf(Duration tolerance, Duration cacheDepth, SourceRateExpressionList<VDouble> expressions) {
if (cacheDepth.equals(Duration.ofMillis(0)) && TimeDuration.toSecondsDouble(cacheDepth) > 0)
throw new IllegalArgumentException("Distance between samples must be non-zero and positive");
List<String> names = new ArrayList<String>();
List<ReadFunction<List<VDouble>>> collectors = new ArrayList<ReadFunction<List<VDouble>>>();
DesiredRateExpressionList<List<VDouble>> desiredRateExpressions = new DesiredRateExpressionListImpl<List<VDouble>>();
for (SourceRateExpression<VDouble> expression : expressions.getSourceRateExpressions()) {
DesiredRateExpression<List<VDouble>> collectorExp = timedCacheOf(expression, cacheDepth);
desiredRateExpressions.and(collectorExp);
collectors.add(collectorExp.getFunction());
names.add(expression.getName());
}
SynchronizedVDoubleAggregator aggregator =
new SynchronizedVDoubleAggregator(names, collectors, tolerance);
return new DesiredRateExpressionImpl<VMultiDouble>(desiredRateExpressions,
(ReadFunction<VMultiDouble>) aggregator, "syncArray");
}
/**
* Returns all the values starting the latest value and older up to
* the time difference given by the interval.
*
* @param <T> type being read
* @param expression expression to read
* @param maxIntervalBetweenSamples maximum time difference between values
* @return a new expression
*/
public static <T extends Time> DesiredRateExpression<List<T>>
timedCacheOf(SourceRateExpression<T> expression, Duration maxIntervalBetweenSamples) {
return new DesiredRateExpressionImpl<List<T>>(expression,
new TimedCacheCollector<T>(expression.getFunction(), maxIntervalBetweenSamples),
expression.getName());
}
/**
* A column for an aggregated vTable.
*
* @param name the name of the column
* @param values the value of the column
* @return the column
*/
public static VTableColumn column(String name, DesiredRateExpressionList<?> values) {
return new VTableColumn(name, values);
}
/**
* Creates a vTable by aggregating different values from different pvs.
*
* @param columns columns of the table
* @return an expression for the table
*/
public static DesiredRateExpression<VTable> vTable(VTableColumn... columns) {
DesiredRateExpressionListImpl<Object> list = new DesiredRateExpressionListImpl<Object>();
List<List<ReadFunction<?>>> functions = new ArrayList<List<ReadFunction<?>>>();
List<String> names = new ArrayList<String>();
for (VTableColumn column : columns) {
functions.add(Expressions.functionsOf(column.getValueExpressions()));
list.and(column.getValueExpressions());
names.add(column.getName());
}
return new DesiredRateExpressionImpl<VTable>(list, new VTableAggregationFunction(functions, names), "table");
}
}