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 2020/05/18 20:55:00 UTC

[incubator-streampipes] branch dev updated: [STREAMPIPES-133] Add CodeInputStaticProperty

This is an automated email from the ASF dual-hosted git repository.

riemer pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git


The following commit(s) were added to refs/heads/dev by this push:
     new 030d999  [STREAMPIPES-133] Add CodeInputStaticProperty
030d999 is described below

commit 030d9997b0ed062cd241fdcd2e34b3ee54be2828
Author: Dominik Riemer <ri...@fzi.de>
AuthorDate: Mon May 18 22:54:43 2020 +0200

    [STREAMPIPES-133] Add CodeInputStaticProperty
---
 .../staticproperty/CodeInputStaticProperty.java    | 66 ++++++++++++++++
 .../model/staticproperty/StaticPropertyType.java   |  3 +-
 .../org/apache/streampipes/model/util/Cloner.java  | 22 +-----
 ...AbstractConfigurablePipelineElementBuilder.java | 33 ++++----
 .../streampipes/sdk/helpers/CodeLanguage.java      | 34 ++++-----
 .../jsonld/CustomAnnotationProvider.java           | 72 ++----------------
 .../apache/streampipes/vocabulary/StreamPipes.java |  4 +
 ui/package.json                                    |  2 +
 .../components/code/code-editor.directive.ts       | 88 ++++++++++++++++++++++
 .../app/editor/components/code/code.component.ts   | 32 ++++----
 .../app/editor/components/code/code.controller.ts  | 30 +++-----
 ui/src/app/editor/components/code/code.tmpl.html   | 28 +++++++
 .../customize/customize-dialog.tmpl.html           |  5 ++
 ui/src/app/editor/editor.module.ts                 |  4 +
 ui/src/scss/main.scss                              |  6 ++
 ui/src/scss/sp/main.scss                           |  4 +
 16 files changed, 280 insertions(+), 153 deletions(-)

diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/CodeInputStaticProperty.java b/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/CodeInputStaticProperty.java
new file mode 100644
index 0000000..9d596c5
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/CodeInputStaticProperty.java
@@ -0,0 +1,66 @@
+/*
+ * 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.staticproperty;
+
+import io.fogsy.empire.annotations.RdfProperty;
+import io.fogsy.empire.annotations.RdfsClass;
+import org.apache.streampipes.vocabulary.StreamPipes;
+
+import javax.persistence.Entity;
+
+@RdfsClass(StreamPipes.CODE_INPUT_STATIC_PROPERTY)
+@Entity
+public class CodeInputStaticProperty extends StaticProperty {
+
+  @RdfProperty(StreamPipes.HAS_LANGUAGE)
+  private String language;
+
+  @RdfProperty(StreamPipes.HAS_CODE_INPUT)
+  private String value;
+
+  public CodeInputStaticProperty() {
+    super(StaticPropertyType.CodeInputStaticProperty);
+  }
+
+  public CodeInputStaticProperty(CodeInputStaticProperty other) {
+    super(other);
+    this.language = other.getLanguage();
+    this.value = other.getValue();
+  }
+
+  public CodeInputStaticProperty(String internalName, String label, String description) {
+    super(StaticPropertyType.CodeInputStaticProperty, internalName, label, description);
+  }
+
+  public String getLanguage() {
+    return language;
+  }
+
+  public void setLanguage(String language) {
+    this.language = language;
+  }
+
+  public String getValue() {
+    return value;
+  }
+
+  public void setValue(String value) {
+    this.value = value;
+  }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/StaticPropertyType.java b/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/StaticPropertyType.java
index 1542bfe..b9e760b 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/StaticPropertyType.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/StaticPropertyType.java
@@ -34,6 +34,7 @@ public enum StaticPropertyType {
     StaticPropertyGroup,
     StaticPropertyAlternatives,
     StaticPropertyAlternative,
-    SecretStaticProperty;
+    SecretStaticProperty,
+    CodeInputStaticProperty;
 
 }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/util/Cloner.java b/streampipes-model/src/main/java/org/apache/streampipes/model/util/Cloner.java
index 56bf62b..4f66239 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/util/Cloner.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/util/Cloner.java
@@ -18,6 +18,7 @@
 
 package org.apache.streampipes.model.util;
 
+import org.apache.streampipes.model.staticproperty.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.streampipes.model.ApplicationLink;
@@ -65,25 +66,6 @@ import org.apache.streampipes.model.schema.EventPropertyNested;
 import org.apache.streampipes.model.schema.EventPropertyPrimitive;
 import org.apache.streampipes.model.schema.QuantitativeValue;
 import org.apache.streampipes.model.schema.ValueSpecification;
-import org.apache.streampipes.model.staticproperty.AnyStaticProperty;
-import org.apache.streampipes.model.staticproperty.CollectionStaticProperty;
-import org.apache.streampipes.model.staticproperty.DomainStaticProperty;
-import org.apache.streampipes.model.staticproperty.FreeTextStaticProperty;
-import org.apache.streampipes.model.staticproperty.MappingPropertyNary;
-import org.apache.streampipes.model.staticproperty.MappingPropertyUnary;
-import org.apache.streampipes.model.staticproperty.MatchingStaticProperty;
-import org.apache.streampipes.model.staticproperty.OneOfStaticProperty;
-import org.apache.streampipes.model.staticproperty.Option;
-import org.apache.streampipes.model.staticproperty.RemoteOneOfStaticProperty;
-import org.apache.streampipes.model.staticproperty.RuntimeResolvableAnyStaticProperty;
-import org.apache.streampipes.model.staticproperty.RuntimeResolvableOneOfStaticProperty;
-import org.apache.streampipes.model.staticproperty.SecretStaticProperty;
-import org.apache.streampipes.model.staticproperty.StaticProperty;
-import org.apache.streampipes.model.staticproperty.StaticPropertyAlternative;
-import org.apache.streampipes.model.staticproperty.StaticPropertyAlternatives;
-import org.apache.streampipes.model.staticproperty.StaticPropertyGroup;
-import org.apache.streampipes.model.staticproperty.SupportedProperty;
-import org.apache.streampipes.model.staticproperty.FileStaticProperty;
 import org.apache.streampipes.model.template.BoundPipelineElement;
 
 import java.util.ArrayList;
@@ -143,6 +125,8 @@ public class Cloner {
       return new SecretStaticProperty((SecretStaticProperty) o);
     } else if (o instanceof FileStaticProperty) {
       return new FileStaticProperty((FileStaticProperty) o);
+    } else if (o instanceof CodeInputStaticProperty) {
+      return new CodeInputStaticProperty((CodeInputStaticProperty) o);
     } else {
       return new StaticPropertyAlternative((StaticPropertyAlternative) o);
     }
diff --git a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/AbstractConfigurablePipelineElementBuilder.java b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/AbstractConfigurablePipelineElementBuilder.java
index b71e9a3..befc3d3 100644
--- a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/AbstractConfigurablePipelineElementBuilder.java
+++ b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/AbstractConfigurablePipelineElementBuilder.java
@@ -18,20 +18,9 @@
 package org.apache.streampipes.sdk.builder;
 
 import org.apache.streampipes.model.base.NamedStreamPipesEntity;
-import org.apache.streampipes.model.staticproperty.AnyStaticProperty;
-import org.apache.streampipes.model.staticproperty.CollectionStaticProperty;
-import org.apache.streampipes.model.staticproperty.DomainStaticProperty;
-import org.apache.streampipes.model.staticproperty.FileStaticProperty;
-import org.apache.streampipes.model.staticproperty.FreeTextStaticProperty;
-import org.apache.streampipes.model.staticproperty.OneOfStaticProperty;
-import org.apache.streampipes.model.staticproperty.Option;
-import org.apache.streampipes.model.staticproperty.PropertyValueSpecification;
-import org.apache.streampipes.model.staticproperty.SecretStaticProperty;
-import org.apache.streampipes.model.staticproperty.StaticProperty;
-import org.apache.streampipes.model.staticproperty.StaticPropertyAlternative;
-import org.apache.streampipes.model.staticproperty.StaticPropertyAlternatives;
-import org.apache.streampipes.model.staticproperty.SupportedProperty;
+import org.apache.streampipes.model.staticproperty.*;
 import org.apache.streampipes.sdk.StaticProperties;
+import org.apache.streampipes.sdk.helpers.CodeLanguage;
 import org.apache.streampipes.sdk.helpers.Label;
 import org.apache.streampipes.sdk.helpers.Labels;
 import org.apache.streampipes.vocabulary.XSD;
@@ -148,6 +137,24 @@ public abstract class AbstractConfigurablePipelineElementBuilder<BU extends
     return me();
   }
 
+  /**
+   * Assigns a new code block parameter which is required
+   * by the processing element.
+   * @param label The {@link org.apache.streampipes.sdk.helpers.Label} that describes why this parameter is needed in a
+   *              user-friendly manner.
+   * @param codeLanguage The {@link org.apache.streampipes.sdk.helpers.CodeLanguage} code language the code block is built for.
+   * @return this
+   */
+  public BU requiredCodeblock(Label label, CodeLanguage codeLanguage) {
+    CodeInputStaticProperty codeInputStaticProperty = new CodeInputStaticProperty(label.getInternalId(),
+            label.getLabel(), label.getDescription());
+    codeInputStaticProperty.setLanguage(codeLanguage.name());
+    codeInputStaticProperty.setValue(codeLanguage.getDefaultSkeleton());
+    this.staticProperties.add(codeInputStaticProperty);
+
+    return me();
+  }
+
 
   /**
    * Assigns a new text-based configuration parameter (a string) which is required by the pipeline
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/StaticPropertyType.java b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/CodeLanguage.java
similarity index 59%
copy from streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/StaticPropertyType.java
copy to streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/CodeLanguage.java
index 1542bfe..8a51d5e 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/StaticPropertyType.java
+++ b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/helpers/CodeLanguage.java
@@ -16,24 +16,22 @@
  *
  */
 
