SequenceRepresentation etc. for LocalColumns.
Signed-off-by: Martin Fleischer <m.fleischer@peak-solution.de>
diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/ODSEntityManager.java b/src/main/java/org/eclipse/mdm/api/odsadapter/ODSEntityManager.java
index de1df72..de9ba71 100644
--- a/src/main/java/org/eclipse/mdm/api/odsadapter/ODSEntityManager.java
+++ b/src/main/java/org/eclipse/mdm/api/odsadapter/ODSEntityManager.java
@@ -359,7 +359,7 @@
*/
@Override
public List<MeasuredValues> readMeasuredValues(ReadRequest readRequest) throws DataAccessException {
- return new ReadRequestHandler(odsModelManager).execute(readRequest);
+ return new ReadRequestHandler(odsModelManager, queryService).execute(readRequest);
}
/**
diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/ReadRequestHandler.java b/src/main/java/org/eclipse/mdm/api/odsadapter/ReadRequestHandler.java
index 4fe53f1..f4323be 100644
--- a/src/main/java/org/eclipse/mdm/api/odsadapter/ReadRequestHandler.java
+++ b/src/main/java/org/eclipse/mdm/api/odsadapter/ReadRequestHandler.java
@@ -15,26 +15,44 @@
package org.eclipse.mdm.api.odsadapter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map.Entry;
-
-import org.asam.ods.AoException;
-import org.asam.ods.Column;
-import org.asam.ods.ElemId;
-import org.asam.ods.NameValueSeqUnit;
-import org.asam.ods.T_LONGLONG;
-import org.asam.ods.ValueMatrix;
-import org.asam.ods.ValueMatrixMode;
-import org.eclipse.mdm.api.base.massdata.ReadRequest;
-import org.eclipse.mdm.api.base.model.Channel;
-import org.eclipse.mdm.api.base.model.Entity;
-import org.eclipse.mdm.api.base.model.MeasuredValues;
-import org.eclipse.mdm.api.base.model.Unit;
-import org.eclipse.mdm.api.base.query.DataAccessException;
-import org.eclipse.mdm.api.odsadapter.query.ODSEntityType;
-import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
-import org.eclipse.mdm.api.odsadapter.utils.ODSConverter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.asam.ods.AoException;
+import org.asam.ods.Column;
+import org.asam.ods.ElemId;
+import org.asam.ods.NameValueSeqUnit;
+import org.asam.ods.T_LONGLONG;
+import org.asam.ods.ValueMatrix;
+import org.asam.ods.ValueMatrixMode;
+import org.eclipse.mdm.api.base.adapter.Attribute;
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.massdata.ReadRequest;
+import org.eclipse.mdm.api.base.massdata.ReadRequest.ValuesMode;
+import org.eclipse.mdm.api.base.model.AxisType;
+import org.eclipse.mdm.api.base.model.Channel;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.MeasuredValues;
+import org.eclipse.mdm.api.base.model.SequenceRepresentation;
+import org.eclipse.mdm.api.base.model.Unit;
+import org.eclipse.mdm.api.base.model.Value;
+import org.eclipse.mdm.api.base.query.ComparisonOperator;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.Filter;
+import org.eclipse.mdm.api.base.query.Query;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.base.query.Result;
+import org.eclipse.mdm.api.odsadapter.query.ODSEntityType;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.eclipse.mdm.api.odsadapter.utils.ODSConverter;
+
+import com.google.common.collect.Lists;
/**
* Reads mass data specified in {@link ReadRequest}s.
@@ -42,13 +60,56 @@
* @since 1.0.0
* @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
*/
-public final class ReadRequestHandler {
+public final class ReadRequestHandler {
+ public static final class ColumnAttributes
+ {
+ private final String name;
+ private final SequenceRepresentation sequenceRepresentation;
+ private final double[] generationParameters;
+ private final boolean independent;
+ private final AxisType axisType;
+
+ public ColumnAttributes(String name, SequenceRepresentation sequenceRepresentation, double[] generationParameters, boolean independent, AxisType axisType)
+ {
+ this.name = name;
+ this.sequenceRepresentation = sequenceRepresentation;
+ this.generationParameters = generationParameters;
+ this.independent = independent;
+ this.axisType = axisType;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public SequenceRepresentation getSequenceRepresentation()
+ {
+ return sequenceRepresentation;
+ }
+
+ public double[] getGenerationParameters()
+ {
+ return generationParameters;
+ }
+
+ public boolean isIndependentColumn()
+ {
+ return independent;
+ }
+
+ public AxisType getAxisType()
+ {
+ return axisType;
+ }
+ }
// ======================================================================
// Instance variables
// ======================================================================
-
- private final ODSModelManager modelManager;
+
+ private final ODSModelManager modelManager;
+ private final QueryService queryService;
// ======================================================================
// Constructors
@@ -60,8 +121,9 @@
* @param modelManager
* Used to gain access to value matrices.
*/
- public ReadRequestHandler(ODSModelManager modelManager) {
- this.modelManager = modelManager;
+ public ReadRequestHandler(ODSModelManager modelManager, QueryService queryService) {
+ this.modelManager = modelManager;
+ this.queryService = queryService;
}
// ======================================================================
@@ -80,18 +142,22 @@
*/
public List<MeasuredValues> execute(ReadRequest readRequest) throws DataAccessException {
ValueMatrix valueMatrix = null;
- Column[] columns = null;
+ Column[] arrColumns = null;
try {
- valueMatrix = getValueMatrix(readRequest);
- columns = getODSColumns(readRequest, valueMatrix);
- NameValueSeqUnit[] nvsus = valueMatrix.getValue(columns, readRequest.getStartIndex(),
+ valueMatrix = getValueMatrix(readRequest);
+ List<Pair<Column, ColumnAttributes>> listColumnPairs = getODSColumns(readRequest, valueMatrix);
+
+ arrColumns = listColumnPairs.stream().map(Pair::getLeft).toArray(Column[]::new);
+ ColumnAttributes[] arrColumnAttributes = listColumnPairs.stream().map(Pair::getRight).toArray(ColumnAttributes[]::new);
+
+ NameValueSeqUnit[] nvsus = valueMatrix.getValue(arrColumns, readRequest.getStartIndex(),
readRequest.getRequestSize());
- return ODSConverter.fromODSMeasuredValuesSeq(nvsus);
+ return ODSConverter.fromODSMeasuredValuesSeq(nvsus, arrColumnAttributes);
} catch (AoException aoe) {
throw new DataAccessException(aoe.reason, aoe);
} finally {
- releaseColumns(columns);
+ releaseColumns(arrColumns);
releaseValueMatrix(valueMatrix);
}
}
@@ -116,38 +182,86 @@
* @throws DataAccessException
* Thrown on wrong {@code ReadRequest} setup.
*/
- private Column[] getODSColumns(ReadRequest readRequest, ValueMatrix valueMatrix)
- throws AoException, DataAccessException {
- if (readRequest.isLoadAllChannels()) {
- // TODO should it be possible to overwrite the unit of some
- // channels?!
- // -> this results in a performance issue since we need to call
- // getName()
- // on each column for mapping!
- return valueMatrix.getColumns("*");
- }
-
- List<Column> columnList = new ArrayList<>();
- try {
- for (Entry<Channel, Unit> entry : readRequest.getChannels().entrySet()) {
- Channel channel = entry.getKey();
- Unit unit = entry.getValue();
- Column[] columns = valueMatrix.getColumns(channel.getName());
- if (columns == null || columns.length != 1) {
- releaseColumns(columns);
- throw new DataAccessException("Column with name '" + channel.getName() + "' not found.");
- }
- Column column = columns[0];
- if (!unit.nameEquals(channel.getUnit().getName())) {
- column.setUnit(unit.getName());
- }
- columnList.add(column);
- }
- return columnList.toArray(new Column[columnList.size()]);
- } catch (AoException e) {
- releaseColumns(columnList.toArray(new Column[columnList.size()]));
- throw new DataAccessException("Unable to load column due to: " + e.reason, e);
- }
+ private List<Pair<Column, ColumnAttributes>> getODSColumns(ReadRequest readRequest, ValueMatrix valueMatrix)
+ throws AoException, DataAccessException {
+ List<Pair<Column, ColumnAttributes>> listColumnPairs = new ArrayList<>();
+ Map<String, Column> mapColumns = new HashMap<>();
+
+ try {
+ if (readRequest.isLoadAllChannels()) {
+ // TODO should it be possible to overwrite the unit of some
+ // channels?!
+ // -> this results in a performance issue since we need to call
+ // getName()
+ // on each column for mapping! (no longer, see below!)
+ Column[] columns = valueMatrix.getColumns("*");
+
+ if (null != columns) {
+ for (Column column : columns) {
+ mapColumns.put(column.getName(), column);
+ }
+ }
+ } else {
+ for (Entry<Channel, Unit> entry : readRequest.getChannels().entrySet()) {
+ Channel channel = entry.getKey();
+ Unit unit = entry.getValue();
+ String channelName = channel.getName();
+ Column[] columns = valueMatrix.getColumns(channelName);
+ if (columns == null || columns.length != 1) {
+ releaseColumns(columns);
+ throw new DataAccessException("Column with name '" + channel.getName() + "' not found.");
+ }
+ Column column = columns[0];
+ if (!unit.nameEquals(channel.getUnit().getName())) {
+ column.setUnit(unit.getName());
+ }
+
+ mapColumns.put(channelName, column);
+ }
+ }
+
+ if (mapColumns.size() > 0) {
+ EntityType localColumnEntityType = modelManager.getEntityType("LocalColumn");
+ Attribute nameAttr = localColumnEntityType.getAttribute("Name");
+ Attribute submatrixAttr = localColumnEntityType.getAttribute("SubMatrix");
+
+ Query query = queryService.createQuery()
+ .select(Lists.newArrayList(nameAttr,
+ localColumnEntityType.getAttribute("SequenceRepresentation"),
+ localColumnEntityType.getAttribute("GenerationParameters"),
+ localColumnEntityType.getAttribute("IndependentFlag"),
+ localColumnEntityType.getAttribute("axistype")));
+
+ Filter filter = Filter.and()
+// .add(ComparisonOperator.IN_SET.create(nameAttr,
+// mapColumns.keySet().stream().toArray(String[]::new)))
+ .add(ComparisonOperator.EQUAL.create(submatrixAttr, Long.valueOf(readRequest.getChannelGroup().getID())));
+
+ Set<String> setColumnNames = mapColumns.keySet();
+
+ for (Result result : query.fetch(filter)) {
+ Map<String, Value> mapValues = result.getRecord(localColumnEntityType).getValues();
+
+ String columnName = mapValues.get("Name").extract();
+
+ if (setColumnNames.contains(columnName))
+ {
+ ColumnAttributes ca = new ColumnAttributes(columnName,
+ (ValuesMode.CALCULATED == readRequest.getValuesMode() ? SequenceRepresentation.EXPLICIT : mapValues.get("SequenceRepresentation").extract()),
+ (ValuesMode.CALCULATED == readRequest.getValuesMode() ? new double[0] : mapValues.get("GenerationParameters").extract()),
+ ((short) mapValues.get("IndependentFlag").extract() != 0),
+ mapValues.get("axistype").extract());
+
+ listColumnPairs.add(new ImmutablePair<Column, ColumnAttributes>(mapColumns.get(columnName), ca));
+ }
+ }
+ }
+
+ return listColumnPairs;
+ } catch (AoException e) {
+ releaseColumns(listColumnPairs.stream().map(Pair::getLeft).toArray(Column[]::new));
+ throw new DataAccessException("Unable to load column due to: " + e.reason, e);
+ }
}
/**
@@ -163,8 +277,18 @@
private ValueMatrix getValueMatrix(ReadRequest readRequest) throws AoException {
Entity entity = readRequest.getChannelGroup();
T_LONGLONG iid = ODSConverter.toODSID(entity.getID());
- T_LONGLONG aid = ((ODSEntityType) modelManager.getEntityType(entity)).getODSID();
- return modelManager.getApplElemAccess().getValueMatrixInMode(new ElemId(aid, iid), ValueMatrixMode.CALCULATED);
+ T_LONGLONG aid = ((ODSEntityType) modelManager.getEntityType(entity)).getODSID();
+ ValueMatrixMode valueMatrixMode = ValueMatrixMode.CALCULATED;
+ switch (readRequest.getValuesMode())
+ {
+ case CALCULATED: valueMatrixMode = ValueMatrixMode.CALCULATED; break;
+ case STORAGE: valueMatrixMode = ValueMatrixMode.STORAGE; break;
+ default:
+ throw new DataAccessException(
+ String.format("Unsupported ValueMode %s!", readRequest.getValuesMode().name()));
+ }
+
+ return modelManager.getApplElemAccess().getValueMatrixInMode(new ElemId(aid, iid), valueMatrixMode);
}
/**
@@ -182,8 +306,10 @@
valueMatrix.destroy();
} catch (AoException aoe) {
// ignore
- } finally {
- valueMatrix._release();
+ } finally {
+ // After valueMatrix.destroy(), the CORBA object may have been removed from the POA and
+ // thus be inaccessible. _release() often doesn't do anything in many ODS implementations, anyway.
+// valueMatrix._release();
}
}
@@ -203,8 +329,10 @@
column.destroy();
} catch (AoException e) {
// ignore
- } finally {
- column._release();
+ } finally {
+ // After column.destroy(), the CORBA object may have been removed from the POA and
+ // thus be inaccessible. _release() often doesn't do anything in many ODS implementations, anyway.
+// column._release();
}
}
}
diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/WriteRequestHandler.java b/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/WriteRequestHandler.java
index 34c8d2c..8a27cfd 100644
--- a/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/WriteRequestHandler.java
+++ b/src/main/java/org/eclipse/mdm/api/odsadapter/transaction/WriteRequestHandler.java
@@ -127,7 +127,7 @@
Map<String, Value> values = core.getValues();
values.get(Entity.ATTR_NAME).set(writeRequest.getChannel().getName());
values.get(Entity.ATTR_MIMETYPE).set("application/x-asam.aolocalcolumn");
- values.get(AE_LC_ATTR_INDEPENDENT).set(ODSConverter.toODSValidFlag(writeRequest.isIndependent()));
+ values.get(AE_LC_ATTR_INDEPENDENT).set((short) (writeRequest.isIndependent() ? 1 : 0));
values.get(AE_LC_ATTR_RAWDATATYPE).set(writeRequest.getRawScalarType());
values.get(AE_LC_ATTR_REPRESENTATION).set(writeRequest.getSequenceRepresentation());
values.get(AE_LC_ATTR_AXISTYPE).set(writeRequest.getAxisType());
@@ -137,26 +137,24 @@
ValueType<?> valueType = writeRequest.getRawScalarType().toValueType();
String unitName = writeRequest.getChannel().getUnit().getName();
values.put(AE_LC_ATTR_VALUES,
- valueType.create(AE_LC_ATTR_VALUES, unitName, true, writeRequest.getValues()));
-
- if (writeRequest.getSequenceRepresentation().isImplicit()) {
- // PEAK ODS server: expects values written as generation
- // parameters
- Object genParamValues = writeRequest.getValues();
- double[] genParamD = new double[Array.getLength(genParamValues)];
- IntStream.range(0, genParamD.length)
- .forEach(i -> genParamD[i] = ((Number) Array.get(genParamValues, i)).doubleValue());
- values.get(AE_LC_ATTR_PARAMETERS).set(genParamD);
- }
+ valueType.create(AE_LC_ATTR_VALUES, unitName, true, writeRequest.getValues()));
+
+ // OpenATFX issue: For "implicit" columns, if no value for the GenerationParameters attribute is present,
+ // it is attempted to transfer the local column values (through which the generation parameters are
+ // available in these cases) to the GenerationParameters attribute without converting them to the
+ // correct DS_DOUBLE data type first (unless it is a DOUBLE or LONG column), resulting in an exception.
+ // Hence, supply correctly converted generation parameters as a workaround:
+ if (writeRequest.getSequenceRepresentation().isImplicit()) {
+ Object genParamValues = writeRequest.getValues();
+ double[] genParamD = new double[Array.getLength(genParamValues)];
+ IntStream.range(0, genParamD.length)
+ .forEach(i -> genParamD[i] = ((Number) Array.get(genParamValues, i)).doubleValue());
+ values.get(AE_LC_ATTR_PARAMETERS).set(genParamD);
+ }
// flags
if (writeRequest.areAllValid()) {
values.get(AE_LC_ATTR_GLOBAL_FLAG).set((short) 15);
- // PEAK ODS server issue: though global flag is true a flags
- // array is expected
- short[] flags = new short[Array.getLength(writeRequest.getValues())];
- Arrays.fill(flags, (short) 15);
- values.get(AE_LC_ATTR_FLAGS).set(flags);
} else {
short[] flags = ODSConverter.toODSValidFlagSeq(writeRequest.getFlags());
values.get(AE_LC_ATTR_FLAGS).set(flags);
diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/utils/ODSConverter.java b/src/main/java/org/eclipse/mdm/api/odsadapter/utils/ODSConverter.java
index ae893ca..25852d5 100644
--- a/src/main/java/org/eclipse/mdm/api/odsadapter/utils/ODSConverter.java
+++ b/src/main/java/org/eclipse/mdm/api/odsadapter/utils/ODSConverter.java
@@ -21,7 +21,8 @@
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoField;
-import java.util.ArrayList;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -49,7 +50,8 @@
import org.eclipse.mdm.api.base.model.Value;
import org.eclipse.mdm.api.base.model.ValueType;
import org.eclipse.mdm.api.base.query.Aggregation;
-import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.base.query.DataAccessException;
+import org.eclipse.mdm.api.odsadapter.ReadRequestHandler;
import org.eclipse.mdm.api.odsadapter.query.ODSAttribute;
import com.google.common.collect.Sets;
@@ -652,12 +654,18 @@
* @throws DataAccessException
* Thrown on conversion errors.
*/
- public static List<MeasuredValues> fromODSMeasuredValuesSeq(NameValueSeqUnit[] odsMeasuredValuesSeq)
+ public static List<MeasuredValues> fromODSMeasuredValuesSeq(NameValueSeqUnit[] odsMeasuredValuesSeq, ReadRequestHandler.ColumnAttributes[] columnAttributesArray)
throws DataAccessException {
- List<MeasuredValues> measuredValues = new ArrayList<>(odsMeasuredValuesSeq.length);
+ List<MeasuredValues> measuredValues = new ArrayList<>(odsMeasuredValuesSeq.length);
+
+ Map<String, ReadRequestHandler.ColumnAttributes> mapColumnAttributes = new HashMap<>();
+ if (null != columnAttributesArray)
+ {
+ Arrays.stream(columnAttributesArray).forEach(ca -> mapColumnAttributes.put(ca.getName(), ca));
+ }
for (NameValueSeqUnit odsMeasuredValues : odsMeasuredValuesSeq) {
- measuredValues.add(fromODSMeasuredValues(odsMeasuredValues));
+ measuredValues.add(fromODSMeasuredValues(odsMeasuredValues, mapColumnAttributes.get(odsMeasuredValues.valName)));
}
return measuredValues;
@@ -672,7 +680,7 @@
* @throws DataAccessException
* Thrown on conversion errors.
*/
- private static MeasuredValues fromODSMeasuredValues(NameValueSeqUnit odsMeasuredValues) throws DataAccessException {
+ private static MeasuredValues fromODSMeasuredValues(NameValueSeqUnit odsMeasuredValues, ReadRequestHandler.ColumnAttributes columnAttributes) throws DataAccessException {
TS_ValueSeq odsValueSeq = odsMeasuredValues.value;
DataType dataType = odsValueSeq.u.discriminator();
ScalarType scalarType;
@@ -720,9 +728,20 @@
} else {
throw new DataAccessException(
"Conversion for ODS measured points of type '" + dataType.toString() + "' does not exist.");
+ }
+
+ if (null == columnAttributes)
+ {
+ columnAttributes = new ReadRequestHandler.ColumnAttributes("", null, new double[0], false, null);
}
- return scalarType.createMeasuredValues(odsMeasuredValues.valName, odsMeasuredValues.unit, values,
+ return scalarType.createMeasuredValues(odsMeasuredValues.valName,
+ odsMeasuredValues.unit,
+ columnAttributes.getSequenceRepresentation(),
+ columnAttributes.getGenerationParameters(),
+ columnAttributes.isIndependentColumn(),
+ columnAttributes.getAxisType(),
+ values,
fromODSValidFlagSeq(odsValueSeq.flag));
}