blob: a08bd991af8f0b942534ad211a15a5759671e573 [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.massdata;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.mdm.api.base.model.AxisType;
import org.eclipse.mdm.api.base.model.Channel;
import org.eclipse.mdm.api.base.model.ChannelGroup;
import org.eclipse.mdm.api.base.model.ScalarType;
import org.eclipse.mdm.api.base.model.SequenceRepresentation;
import org.eclipse.mdm.api.base.model.Unit;
/**
* Holds required data to write mass data.
*
* @since 1.0.0
* @author Viktor Stoehr, Gigatronik Ingolstadt GmbH
* @author Sebastian Dirsch, Gigatronik Ingolstadt GmbH
*/
public final class WriteRequest {
// ======================================================================
// Instance variables
// ======================================================================
private final List<ExternalComponent> externalComponents = new ArrayList<>();
private final ChannelGroup channelGroup;
private final Channel channel;
private final AxisType axisType;
private SequenceRepresentation sequenceRepresentation;
private double[] generationParameters;
private boolean independent;
private ScalarType rawScalarType;
private Object values;
private boolean allValid;
private boolean[] flags;
// ======================================================================
// Constructors
// ======================================================================
/**
* Constructor.
*
* @param channelGroup The {@link ChannelGroup} for this request.
* @param channel The {@link Channel} specified mass data will be dedicated
* to.
* @param axisType The {@link AxisType} of the written mass data.
*/
private WriteRequest(ChannelGroup channelGroup, Channel channel, AxisType axisType) {
this.channelGroup = channelGroup;
this.channel = channel;
this.axisType = axisType;
}
// ======================================================================
// Public methods
// ======================================================================
/**
* Starts a new {@link WriteRequest} by returning a {@link WriteRequestBuilder}.
*
* @param channelGroup The {@link ChannelGroup} for this request.
* @param channel The {@link Channel} specified mass data will be dedicated
* to.
* @param axisType The {@link AxisType} of the written mass data.
* @return A {@code WriteRequestBuilder} is returned.
*/
public static WriteRequestBuilder create(ChannelGroup channelGroup, Channel channel, AxisType axisType) {
return new WriteRequestBuilder(new WriteRequest(channelGroup, channel, axisType));
}
/**
* Returns the {@link ChannelGroup} of this request.
*
* @return The {@code ChannelGroup} is returned.
*/
public ChannelGroup getChannelGroup() {
return channelGroup;
}
/**
* Returns the {@link Channel} of this request.
*
* @return The {@code Channel} is returned.
*/
public Channel getChannel() {
return channel;
}
/**
* Returns the {@link AxisType} of this request.
*
* @return The {@code AxisType} is returned.
*/
public AxisType getAxisType() {
return axisType;
}
/**
* Returns the {@link SequenceRepresentation} of this request.
*
* @return The {@code SequenceRepresentation} is returned.
*/
public SequenceRepresentation getSequenceRepresentation() {
return sequenceRepresentation;
}
/**
* Returns the generation parameters of this request. The length of the returned
* array depends on the {@link SequenceRepresentation} of this request.
*
* <p>
* <b>NOTE:</b> In case of an implicit sequence representation this method will
* always return an empty array since these generation parameters are correctly
* typed and stored as measured values.
*
* @return If none available, then an empty array is returned.
*/
public double[] getGenerationParameters() {
return generationParameters == null ? new double[0] : generationParameters.clone();
}
/**
* Returns the independent flag of this request.
*
* @return Returns {@code true} if the measured values do not depend on those of
* other {@link Channel}s within their common {@link ChannelGroup}.
*/
public boolean isIndependent() {
return independent;
}
/**
* Checks whether this request has measured values.
*
* @return Returns {@code true} if {@link SequenceRepresentation#isExternal()}
* returns {@code false}.
* @see #hasExternalComponents()
*/
public boolean hasValues() {
return !getSequenceRepresentation().isExternal();
}
/**
* Returns the stored measured values.
*
* @return The measured values are returned.
* @throws IllegalStateException Thrown if values are not available.
*/
public Object getValues() {
if (hasValues()) {
return values;
}
throw new IllegalStateException("Values are not available.");
}
/**
* Checks whether this request has measured values, stored in externally linked
* files.
*
* @return Returns {@code true} if {@link SequenceRepresentation#isExternal()}
* returns {@code true}.
* @see #hasValues()
*/
public boolean hasExternalComponents() {
return getSequenceRepresentation().isExternal();
}
/**
* Returns the configurations for measured values stored in externally
* referenced files.
*
* @return Returned {@code List} is unmodifiable.
* @throws IllegalStateException Thrown if configurations are not available.
*/
public List<ExternalComponent> getExternalComponents() {
if (!hasExternalComponents()) {
throw new IllegalStateException("External components are not available.");
}
return Collections.unmodifiableList(externalComponents);
}
/**
* Returns the {@link ScalarType} of the stored measured value sequence.
*
* @return The raw {@code ScalarType} is returned.
*/
public ScalarType getRawScalarType() {
return rawScalarType;
}
/**
* Returns the calculated {@link ScalarType} which reflects the final
* {@code ScalarType} of the generated measured value sequence. If
* {@link #getGenerationParameters()} returns a not empty array and
* {@link #getRawScalarType()} is an integer type (byte, short, int, long), then
* the returned {@code ScalarType} is bumped to the next suitable floating point
* type as listed below:
*
* <ul>
* <li>{@link ScalarType#BYTE} -&gt; {@link ScalarType#FLOAT}</li>
* <li>{@link ScalarType#SHORT} -&gt; {@link ScalarType#FLOAT}</li>
* <li>{@link ScalarType#INTEGER} -&gt; {@link ScalarType#FLOAT}</li>
* <li>{@link ScalarType#LONG} -&gt; {@link ScalarType#DOUBLE}</li>
* </ul>
*
* @return The calculated {@code ScalarType} is returned.
*/
public ScalarType getCalculatedScalarType() {
if (getGenerationParameters().length > 0 && getRawScalarType().isIntegerType()) {
return getRawScalarType().isLong() ? ScalarType.DOUBLE : ScalarType.FLOAT;
}
return getRawScalarType();
}
/**
* Checks whether all measured values within the whole sequence are valid. If
* this method returns {@code true}, then {@link #getFlags()} will return an
* empty array.
*
* @return Returns {@code true} if all measured values are valid.
* @see #getFlags()
*/
public boolean areAllValid() {
return allValid;
}
/**
* Returns the validity flags sequence for the stored measured values. If
* {@link #areAllValid()} returns {@code false} this method will return an array
* with the same length as the measured values sequence, where each flag
* indicates whether the corresponding measured value is valid or not.
*
* @return The validity flags sequence is returned.
* @see #allValid
*/
public boolean[] getFlags() {
return flags.clone();
}
// ======================================================================
// Package methods
// ======================================================================
/**
* Sets the {@link SequenceRepresentation} for this request.
*
* @param sequenceRepresentation The {@link SequenceRepresentation}.
*/
void setSequenceRepresentation(SequenceRepresentation sequenceRepresentation) {
this.sequenceRepresentation = sequenceRepresentation;
}
/**
* Sets generation parameters for this request.
*
* @param generationParameters The generation parameters.
*/
void setGenerationParameters(double[] generationParameters) {
this.generationParameters = generationParameters.clone();
}
/**
* Sets the independent flag for this request.
*/
void setIndependent() {
independent = true;
}
/**
* Sets the independent flag for this request to the value specified.
*
* @param independent The independent flag.
*/
void setIndependent(boolean independent) {
this.independent = independent;
}
/**
* Triggers an adjustment of the generation parameters and modification of the
* {@link SequenceRepresentation} of this request to match the {@link Channel}s
* default {@link Unit}.
*
* @param sourceUnit The {@link Unit} of the measured values.
*/
void setSourceUnit(Unit sourceUnit) {
throw new UnsupportedOperationException("Conversion between units is not implemented yet.");
}
/**
* Sets the raw {@link ScalarType} for this request.
*
* @param rawScalarType The {@link ScalarType}.
*/
void setRawScalarType(ScalarType rawScalarType) {
this.rawScalarType = rawScalarType;
}
/**
* Sets the measured values sequence where each value in the sequence is
* expected to be valid.
*
* @param values The measured value sequence.
* @throws IllegalStateException Thrown if {@link #hasValues()} returns
* {@code false}.
*/
void setValues(Object values) {
if (hasValues()) {
this.values = values;
allValid = true;
} else {
throw new IllegalStateException("Measured values stored in externally linked files expected.");
}
}
/**
* Sets the measured values sequence where each value's validity is specified in
* the given flags array.
*
* @param values The measured value sequence.
* @param flags The validity flag sequence.
* @throws IllegalStateException Thrown if {@link #hasValues()} returns
* {@code false}.
*/
void setValues(Object values, boolean[] flags) {
if (hasValues()) {
this.values = values;
this.flags = flags.clone();
} else {
throw new IllegalStateException("Measured values stored in externally linked files expected.");
}
}
/**
* Adds a configuration for measured values stored in externally linked files.
*
* @param externalComponent The new configuration.
* @throws IllegalStateException Thrown if {@link #hasExternalComponents()}
* returns {@code false}.
*/
void addExternalComponent(ExternalComponent externalComponent) {
if (hasExternalComponents()) {
externalComponents.add(externalComponent);
} else {
throw new IllegalStateException("Measured values expected");
}
}
}