Skip to content

Commit

Permalink
feat(web2): Added dynamic validator for scale and offset fields (#5530)
Browse files Browse the repository at this point in the history
* Added dynamic validator for scale and offset fields

* Removed debugging loggers

* Added check on empty String and fixed test
  • Loading branch information
salvatore-coppola authored Nov 22, 2024
1 parent 11550f4 commit 49d787c
Show file tree
Hide file tree
Showing 12 changed files with 538 additions and 200 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@ protected BaseChannelDescriptor() {
final Tad valueScale = new Tad();
valueScale.setName(VALUE_SCALE.value().substring(1));
valueScale.setId(VALUE_SCALE.value());
valueScale.setDescription("Scale to be applied to the numeric value of the channel");
valueScale.setType(Tscalar.DOUBLE);
valueScale.setDescription("Scale to be applied to the numeric value of the channel.");
valueScale.setType(Tscalar.STRING);
valueScale.setRequired(false);

this.defaultElements.add(valueScale);
Expand All @@ -168,7 +168,7 @@ protected BaseChannelDescriptor() {
valueOffset.setName(VALUE_OFFSET.value().substring(1));
valueOffset.setId(VALUE_OFFSET.value());
valueOffset.setDescription("Offset to be applied to the numeric value of the channel");
valueOffset.setType(Tscalar.DOUBLE);
valueOffset.setType(Tscalar.STRING);
valueOffset.setRequired(false);

this.defaultElements.add(valueOffset);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ private static ScaleOffsetType getScaleOffsetType(final Map<String, Object> prop
private static Number getValueScale(final Map<String, Object> properties) {
final String valueScale = (String) properties.get(VALUE_SCALE.value());

if (valueScale == null) {
if (valueScale == null || valueScale.isEmpty()) {
return 1.0d;
}
return parseScaleOffsetTypedValue(getScaleOffsetType(properties), valueScale);
Expand All @@ -351,7 +351,7 @@ private static Number getValueScale(final Map<String, Object> properties) {
private static Number getValueOffset(final Map<String, Object> properties) {
final String valueOffset = (String) properties.get(VALUE_OFFSET.value());

if (valueOffset == null) {
if (valueOffset == null || valueOffset.isEmpty()) {
return 0.0d;
}
return parseScaleOffsetTypedValue(getScaleOffsetType(properties), valueOffset);
Expand Down Expand Up @@ -411,8 +411,7 @@ private static Number parseScaleOffsetTypedValue(ScaleOffsetType type, String va
case DOUBLE:
return Double.parseDouble(value);
case LONG:
// TODO replace with Long.parseLong(value) once scale and offset are turned in String in the metatype
return (Double.valueOf(value).longValue());
return Long.parseLong(value);
default:
throw new IllegalArgumentException(value + " cannot be converted into a Number of type " + type);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import org.eclipse.kura.web.Console;
Expand Down Expand Up @@ -98,8 +97,6 @@ public class AssetConfigurationUi extends AbstractServicesUi implements HasConfi

private static final String COLUMN_VISIBILITY_SETTINGS_KEY = "org.eclipse.kura.settings.column.asset.";

private static final Logger logger = Logger.getLogger(AssetConfigurationUi.class.getSimpleName());

private static final List<String> defaultHiddenColumns = //
Arrays.asList(//
AssetConstants.VALUE_UNIT.value(), //
Expand Down Expand Up @@ -323,8 +320,6 @@ public void setPageStart(int index) {
this.btnManageHiddenColumn.setText(MSGS.columnVisibilityModalButton(//
String.valueOf(totalEnabledColumns(this.columnNameVisibilityMap)),
String.valueOf(this.columnNameVisibilityMap.size())));

logger.info("created AssetConfigurationUi for: " + this.model.getAssetPid());
}

private void fillColumnVisibilityCheckBox() {
Expand Down Expand Up @@ -394,7 +389,6 @@ private void resetDefaultColumnVisibilityMap() {

private void populateColumnVisibilityMap() {
this.model.getChannelDescriptor().getParameters().forEach(param -> {
AssetConfigurationUi.logger.info("Id: " + param.getId() + ", Name: " + param.getName());
if (!param.getId().equals(AssetConstants.ENABLED.value())
&& !param.getId().equals(AssetConstants.NAME.value())) {
boolean visible = !defaultHiddenColumns.contains(param.getId());
Expand Down Expand Up @@ -530,10 +524,11 @@ private Column<ChannelModel, String> getInputCellColumn(final GwtConfigParameter
final Column<ChannelModel, String> result = new ChannelColumn(cell, param);

if (!isReadOnly) {
result.setFieldUpdater((index, object, value) -> {
final String paramId = object.getChannelName() + '#' + param.getId();
object.setValue(param.getId(), value);
if (!object.isValid(param.getId())) {
result.setFieldUpdater((index, channelModel, value) -> {
final String paramId = channelModel.getChannelName() + '#' + param.getId();
Integer paramIndex = AssetConfigurationUi.this.model.getParameterIndex(param.getId());
channelModel.setValue(paramIndex, value);
if (!channelModel.isValid(paramIndex)) {
AssetConfigurationUi.this.invalidParameters.add(paramId);
} else {
AssetConfigurationUi.this.invalidParameters.remove(paramId);
Expand All @@ -552,35 +547,60 @@ private Column<ChannelModel, String> getInputCellColumn(final GwtConfigParameter
}

private Column<ChannelModel, String> getSelectionInputColumn(final GwtConfigParameter param, boolean isReadOnly) {
final String id = param.getId();
final Map<String, String> labelsToValues = param.getOptions();
ArrayList<Entry<String, String>> sortedLabelsToValues = new ArrayList<>(labelsToValues.entrySet());
Collections.sort(sortedLabelsToValues, DROPDOWN_LABEL_COMPARATOR);

final ArrayList<String> labels = new ArrayList<>();
final Map<String, String> valuesToLabels = new HashMap<>();

for (Entry<String, String> entry : sortedLabelsToValues) {
labels.add(entry.getKey());
valuesToLabels.put(entry.getValue(), entry.getKey());
}

final SelectionCell cell = new SelectionCell(new ArrayList<>(labels));
final Column<ChannelModel, String> result = new Column<ChannelModel, String>(cell) {

@Override
public String getValue(final ChannelModel object) {
String result = object.getValue(id);
public String getValue(final ChannelModel channelModel) {
Integer paramIndex = AssetConfigurationUi.this.model.getParameterIndex(param.getId());
String result = channelModel.getValue(paramIndex);
if (result == null) {
final String defaultValue = param.getDefault();
result = defaultValue != null ? defaultValue : labelsToValues.get(labels.get(0));
object.setValue(id, result);
channelModel.setValue(paramIndex, result);
}
return valuesToLabels.get(result);
}
};

if (!isReadOnly) {
result.setFieldUpdater((index, object, label) -> {
result.setFieldUpdater((index, channelModel, label) -> {
String paramId = param.getId();
AssetConfigurationUi.this.setDirty(true);
object.setValue(param.getId(), labelsToValues.get(label));
String newValue = labelsToValues.get(label);
Integer paramIndex = AssetConfigurationUi.this.model.getParameterIndex(paramId);
String oldValue = channelModel.getValue(paramIndex);
channelModel.setValue(paramIndex, newValue);
if ((param.getId().equals(AssetConstants.VALUE_TYPE.value())
|| param.getId().equals(AssetConstants.SCALE_OFFSET_TYPE.value())
&& !oldValue.equals(newValue))) {

for (Map.Entry<String, Integer> paramEntry : AssetConfigurationUi.this.model.getParameterIndexes()
.entrySet()) {
String paramIdentifier = channelModel.getChannelName() + '#' + paramEntry.getKey();
Integer parameterIndex = paramEntry.getValue();
if (!channelModel.isValid(parameterIndex)) {
AssetConfigurationUi.this.invalidParameters.add(paramIdentifier);
} else {
AssetConfigurationUi.this.invalidParameters.remove(paramIdentifier);
}
}

this.channelTable.redrawRow(index);

}
});
}

Expand Down Expand Up @@ -878,7 +898,7 @@ public static ColumnVisibilityMap fromString(String text) {
}
}

private static class ChannelColumn extends Column<ChannelModel, String> {
private class ChannelColumn extends Column<ChannelModel, String> {

private final GwtConfigParameter param;

Expand All @@ -888,17 +908,19 @@ public ChannelColumn(final Cell<String> cell, final GwtConfigParameter param) {
}

@Override
public String getValue(final ChannelModel object) {
String result = object.getValue(this.param.getId());
public String getValue(final ChannelModel channelModel) {
Integer paramIndex = AssetConfigurationUi.this.model.getParameterIndex(this.param.getId());
String result = channelModel.getValue(paramIndex);
if (result != null) {
return result;
}
return this.param.isRequired() ? this.param.getDefault() : null;
}

@Override
public String getCellStyleNames(Context context, ChannelModel object) {
if (!object.isValid(this.param.getId())) {
public String getCellStyleNames(Context context, ChannelModel channelModel) {
Integer paramIndex = AssetConfigurationUi.this.model.getParameterIndex(this.param.getId());
if (!channelModel.isValid(paramIndex)) {
return "config-cell-not-valid";
} else {
return "";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017, 2020 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
Expand Down Expand Up @@ -124,8 +124,8 @@ private void initTable() {
@Override
public void onBrowserEvent(Context context, Element elem, ChannelModel object, NativeEvent event) {
if (getChannelStatus(object) == ChannelStatus.FAILURE) {
final GwtChannelRecord record = AssetDataUi.this.channelValues.get(object.getChannelName());
showFailureDetails(record);
final GwtChannelRecord channelRecord = AssetDataUi.this.channelValues.get(object.getChannelName());
showFailureDetails(channelRecord);
}
}

Expand Down Expand Up @@ -154,9 +154,10 @@ public void render(final Context context, final ChannelModel object, final SafeH
this.valuesCell) {

@Override
public void onBrowserEvent(Context context, Element elem, ChannelModel object, NativeEvent event) {
if (!"READ".equals(object.getValue(AssetConstants.TYPE.value()))) {
super.onBrowserEvent(context, elem, object, event);
public void onBrowserEvent(Context context, Element elem, ChannelModel channelModel, NativeEvent event) {
if (!"READ".equals(
channelModel.getValue(AssetDataUi.this.model.getParameterIndex(AssetConstants.TYPE.value())))) {
super.onBrowserEvent(context, elem, channelModel, event);
}
}

Expand All @@ -178,15 +179,16 @@ public String getValue(final AssetModel.ChannelModel object) {
}

@Override
public void render(Context context, ChannelModel object, SafeHtmlBuilder sb) {
if ("READ".equals(object.getValue(AssetConstants.TYPE.value()))) {
sb.appendEscaped(getValue(object));
public void render(Context context, ChannelModel channelModel, SafeHtmlBuilder sb) {
if ("READ".equals(
channelModel.getValue(AssetDataUi.this.model.getParameterIndex(AssetConstants.TYPE.value())))) {
sb.appendEscaped(getValue(channelModel));
return;
}
if (!isDirty(object.getChannelName())) {
if (!isDirty(channelModel.getChannelName())) {
AssetDataUi.this.valuesCell.clearViewData(context.getKey());
}
super.render(context, object, sb);
super.render(context, channelModel, sb);
}
};

Expand All @@ -205,24 +207,25 @@ public void render(Context context, ChannelModel object, SafeHtmlBuilder sb) {
this.assetDataTable.addColumn(valueColumn, new TextHeader(MSGS.devicePropValue()));
}

private static void showFailureDetails(final GwtChannelRecord record) {
record.setUnescaped(true);
String reason = record.getExceptionMessage();
record.setUnescaped(false);
private static void showFailureDetails(final GwtChannelRecord channelRecord) {
channelRecord.setUnescaped(true);
String reason = channelRecord.getExceptionMessage();
channelRecord.setUnescaped(false);

if (reason == null || reason.trim().isEmpty()) {
reason = "unknown";
}

FailureHandler.showErrorMessage("Channel failure details", "Reason: " + reason,
record.getExceptionStackTrace());
channelRecord.getExceptionStackTrace());
}

private GwtChannelRecord createWriteRecord(AssetModel.ChannelModel channel) {
final GwtChannelRecord result = new GwtChannelRecord();
result.setUnescaped(true);
result.setName(channel.getChannelName());
result.setValueType(channel.getValue(AssetConstants.VALUE_TYPE.value()));
result.setValueType(
channel.getValue(AssetDataUi.this.model.getParameterIndex(AssetConstants.VALUE_TYPE.value())));
return result;
}

Expand All @@ -234,11 +237,11 @@ private void write() {
final ArrayList<GwtChannelRecord> writeRecords = new ArrayList<>();

for (final String channelName : this.modifiedWriteChannels) {
final GwtChannelRecord record = this.channelValues.get(channelName);
if (record == null) {
final GwtChannelRecord channelRecord = this.channelValues.get(channelName);
if (channelRecord == null) {
continue;
}
writeRecords.add(record);
writeRecords.add(channelRecord);
}

if (writeRecords.isEmpty()) {
Expand Down Expand Up @@ -299,9 +302,9 @@ public void renderForm() {
final List<GwtChannelRecord> records = result.getRecords();

if (records != null) {
for (final GwtChannelRecord record : records) {
record.setUnescaped(true);
this.channelValues.put(record.getName(), record);
for (final GwtChannelRecord channelRecord : records) {
channelRecord.setUnescaped(true);
this.channelValues.put(channelRecord.getName(), channelRecord);
}
AssetDataUi.this.channelsDataProvider.getList().addAll(this.model.getChannels());
AssetDataUi.this.channelsDataProvider.refresh();
Expand All @@ -319,22 +322,22 @@ public void renderForm() {

private ChannelStatus getChannelStatus(final ChannelModel model) {
final String channelName = model.getChannelName();
final GwtChannelRecord record = this.channelValues.get(model.getChannelName());
final GwtChannelRecord channelRecord = this.channelValues.get(model.getChannelName());

if ("false".equals(model.getValue(AssetConstants.ENABLED.value()))) {
if ("false".equals(model.getValue(AssetDataUi.this.model.getParameterIndex(AssetConstants.ENABLED.value())))) {
return ChannelStatus.DISABLED;
} else if (this.modifiedWriteChannels.contains(channelName)) {
return ChannelStatus.DIRTY;
} else if (record == null) {
} else if (channelRecord == null) {
return ChannelStatus.UNKNOWN;
} else if (record.getValue() == null) {
} else if (channelRecord.getValue() == null) {
return ChannelStatus.FAILURE;
} else {
return ChannelStatus.SUCCESS;
}
}

private static final class StaticColumn extends Column<AssetModel.ChannelModel, String> {
private final class StaticColumn extends Column<AssetModel.ChannelModel, String> {

private final String key;

Expand All @@ -344,12 +347,12 @@ public StaticColumn(final String key) {
}

@Override
public String getValue(final AssetModel.ChannelModel object) {
return object.getValue(this.key);
public String getValue(final AssetModel.ChannelModel channelModel) {
return channelModel.getValue(AssetDataUi.this.model.getParameterIndex(this.key));
}
}

private static final class StatusCell extends TextCell {
private final class StatusCell extends TextCell {

@Override
public Set<String> getConsumedEvents() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package org.eclipse.kura.web.client.ui.drivers.assets;

import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.kura.web.shared.model.GwtConfigComponent;
Expand Down Expand Up @@ -40,16 +41,21 @@ public interface AssetModel {

public boolean isValid();

public Integer getParameterIndex(String value);

public Map<String, Integer> getParameterIndexes();

public interface ChannelModel {

public GwtConfigParameter getParameter(int index);

public void setValue(String id, String value);
public void setValue(Integer index, String value);

public boolean isValid(String id);
public boolean isValid(Integer index);

public String getValue(String id);
public String getValue(Integer index);

public String getChannelName();
}

}
Loading

0 comments on commit 49d787c

Please sign in to comment.