-package org.apache.streampipes.model.staticproperty;
+package org.apache.streampipes.sdk.helpers;
 
-public enum StaticPropertyType {
-    AnyStaticProperty,
-    CollectionStaticProperty,
-    ColorPickerStaticProperty,
-    DomainStaticProperty,
-    FreeTextStaticProperty,
-    FileStaticProperty,
-    MappingPropertyUnary,
-    MappingPropertyNary,
-    MatchingStaticProperty,
-    OneOfStaticProperty,
-    RuntimeResolvableAnyStaticProperty,
-    RuntimeResolvableOneOfStaticProperty,
-    StaticPropertyGroup,
-    StaticPropertyAlternatives,
-    StaticPropertyAlternative,
-    SecretStaticProperty;
+public enum CodeLanguage {
+  Javascript("function process(event) {\n" +
+          "    // do processing here.\n" +
+          "    // return processed event.\n" +
+          "    return {id: event.id, tempInCelsius: (event.tempInKelvin - 273.15)};\n" +
+          "};");
 
+  private String defaultSkeleton;
+
+  CodeLanguage(String defaultSkeleton) {
+    this.defaultSkeleton = defaultSkeleton;
+  }
+
+  public String getDefaultSkeleton() {
+    return defaultSkeleton;
+  }
 }
diff --git a/streampipes-serializers/src/main/java/org/apache/streampipes/serializers/jsonld/CustomAnnotationProvider.java b/streampipes-serializers/src/main/java/org/apache/streampipes/serializers/jsonld/CustomAnnotationProvider.java
index 07fcff4..b04b7f1 100644
--- a/streampipes-serializers/src/main/java/org/apache/streampipes/serializers/jsonld/CustomAnnotationProvider.java
+++ b/streampipes-serializers/src/main/java/org/apache/streampipes/serializers/jsonld/CustomAnnotationProvider.java
@@ -28,11 +28,7 @@ import org.apache.streampipes.model.client.messages.ErrorMessageLd;
 import org.apache.streampipes.model.client.messages.MessageLd;
 import org.apache.streampipes.model.client.messages.NotificationLd;
 import org.apache.streampipes.model.client.messages.SuccessMessageLd;
-import org.apache.streampipes.model.connect.adapter.AdapterDescriptionList;
-import org.apache.streampipes.model.connect.adapter.GenericAdapterSetDescription;
-import org.apache.streampipes.model.connect.adapter.GenericAdapterStreamDescription;
-import org.apache.streampipes.model.connect.adapter.SpecificAdapterSetDescription;
-import org.apache.streampipes.model.connect.adapter.SpecificAdapterStreamDescription;
+import org.apache.streampipes.model.connect.adapter.*;
 import org.apache.streampipes.model.connect.grounding.FormatDescription;
 import org.apache.streampipes.model.connect.grounding.FormatDescriptionList;
 import org.apache.streampipes.model.connect.grounding.ProtocolDescription;
@@ -53,68 +49,15 @@ import org.apache.streampipes.model.connect.rules.value.UnitTransformRuleDescrip
 import org.apache.streampipes.model.connect.worker.ConnectWorkerContainer;
 import org.apache.streampipes.model.dashboard.DashboardWidgetModel;
 import org.apache.streampipes.model.dashboard.VisualizablePipeline;
-import org.apache.streampipes.model.graph.DataProcessorDescription;
-import org.apache.streampipes.model.graph.DataProcessorInvocation;
-import org.apache.streampipes.model.graph.DataSinkDescription;
-import org.apache.streampipes.model.graph.DataSinkInvocation;
-import org.apache.streampipes.model.graph.DataSourceDescription;
-import org.apache.streampipes.model.grounding.EventGrounding;
-import org.apache.streampipes.model.grounding.JmsTransportProtocol;
-import org.apache.streampipes.model.grounding.KafkaTransportProtocol;
-import org.apache.streampipes.model.grounding.MqttTransportProtocol;
-import org.apache.streampipes.model.grounding.SimpleTopicDefinition;
-import org.apache.streampipes.model.grounding.TransportFormat;
-import org.apache.streampipes.model.grounding.TransportProtocol;
-import org.apache.streampipes.model.grounding.WildcardTopicDefinition;
+import org.apache.streampipes.model.graph.*;
+import org.apache.streampipes.model.grounding.*;
 import org.apache.streampipes.model.monitoring.ElementStatusInfoSettings;
-import org.apache.streampipes.model.output.AppendOutputStrategy;
-import org.apache.streampipes.model.output.CustomOutputStrategy;
-import org.apache.streampipes.model.output.CustomTransformOutputStrategy;
-import org.apache.streampipes.model.output.FixedOutputStrategy;
-import org.apache.streampipes.model.output.KeepOutputStrategy;
-import org.apache.streampipes.model.output.ListOutputStrategy;
-import org.apache.streampipes.model.output.PropertyRenameRule;
-import org.apache.streampipes.model.output.TransformOperation;
-import org.apache.streampipes.model.output.TransformOutputStrategy;
-import org.apache.streampipes.model.quality.Accuracy;
-import org.apache.streampipes.model.quality.EventPropertyQualityRequirement;
-import org.apache.streampipes.model.quality.EventStreamQualityRequirement;
-import org.apache.streampipes.model.quality.Frequency;
-import org.apache.streampipes.model.quality.Latency;
-import org.apache.streampipes.model.quality.MeasurementCapability;
-import org.apache.streampipes.model.quality.MeasurementObject;
-import org.apache.streampipes.model.quality.MeasurementProperty;
-import org.apache.streampipes.model.quality.MeasurementRange;
-import org.apache.streampipes.model.quality.Precision;
-import org.apache.streampipes.model.quality.Resolution;
+import org.apache.streampipes.model.output.*;
+import org.apache.streampipes.model.quality.*;
 import org.apache.streampipes.model.runtime.RuntimeOptionsRequest;
 import org.apache.streampipes.model.runtime.RuntimeOptionsResponse;
-import org.apache.streampipes.model.schema.Enumeration;
-import org.apache.streampipes.model.schema.EventPropertyList;
-import org.apache.streampipes.model.schema.EventPropertyNested;
-import org.apache.streampipes.model.schema.EventPropertyPrimitive;
-import org.apache.streampipes.model.schema.EventSchema;
-import org.apache.streampipes.model.schema.QuantitativeValue;
-import org.apache.streampipes.model.staticproperty.AnyStaticProperty;
-import org.apache.streampipes.model.staticproperty.CollectionStaticProperty;
-import org.apache.streampipes.model.staticproperty.ColorPickerStaticProperty;
-import org.apache.streampipes.model.staticproperty.DomainStaticProperty;
-import org.apache.streampipes.model.staticproperty.FileStaticProperty;
-import org.apache.streampipes.model.staticproperty.FreeTextStaticProperty;
-import org.apache.streampipes.model.staticproperty.MappingProperty;
-import org.apache.streampipes.model.staticproperty.MappingPropertyNary;
-import org.apache.streampipes.model.staticproperty.MappingPropertyUnary;
-import org.apache.streampipes.model.staticproperty.MatchingStaticProperty;
-import org.apache.streampipes.model.staticproperty.OneOfStaticProperty;
-import org.apache.streampipes.model.staticproperty.Option;
-import org.apache.streampipes.model.staticproperty.RemoteOneOfStaticProperty;
-import org.apache.streampipes.model.staticproperty.RuntimeResolvableAnyStaticProperty;
-import org.apache.streampipes.model.staticproperty.RuntimeResolvableOneOfStaticProperty;
-import org.apache.streampipes.model.staticproperty.SecretStaticProperty;
-import org.apache.streampipes.model.staticproperty.StaticPropertyAlternative;
-import org.apache.streampipes.model.staticproperty.StaticPropertyAlternatives;
-import org.apache.streampipes.model.staticproperty.StaticPropertyGroup;
-import org.apache.streampipes.model.staticproperty.SupportedProperty;
+import org.apache.streampipes.model.schema.*;
+import org.apache.streampipes.model.staticproperty.*;
 import org.apache.streampipes.model.template.BoundPipelineElement;
 import org.apache.streampipes.model.template.PipelineTemplateDescription;
 import org.apache.streampipes.model.template.PipelineTemplateDescriptionContainer;
@@ -147,6 +90,7 @@ public class CustomAnnotationProvider implements EmpireAnnotationProvider {
   private List<Class<?>> getAnnotatedClasses() {
     return Arrays.asList(
             Accuracy.class,
+            CodeInputStaticProperty.class,
             ColorPickerStaticProperty.class,
             CustomOutputStrategy.class,
             DataSinkDescription.class,
diff --git a/streampipes-vocabulary/src/main/java/org/apache/streampipes/vocabulary/StreamPipes.java b/streampipes-vocabulary/src/main/java/org/apache/streampipes/vocabulary/StreamPipes.java
index 9970a6b..8aad8f9 100644
--- a/streampipes-vocabulary/src/main/java/org/apache/streampipes/vocabulary/StreamPipes.java
+++ b/streampipes-vocabulary/src/main/java/org/apache/streampipes/vocabulary/StreamPipes.java
@@ -381,4 +381,8 @@ public class StreamPipes {
   public static final String HAS_WIDGET_ICON_NAME = NS + "hasWidgetIconName";
   public static final String HAS_WIDGET_DESCRIPTION = NS + "hasWidgetDescription";
   public static final String CORRESPONDING_USER = NS + "hasCorrespondingUser";
+
+  public static final String CODE_INPUT_STATIC_PROPERTY = NS + "CodeInputStaticProperty";
+  public static final String HAS_LANGUAGE = NS + "hasLanguage";
+  public static final String HAS_CODE_INPUT = NS + "hasCodeInput";
 }
diff --git a/ui/package.json b/ui/package.json
index 7b7820c..0a69271 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -67,6 +67,7 @@
     "angularjs-datetime-picker": "0.1.16",
     "bootstrap": "3.3.4",
     "calendar-heatmap-graph": "0.0.14",
+    "codemirror": "5.53.2",
     "core-js": "2.5.3",
     "dagre": "0.8.4",
     "fast-json-patch": "2.1.0",
@@ -75,6 +76,7 @@
     "jquery-ui-dist": "1.12.1",
     "jquery.panzoom": "2.0.5",
     "datatables.net": "1.10.20",
+    "jshint": "2.11.1",
     "jsonld": "0.4.12",
     "jsplumb": "2.1.3",
     "jszip": "3.2.1",
diff --git a/ui/src/app/editor/components/code/code-editor.directive.ts b/ui/src/app/editor/components/code/code-editor.directive.ts
new file mode 100644
index 0000000..a712f50
--- /dev/null
+++ b/ui/src/app/editor/components/code/code-editor.directive.ts
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ *
+ */
+
+import CodeMirror from 'codemirror';
+import 'codemirror/mode/javascript/javascript';
+import 'codemirror/addon/edit/closebrackets';
+import 'codemirror/addon/hint/show-hint';
+import 'codemirror/addon/hint/javascript-hint';
+import 'codemirror/addon/lint/lint';
+import 'codemirror/addon/lint/javascript-lint';
+import {JSHINT} from 'jshint';
+
+export class CodeEditorDirective {
+
+    require: string = "?ngModel";
+    replace: boolean = true;
+    transclude: boolean = true;
+    template: string = '<div class="code-editor"></div>';
+
+    constructor() {
+        (<any>window).JSHINT = JSHINT;
+    }
+
+    link(scope, element, attrs, ngModelCtrl, transclude) {
+        let selectedElement = scope.$eval(attrs.inputStreams);
+        scope.editor = CodeMirror(element[0], {
+            mode: "javascript",
+            autoRefresh: true,
+            theme: 'dracula',
+            autoCloseBrackets: true,
+            lineNumbers: true,
+            lineWrapping: true,
+            gutters: ["CodeMirror-lint-markers"],
+            lint: true,
+            extraKeys: {
+                "Ctrl-Space": "autocomplete"
+            }
+        });
+        this.enableCodeHints(selectedElement);
+
+        if (ngModelCtrl) {
+            ngModelCtrl.$render = () => {
+                setTimeout(() => {
+                    scope.editor.setValue(ngModelCtrl.$viewValue);
+                    scope.editor.refresh();
+                },200);
+            }
+        }
+        scope.editor.on('change', () => {
+            ngModelCtrl.$setViewValue(scope.editor.getValue());
+            scope.$emit('editor-change')
+        })
+    }
+
+    enableCodeHints(selectedElement: any) {
+        var jsHint = CodeMirror.hint.javascript;
+        CodeMirror.hint.javascript = (cm) => {
+            let cursor = cm.getCursor();
+            let token = cm.getTokenAt(cursor);
+            let inner = {from: cm.getCursor(), to: cm.getCursor(), list: []};
+            let previousCursor = {line: cursor.line, ch: (cursor.ch - 1), sticky: null}
+            let previousToken = cm.getTokenAt(previousCursor);
+            if (token.string === "." && previousToken.string === "event") {
+                selectedElement.inputStreams[0].eventSchema.eventProperties.forEach(ep => {
+                    inner.list.unshift(ep.properties.runtimeName);
+                })
+            } else {
+                inner = jsHint(cm);
+            }
+            return inner;
+        };
+    }
+}
\ No newline at end of file
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/StaticPropertyType.java b/ui/src/app/editor/components/code/code.component.ts
similarity index 59%
copy from streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/StaticPropertyType.java
copy to ui/src/app/editor/components/code/code.component.ts
index 1542bfe..f3fdaec 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/StaticPropertyType.java
+++ b/ui/src/app/editor/components/code/code.component.ts
@@ -16,24 +16,18 @@
  *
  */
 
-package org.apache.streampipes.model.staticproperty;
+import {CodeInputController} from "./code.controller";
 
-public enum StaticPropertyType {
-    AnyStaticProperty,
-    CollectionStaticProperty,
-    ColorPickerStaticProperty,
-    DomainStaticProperty,
-    FreeTextStaticProperty,
-    FileStaticProperty,
-    MappingPropertyUnary,
-    MappingPropertyNary,
-    MatchingStaticProperty,
-    OneOfStaticProperty,
-    RuntimeResolvableAnyStaticProperty,
-    RuntimeResolvableOneOfStaticProperty,
-    StaticPropertyGroup,
-    StaticPropertyAlternatives,
-    StaticPropertyAlternative,
-    SecretStaticProperty;
+declare const require: any;
 
-}
+export let CodeInputComponent = {
+    template: require('./code.tmpl.html'),
+    bindings: {
+        staticProperty: "=",
+        displayRecommended: "=",
+        customizeForm: "=",
+        selectedElement: "="
+    },
+    controller: CodeInputController,
+    controllerAs: 'ctrl'
+};
\ No newline at end of file
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/StaticPropertyType.java b/ui/src/app/editor/components/code/code.controller.ts
similarity index 59%
copy from streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/StaticPropertyType.java
copy to ui/src/app/editor/components/code/code.controller.ts
index 1542bfe..7507c20 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/StaticPropertyType.java
+++ b/ui/src/app/editor/components/code/code.controller.ts
@@ -16,24 +16,16 @@
  *
  */
 
-package org.apache.streampipes.model.staticproperty;
+export class CodeInputController {
 
-public enum StaticPropertyType {
-    AnyStaticProperty,
-    CollectionStaticProperty,
-    ColorPickerStaticProperty,
-    DomainStaticProperty,
-    FreeTextStaticProperty,
-    FileStaticProperty,
-    MappingPropertyUnary,
-    MappingPropertyNary,
-    MatchingStaticProperty,
-    OneOfStaticProperty,
-    RuntimeResolvableAnyStaticProperty,
-    RuntimeResolvableOneOfStaticProperty,
-    StaticPropertyGroup,
-    StaticPropertyAlternatives,
-    StaticPropertyAlternative,
-    SecretStaticProperty;
+    staticProperty: any;
+    displayRecommended: boolean;
+    customizeForm: any;
+    selectedElement: any;
 
-}
+    showEditor: boolean = false;
+
+    $postLink() {
+        this.showEditor = true;
+    }
+}
\ No newline at end of file
diff --git a/ui/src/app/editor/components/code/code.tmpl.html b/ui/src/app/editor/components/code/code.tmpl.html
new file mode 100644
index 0000000..fe48ceb
--- /dev/null
+++ b/ui/src/app/editor/components/code/code.tmpl.html
@@ -0,0 +1,28 @@
+<!--
+  ~ 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.
+  ~
+  -->
+<div layout="row" flex="100">
+<div layout="column" layout-align="start center">
+<i class="material-icons">info</i>
+</div>
+    <div layout="column" layout-align="center center">Use Ctrl-Space to get code hints.</div>
+</div>
+
+<code-editor ng-model="ctrl.staticProperty.properties.value"
+             ng-if="ctrl.showEditor"
+             input-streams="{{ctrl.selectedElement}}">
+</code-editor>
\ No newline at end of file
diff --git a/ui/src/app/editor/components/customize/customize-dialog.tmpl.html b/ui/src/app/editor/components/customize/customize-dialog.tmpl.html
index 1a2737b..6c48606 100644
--- a/ui/src/app/editor/components/customize/customize-dialog.tmpl.html
+++ b/ui/src/app/editor/components/customize/customize-dialog.tmpl.html
@@ -87,5 +87,10 @@
                                   restricted-edit-mode="ctrl.restrictedEditMode">
             </file-static-property>
         </div>
+        <div ng-if="ctrl.staticProperty.properties.staticPropertyType == 'CodeInputStaticProperty'">
+            <code-input customize-form="ctrl.customizeForm" display-recommended="ctrl.displayRecommended"
+                                  static-property="ctrl.staticProperty" selected-element="ctrl.selectedElement">
+            </code-input>
+        </div>
     </div>
 </div>
\ No newline at end of file
diff --git a/ui/src/app/editor/editor.module.ts b/ui/src/app/editor/editor.module.ts
index 5cdcfed..1305c2a 100644
--- a/ui/src/app/editor/editor.module.ts
+++ b/ui/src/app/editor/editor.module.ts
@@ -71,6 +71,8 @@ import {GroupComponent} from "./components/group/group.component";
 import {SecretComponent} from "./components/secret/secret.component";
 import {FileUploadComponent} from "./components/fileupload/fileupload.component";
 import {AnyRemoteComponent} from "./components/any-remote/any-remote.component";
+import {CodeInputComponent} from "./components/code/code.component";
+import {CodeEditorDirective} from "./components/code/code-editor.directive";
 
 
 export default angular.module('sp.editor', [spServices, 'ngSanitize', 'angularTrix', 'ngAnimate', 'datatables', 'ng-showdown'])
@@ -109,7 +111,9 @@ export default angular.module('sp.editor', [spServices, 'ngSanitize', 'angularTr
     .component('alternative', AlternativeComponent)
     .component('group', GroupComponent)
     .component('fileStaticProperty', FileUploadComponent)
+    .component('codeInput', CodeInputComponent)
     .service('EditorDialogManager', EditorDialogManager)
     .service('PipelineElementRecommendationService', PipelineElementRecommendationService)
     .service('PipelineValidationService', PipelineValidationService)
+    .directive('codeEditor', () => new CodeEditorDirective())
     .name;
diff --git a/ui/src/scss/main.scss b/ui/src/scss/main.scss
index 2532e19..e7b2b33 100644
--- a/ui/src/scss/main.scss
+++ b/ui/src/scss/main.scss
@@ -64,3 +64,9 @@
 @import './sp/stepper';
 
 @import './sp/colors.scss';
+
+@import '~codemirror/lib/codemirror.css';
+@import '~codemirror/theme/darcula.css';
+@import '~codemirror/theme/dracula.css';
+@import '~codemirror/addon/hint/show-hint.css';
+@import '~codemirror/addon/lint/lint.css';
diff --git a/ui/src/scss/sp/main.scss b/ui/src/scss/sp/main.scss
index e626924..538bed9 100644
--- a/ui/src/scss/sp/main.scss
+++ b/ui/src/scss/sp/main.scss
@@ -51,6 +51,10 @@ code[class*="language-"], pre[class*="language-"] {
   white-space:pre-wrap;
 }
 
+.CodeMirror-hints {
+  z-index: 1000;
+}
+
 .editor-error-notifications {
   position: absolute;
   left: -226px;