From c65d8006cc6a714f3b6f6bd5107afa9d2c560c8a Mon Sep 17 00:00:00 2001 From: Salvatore Coppola <83589980+salvatore-coppola@users.noreply.github.com> Date: Mon, 7 Oct 2024 10:33:11 +0200 Subject: [PATCH] feat(asset.provider): Added type for Scale and Offset in Channels (#5418) * Added new field for Channel, scaleoffset.type which assign a type (Double, Float, Integer or Long) to scale and offset value used in the channel. Fixed bug on applyscaleoffset condition Now offsetScale Type is not mandatory to preserver backward compatibility Updated expected OCD rewritten adding a new ScaleOffsetType with DEFINED_BY_VALUE_TYPE minor fixes Moved ScaleOffsetType into org.eclipse.kura.channel Removed throwing IAE for old scale/offset getters Removed all ScaleOffsetType except for DOUBLE fixed tests fixed test Reverted org.eclipse.kura.type version change * Restore getKuraServicePid change from develop. * fix: Sonar fixes Signed-off-by: MMaiero * fix: Added another sonar suggested improvement Signed-off-by: MMaiero --------- Signed-off-by: MMaiero Co-authored-by: MMaiero --- .../org.eclipse.kura.api/META-INF/MANIFEST.MF | 2 +- .../org/eclipse/kura/channel/Channel.java | 222 +++++++++++++----- .../eclipse/kura/channel/ScaleOffsetType.java | 49 ++++ .../META-INF/MANIFEST.MF | 4 +- .../kura/asset/provider/AssetConstants.java | 5 +- .../kura/asset/provider/BaseAsset.java | 138 ++++++++--- .../asset/provider/BaseChannelDescriptor.java | 24 +- .../provider/BaseAssetConfiguration.java | 53 +++-- .../META-INF/MANIFEST.MF | 2 +- .../META-INF/MANIFEST.MF | 2 +- .../kura/asset/provider/test/AssetTest.java | 4 +- .../rest/wire/provider/test/Snippets.java | 21 +- .../wire/asset/test/ScaleOffsetTest.java | 67 ++++-- .../wire/asset/test/WireAssetTestBase.java | 76 +++--- 14 files changed, 491 insertions(+), 178 deletions(-) create mode 100644 kura/org.eclipse.kura.api/src/main/java/org/eclipse/kura/channel/ScaleOffsetType.java diff --git a/kura/org.eclipse.kura.api/META-INF/MANIFEST.MF b/kura/org.eclipse.kura.api/META-INF/MANIFEST.MF index a607495520a..5a6e3e2c168 100644 --- a/kura/org.eclipse.kura.api/META-INF/MANIFEST.MF +++ b/kura/org.eclipse.kura.api/META-INF/MANIFEST.MF @@ -15,7 +15,7 @@ Export-Package: org.eclipse.kura;version="1.7.0", org.eclipse.kura.bluetooth.le.beacon.listener;version="1.0.0", org.eclipse.kura.certificate;version="2.1.0", org.eclipse.kura.certificate.enrollment;version="1.0.0", - org.eclipse.kura.channel;version="1.2.0", + org.eclipse.kura.channel;version="1.3.0", org.eclipse.kura.channel.listener;version="1.0.0", org.eclipse.kura.clock;version="1.0.1", org.eclipse.kura.cloud;version="1.1.0", diff --git a/kura/org.eclipse.kura.api/src/main/java/org/eclipse/kura/channel/Channel.java b/kura/org.eclipse.kura.api/src/main/java/org/eclipse/kura/channel/Channel.java index 142247ce536..242d67582e8 100644 --- a/kura/org.eclipse.kura.api/src/main/java/org/eclipse/kura/channel/Channel.java +++ b/kura/org.eclipse.kura.api/src/main/java/org/eclipse/kura/channel/Channel.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2021 Eurotech and/or its affiliates and others + * Copyright (c) 2017, 2024 Eurotech and/or its affiliates and others * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -17,6 +17,7 @@ import java.util.Collections; import java.util.Map; +import java.util.Objects; import org.eclipse.kura.annotation.NotThreadSafe; import org.eclipse.kura.type.DataType; @@ -35,6 +36,14 @@ @ProviderType public class Channel { + private static final String MESSAGE_CHANNEL_CONFIGURATION_CANNOT_BE_NULL = "Channel configuration cannot be null"; + + private static final String MESSAGE_CHANNEL_VALUE_TYPE_CANNOT_BE_NULL = "Channel value type cannot be null"; + + private static final String MESSAGE_CHANNEL_TYPE_CANNOT_BE_NULL = "Channel type cannot be null"; + + private static final String MESSAGE_CHANNEL_NAME_CANNOT_BE_NULL = "Channel name cannot be null"; + /** The communication channel configuration. */ private final transient Map configuration; @@ -49,11 +58,22 @@ public class Channel { */ private DataType valueType; - private double valueScale; + /** + * The data type of the scale/offset as expected from the operation + */ + private ScaleOffsetType scaleOffsetType = ScaleOffsetType.DEFINED_BY_VALUE_TYPE; - private double valueOffset; + /* + * The value used to scale the value + */ + private Number valueScale = 1.0d; - private String unit; + /** + * The value used as offset of the value + */ + private Number valueOffset = 0.0d; + + private String unit = ""; /** * Determines if this channel is enabled or not @@ -73,21 +93,68 @@ public class Channel { * the configuration * @throws NullPointerException * if any of the arguments is null + * @deprecated Use {@link #Channel(String, ChannelType, DataType, ScaleOffsetType, Number, Number, Map)} */ + + @Deprecated public Channel(final String name, final ChannelType type, final DataType valueType, final Map config) { - requireNonNull(name, "Channel name cannot be null"); - requireNonNull(type, "Channel type cannot be null"); - requireNonNull(valueType, "Channel value type cannot be null"); - requireNonNull(config, "Channel configuration cannot be null"); + + requireNonNull(name, MESSAGE_CHANNEL_NAME_CANNOT_BE_NULL); + requireNonNull(type, MESSAGE_CHANNEL_TYPE_CANNOT_BE_NULL); + requireNonNull(valueType, MESSAGE_CHANNEL_VALUE_TYPE_CANNOT_BE_NULL); + requireNonNull(config, MESSAGE_CHANNEL_CONFIGURATION_CANNOT_BE_NULL); this.configuration = Collections.unmodifiableMap(config); this.name = name; this.type = type; this.valueType = valueType; - this.valueScale = 1.0d; - this.valueOffset = 0d; - this.unit = ""; + } + + /** + * Instantiates a new channel. + * + * @param name + * the name for this channel + * @param type + * the type + * @param valueType + * the value type + * @param valueScale + * the value used to scale the value, must have the same {@link DataType} as valueOffset + * @param valueOffset + * the value used as offset of the value, must have the same {@link DataType} as valueScale + * @param config + * the configuration + * @throws NullPointerException + * if any of the arguments is null + * @throws IllegalArgumentException + * if any of the valueScale and valueOffset have different types + * + * @since 2.8 + */ + public Channel(final String name, final ChannelType type, final DataType valueType, + final ScaleOffsetType scaleOffsetType, final Number valueScale, final Number valueOffset, + final Map config) { + + requireNonNull(name, MESSAGE_CHANNEL_NAME_CANNOT_BE_NULL); + requireNonNull(type, MESSAGE_CHANNEL_TYPE_CANNOT_BE_NULL); + requireNonNull(valueType, MESSAGE_CHANNEL_VALUE_TYPE_CANNOT_BE_NULL); + requireNonNull(config, MESSAGE_CHANNEL_CONFIGURATION_CANNOT_BE_NULL); + + requireNonNull(scaleOffsetType, "Scale/Offset type cannot be null"); + requireNonNull(valueScale, "Channel value scale cannot be null"); + requireNonNull(valueOffset, "Channel value offset cannot be null"); + + this.configuration = Collections.unmodifiableMap(config); + this.name = name; + this.type = type; + this.valueType = valueType; + + this.scaleOffsetType = scaleOffsetType; + this.valueScale = valueScale; + this.valueOffset = valueOffset; + } /** @@ -126,6 +193,17 @@ public DataType getValueType() { return this.valueType; } + /** + * Gets the Scale/Offset type as expected for operations. + * + * @return the value type + * + * @since 2.8 + */ + public ScaleOffsetType getScaleOffsetType() { + return this.scaleOffsetType; + } + /** * Returns a boolean indicating if this channel is enabled or not * @@ -143,8 +221,23 @@ public boolean isEnabled() { * @return a double that represents the scale factor to be applied to the read value * * @since 2.3 + * + * @deprecated Use {@link #getValueScaleAsNumber()} */ + @Deprecated public double getValueScale() { + return this.valueScale.doubleValue(); + } + + /** + * Returns a {@link Number} that represents the scale factor to be applied to the read + * value + * + * @return a {@link Number} that represents the scale factor to be applied to the read value + * + * @since 2.8 + */ + public Number getValueScaleAsNumber() { return this.valueScale; } @@ -154,8 +247,23 @@ public double getValueScale() { * @return a double that represents the offset to be applied to the read value * * @since 2.3 + * + * @deprecated Use {@link #getValueOffsetAsNumber()} */ + @Deprecated public double getValueOffset() { + return this.valueOffset.doubleValue(); + } + + /** + * Returns a {@link TypedValue} that represents the offset factor to be applied to the read + * value + * + * @return a {@link TypedValue} that represents the offset factor to be applied to the read value + * + * @since 2.8 + */ + public Number getValueOffsetAsNumber() { return this.valueOffset; } @@ -175,7 +283,7 @@ public String getUnit() { * if the argument is null */ public void setName(final String name) { - requireNonNull(name, "Channel name cannot be null"); + requireNonNull(name, MESSAGE_CHANNEL_NAME_CANNOT_BE_NULL); this.name = name; } @@ -188,7 +296,7 @@ public void setName(final String name) { * if the argument is null */ public void setType(final ChannelType type) { - requireNonNull(type, "Channel type cannot be null"); + requireNonNull(type, MESSAGE_CHANNEL_TYPE_CANNOT_BE_NULL); this.type = type; } @@ -201,10 +309,25 @@ public void setType(final ChannelType type) { * if the argument is null */ public void setValueType(final DataType valueType) { - requireNonNull(valueType, "Channel value type cannot be null"); + requireNonNull(valueType, MESSAGE_CHANNEL_VALUE_TYPE_CANNOT_BE_NULL); this.valueType = valueType; } + /** + * Set the type of the scale/offset. + * + * @param scaleOffsetType + * the scale/offset type + * @throws NullPointerException + * if the argument is null + * + * @since 2.8 + */ + public void setScaleOffsetType(ScaleOffsetType scaleOffsetType) { + requireNonNull(this.valueType, "Scale/Offset value type cannot be null"); + this.scaleOffsetType = scaleOffsetType; + } + /** * Specifies if this channel is enabled or not * @@ -227,6 +350,17 @@ public void setScale(double scale) { this.valueScale = scale; } + /** + * Specifies the scale to be applied to the channel value + * + * @param scale + * a {@link Number} value that specifies the scale to be applied to the channel value + * @since 2.8 + */ + public void setScale(Number scale) { + this.valueScale = scale; + } + /** * Specifies the offset to be applied to the channel value * @@ -238,6 +372,17 @@ public void setOffset(double offset) { this.valueOffset = offset; } + /** + * Specifies the offset to be applied to the channel value + * + * @param offset + * a {@link Number} value that specifies the offset to be applied to the channel value + * @since 2.8 + */ + public void setOffset(Number offset) { + this.valueOffset = offset; + } + /** * @since 2.3 */ @@ -294,19 +439,8 @@ public ChannelRecord createWriteRecord(TypedValue value) { @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (this.isEnabled ? 1231 : 1237); - result = prime * result + (this.name == null ? 0 : this.name.hashCode()); - result = prime * result + (this.type == null ? 0 : this.type.hashCode()); - result = prime * result + (this.unit == null ? 0 : this.unit.hashCode()); - long temp; - temp = Double.doubleToLongBits(this.valueOffset); - result = prime * result + (int) (temp ^ temp >>> 32); - temp = Double.doubleToLongBits(this.valueScale); - result = prime * result + (int) (temp ^ temp >>> 32); - result = prime * result + (this.valueType == null ? 0 : this.valueType.hashCode()); - return result; + return Objects.hash(this.isEnabled, this.name, this.scaleOffsetType, this.type, this.unit, this.valueOffset, + this.valueScale, this.valueType); } @Override @@ -318,36 +452,10 @@ public boolean equals(Object obj) { return false; } Channel other = (Channel) obj; - if (this.isEnabled != other.isEnabled) { - return false; - } - if (this.name == null) { - if (other.name != null) { - return false; - } - } else if (!this.name.equals(other.name)) { - return false; - } - if (this.type != other.type) { - return false; - } - if (this.unit == null) { - if (other.unit != null) { - return false; - } - } else if (!this.unit.equals(other.unit)) { - return false; - } - if (Double.doubleToLongBits(this.valueOffset) != Double.doubleToLongBits(other.valueOffset)) { - return false; - } - if (Double.doubleToLongBits(this.valueScale) != Double.doubleToLongBits(other.valueScale)) { - return false; - } - if (this.valueType != other.valueType) { - return false; - } - return true; + return this.isEnabled == other.isEnabled && Objects.equals(this.name, other.name) + && this.scaleOffsetType == other.scaleOffsetType && this.type == other.type + && Objects.equals(this.unit, other.unit) && Objects.equals(this.valueOffset, other.valueOffset) + && Objects.equals(this.valueScale, other.valueScale) && this.valueType == other.valueType; } } diff --git a/kura/org.eclipse.kura.api/src/main/java/org/eclipse/kura/channel/ScaleOffsetType.java b/kura/org.eclipse.kura.api/src/main/java/org/eclipse/kura/channel/ScaleOffsetType.java new file mode 100644 index 00000000000..b5cadd00056 --- /dev/null +++ b/kura/org.eclipse.kura.api/src/main/java/org/eclipse/kura/channel/ScaleOffsetType.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2024 Eurotech and/or its affiliates and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Eurotech + ******************************************************************************/ +package org.eclipse.kura.channel; + +/** + * This contains all the required type constants for representing + * Scale and Offset. + * + * @since 2.8 + */ +public enum ScaleOffsetType { + + DEFINED_BY_VALUE_TYPE, + + DOUBLE; + + /** + * Converts {@code stringScaleOffsetType}, if possible, to the related {@link ScaleOffsetType}. + * + * @param stringDataType + * String that we want to use to get the respective {@link ScaleOffsetType}. + * @return a ScaleOffsetType that corresponds to the String passed as argument. + * @throws IllegalArgumentException + * if the passed string does not correspond to an existing {@link ScaleOffsetType}. + */ + public static ScaleOffsetType getScaleOffsetType(String stringScaleOffsetType) { + + if (DEFINED_BY_VALUE_TYPE.name().equalsIgnoreCase(stringScaleOffsetType)) { + return DEFINED_BY_VALUE_TYPE; + } + + if (DOUBLE.name().equalsIgnoreCase(stringScaleOffsetType)) { + return DOUBLE; + } + + throw new IllegalArgumentException("Cannot convert to DataType"); + } + +} diff --git a/kura/org.eclipse.kura.asset.provider/META-INF/MANIFEST.MF b/kura/org.eclipse.kura.asset.provider/META-INF/MANIFEST.MF index 83a6fc0e072..7b213a75efc 100644 --- a/kura/org.eclipse.kura.asset.provider/META-INF/MANIFEST.MF +++ b/kura/org.eclipse.kura.asset.provider/META-INF/MANIFEST.MF @@ -10,7 +10,7 @@ Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))" Import-Package: org.eclipse.kura;version="[1.2,2.0)", org.eclipse.kura.annotation;version="[1.0,2.0)", org.eclipse.kura.asset;version="[1.0,1.1)", - org.eclipse.kura.channel;version="[1.1,2.0)", + org.eclipse.kura.channel;version="[1.2,2.0)", org.eclipse.kura.channel.listener;version="[1.0,1.1)", org.eclipse.kura.configuration;version="[1.1,2.0)", org.eclipse.kura.configuration.metatype;version="[1.1,2.0)", @@ -26,6 +26,6 @@ Import-Package: org.eclipse.kura;version="[1.2,2.0)", org.osgi.service.component;version="1.2.0", org.osgi.util.tracker;version="1.5.0", org.slf4j;version="1.6.4" -Export-Package: org.eclipse.kura.asset.provider;version="2.0.0" +Export-Package: org.eclipse.kura.asset.provider;version="2.1.0" Service-Component: OSGI-INF/*.xml Bundle-ActivationPolicy: lazy diff --git a/kura/org.eclipse.kura.asset.provider/src/main/java/org/eclipse/kura/asset/provider/AssetConstants.java b/kura/org.eclipse.kura.asset.provider/src/main/java/org/eclipse/kura/asset/provider/AssetConstants.java index a095c80df0d..914d37a85e5 100644 --- a/kura/org.eclipse.kura.asset.provider/src/main/java/org/eclipse/kura/asset/provider/AssetConstants.java +++ b/kura/org.eclipse.kura.asset.provider/src/main/java/org/eclipse/kura/asset/provider/AssetConstants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2021 Eurotech and/or its affiliates and others + * Copyright (c) 2016, 2024 Eurotech and/or its affiliates and others * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -45,6 +45,9 @@ public enum AssetConstants { /** Value type Property to be used in the configuration. */ VALUE_TYPE(CHANNEL_DEFAULT_PROPERTY_PREFIX.value() + "value.type"), + /** Scale Offset type Property to be used in the configuration. */ + SCALE_OFFSET_TYPE(CHANNEL_DEFAULT_PROPERTY_PREFIX.value() + "scaleoffset.type"), + /** Scale Property to be used in the configuration. */ VALUE_SCALE(CHANNEL_DEFAULT_PROPERTY_PREFIX.value() + "scale"), diff --git a/kura/org.eclipse.kura.asset.provider/src/main/java/org/eclipse/kura/asset/provider/BaseAsset.java b/kura/org.eclipse.kura.asset.provider/src/main/java/org/eclipse/kura/asset/provider/BaseAsset.java index ac5eeda71bd..63a287c5380 100644 --- a/kura/org.eclipse.kura.asset.provider/src/main/java/org/eclipse/kura/asset/provider/BaseAsset.java +++ b/kura/org.eclipse.kura.asset.provider/src/main/java/org/eclipse/kura/asset/provider/BaseAsset.java @@ -48,9 +48,11 @@ import org.eclipse.kura.channel.ChannelRecord; import org.eclipse.kura.channel.ChannelStatus; import org.eclipse.kura.channel.ChannelType; +import org.eclipse.kura.channel.ScaleOffsetType; import org.eclipse.kura.channel.listener.ChannelEvent; import org.eclipse.kura.channel.listener.ChannelListener; import org.eclipse.kura.configuration.ComponentConfiguration; +import org.eclipse.kura.configuration.ConfigurationService; import org.eclipse.kura.configuration.SelfConfiguringComponent; import org.eclipse.kura.core.configuration.ComponentConfigurationImpl; import org.eclipse.kura.core.configuration.metatype.Tad; @@ -60,10 +62,8 @@ import org.eclipse.kura.internal.asset.provider.BaseAssetConfiguration; import org.eclipse.kura.internal.asset.provider.DriverTrackerCustomizer; import org.eclipse.kura.type.DataType; -import org.eclipse.kura.type.DoubleValue; -import org.eclipse.kura.type.FloatValue; -import org.eclipse.kura.type.IntegerValue; -import org.eclipse.kura.type.LongValue; +import org.eclipse.kura.type.TypedValue; +import org.eclipse.kura.type.TypedValues; import org.osgi.service.component.ComponentContext; import org.osgi.util.tracker.ServiceTracker; import org.slf4j.Logger; @@ -224,10 +224,8 @@ private void reopenDriverTracker(final String driverId) { this.driverServiceTracker.close(); this.driverServiceTracker = null; } - final DriverTrackerCustomizer driverTrackerCustomizer = new DriverTrackerCustomizer( - this.context.getBundleContext(), this, driverId); this.driverServiceTracker = new ServiceTracker<>(this.context.getBundleContext(), Driver.class.getName(), - driverTrackerCustomizer); + new DriverTrackerCustomizer(this.context.getBundleContext(), this, driverId)); this.driverServiceTracker.open(); logger.debug("Attaching driver instance...Done"); @@ -292,13 +290,15 @@ public ComponentConfiguration getConfiguration() throws KuraException { final Map properties = this.config.getProperties(); + final String componentName = properties.get(ConfigurationService.KURA_SERVICE_PID).toString(); + Tocd ocd = this.config.getDefinition(); if (ocd == null) { ocd = getOCD(); } - return new ComponentConfigurationImpl(getKuraServicePid(), ocd, new HashMap<>(properties)); + return new ComponentConfigurationImpl(componentName, ocd, new HashMap<>(properties)); } /** @@ -379,16 +379,16 @@ public List read(final Set channelNames) throws KuraExcep validateChannel(channel, EnumSet.of(READ, READ_WRITE), "Channel type not within expected types (READ or READ_WRITE)"); } catch (Exception e) { - final ChannelRecord record = ChannelRecord.createStatusRecord(name, + final ChannelRecord channelRecord = ChannelRecord.createStatusRecord(name, new ChannelStatus(FAILURE, e.getMessage(), e)); - record.setTimestamp(System.currentTimeMillis()); - channelRecords.add(record); + channelRecord.setTimestamp(System.currentTimeMillis()); + channelRecords.add(channelRecord); continue; } - final ChannelRecord record = channel.createReadRecord(); - validRecords.add(record); - channelRecords.add(record); + final ChannelRecord channelRecord = channel.createReadRecord(); + validRecords.add(channelRecord); + channelRecords.add(channelRecord); } if (!validRecords.isEmpty()) { @@ -414,27 +414,103 @@ protected List getFinalRecords(List channelRecords } private boolean shouldApplyScaleAndOffset(final ChannelRecord channelRecord, final Channel channel) { - return !isNull(channelRecord) && !isNull(channelRecord.getValueType()) && !isNull(channelRecord.getValue()) - && (channel.getValueScale() != 1.0d || channel.getValueOffset() != 0.0d); + return !isNull(channelRecord) && // + !isNull(channelRecord.getValueType()) && // + !isNull(channelRecord.getValue()) && // + (!channel.getValueScaleAsNumber().equals(1.0d) || !channel.getValueOffsetAsNumber().equals(0.0d)); } + @SuppressWarnings("unchecked") private void applyScaleAndOffset(final ChannelRecord channelRecord, final Channel channel) { - final double channelScale = channel.getValueScale(); - final double channelOffset = channel.getValueOffset(); - - if (channelRecord.getValueType().equals(DataType.DOUBLE)) { - channelRecord.setValue( - new DoubleValue((double) channelRecord.getValue().getValue() * channelScale + channelOffset)); - } else if (channelRecord.getValueType().equals(DataType.FLOAT)) { - channelRecord.setValue(new FloatValue( - (float) channelRecord.getValue().getValue() * (float) channelScale + (float) channelOffset)); - } else if (channelRecord.getValueType().equals(DataType.INTEGER)) { - channelRecord.setValue(new IntegerValue( - (int) channelRecord.getValue().getValue() * (int) channelScale + (int) channelOffset)); - } else if (channelRecord.getValueType().equals(DataType.LONG)) { - channelRecord.setValue(new LongValue( - (long) channelRecord.getValue().getValue() * (long) channelScale + (long) channelOffset)); + final Number channelScale = channel.getValueScaleAsNumber(); + final Number channelOffset = channel.getValueOffsetAsNumber(); + + switch (channel.getValueType()) { + case DOUBLE: + case FLOAT: + case INTEGER: + case LONG: + TypedValue newValue; + if (channel.getScaleOffsetType() == ScaleOffsetType.DEFINED_BY_VALUE_TYPE) { + newValue = calculateScaleAndOffsetByTypedValue((TypedValue) channelRecord.getValue(), + channelScale, channelOffset); + } else { + newValue = calculateScaleAndOffset((TypedValue) channelRecord.getValue(), + channel.getScaleOffsetType(), channelScale, channelOffset); + } + + channelRecord.setValue(newValue); + break; + case BOOLEAN: + case BYTE_ARRAY: + case STRING: + // DO NOTHING + break; + default: + throw new IllegalStateException("Unsupported channel type: " + channel.getValueType()); } + + } + + // legacy method + private TypedValue calculateScaleAndOffsetByTypedValue(TypedValue typedValue, + Number scale, Number offset) { + + Number result; + + switch (typedValue.getType()) { + case DOUBLE: + result = (double) typedValue.getValue() * scale.doubleValue() + offset.doubleValue(); + break; + case FLOAT: + result = (float) typedValue.getValue() * scale.floatValue() + offset.floatValue(); + break; + case INTEGER: + result = (int) typedValue.getValue() * scale.intValue() + offset.intValue(); + break; + case LONG: + result = (long) typedValue.getValue() * scale.longValue() + offset.longValue(); + break; + default: + throw new IllegalArgumentException("Unknown value type" + typedValue.getType()); + } + + return toTypedValue(typedValue.getType(), result); + + } + + private TypedValue calculateScaleAndOffset(TypedValue typedValue, + ScaleOffsetType scaleOffsetType, Number scale, Number offset) { + + Number result = null; + + if (ScaleOffsetType.DOUBLE.equals(scaleOffsetType)) { + result = scale.doubleValue() * typedValue.getValue().doubleValue() + offset.doubleValue(); + } else { + throw new IllegalArgumentException("Invalid scale/offset type"); + } + + return toTypedValue(typedValue.getType(), result); + + } + + private static TypedValue toTypedValue(final DataType type, final Number value) { + Objects.requireNonNull(type, "type cannot be null"); + Objects.requireNonNull(value, "value cannot be null"); + + switch (type) { + case DOUBLE: + return TypedValues.newDoubleValue(value.doubleValue()); + case FLOAT: + return TypedValues.newFloatValue(value.floatValue()); + case INTEGER: + return TypedValues.newIntegerValue(value.intValue()); + case LONG: + return TypedValues.newLongValue(value.longValue()); + default: + throw new IllegalArgumentException(value + " cannot be converted into a TypedValue of type " + type); + } + } public boolean hasReadChannels() { diff --git a/kura/org.eclipse.kura.asset.provider/src/main/java/org/eclipse/kura/asset/provider/BaseChannelDescriptor.java b/kura/org.eclipse.kura.asset.provider/src/main/java/org/eclipse/kura/asset/provider/BaseChannelDescriptor.java index 66ea7cd9184..b476a0c1dc8 100644 --- a/kura/org.eclipse.kura.asset.provider/src/main/java/org/eclipse/kura/asset/provider/BaseChannelDescriptor.java +++ b/kura/org.eclipse.kura.asset.provider/src/main/java/org/eclipse/kura/asset/provider/BaseChannelDescriptor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2021 Eurotech and/or its affiliates and others + * Copyright (c) 2016, 2024 Eurotech and/or its affiliates and others * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -24,6 +24,7 @@ import java.util.List; import org.eclipse.kura.channel.ChannelType; +import org.eclipse.kura.channel.ScaleOffsetType; import org.eclipse.kura.configuration.metatype.Option; import org.eclipse.kura.core.configuration.metatype.Tad; import org.eclipse.kura.core.configuration.metatype.Toption; @@ -61,6 +62,15 @@ *
  • STRING
  • *
  • BYTE_ARRAY
  • * + * + * The scaleoffset.type would be one of the following: + *
      + *
    • DEFINED_BY_VALUE_TYPE
    • + *
    • INTEGER
    • + *
    • DOUBLE
    • + *
    • FLOAT
    • + *
    • LONG
    • + *
    * * @see org.eclipse.kura.asset.AssetConfiguration */ @@ -133,6 +143,18 @@ protected BaseChannelDescriptor() { this.defaultElements.add(valueType); + final Tad scaleOffsetType = new Tad(); + scaleOffsetType.setName(AssetConstants.SCALE_OFFSET_TYPE.value().substring(1)); + scaleOffsetType.setId(AssetConstants.SCALE_OFFSET_TYPE.value()); + scaleOffsetType.setDescription("Scale/Offset type of the channel"); + scaleOffsetType.setType(Tscalar.STRING); + scaleOffsetType.setRequired(false); + scaleOffsetType.setDefault(ScaleOffsetType.DEFINED_BY_VALUE_TYPE.name()); + + addOptions(scaleOffsetType, ScaleOffsetType.values()); + + this.defaultElements.add(scaleOffsetType); + final Tad valueScale = new Tad(); valueScale.setName(VALUE_SCALE.value().substring(1)); valueScale.setId(VALUE_SCALE.value()); diff --git a/kura/org.eclipse.kura.asset.provider/src/main/java/org/eclipse/kura/internal/asset/provider/BaseAssetConfiguration.java b/kura/org.eclipse.kura.asset.provider/src/main/java/org/eclipse/kura/internal/asset/provider/BaseAssetConfiguration.java index 74de53fa19d..46a0d440b56 100644 --- a/kura/org.eclipse.kura.asset.provider/src/main/java/org/eclipse/kura/internal/asset/provider/BaseAssetConfiguration.java +++ b/kura/org.eclipse.kura.asset.provider/src/main/java/org/eclipse/kura/internal/asset/provider/BaseAssetConfiguration.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2021 Eurotech and/or its affiliates and others + * Copyright (c) 2016, 2024 Eurotech and/or its affiliates and others * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -40,6 +40,7 @@ import org.eclipse.kura.channel.Channel; import org.eclipse.kura.channel.ChannelRecord; import org.eclipse.kura.channel.ChannelType; +import org.eclipse.kura.channel.ScaleOffsetType; import org.eclipse.kura.configuration.ConfigurationService; import org.eclipse.kura.configuration.metatype.AD; import org.eclipse.kura.configuration.metatype.Option; @@ -328,22 +329,31 @@ private static DataType getDataType(final Map properties) { return DataType.getDataType(valueTypeProp); } - private static double getValueScale(final Map properties) { + private static ScaleOffsetType getScaleOffsetType(final Map properties) { + final String scaleOffsetypeProp = (String) properties.get(AssetConstants.SCALE_OFFSET_TYPE.value()); + + if (scaleOffsetypeProp == null) { + return ScaleOffsetType.DEFINED_BY_VALUE_TYPE; + } + return ScaleOffsetType.getScaleOffsetType(scaleOffsetypeProp); + } + + private static Number getValueScale(final Map properties) { final String valueScale = (String) properties.get(VALUE_SCALE.value()); if (valueScale == null) { return 1.0d; } - return Double.valueOf(valueScale); + return parseScaleOffsetTypedValue(getScaleOffsetType(properties), valueScale); } - private static double getValueOffset(final Map properties) { - final String valueScale = (String) properties.get(VALUE_OFFSET.value()); + private static Number getValueOffset(final Map properties) { + final String valueOffset = (String) properties.get(VALUE_OFFSET.value()); - if (valueScale == null) { + if (valueOffset == null) { return 0.0d; } - return Double.valueOf(valueScale); + return parseScaleOffsetTypedValue(getScaleOffsetType(properties), valueOffset); } private static String getUnit(final Map properties) { @@ -376,25 +386,33 @@ private static Channel extractChannel(final String channelName, final Map fillOcdDefaults(final Map properties, final Tocd ocd, @@ -403,4 +421,5 @@ private static Map fillOcdDefaults(final Map pro defaultProperties.putAll(properties); return defaultProperties; } + } diff --git a/kura/org.eclipse.kura.web2/META-INF/MANIFEST.MF b/kura/org.eclipse.kura.web2/META-INF/MANIFEST.MF index f2105a32f56..5ca6aa81455 100644 --- a/kura/org.eclipse.kura.web2/META-INF/MANIFEST.MF +++ b/kura/org.eclipse.kura.web2/META-INF/MANIFEST.MF @@ -27,7 +27,7 @@ Import-Package: com.eclipsesource.json;version="0.9.5", org.eclipse.kura;version="[1.2,2.0)", org.eclipse.kura.annotation;version="[1.0,2.0)", org.eclipse.kura.asset;version="[0.9,2.0)", - org.eclipse.kura.asset.provider;version="[2.0,2.1)", + org.eclipse.kura.asset.provider;version="[2.1,2.2)", org.eclipse.kura.audit;version="[1.0,2.0)", org.eclipse.kura.certificate;version="[2.1,3.0)", org.eclipse.kura.channel;version="[1.0,2.0)", diff --git a/kura/org.eclipse.kura.wire.component.provider/META-INF/MANIFEST.MF b/kura/org.eclipse.kura.wire.component.provider/META-INF/MANIFEST.MF index 89285207779..5fad72791f9 100644 --- a/kura/org.eclipse.kura.wire.component.provider/META-INF/MANIFEST.MF +++ b/kura/org.eclipse.kura.wire.component.provider/META-INF/MANIFEST.MF @@ -10,7 +10,7 @@ Import-Package: org.apache.logging.log4j;version="2.8.2", org.apache.logging.log4j.util;version="2.8.2", org.eclipse.kura;version="[1.2,2.0)", org.eclipse.kura.asset;version="[1.0,2.0)", - org.eclipse.kura.asset.provider;version="[2.0,2.1)", + org.eclipse.kura.asset.provider;version="[2.1,2.2)", org.eclipse.kura.channel;version="[1.0,2.0)", org.eclipse.kura.channel.listener;version="[1.0,2.0)", org.eclipse.kura.clock;version="[1.0,2.0)", diff --git a/kura/test/org.eclipse.kura.asset.provider.test/src/main/java/org/eclipse/kura/asset/provider/test/AssetTest.java b/kura/test/org.eclipse.kura.asset.provider.test/src/main/java/org/eclipse/kura/asset/provider/test/AssetTest.java index e098ae1ef14..a7c1e3bfbc4 100644 --- a/kura/test/org.eclipse.kura.asset.provider.test/src/main/java/org/eclipse/kura/asset/provider/test/AssetTest.java +++ b/kura/test/org.eclipse.kura.asset.provider.test/src/main/java/org/eclipse/kura/asset/provider/test/AssetTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2021 Eurotech and/or its affiliates and others + * Copyright (c) 2016, 2024 Eurotech and/or its affiliates and others * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -486,7 +486,7 @@ public void testGetConfiguration() throws KuraException { List ads = ocd.getAD(); assertNotNull(ads); - assertEquals(34, ads.size()); // description, driver, 32 from BaseChannelDescriptor and StubChannelDescriptor + assertEquals(38, ads.size()); // description, driver, 32 from BaseChannelDescriptor and StubChannelDescriptor assertEquals("asset.desc", ads.get(0).getId()); assertEquals("driver.pid", ads.get(1).getId()); diff --git a/kura/test/org.eclipse.kura.rest.wire.provider.test/src/main/java/org/eclipse/kura/rest/wire/provider/test/Snippets.java b/kura/test/org.eclipse.kura.rest.wire.provider.test/src/main/java/org/eclipse/kura/rest/wire/provider/test/Snippets.java index 2ed8b775daf..3984c28c004 100644 --- a/kura/test/org.eclipse.kura.rest.wire.provider.test/src/main/java/org/eclipse/kura/rest/wire/provider/test/Snippets.java +++ b/kura/test/org.eclipse.kura.rest.wire.provider.test/src/main/java/org/eclipse/kura/rest/wire/provider/test/Snippets.java @@ -96,6 +96,25 @@ public class Snippets { + " \"isRequired\": true\n" // + " },\n" // + " {\n" // + + " \"option\": [\n" // + + " {\n" // + + " \"label\": \"DEFINED_BY_VALUE_TYPE\",\n" // + + " \"value\": \"DEFINED_BY_VALUE_TYPE\"\n" // + + " },\n" // + + " {\n" // + + " \"label\": \"DOUBLE\",\n" // + + " \"value\": \"DOUBLE\"\n" // + + " }\n" // + + " ],\n" // + + " \"name\": \"scaleoffset.type\",\n" // + + " \"description\": \"Scale/Offset type of the channel\",\n" // + + " \"id\": \"+scaleoffset.type\",\n" // + + " \"type\": \"STRING\",\n" // + + " \"cardinality\": 0,\n" // + + " \"defaultValue\": \"DEFINED_BY_VALUE_TYPE\",\n" // + + " \"isRequired\": false\n" // + + " },\n" // + + " {\n" // + " \"name\": \"scale\",\n" // + " \"description\": \"Scale to be applied to the numeric value of the channel\",\n" // + " \"id\": \"+scale\",\n" // @@ -413,7 +432,7 @@ public class Snippets { + " \"cardinality\": 0,\n" // + " \"defaultValue\": \"10\",\n" // + " \"isRequired\": true\n" // - + " },\n" // + + " },\n" // + " {\n" // + " \"option\": [\n" // + " {\n" // diff --git a/kura/test/org.eclipse.kura.wire.component.provider.test/src/main/java/org/eclipse/kura/internal/wire/asset/test/ScaleOffsetTest.java b/kura/test/org.eclipse.kura.wire.component.provider.test/src/main/java/org/eclipse/kura/internal/wire/asset/test/ScaleOffsetTest.java index c4e099fbbb6..e82a77c6a0b 100644 --- a/kura/test/org.eclipse.kura.wire.component.provider.test/src/main/java/org/eclipse/kura/internal/wire/asset/test/ScaleOffsetTest.java +++ b/kura/test/org.eclipse.kura.wire.component.provider.test/src/main/java/org/eclipse/kura/internal/wire/asset/test/ScaleOffsetTest.java @@ -1,19 +1,20 @@ /******************************************************************************* - * Copyright (c) 2023 Eurotech and/or its affiliates and others - * + * Copyright (c) 2024 Eurotech and/or its affiliates and others + * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 - * + * * Contributors: * Eurotech *******************************************************************************/ package org.eclipse.kura.internal.wire.asset.test; -import java.util.OptionalDouble; +import java.util.Optional; +import org.eclipse.kura.channel.ScaleOffsetType; import org.eclipse.kura.type.DataType; import org.junit.Test; import org.junit.runner.RunWith; @@ -24,7 +25,8 @@ public class ScaleOffsetTest extends WireAssetTestBase { @Test public void shouldSupportMissingScaleOffset() { - givenAssetChannel("foo", DataType.DOUBLE, OptionalDouble.empty(), OptionalDouble.empty()); + givenAssetChannel("foo", DataType.DOUBLE, ScaleOffsetType.DEFINED_BY_VALUE_TYPE, Optional.empty(), + Optional.empty()); whenDriverProducesValue("foo", 1.0d); @@ -33,7 +35,7 @@ public void shouldSupportMissingScaleOffset() { @Test public void shouldApplyScaleToDouble() { - givenAssetChannel("foo", DataType.DOUBLE, OptionalDouble.of(3.0d), OptionalDouble.empty()); + givenAssetChannel("foo", DataType.DOUBLE, ScaleOffsetType.DOUBLE, Optional.of(3.0d), Optional.empty()); whenDriverProducesValue("foo", 1.0d); @@ -42,7 +44,7 @@ public void shouldApplyScaleToDouble() { @Test public void shouldApplyScaleToFloat() { - givenAssetChannel("foo", DataType.FLOAT, OptionalDouble.of(3.0d), OptionalDouble.empty()); + givenAssetChannel("foo", DataType.FLOAT, ScaleOffsetType.DOUBLE, Optional.of(3.0d), Optional.empty()); whenDriverProducesValue("foo", 1.0f); @@ -50,8 +52,8 @@ public void shouldApplyScaleToFloat() { } @Test - public void shouldApplyScaleToIngeger() { - givenAssetChannel("foo", DataType.INTEGER, OptionalDouble.of(3.0d), OptionalDouble.empty()); + public void shouldApplyScaleToInteger() { + givenAssetChannel("foo", DataType.INTEGER, ScaleOffsetType.DOUBLE, Optional.of(3.0d), Optional.empty()); whenDriverProducesValue("foo", 1); @@ -59,8 +61,27 @@ public void shouldApplyScaleToIngeger() { } @Test - public void shouldApplyScaleToLong() { - givenAssetChannel("foo", DataType.LONG, OptionalDouble.of(3.0d), OptionalDouble.empty()); + public void shouldApplyScaleToIntegerWithDoubleScale() { + givenAssetChannel("foo", DataType.INTEGER, ScaleOffsetType.DOUBLE, Optional.of(3.0f), Optional.empty()); + + whenDriverProducesValue("foo", 1); + + thenAssetOutputContains(0, "foo", 3); + } + + @Test + public void shouldApplyScaleToIntegerWithIntegerScale() { + givenAssetChannel("foo", DataType.INTEGER, ScaleOffsetType.DEFINED_BY_VALUE_TYPE, Optional.of(3), + Optional.empty()); + + whenDriverProducesValue("foo", 1); + + thenAssetOutputContains(0, "foo", 3); + } + + @Test + public void shouldApplyScaleToLongWithDoubleScale() { + givenAssetChannel("foo", DataType.LONG, ScaleOffsetType.DOUBLE, Optional.of(3.0d), Optional.empty()); whenDriverProducesValue("foo", 1l); @@ -69,7 +90,7 @@ public void shouldApplyScaleToLong() { @Test public void shouldApplyOffsetToDouble() { - givenAssetChannel("foo", DataType.DOUBLE, OptionalDouble.empty(), OptionalDouble.of(10.0d)); + givenAssetChannel("foo", DataType.DOUBLE, ScaleOffsetType.DOUBLE, Optional.empty(), Optional.of(10.0d)); whenDriverProducesValue("foo", 1.0d); @@ -78,7 +99,7 @@ public void shouldApplyOffsetToDouble() { @Test public void shouldApplyOffsetToFloat() { - givenAssetChannel("foo", DataType.FLOAT, OptionalDouble.empty(), OptionalDouble.of(-2.0d)); + givenAssetChannel("foo", DataType.FLOAT, ScaleOffsetType.DOUBLE, Optional.empty(), Optional.of(-2.0d)); whenDriverProducesValue("foo", 1.0f); @@ -87,7 +108,7 @@ public void shouldApplyOffsetToFloat() { @Test public void shouldApplyOffsetToIngeger() { - givenAssetChannel("foo", DataType.INTEGER, OptionalDouble.empty(), OptionalDouble.of(10.0d)); + givenAssetChannel("foo", DataType.INTEGER, ScaleOffsetType.DOUBLE, Optional.empty(), Optional.of(10.0d)); whenDriverProducesValue("foo", 1); @@ -96,7 +117,7 @@ public void shouldApplyOffsetToIngeger() { @Test public void shouldApplyOffsetToLong() { - givenAssetChannel("foo", DataType.LONG, OptionalDouble.empty(), OptionalDouble.of(-2.0d)); + givenAssetChannel("foo", DataType.LONG, ScaleOffsetType.DOUBLE, Optional.empty(), Optional.of(-2.0d)); whenDriverProducesValue("foo", 1l); @@ -105,7 +126,7 @@ public void shouldApplyOffsetToLong() { @Test public void shouldApplyBothScaleAndOffset() { - givenAssetChannel("foo", DataType.LONG, OptionalDouble.of(6.0f), OptionalDouble.of(-2.0d)); + givenAssetChannel("foo", DataType.LONG, ScaleOffsetType.DOUBLE, Optional.of(6.0f), Optional.of(-2.0d)); whenDriverProducesValue("foo", 2l); @@ -114,7 +135,7 @@ public void shouldApplyBothScaleAndOffset() { @Test public void shouldTolerateScaleAndOffsetOnBoolean() { - givenAssetChannel("foo", DataType.BOOLEAN, OptionalDouble.of(6.0f), OptionalDouble.of(-2.0d)); + givenAssetChannel("foo", DataType.BOOLEAN, ScaleOffsetType.DOUBLE, Optional.of(6.0f), Optional.of(-2.0d)); whenDriverProducesValue("foo", true); @@ -123,7 +144,7 @@ public void shouldTolerateScaleAndOffsetOnBoolean() { @Test public void shouldTolerateScaleAndOffsetOnString() { - givenAssetChannel("foo", DataType.STRING, OptionalDouble.of(6.0f), OptionalDouble.of(-2.0d)); + givenAssetChannel("foo", DataType.STRING, ScaleOffsetType.DOUBLE, Optional.of(6.0f), Optional.of(-2.0d)); whenDriverProducesValue("foo", "bar"); @@ -132,7 +153,7 @@ public void shouldTolerateScaleAndOffsetOnString() { @Test public void shouldTolerateScaleAndOffsetOnByteArray() { - givenAssetChannel("foo", DataType.BYTE_ARRAY, OptionalDouble.of(6.0f), OptionalDouble.of(-2.0d)); + givenAssetChannel("foo", DataType.BYTE_ARRAY, ScaleOffsetType.DOUBLE, Optional.of(6.0f), Optional.of(-2.0d)); whenDriverProducesValue("foo", new byte[] { 1, 2, 3, 4 }); @@ -155,9 +176,9 @@ public ScaleOffsetTest(final TriggerMode triggerMode) { this.triggerMode = triggerMode; } - private void givenAssetChannel(String name, DataType dataType, OptionalDouble scale, - OptionalDouble offset) { - super.givenAssetChannel(name, this.triggerMode == TriggerMode.LISTEN, dataType, scale, offset); + private void givenAssetChannel(String name, DataType dataType, ScaleOffsetType scaleOffsetType, + Optional scale, Optional offset) { + super.givenAssetChannel(name, this.triggerMode == TriggerMode.LISTEN, dataType, scaleOffsetType, scale, offset); } private void whenDriverProducesValue(final String channelName, final Object value) { diff --git a/kura/test/org.eclipse.kura.wire.component.provider.test/src/main/java/org/eclipse/kura/internal/wire/asset/test/WireAssetTestBase.java b/kura/test/org.eclipse.kura.wire.component.provider.test/src/main/java/org/eclipse/kura/internal/wire/asset/test/WireAssetTestBase.java index 75533d2ced7..294626543ab 100644 --- a/kura/test/org.eclipse.kura.wire.component.provider.test/src/main/java/org/eclipse/kura/internal/wire/asset/test/WireAssetTestBase.java +++ b/kura/test/org.eclipse.kura.wire.component.provider.test/src/main/java/org/eclipse/kura/internal/wire/asset/test/WireAssetTestBase.java @@ -1,12 +1,12 @@ /******************************************************************************* - * Copyright (c) 2023 Eurotech and/or its affiliates and others - * + * Copyright (c) 2024 Eurotech and/or its affiliates and others + * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 - * + * * Contributors: * Eurotech *******************************************************************************/ @@ -28,10 +28,10 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.OptionalDouble; import java.util.concurrent.TimeUnit; import org.eclipse.kura.channel.ChannelType; +import org.eclipse.kura.channel.ScaleOffsetType; import org.eclipse.kura.driver.Driver; import org.eclipse.kura.type.DataType; import org.eclipse.kura.type.TypedValue; @@ -53,27 +53,29 @@ public class WireAssetTestBase { private TestEmitterReceiver testReceiver; private TestEmitterReceiver testEmitter; - private MockDriver driver = new MockDriver(); + private final MockDriver driver = new MockDriver(); - private List envelopes = new ArrayList<>(); + private final List envelopes = new ArrayList<>(); protected void givenAssetChannel(final String name, final boolean listen, final DataType dataType, - final OptionalDouble scale, final OptionalDouble offset) { + final ScaleOffsetType scaleOffsetType, final Optional scale, + final Optional offset) { final Map config = new HashMap<>(); config.put("driver.pid", "testDriver"); config.put(name + "#+name", name); config.put(name + "#+type", ChannelType.READ.name()); config.put(name + "#+value.type", dataType.name()); + config.put(name + "#+scaleoffset.type", scaleOffsetType.name()); config.put(name + "#+enabled", true); config.put(name + "#+listen", listen); if (scale.isPresent()) { - config.put(name + "#+scale", Double.toString(scale.getAsDouble())); + config.put(name + "#+scale", scale.get().toString()); } if (offset.isPresent()) { - config.put(name + "#+offset", Double.toString(offset.getAsDouble())); + config.put(name + "#+offset", offset.get().toString()); } givenAssetConfig(config); @@ -88,8 +90,7 @@ protected void givenAssetConfig(final Map assetConfig) { final BundleContext bundleContext = FrameworkUtil.getBundle(OnChangeCacheTest.class).getBundleContext(); final WireGraphService wireGraphService = WireTestUtil - .trackService(WireGraphService.class, Optional.empty()) - .get(30, TimeUnit.SECONDS); + .trackService(WireGraphService.class, Optional.empty()).get(30, TimeUnit.SECONDS); final GraphBuilder graphBuilder = new GraphBuilder().addTestEmitterReceiver("emitter") .addTestEmitterReceiver("receiver") @@ -101,11 +102,11 @@ protected void givenAssetConfig(final Map assetConfig) { graphBuilder.replaceExistingGraph(bundleContext, wireGraphService).get(30, TimeUnit.SECONDS); - testEmitter = graphBuilder.getTrackedWireComponent("emitter"); - testReceiver = graphBuilder.getTrackedWireComponent("receiver"); + this.testEmitter = graphBuilder.getTrackedWireComponent("emitter"); + this.testReceiver = graphBuilder.getTrackedWireComponent("receiver"); - testReceiver.setConsumer(e -> { - synchronized (envelopes) { + this.testReceiver.setConsumer(e -> { + synchronized (this.envelopes) { this.envelopes.add(e); this.envelopes.notifyAll(); } @@ -114,10 +115,10 @@ protected void givenAssetConfig(final Map assetConfig) { final Dictionary properties = new Hashtable<>(); properties.put("kura.service.pid", "testDriver"); - driverRegistration = Optional.of(bundleContext.registerService(Driver.class, driver, properties)); + driverRegistration = Optional.of(bundleContext.registerService(Driver.class, this.driver, properties)); try { - driver.preparedReadCalled.get(30, TimeUnit.SECONDS); + this.driver.preparedReadCalled.get(30, TimeUnit.SECONDS); } catch (Exception e) { fail("driver not ready"); } @@ -131,12 +132,11 @@ protected void givenAssetConfig(final Map assetConfig) { return split[1].equals("+listen"); - }).filter(k -> Objects.equals(true, assetConfig.get(k))) - .count(); + }).filter(k -> Objects.equals(true, assetConfig.get(k))).count(); - synchronized (driver.listeners) { - while (driver.listeners.size() != listenChannelCount) { - driver.listeners.wait(30000); + synchronized (this.driver.listeners) { + while (this.driver.listeners.size() != listenChannelCount) { + this.driver.listeners.wait(30000); } } @@ -146,7 +146,7 @@ protected void givenAssetConfig(final Map assetConfig) { } protected void givenChannelValue(final String key, final Object value) { - driver.addReadResult(key, TypedValues.newTypedValue(value)); + this.driver.addReadResult(key, TypedValues.newTypedValue(value)); } protected void givenChannelValues(final String key, final Object... values) { @@ -157,7 +157,7 @@ protected void givenChannelValues(final String key, final Object... values) { protected void whenAssetReceivesEnvelope() { - testEmitter.emit(); + this.testEmitter.emit(); } protected void whenDriverEmitsEvents(final Object... values) { @@ -167,7 +167,7 @@ protected void whenDriverEmitsEvents(final Object... values) { final String channelName = (String) iter.next(); final TypedValue value = TypedValues.newTypedValue(iter.next()); - driver.emitChannelEvent(channelName, value); + this.driver.emitChannelEvent(channelName, value); } } @@ -178,15 +178,15 @@ protected void whenAssetReceivesEnvelopes(final int count) { } protected void awaitEnvelope(final int index) { - synchronized (envelopes) { - if (index >= envelopes.size()) { + synchronized (this.envelopes) { + if (index >= this.envelopes.size()) { try { - envelopes.wait(30000); + this.envelopes.wait(30000); } catch (InterruptedException e) { throw new IllegalStateException("Interrupted while waiting for envelope"); } - if (index >= envelopes.size()) { + if (index >= this.envelopes.size()) { fail("expected to receive at least " + (index + 1) + " envelopes"); } } @@ -196,7 +196,7 @@ protected void awaitEnvelope(final int index) { protected void thenAssetOutputContains(final int index, final Object... properties) { awaitEnvelope(index); - final WireEnvelope envelope = envelopes.get(index); + final WireEnvelope envelope = this.envelopes.get(index); final Iterator iter = Arrays.asList(properties).iterator(); @@ -211,7 +211,7 @@ protected void thenAssetOutputContains(final int index, final Object... properti protected void thenAssetOutputContainsKey(final int index, final String key) { awaitEnvelope(index); - final WireEnvelope envelope = envelopes.get(index); + final WireEnvelope envelope = this.envelopes.get(index); assertTrue(envelope.getRecords().get(0).getProperties().containsKey(key)); } @@ -219,7 +219,7 @@ protected void thenAssetOutputContainsKey(final int index, final String key) { protected void thenAssetOutputPropertyCountIs(final int index, final int expectedCount) { awaitEnvelope(index); - final WireEnvelope envelope = envelopes.get(index); + final WireEnvelope envelope = this.envelopes.get(index); assertEquals(expectedCount, envelope.getRecords().get(0).getProperties().size()); } @@ -227,13 +227,9 @@ protected void thenAssetOutputPropertyCountIs(final int index, final int expecte protected void thenAssetOutputDoesNotContain(final int index, final String... properties) { awaitEnvelope(index); - final WireEnvelope envelope = envelopes.get(index); - - final Iterator iter = Arrays.asList(properties).iterator(); - - while (iter.hasNext()) { - final String key = (String) iter.next(); + final WireEnvelope envelope = this.envelopes.get(index); + for (String key : Arrays.asList(properties)) { assertFalse(envelope.getRecords().get(0).getProperties().containsKey(key)); } } @@ -245,7 +241,7 @@ protected void thenTotalEmittedEnvelopeCountAfter1SecIs(final int expectedCount) throw new IllegalStateException("sleep interrupted"); } - assertEquals(expectedCount, envelopes.size()); + assertEquals(expectedCount, this.envelopes.size()); } }