blob: 7d4603ea08b5f23a11c84e062fcb973bef1fd15f [file] [log] [blame]
/********************************************************************************
* Copyright (c) 2015-2018 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.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;
/**
* Reads mass data specified in {@link ReadRequest}s.
*
* @since 1.0.0
* @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
*/
final class ReadRequestHandler {
// ======================================================================
// Instance variables
// ======================================================================
private final ODSModelManager modelManager;
// ======================================================================
// Constructors
// ======================================================================
/**
* Constructor.
*
* @param modelManager
* Used to gain access to value matrices.
*/
public ReadRequestHandler(ODSModelManager modelManager) {
this.modelManager = modelManager;
}
// ======================================================================
// Public methods
// ======================================================================
/**
* Loads {@link MeasuredValues} as defined in given {@link ReadRequest}.
*
* @param readRequest
* The {@code MeasuredValues} request configuration.
* @return The loaded {@code MeasuredValues} are returned.
* @throws DataAccessException
* Thrown if unable to load {@code
* MeasuredValues}.
*/
public List<MeasuredValues> execute(ReadRequest readRequest) throws DataAccessException {
ValueMatrix valueMatrix = null;
Column[] columns = null;
try {
valueMatrix = getValueMatrix(readRequest);
columns = getODSColumns(readRequest, valueMatrix);
NameValueSeqUnit[] nvsus = valueMatrix.getValue(columns, readRequest.getStartIndex(),
readRequest.getRequestSize());
return ODSConverter.fromODSMeasuredValuesSeq(nvsus);
} catch (AoException aoe) {
throw new DataAccessException(aoe.reason, aoe);
} finally {
releaseColumns(columns);
releaseValueMatrix(valueMatrix);
}
}
// ======================================================================
// Private methods
// ======================================================================
/**
* Loads all for each defined {@link Channel} in given {@link ReadRequest}
* and loads the corresponding {@link Column} using given
* {@link ValueMatrix}.
*
* @param readRequest
* Defines required {@code Column}s.
* @param valueMatrix
* Used to load required {@code Column}s.
* @return {@code Column} configured in given {@code ReadRequest} are
* returned with defined {@link Unit} setup.
* @throws AoException
* Throw if unable to load all available {@code Column}s.
* @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);
}
}
/**
* Returns the {@link ValueMatrix} CORBA service object associated with
* given {@link ReadRequest}.
*
* @param readRequest
* The {@code ReadRequest}.
* @return The {@code ValueMatrix} is returned.
* @throws AoException
* Thrown if unable to load the {@code ValueMatrix}.
*/
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);
}
/**
* Releases given {@link ValueMatrix} CORBA object.
*
* @param valueMatrix
* Will be released.
*/
private void releaseValueMatrix(ValueMatrix valueMatrix) {
if (valueMatrix == null) {
return;
}
try {
valueMatrix.destroy();
} catch (AoException aoe) {
// ignore
} finally {
valueMatrix._release();
}
}
/**
* Releases each CORBA {@link Column} object.
*
* @param columns
* Will be released.
*/
private void releaseColumns(Column[] columns) {
if (columns == null) {
return;
}
for (Column column : columns) {
try {
column.destroy();
} catch (AoException e) {
// ignore
} finally {
column._release();
}
}
}
}