You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by ri...@apache.org on 2022/08/18 20:33:09 UTC
[incubator-streampipes] 03/15: [STREAMPIPES-577] Show live preview for OPC-UA adapter
This is an automated email from the ASF dual-hosted git repository.
riemer pushed a commit to branch rel/0.70.0
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git
commit d995362d3d637e88f15db9a1235fe56f5b1a3563
Author: Dominik Riemer <do...@gmail.com>
AuthorDate: Tue Aug 16 13:20:26 2022 +0200
[STREAMPIPES-577] Show live preview for OPC-UA adapter
---
.../connect/iiot/adapters/opcua/OpcUaAdapter.java | 22 ++++---
.../iiot/adapters/opcua/OpcUaNodeBrowser.java | 10 ++++
.../iiot/adapters/opcua/utils/OpcUaUtil.java | 50 ++++++++++++++--
.../streampipes/model/StreamPipesErrorMessage.java | 11 +++-
.../model/connect/guess/FieldStatus.java | 31 ++--------
.../model/connect/guess/FieldStatusInfo.java | 69 ++++++++++++++++++++++
.../model/connect/guess/GuessSchema.java | 30 ++++++++++
.../model/connect/guess/GuessTypeInfo.java | 47 ++++++++-------
.../src/lib/model/gen/streampipes-model.ts | 48 +++++++++++++--
.../event-property-row.component.html | 27 ++++++---
.../event-property-row.component.scss | 25 ++++++++
.../event-property-row.component.ts | 35 ++++++++---
.../event-schema/event-schema.component.html | 8 ++-
.../event-schema/event-schema.component.ts | 10 +++-
14 files changed, 337 insertions(+), 86 deletions(-)
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaAdapter.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaAdapter.java
index 76b3df7e2..9b00f84d5 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaAdapter.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaAdapter.java
@@ -31,6 +31,7 @@ import org.apache.streampipes.container.api.SupportsRuntimeConfig;
import org.apache.streampipes.model.AdapterType;
import org.apache.streampipes.model.connect.adapter.SpecificAdapterStreamDescription;
import org.apache.streampipes.model.connect.guess.GuessSchema;
+import org.apache.streampipes.model.connect.rules.schema.DeleteRuleDescription;
import org.apache.streampipes.model.staticproperty.StaticProperty;
import org.apache.streampipes.sdk.StaticProperties;
import org.apache.streampipes.sdk.builder.adapter.SpecificDataStreamAdapterBuilder;
@@ -47,14 +48,10 @@ import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.CompletableFuture;
+import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
public class OpcUaAdapter extends PullAdapter implements SupportsRuntimeConfig {
@@ -91,11 +88,18 @@ public class OpcUaAdapter extends PullAdapter implements SupportsRuntimeConfig {
protected void before() throws AdapterException {
this.allNodeIds = new ArrayList<>();
+ List<String> deleteKeys = this.adapterDescription
+ .getSchemaRules()
+ .stream()
+ .filter(rule -> rule instanceof DeleteRuleDescription)
+ .map(rule -> ((DeleteRuleDescription) rule).getRuntimeKey())
+ .collect(Collectors.toList());
+
try {
this.spOpcUaClient.connect();
OpcUaNodeBrowser browserClient =
new OpcUaNodeBrowser(this.spOpcUaClient.getClient(), this.spOpcUaClient.getSpOpcConfig());
- this.allNodes = browserClient.findNodes();
+ this.allNodes = browserClient.findNodes(deleteKeys);
for (OpcNode node : this.allNodes) {
@@ -141,8 +145,8 @@ public class OpcUaAdapter extends PullAdapter implements SupportsRuntimeConfig {
@Override
protected void pullData() {
- CompletableFuture<List<DataValue>> response =
- this.spOpcUaClient.getClient().readValues(0, TimestampsToReturn.Both, this.allNodeIds);
+ var response =
+ this.spOpcUaClient.getClient().readValues(0, TimestampsToReturn.Both, this.allNodeIds);
boolean badStatusCodeReceived = false;
boolean emptyValueReceived = false;
try {
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaNodeBrowser.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaNodeBrowser.java
index 2e8e3dbc5..c1cbc202e 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaNodeBrowser.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/OpcUaNodeBrowser.java
@@ -37,6 +37,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
public class OpcUaNodeBrowser {
@@ -61,6 +62,15 @@ public class OpcUaNodeBrowser {
return opcNodes;
}
+ public List<OpcNode> findNodes(List<String> runtimeNameFilters) throws UaException {
+ return findNodes()
+ .stream()
+ .filter(node -> runtimeNameFilters
+ .stream()
+ .noneMatch(f -> f.equals(node.getLabel())))
+ .collect(Collectors.toList());
+ }
+
public List<TreeInputNode> buildNodeTreeFromOrigin() throws UaException, ExecutionException, InterruptedException {
NodeId origin = spOpcConfig.getOriginNodeId();
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/utils/OpcUaUtil.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/utils/OpcUaUtil.java
index d9f95872f..766433a24 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/utils/OpcUaUtil.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/opcua/utils/OpcUaUtil.java
@@ -26,7 +26,9 @@ import org.apache.streampipes.connect.iiot.adapters.opcua.OpcUaNodeBrowser;
import org.apache.streampipes.connect.iiot.adapters.opcua.SpOpcUaClient;
import org.apache.streampipes.connect.iiot.adapters.opcua.configuration.SpOpcUaConfigBuilder;
import org.apache.streampipes.model.connect.adapter.SpecificAdapterStreamDescription;
+import org.apache.streampipes.model.connect.guess.FieldStatusInfo;
import org.apache.streampipes.model.connect.guess.GuessSchema;
+import org.apache.streampipes.model.connect.guess.GuessTypeInfo;
import org.apache.streampipes.model.schema.EventProperty;
import org.apache.streampipes.model.schema.EventSchema;
import org.apache.streampipes.model.staticproperty.RuntimeResolvableTreeInputStaticProperty;
@@ -34,14 +36,20 @@ import org.apache.streampipes.sdk.builder.PrimitivePropertyBuilder;
import org.apache.streampipes.sdk.extractor.StaticPropertyExtractor;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.stack.core.UaException;
+import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
+import org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode;
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
+import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
/***
* Collection of several utility functions in context of OPC UA
@@ -73,6 +81,8 @@ public class OpcUaUtil {
throws AdapterException, ParseException {
GuessSchema guessSchema = new GuessSchema();
EventSchema eventSchema = new EventSchema();
+ List<Map<String, GuessTypeInfo>> eventPreview = new ArrayList<>();
+ Map<String, FieldStatusInfo> fieldStatusInfos = new HashMap<>();
List<EventProperty> allProperties = new ArrayList<>();
SpOpcUaClient spOpcUaClient = new SpOpcUaClient(SpOpcUaConfigBuilder.from(adapterStreamDescription));
@@ -97,22 +107,53 @@ public class OpcUaUtil {
.label(opcNode.getLabel())
.build());
}
-
}
}
- spOpcUaClient.disconnect();
+ var nodeIds = selectedNodes.stream().map(OpcNode::getNodeId).collect(Collectors.toList());
+ var response = spOpcUaClient.getClient().readValues(0, TimestampsToReturn.Both, nodeIds);
+
+ var returnValues = response.get();
+
+ makeEventPreview(selectedNodes, eventPreview, fieldStatusInfos, returnValues);
+
} catch (Exception e) {
- throw new AdapterException("Could not guess schema for opc node: " + e.getMessage(), e.getCause());
+ throw new AdapterException("Could not guess schema for opc node: " + e.getMessage(), e);
+ } finally {
+ spOpcUaClient.disconnect();
}
eventSchema.setEventProperties(allProperties);
guessSchema.setEventSchema(eventSchema);
+ guessSchema.setEventPreview(eventPreview);
+ guessSchema.setFieldStatusInfo(fieldStatusInfos);
return guessSchema;
}
+ private static void makeEventPreview(List<OpcNode> selectedNodes,
+ List<Map<String, GuessTypeInfo>> eventPreview,
+ Map<String, FieldStatusInfo> fieldStatusInfos,
+ List<DataValue> dataValues) {
+ var singlePreview = new HashMap<String, GuessTypeInfo>();
+
+ for (int i = 0; i < dataValues.size(); i++) {
+ var dv = dataValues.get(i);
+ String label = selectedNodes.get(i).getLabel();
+ if (StatusCode.GOOD.equals(dv.getStatusCode())) {
+ var value = dv.getValue().getValue();
+ singlePreview.put(label, new GuessTypeInfo(value.getClass().getCanonicalName(), value));
+ fieldStatusInfos.put(label, FieldStatusInfo.good());
+ } else {
+ String additionalInfo = dv.getStatusCode() != null ? dv.getStatusCode().toString() : "Status code is null";
+ fieldStatusInfos.put(label, FieldStatusInfo.bad(additionalInfo, false));
+ }
+ }
+
+ eventPreview.add(singlePreview);
+ }
+
/***
* OPC UA specific implementation of {@link
@@ -142,13 +183,14 @@ public class OpcUaUtil {
OpcUaNodeBrowser nodeBrowser =
new OpcUaNodeBrowser(spOpcUaClient.getClient(), spOpcUaClient.getSpOpcConfig());
config.setNodes(nodeBrowser.buildNodeTreeFromOrigin());
- spOpcUaClient.disconnect();
return config;
} catch (UaException e) {
throw new SpConfigurationException(ExceptionMessageExtractor.getDescription(e), e);
} catch (ExecutionException | InterruptedException | URISyntaxException e) {
throw new SpConfigurationException("Could not connect to the OPC UA server with the provided settings", e);
+ } finally {
+ spOpcUaClient.disconnect();
}
}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/StreamPipesErrorMessage.java b/streampipes-model/src/main/java/org/apache/streampipes/model/StreamPipesErrorMessage.java
index d2d964090..c6bf711a6 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/StreamPipesErrorMessage.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/StreamPipesErrorMessage.java
@@ -31,9 +31,6 @@ public class StreamPipesErrorMessage {
private String cause;
private String fullStackTrace;
- public StreamPipesErrorMessage() {
- }
-
public static StreamPipesErrorMessage from(Exception exception) {
String cause = exception.getCause() != null ? exception.getCause().getMessage() : exception.getMessage();
return new StreamPipesErrorMessage(
@@ -44,6 +41,14 @@ public class StreamPipesErrorMessage {
cause);
}
+ public StreamPipesErrorMessage(String level,
+ String title,
+ String detail) {
+ this.level = level;
+ this.title = title;
+ this.detail = detail;
+ }
+
public StreamPipesErrorMessage(String level,
String title,
String detail,
diff --git a/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.scss b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/FieldStatus.java
similarity index 56%
copy from ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.scss
copy to streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/FieldStatus.java
index aa6f60f17..eec688b79 100644
--- a/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.scss
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/FieldStatus.java
@@ -16,31 +16,10 @@
*
*/
+package org.apache.streampipes.model.connect.guess;
-::ng-deep .mat-checkbox-checked.mat-accent .mat-checkbox-background, .mat-checkbox-indeterminate.mat-accent .mat-checkbox-background {
- background-color: var(--color-accent) !important;
+public enum FieldStatus {
+ GOOD,
+ BAD,
+ ATTENTION
}
-
-::ng-deep .mat-checkbox:not(.mat-checkbox-disabled).mat-accent .mat-checkbox-ripple .mat-ripple-element {
- background-color: var(--color-accent) !important;
-}
-
-.checkbox-selected {
- opacity: 1 !important;
-}
-
-.timestamp-property {
- margin-left: 15px;
- border-radius: 10px;
- background: var(--color-processor);
- padding: 0px 10px;
- font-size: 12px;
- color: #FFFFFF;
-}
-
-.timestamp-icon {
- font-size: 12px;
-}
-
-
-
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/FieldStatusInfo.java b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/FieldStatusInfo.java
new file mode 100644
index 000000000..a66b83ddb
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/FieldStatusInfo.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model.connect.guess;
+
+public class FieldStatusInfo {
+
+ private FieldStatus fieldStatus;
+ private String additionalInfo;
+ private boolean changesRequired;
+
+ public static FieldStatusInfo good() {
+ var info = new FieldStatusInfo();
+ info.setFieldStatus(FieldStatus.GOOD);
+ return info;
+ }
+
+ public static FieldStatusInfo bad(String additionalInfo,
+ boolean changesRequired) {
+ var info = new FieldStatusInfo();
+ info.setFieldStatus(FieldStatus.BAD);
+ info.setAdditionalInfo(additionalInfo);
+ info.setChangesRequired(changesRequired);
+
+ return info;
+ }
+
+ public FieldStatusInfo() {
+ }
+
+ public FieldStatus getFieldStatus() {
+ return fieldStatus;
+ }
+
+ public void setFieldStatus(FieldStatus fieldStatus) {
+ this.fieldStatus = fieldStatus;
+ }
+
+ public String getAdditionalInfo() {
+ return additionalInfo;
+ }
+
+ public void setAdditionalInfo(String additionalInfo) {
+ this.additionalInfo = additionalInfo;
+ }
+
+ public boolean isChangesRequired() {
+ return changesRequired;
+ }
+
+ public void setChangesRequired(boolean changesRequired) {
+ this.changesRequired = changesRequired;
+ }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/GuessSchema.java b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/GuessSchema.java
index 4bda9da85..ba39f8925 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/GuessSchema.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/GuessSchema.java
@@ -22,18 +22,31 @@ import org.apache.streampipes.model.base.UnnamedStreamPipesEntity;
import org.apache.streampipes.model.schema.EventSchema;
import org.apache.streampipes.model.shared.annotation.TsModel;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
@TsModel
public class GuessSchema extends UnnamedStreamPipesEntity {
public EventSchema eventSchema;
+ public List<Map<String, GuessTypeInfo>> eventPreview;
+
+ public Map<String, FieldStatusInfo> fieldStatusInfo;
+
public GuessSchema() {
super();
+ this.eventPreview = new ArrayList<>();
+ this.fieldStatusInfo = new HashMap<>();
}
public GuessSchema(GuessSchema other) {
super(other);
this.eventSchema = other.getEventSchema() != null ? new EventSchema(other.getEventSchema()) : null;
+ this.eventPreview = other.getEventPreview();
+ this.fieldStatusInfo = other.getFieldStatusInfo();
}
public EventSchema getEventSchema() {
return eventSchema;
@@ -43,4 +56,21 @@ public class GuessSchema extends UnnamedStreamPipesEntity {
this.eventSchema = eventSchema;
}
+ public List<Map<String, GuessTypeInfo>> getEventPreview() {
+ return eventPreview;
+ }
+
+ public void setEventPreview(List<Map<String, GuessTypeInfo>> eventPreview) {
+ this.eventPreview = eventPreview;
+ }
+
+ public Map<String, FieldStatusInfo> getFieldStatusInfo() {
+ return fieldStatusInfo;
+ }
+
+ public void setFieldStatusInfo(Map<String, FieldStatusInfo> fieldStatusInfo) {
+ this.fieldStatusInfo = fieldStatusInfo;
+ }
+
+
}
diff --git a/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.scss b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/GuessTypeInfo.java
similarity index 56%
copy from ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.scss
copy to streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/GuessTypeInfo.java
index aa6f60f17..7404451d6 100644
--- a/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.scss
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/guess/GuessTypeInfo.java
@@ -16,31 +16,38 @@
*
*/
+package org.apache.streampipes.model.connect.guess;
-::ng-deep .mat-checkbox-checked.mat-accent .mat-checkbox-background, .mat-checkbox-indeterminate.mat-accent .mat-checkbox-background {
- background-color: var(--color-accent) !important;
-}
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
-::ng-deep .mat-checkbox:not(.mat-checkbox-disabled).mat-accent .mat-checkbox-ripple .mat-ripple-element {
- background-color: var(--color-accent) !important;
-}
+public class GuessTypeInfo {
-.checkbox-selected {
- opacity: 1 !important;
-}
+ private String type;
-.timestamp-property {
- margin-left: 15px;
- border-radius: 10px;
- background: var(--color-processor);
- padding: 0px 10px;
- font-size: 12px;
- color: #FFFFFF;
-}
+ @JsonTypeInfo(use = JsonTypeInfo.Id.NONE, property = "type")
+ private Object value;
-.timestamp-icon {
- font-size: 12px;
-}
+ public GuessTypeInfo() {
+ }
+
+ public GuessTypeInfo(String type, Object value) {
+ this.type = type;
+ this.value = value;
+ }
+ public String getType() {
+ return type;
+ }
+ public void setType(String type) {
+ this.type = type;
+ }
+ public Object getValue() {
+ return value;
+ }
+
+ public void setValue(Object value) {
+ this.value = value;
+ }
+}
diff --git a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
index 24ebb69e4..7d282d6de 100644
--- a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
@@ -18,7 +18,7 @@
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
-// Generated using typescript-generator version 2.27.744 on 2022-08-14 22:39:25.
+// Generated using typescript-generator version 2.27.744 on 2022-08-16 11:39:37.
export class AbstractStreamPipesEntity {
"@class": "org.apache.streampipes.model.base.AbstractStreamPipesEntity" | "org.apache.streampipes.model.base.NamedStreamPipesEntity" | "org.apache.streampipes.model.connect.adapter.AdapterDescription" | "org.apache.streampipes.model.connect.adapter.AdapterSetDescription" | "org.apache.streampipes.model.connect.adapter.GenericAdapterSetDescription" | "org.apache.streampipes.model.connect.adapter.SpecificAdapterSetDescription" | "org.apache.streampipes.model.connect.adapter.AdapterStre [...]
@@ -192,9 +192,9 @@ export class AdapterDescription extends NamedStreamPipesEntity {
instance.selectedEndpointUrl = data.selectedEndpointUrl;
instance.correspondingServiceGroup = data.correspondingServiceGroup;
instance.correspondingDataStreamElementId = data.correspondingDataStreamElementId;
+ instance.valueRules = __getCopyArrayFn(TransformationRuleDescription.fromDataUnion)(data.valueRules);
instance.streamRules = __getCopyArrayFn(TransformationRuleDescription.fromDataUnion)(data.streamRules);
instance.schemaRules = __getCopyArrayFn(TransformationRuleDescription.fromDataUnion)(data.schemaRules);
- instance.valueRules = __getCopyArrayFn(TransformationRuleDescription.fromDataUnion)(data.valueRules);
return instance;
}
@@ -1592,6 +1592,23 @@ export class ExportItem {
}
}
+export class FieldStatusInfo {
+ additionalInfo: string;
+ changesRequired: boolean;
+ fieldStatus: FieldStatus;
+
+ static fromData(data: FieldStatusInfo, target?: FieldStatusInfo): FieldStatusInfo {
+ if (!data) {
+ return data;
+ }
+ const instance = target || new FieldStatusInfo();
+ instance.fieldStatus = data.fieldStatus;
+ instance.additionalInfo = data.additionalInfo;
+ instance.changesRequired = data.changesRequired;
+ return instance;
+ }
+}
+
export class FileMetadata {
createdAt: number;
createdByUser: string;
@@ -1736,8 +1753,8 @@ export class GenericAdapterSetDescription extends AdapterSetDescription implemen
const instance = target || new GenericAdapterSetDescription();
super.fromData(data, instance);
instance.eventSchema = EventSchema.fromData(data.eventSchema);
- instance.formatDescription = FormatDescription.fromData(data.formatDescription);
instance.protocolDescription = ProtocolDescription.fromData(data.protocolDescription);
+ instance.formatDescription = FormatDescription.fromData(data.formatDescription);
return instance;
}
}
@@ -1755,15 +1772,17 @@ export class GenericAdapterStreamDescription extends AdapterStreamDescription im
const instance = target || new GenericAdapterStreamDescription();
super.fromData(data, instance);
instance.eventSchema = EventSchema.fromData(data.eventSchema);
- instance.formatDescription = FormatDescription.fromData(data.formatDescription);
instance.protocolDescription = ProtocolDescription.fromData(data.protocolDescription);
+ instance.formatDescription = FormatDescription.fromData(data.formatDescription);
return instance;
}
}
export class GuessSchema extends UnnamedStreamPipesEntity {
"@class": "org.apache.streampipes.model.connect.guess.GuessSchema";
+ eventPreview: { [index: string]: GuessTypeInfo }[];
eventSchema: EventSchema;
+ fieldStatusInfo: { [index: string]: FieldStatusInfo };
static fromData(data: GuessSchema, target?: GuessSchema): GuessSchema {
if (!data) {
@@ -1772,6 +1791,23 @@ export class GuessSchema extends UnnamedStreamPipesEntity {
const instance = target || new GuessSchema();
super.fromData(data, instance);
instance.eventSchema = EventSchema.fromData(data.eventSchema);
+ instance.eventPreview = __getCopyArrayFn(__getCopyObjectFn(GuessTypeInfo.fromData))(data.eventPreview);
+ instance.fieldStatusInfo = __getCopyObjectFn(FieldStatusInfo.fromData)(data.fieldStatusInfo);
+ return instance;
+ }
+}
+
+export class GuessTypeInfo {
+ type: string;
+ value: any;
+
+ static fromData(data: GuessTypeInfo, target?: GuessTypeInfo): GuessTypeInfo {
+ if (!data) {
+ return data;
+ }
+ const instance = target || new GuessTypeInfo();
+ instance.type = data.type;
+ instance.value = data.value;
return instance;
}
}
@@ -2567,8 +2603,8 @@ export class PipelineTemplateDescription extends NamedStreamPipesEntity {
const instance = target || new PipelineTemplateDescription();
super.fromData(data, instance);
instance.boundTo = __getCopyArrayFn(BoundPipelineElement.fromData)(data.boundTo);
- instance.pipelineTemplateId = data.pipelineTemplateId;
instance.pipelineTemplateName = data.pipelineTemplateName;
+ instance.pipelineTemplateId = data.pipelineTemplateId;
instance.pipelineTemplateDescription = data.pipelineTemplateDescription;
return instance;
}
@@ -3384,6 +3420,8 @@ export type EventPropertyUnion = EventPropertyList | EventPropertyNested | Event
export type EventStreamQualityDefinitionUnion = Frequency | Latency;
+export type FieldStatus = "GOOD" | "BAD" | "ATTENTION";
+
export type MappingPropertyUnion = MappingPropertyNary | MappingPropertyUnary;
export type MeasurementPropertyUnion = EventPropertyQualityDefinition | EventStreamQualityDefinition;
diff --git a/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.html b/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.html
index 47ac53898..be87eb7e2 100644
--- a/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.html
+++ b/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.html
@@ -16,8 +16,8 @@
~
-->
-<div fxLayout="row">
- <div fxFlex="1 1 auto" fxLayout="row" fxLayoutAlign="start center">
+<div fxLayout="row" fxFlex="100" fxLayoutGap="10px">
+ <div fxFlex fxLayout="row" fxLayoutAlign="start center">
<b>
{{ label }}
</b>
@@ -29,8 +29,20 @@
</div>
<p style="margin: 0px 10px 10px;" *ngIf="isList">[List]</p>
</div>
+ <div fxFlex="15" fxLayoutAlign="start center" *ngIf="runtimeType">
+ <span class="runtime-type-info">{{runtimeType}}</span>
+ </div>
+ <div fxFlex="15" fxLayoutAlign="start center">
+ <span *ngIf="showEventPreview">{{eventPreview[0][node.data.runtimeName].value || 'n/a'}}</span>
+ </div>
+ <div fxFlex="15" fxLayoutAlign="start center">
+ <span *ngIf="showFieldStatus"
+ [ngClass]="'status status-' +fieldStatusInfo[node.data.runtimeName].fieldStatus.toLowerCase()"
+ [matTooltip]="fieldStatusInfo[node.data.runtimeName].additionalInfo">{{fieldStatusInfo[node.data.runtimeName].fieldStatus}}</span>
+ </div>
- <div fxFlex="15" *ngIf="isPrimitive" fxLayoutAlign="center center">
+ <div fxLayout="row" fxLayoutAlign="end center">
+ <div fxFlex="15" *ngIf="isPrimitive" fxLayoutAlign="end center">
<mat-form-field class="small-select" color="accent">
<mat-select [(ngModel)]="node.data.propertyScope" panelClass="small-select"
[attr.data-cy]="'property-scope-' + label">
@@ -41,14 +53,14 @@
</mat-form-field>
</div>
- <div fxFlex="0 1 auto" fxLayoutAlign="center center"
+ <div fxLayoutAlign="end center"
*ngIf="isNested">
<button [disabled]="!isEditable" color="accent" mat-button (click)=addNestedProperty(node.data)>
<mat-icon matTooltip="Add a Nested Property">queue</mat-icon>
</button>
</div>
- <div fxFlex="0 1 auto"
- fxLayoutAlign="center center"
+ <div
+ fxLayoutAlign="end center"
class="ml-5 mr-5"
*ngIf="isNested || isPrimitive || isList">
<button [disabled]="!isEditable" color="accent" mat-button
@@ -57,7 +69,7 @@
<mat-icon>edit</mat-icon> Edit field
</button>
</div>
- <div fxFlex="0 1 auto" fxLayoutAlign="center center">
+ <div fxLayoutAlign="end center">
<mat-checkbox
*ngIf="isNested || isPrimitive || isList"
(click)="selectProperty(node.data.id, undefined)"
@@ -67,4 +79,5 @@
[attr.data-cy]="'delete-property-' + label.toLowerCase()">
</mat-checkbox>
</div>
+ </div>
</div>
diff --git a/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.scss b/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.scss
index aa6f60f17..c20307e9b 100644
--- a/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.scss
+++ b/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.scss
@@ -42,5 +42,30 @@
font-size: 12px;
}
+.status-good {
+ background: #75c575;
+ color: white;
+}
+
+.status-bad {
+ background: #d2a169;
+ color: white;
+}
+
+.status {
+ width: 60px;
+ text-align: center;
+ padding: 5px;
+ border-radius: 3px;
+}
+
+.runtime-type-info {
+ padding: 5px;
+ border-radius: 3px;
+ background: var(--color-bg-3);
+ color: var(--color-default-text);
+ width: 70px;
+ text-align: center;
+}
diff --git a/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.ts b/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.ts
index c4fb32923..f2be21368 100644
--- a/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.ts
+++ b/ui/src/app/connect/components/new-adapter/schema-editor/event-property-row/event-property-row.component.ts
@@ -21,15 +21,18 @@ import { UUID } from 'angular2-uuid';
import { TreeNode } from '@circlon/angular-tree-component';
import { MatDialog } from '@angular/material/dialog';
import {
- EventProperty,
- EventPropertyList,
- EventPropertyNested,
- EventPropertyPrimitive,
- EventPropertyUnion,
- EventSchema
+ EventProperty,
+ EventPropertyList,
+ EventPropertyNested,
+ EventPropertyPrimitive,
+ EventPropertyUnion,
+ EventSchema,
+ FieldStatusInfo,
+
} from '@streampipes/platform-services';
import { EditEventPropertyComponent } from '../../../../dialog/edit-event-property/edit-event-property.component';
import { DialogService, PanelType } from '@streampipes/shared-ui';
+import { GuessTypeInfo } from '../../../../../../../projects/streampipes/platform-services/src/lib/model/gen/streampipes-model';
@Component({
selector: 'event-property-row',
@@ -42,6 +45,8 @@ export class EventPropertyRowComponent implements OnInit, OnChanges {
@Input() isEditable = true;
@Input() eventSchema: EventSchema = new EventSchema();
@Input() countSelected: number;
+ @Input() eventPreview: Record<string, GuessTypeInfo>[];
+ @Input() fieldStatusInfo: Record<string, FieldStatusInfo>;
@Output() isEditableChange = new EventEmitter<boolean>();
@Output() eventSchemaChange = new EventEmitter<EventSchema>();
@@ -53,6 +58,10 @@ export class EventPropertyRowComponent implements OnInit, OnChanges {
isNested = false;
isList = false;
timestampProperty = false;
+ showEventPreview = false;
+ showFieldStatus = false;
+
+ runtimeType: string;
constructor(private dialog: MatDialog,
private dialogService: DialogService) {
@@ -60,12 +69,18 @@ export class EventPropertyRowComponent implements OnInit, OnChanges {
}
ngOnInit() {
+ this.showFieldStatus = this.fieldStatusInfo && this.fieldStatusInfo[this.node.data.runtimeName] !== undefined;
+ this.showEventPreview = this.eventPreview && this.eventPreview.length > 0 && this.eventPreview[0][this.node.data.runtimeName] !== undefined;
this.label = this.getLabel(this.node.data);
this.isPrimitive = this.isEventPropertyPrimitive(this.node.data);
this.isList = this.isEventPropertyList(this.node.data);
this.isNested = this.isEventPropertyNested(this.node.data);
this.timestampProperty = this.isTimestampProperty(this.node.data);
+ if (this.isPrimitive) {
+ this.runtimeType = this.parseType(this.node.data.runtimeType);
+ }
+
if (!this.node.data.propertyScope) {
this.node.data.propertyScope = 'MEASUREMENT_PROPERTY';
}
@@ -74,6 +89,10 @@ export class EventPropertyRowComponent implements OnInit, OnChanges {
ngOnChanges(changes: SimpleChanges): void {
}
+ private parseType(runtimeType: string) {
+ return runtimeType.split('#')[1].toUpperCase();
+ }
+
private isEventPropertyPrimitive(instance: EventProperty): boolean {
return instance instanceof EventPropertyPrimitive;
}
@@ -122,8 +141,8 @@ export class EventPropertyRowComponent implements OnInit, OnChanges {
});
dialogRef.afterClosed().subscribe(refresh => {
- this.timestampProperty = this.isTimestampProperty(this.node.data);
- this.refreshTreeEmitter.emit();
+ this.timestampProperty = this.isTimestampProperty(this.node.data);
+ this.refreshTreeEmitter.emit();
});
}
diff --git a/ui/src/app/connect/components/new-adapter/schema-editor/event-schema/event-schema.component.html b/ui/src/app/connect/components/new-adapter/schema-editor/event-schema/event-schema.component.html
index 6e85d424f..8344671e5 100644
--- a/ui/src/app/connect/components/new-adapter/schema-editor/event-schema/event-schema.component.html
+++ b/ui/src/app/connect/components/new-adapter/schema-editor/event-schema/event-schema.component.html
@@ -18,7 +18,7 @@
<div fxLayout="row" fxLayoutAlign="center" class="mt-20">
- <div fxFlex="80" fxLayout="column">
+ <div fxFlex="90" fxLayout="column">
<div fxLayout="column"
fxFlex="100"
fxLayoutAlign="start center"
@@ -73,10 +73,10 @@
<sp-error-message
[errorMessage]="errorMessage"
- *ngIf="isError">
+ *ngIf="isError && !isLoading">
</sp-error-message>
- <div *ngIf="!isError && !isLoading"
+ <div *ngIf="!isError && !isLoading && eventSchema"
fxLayout="column"
fxLayoutAlign="space-evenly stretched"
class="drag-drop-tree"
@@ -90,6 +90,8 @@
[node]="node"
[(isEditable)]="isEditable"
[(eventSchema)]="eventSchema"
+ [eventPreview]="eventPreview"
+ [fieldStatusInfo]="fieldStatusInfo"
(refreshTreeEmitter)="refreshTree()"
[(countSelected)]="countSelected"></event-property-row>
</ng-template>
diff --git a/ui/src/app/connect/components/new-adapter/schema-editor/event-schema/event-schema.component.ts b/ui/src/app/connect/components/new-adapter/schema-editor/event-schema/event-schema.component.ts
index 5ca2b4e58..d70a53048 100644
--- a/ui/src/app/connect/components/new-adapter/schema-editor/event-schema/event-schema.component.ts
+++ b/ui/src/app/connect/components/new-adapter/schema-editor/event-schema/event-schema.component.ts
@@ -32,7 +32,10 @@ import {
} from '@streampipes/platform-services';
import { MatStepper } from '@angular/material/stepper';
import { UserErrorMessage } from '../../../../../core-model/base/UserErrorMessage';
-import { StreamPipesErrorMessage } from '../../../../../../../projects/streampipes/platform-services/src/lib/model/gen/streampipes-model';
+import {
+ FieldStatusInfo, GuessTypeInfo,
+ StreamPipesErrorMessage
+} from '../../../../../../../projects/streampipes/platform-services/src/lib/model/gen/streampipes-model';
@Component({
selector: 'sp-event-schema',
@@ -79,6 +82,9 @@ export class EventSchemaComponent implements OnChanges {
validEventSchema = false;
schemaErrorHints: UserErrorMessage[] = [];
+ eventPreview: Record<string, GuessTypeInfo>[];
+ fieldStatusInfo: Record<string, FieldStatusInfo>;
+
options: ITreeOptions = {
childrenField: 'eventProperties',
allowDrag: () => {
@@ -99,6 +105,8 @@ export class EventSchemaComponent implements OnChanges {
this.isLoading = true;
this.isError = false;
this.restService.getGuessSchema(this.adapterDescription).subscribe(guessSchema => {
+ this.eventPreview = guessSchema.eventPreview;
+ this.fieldStatusInfo = guessSchema.fieldStatusInfo;
this.eventSchema = guessSchema.eventSchema;
this.eventSchema.eventProperties.sort((a, b) => {
return a.runtimeName < b.runtimeName ? -1 : 1;