| /********************************************************************************
|
| * 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.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} -> {@link ScalarType#FLOAT}</li> |
| * <li>{@link ScalarType#SHORT} -> {@link ScalarType#FLOAT}</li> |
| * <li>{@link ScalarType#INTEGER} -> {@link ScalarType#FLOAT}</li> |
| * <li>{@link ScalarType#LONG} -> {@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; |
| } |
| |
| /** |
| * 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"); |
| } |
| } |
| |
| } |