Merge "Rework tosca converter"
authorXue Gao <xg353y@intl.att.com>
Tue, 10 Mar 2020 10:18:34 +0000 (10:18 +0000)
committerGerrit Code Review <gerrit@onap.org>
Tue, 10 Mar 2020 10:18:34 +0000 (10:18 +0000)
29 files changed:
src/main/java/org/onap/clamp/clds/client/CdsServices.java [new file with mode: 0644]
src/main/java/org/onap/clamp/clds/model/cds/CdsBpWorkFlowListResponse.java [new file with mode: 0644]
src/main/java/org/onap/clamp/loop/service/CsarServiceInstaller.java
src/main/java/org/onap/clamp/policy/operational/LegacyOperationalPolicy.java
src/main/java/org/onap/clamp/policy/operational/OperationalPolicy.java
src/main/java/org/onap/clamp/policy/operational/OperationalPolicyRepresentationBuilder.java
src/main/resources/application.properties
src/main/resources/clds/camel/routes/cds-flows.xml [new file with mode: 0644]
src/main/resources/clds/json-schema/operational_policies/operational_policy.json
src/test/resources/application.properties
src/test/resources/example/sdc/service_Vloadbalancerms_csar.csar
src/test/resources/http-cache/example/api/v1/blueprint-model/workflow-spec&#63;connectionTimeToLive=5000/.file [new file with mode: 0644]
src/test/resources/http-cache/example/api/v1/blueprint-model/workflow-spec&#63;connectionTimeToLive=5000/.header [new file with mode: 0644]
src/test/resources/http-cache/example/api/v1/blueprint-model/workflows/blueprint-name/baseconfiguration/version/1.0.0&#63;connectionTimeToLive=5000/.file [new file with mode: 0644]
src/test/resources/http-cache/example/api/v1/blueprint-model/workflows/blueprint-name/baseconfiguration/version/1.0.0&#63;connectionTimeToLive=5000/.header [new file with mode: 0644]
src/test/resources/tosca/model-properties.json
src/test/resources/tosca/operational-policy-json-schema.json
src/test/resources/tosca/operational-policy-payload.yaml
src/test/resources/tosca/operational-policy-properties.json
src/test/resources/tosca/resource-details.json
ui-react/src/LoopUI.js
ui-react/src/__snapshots__/LoopUI.test.js.snap
ui-react/src/__snapshots__/OnapClamp.test.js.snap
ui-react/src/api/TemplateService.js
ui-react/src/components/dialogs/ManageDictionaries/ManageDictionaries.js [new file with mode: 0644]
ui-react/src/components/dialogs/ManageDictionaries/ManageDictionaries.test.js [new file with mode: 0644]
ui-react/src/components/dialogs/ManageDictionaries/__snapshots__/ManageDictionaries.test.js.snap [new file with mode: 0644]
ui-react/src/components/menu/MenuBar.js
ui-react/src/components/menu/__snapshots__/MenuBar.test.js.snap

diff --git a/src/main/java/org/onap/clamp/clds/client/CdsServices.java b/src/main/java/org/onap/clamp/clds/client/CdsServices.java
new file mode 100644 (file)
index 0000000..fe1937a
--- /dev/null
@@ -0,0 +1,171 @@
+/*-\r
+ * ============LICENSE_START=======================================================\r
+ * ONAP CLAMP\r
+ * ================================================================================\r
+ * Copyright (C) 2020 Huawei Technologies Co., Ltd.\r
+ * ================================================================================\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * ============LICENSE_END=========================================================\r
+ * ================================================================================\r
+ *\r
+ */\r
+\r
+package org.onap.clamp.clds.client;\r
+\r
+import com.att.eelf.configuration.EELFLogger;\r
+import com.att.eelf.configuration.EELFManager;\r
+import com.google.gson.JsonElement;\r
+import com.google.gson.JsonObject;\r
+import com.google.gson.JsonParser;\r
+\r
+import java.util.Date;\r
+import java.util.Map;\r
+\r
+import org.apache.camel.CamelContext;\r
+import org.apache.camel.Exchange;\r
+import org.apache.camel.builder.ExchangeBuilder;\r
+import org.onap.clamp.clds.model.cds.CdsBpWorkFlowListResponse;\r
+import org.onap.clamp.clds.util.JsonUtils;\r
+import org.onap.clamp.clds.util.LoggingUtils;\r
+import org.springframework.beans.factory.annotation.Autowired;\r
+import org.springframework.stereotype.Component;\r
+\r
+/**\r
+ * This class implements the communication with CDS for the service inventory.\r
+ */\r
+@Component\r
+public class CdsServices {\r
+\r
+    @Autowired\r
+    CamelContext camelContext;\r
+\r
+    protected static final EELFLogger logger = EELFManager.getInstance().getLogger(CdsServices.class);\r
+\r
+    /**\r
+     * Constructor.\r
+     */\r
+    @Autowired\r
+    public CdsServices() {\r
+    }\r
+\r
+\r
+    /**\r
+     * Query CDS to get blueprint's workflow list.\r
+     *\r
+     * @param blueprintName    CDS blueprint name\r
+     * @param blueprintVersion CDS blueprint version\r
+     * @return CdsBpWorkFlowListResponse CDS blueprint's workflow list\r
+     */\r
+    public CdsBpWorkFlowListResponse getBlueprintWorkflowList(String blueprintName, String blueprintVersion) {\r
+        LoggingUtils.setTargetContext("CDS", "getBlueprintWorkflowList");\r
+\r
+        Exchange myCamelExchange = ExchangeBuilder.anExchange(camelContext)\r
+                .withProperty("blueprintName", blueprintName).withProperty("blueprintVersion", blueprintVersion)\r
+                .build();\r
+\r
+        Exchange exchangeResponse = camelContext.createProducerTemplate()\r
+                .send("direct:get-blueprint-workflow-list", myCamelExchange);\r
+\r
+        if (Integer.valueOf(200).equals(exchangeResponse.getIn().getHeader("CamelHttpResponseCode"))) {\r
+            String cdsResponse = (String) exchangeResponse.getIn().getBody();\r
+            logger.info("getBlueprintWorkflowList, response from CDS:" + cdsResponse);\r
+            LoggingUtils.setResponseContext("0", "Get Blueprint workflow list", this.getClass().getName());\r
+            Date startTime = new Date();\r
+            LoggingUtils.setTimeContext(startTime, new Date());\r
+            return JsonUtils.GSON_JPA_MODEL.fromJson(cdsResponse, CdsBpWorkFlowListResponse.class);\r
+        }\r
+        return null;\r
+    }\r
+\r
+    /**\r
+     * Query CDS to get input properties of workflow.\r
+     *\r
+     * @param blueprintName    CDS blueprint name\r
+     * @param blueprintVersion CDS blueprint name\r
+     * @param workflow         CDS blueprint's workflow\r
+     * @return input properties in json format\r
+     */\r
+    public JsonObject getWorkflowInputProperties(String blueprintName, String blueprintVersion,\r
+                                                 String workflow) {\r
+        LoggingUtils.setTargetContext("CDS", "getWorkflowInputProperties");\r
+\r
+        Exchange myCamelExchange = ExchangeBuilder.anExchange(camelContext)\r
+                .withBody(getCdsPayloadForWorkFlow(blueprintName, blueprintVersion, workflow))\r
+                .build();\r
+\r
+        Exchange exchangeResponse = camelContext.createProducerTemplate()\r
+                .send("direct:get-blueprint-workflow-input-properties", myCamelExchange);\r
+\r
+        if (Integer.valueOf(200).equals(exchangeResponse.getIn().getHeader("CamelHttpResponseCode"))) {\r
+            String cdsResponse = (String) exchangeResponse.getIn().getBody();\r
+            logger.info("getWorkflowInputProperties, response from CDS:" + cdsResponse);\r
+            LoggingUtils.setResponseContext("0", "Get Blueprint workflow input properties", this.getClass().getName());\r
+            Date startTime = new Date();\r
+            LoggingUtils.setTimeContext(startTime, new Date());\r
+            return parseCdsResponse(cdsResponse);\r
+        }\r
+        return null;\r
+    }\r
+\r
+    private JsonObject parseCdsResponse(String response) {\r
+        JsonObject root = JsonParser.parseString(response).getAsJsonObject();\r
+        JsonObject inputs = root.getAsJsonObject("workFlowData").getAsJsonObject("inputs");\r
+        JsonObject dataTypes = root.getAsJsonObject("dataTypes");\r
+\r
+        JsonObject workFlowProperties = new JsonObject();\r
+        workFlowProperties.add("inputs", getInputProperties(inputs, dataTypes));\r
+        return workFlowProperties;\r
+    }\r
+\r
+    private JsonObject getInputProperties(JsonObject inputs, JsonObject dataTypes) {\r
+        JsonObject inputObject = new JsonObject();\r
+        for (Map.Entry<String, JsonElement> entry : inputs.entrySet()) {\r
+            String key = entry.getKey();\r
+            JsonObject inputProperty = inputs.getAsJsonObject(key);\r
+            String type = inputProperty.get("type").getAsString();\r
+            if (isComplexType(type, dataTypes)) {\r
+                inputObject.add(key, handleComplexType(type, dataTypes));\r
+            } else {\r
+                inputObject.addProperty(key, "");\r
+            }\r
+        }\r
+        return inputObject;\r
+    }\r
+\r
+    private JsonObject handleComplexType(String key, JsonObject dataTypes) {\r
+        JsonObject properties = dataTypes.get(key).getAsJsonObject().get("properties").getAsJsonObject();\r
+        return getInputProperties(properties, dataTypes);\r
+    }\r
+\r
+    private boolean isComplexType(String type, JsonObject dataTypes) {\r
+        return dataTypes.get(type) != null;\r
+    }\r
+\r
+    /**\r
+     * Creates payload to query CDS to get workflow input properties.\r
+     *\r
+     * @param blueprintName CDS blueprint name\r
+     * @param version       CDS blueprint version\r
+     * @param workflow      CDS blueprint workflow\r
+     * @return returns payload in json format\r
+     */\r
+    public String getCdsPayloadForWorkFlow(String blueprintName, String version, String workflow) {\r
+        JsonObject jsonObject = new JsonObject();\r
+        jsonObject.addProperty("blueprintName", blueprintName);\r
+        jsonObject.addProperty("version", version);\r
+        jsonObject.addProperty("returnContent", "json");\r
+        jsonObject.addProperty("workflowName", workflow);\r
+        jsonObject.addProperty("specType", "TOSCA");\r
+        return jsonObject.toString();\r
+    }\r
+}\r
diff --git a/src/main/java/org/onap/clamp/clds/model/cds/CdsBpWorkFlowListResponse.java b/src/main/java/org/onap/clamp/clds/model/cds/CdsBpWorkFlowListResponse.java
new file mode 100644 (file)
index 0000000..66025c4
--- /dev/null
@@ -0,0 +1,67 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 Huawei Technologies Co., Ltd.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ * ================================================================================
+ *
+ */
+
+package org.onap.clamp.clds.model.cds;
+
+import com.google.gson.annotations.Expose;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * This class maps the CDS response to a pojo.
+ */
+public class CdsBpWorkFlowListResponse {
+
+    @Expose
+    private String blueprintName;
+
+    @Expose
+    private String version;
+
+    @Expose
+    private List<String> workflows = new LinkedList<String>();
+
+    public String getBlueprintName() {
+        return blueprintName;
+    }
+
+    public void setBlueprintName(String blueprintName) {
+        this.blueprintName = blueprintName;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public List<String> getWorkflows() {
+        return workflows;
+    }
+
+    public void setWorkflows(List<String> workflows) {
+        this.workflows = workflows;
+    }
+}
index 277fe00..889125f 100644 (file)
@@ -4,6 +4,7 @@
  * ================================================================================
  * Copyright (C) 2020 AT&T Intellectual Property. All rights
  *                             reserved.
+ * Modifications Copyright (C) 2020 Huawei Technologies Co., Ltd.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -29,7 +30,9 @@ import com.google.gson.JsonObject;
 
 import java.util.Map.Entry;
 
+import org.onap.clamp.clds.client.CdsServices;
 import org.onap.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException;
+import org.onap.clamp.clds.model.cds.CdsBpWorkFlowListResponse;
 import org.onap.clamp.clds.sdc.controller.installer.CsarHandler;
 import org.onap.clamp.clds.util.JsonUtils;
 import org.onap.sdc.tosca.parser.api.IEntityDetails;
@@ -53,9 +56,12 @@ public class CsarServiceInstaller {
     @Autowired
     ServiceRepository serviceRepository;
 
+    @Autowired
+    CdsServices cdsServices;
+
     /**
      * Install the Service from the csar.
-     * 
+     *
      * @param csar The Csar Handler
      * @return The service object
      */
@@ -77,7 +83,7 @@ public class CsarServiceInstaller {
         return modelService;
     }
 
-    private static JsonObject createServicePropertiesByType(CsarHandler csar) {
+    private JsonObject createServicePropertiesByType(CsarHandler csar) {
         JsonObject resourcesProp = new JsonObject();
         // Iterate on all types defined in the tosca lib
         for (SdcTypes type : SdcTypes.values()) {
@@ -86,6 +92,13 @@ public class CsarServiceInstaller {
             for (NodeTemplate nodeTemplate : csar.getSdcCsarHelper().getServiceNodeTemplateBySdcType(type)) {
                 resourcesPropByType.add(nodeTemplate.getName(),
                         JsonUtils.GSON.toJsonTree(nodeTemplate.getMetaData().getAllProperties()));
+                // get cds artifact information and save in resources Prop
+                if (SdcTypes.PNF == type || SdcTypes.VF == type) {
+                    JsonObject controllerProperties = createCdsArtifactProperties(nodeTemplate);
+                    if (controllerProperties != null) {
+                        resourcesPropByType.getAsJsonObject(nodeTemplate.getName()).add("controllerProperties", controllerProperties);
+                    }
+                }
             }
             resourcesProp.add(type.getValue(), resourcesPropByType);
         }
@@ -114,7 +127,7 @@ public class CsarServiceInstaller {
 
     /**
      * Verify whether Service in Csar is deployed.
-     * 
+     *
      * @param csar The Csar Handler
      * @return The flag indicating whether Service is deployed
      * @throws SdcArtifactInstallerException The SdcArtifactInstallerException
@@ -127,4 +140,43 @@ public class CsarServiceInstaller {
 
         return alreadyInstalled;
     }
+
+    /**
+     * Retrive CDS artifacts information from node template and save in resource object.
+     *
+     * @param nodeTemplate node template
+     * @return Returns CDS artifacts information
+     */
+    private JsonObject createCdsArtifactProperties(NodeTemplate nodeTemplate) {
+        Object artifactName = nodeTemplate.getPropertyValue("sdnc_model_name");
+        Object artifactVersion = nodeTemplate.getPropertyValue("sdnc_model_version");
+        if (artifactName != null && artifactVersion != null) {
+            CdsBpWorkFlowListResponse response = queryCdsToGetWorkFlowList(artifactName.toString(), artifactVersion.toString());
+            if (response == null) {
+                return null;
+            }
+
+            JsonObject workFlowProps = new JsonObject();
+            for (String workFlow : response.getWorkflows()) {
+                JsonObject inputs = queryCdsToGetWorkFlowInputProperties(response.getBlueprintName(),
+                                                                         response.getVersion(), workFlow);
+                workFlowProps.add(workFlow, inputs);
+            }
+
+            JsonObject controllerProperties = new JsonObject();
+            controllerProperties.addProperty("sdnc_model_name", artifactName.toString());
+            controllerProperties.addProperty("sdnc_model_version", artifactVersion.toString());
+            controllerProperties.add("workflows", workFlowProps);
+            return controllerProperties;
+        }
+        return null;
+    }
+
+    private CdsBpWorkFlowListResponse queryCdsToGetWorkFlowList(String artifactName, String artifactVersion) {
+        return cdsServices.getBlueprintWorkflowList(artifactName, artifactVersion);
+    }
+
+    private JsonObject queryCdsToGetWorkFlowInputProperties(String artifactName, String artifactVersion, String workFlow) {
+        return cdsServices.getWorkflowInputProperties(artifactName, artifactVersion, workFlow);
+    }
 }
index ff7777f..033f2ce 100644 (file)
@@ -4,6 +4,7 @@
  * ================================================================================
  * Copyright (C) 2019 AT&T Intellectual Property. All rights
  *                             reserved.
+ * Modifications Copyright (C) 2020 Huawei Technologies Co., Ltd.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -46,6 +47,11 @@ import org.yaml.snakeyaml.Yaml;
  */
 public class LegacyOperationalPolicy {
 
+    private static final String ACTOR = "actor";
+    private static final String RECIPE = "recipe";
+    private static final String POLICIES = "policies";
+    private static final String PAYLOAD = "payload";
+
     private LegacyOperationalPolicy() {
 
     }
@@ -79,7 +85,7 @@ public class LegacyOperationalPolicy {
     /**
      * This method rework the payload attribute (yaml) that is normally wrapped in a
      * string when coming from the UI.
-     * 
+     *
      * @param policyJson The operational policy json config
      * @return The same object reference but modified
      */
@@ -150,7 +156,7 @@ public class LegacyOperationalPolicy {
 
     /**
      * This method transforms the configuration json to a Yaml format.
-     * 
+     *
      * @param operationalPolicyJsonElement The operational policy json config
      * @return The Yaml as string
      */
@@ -162,13 +168,13 @@ public class LegacyOperationalPolicy {
         // Policy can't support { } in the yaml
         options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
         return (new Yaml(options)).dump(createMap(fulfillPoliciesTreeField(
-                removeAllQuotes(reworkPayloadAttributes(operationalPolicyJsonElement.getAsJsonObject().deepCopy())))));
+                removeAllQuotes(reworkActorAttributes(operationalPolicyJsonElement.getAsJsonObject().deepCopy())))));
     }
 
     /**
      * This method load mandatory field in the operational policy configuration
      * JSON.
-     * 
+     *
      * @param configurationsJson The operational policy JSON
      * @param loop               The parent loop object
      */
@@ -182,4 +188,45 @@ public class LegacyOperationalPolicy {
             configurationsJson.add("operational_policy", controlLoop);
         }
     }
+
+    /**
+     * This method rework on the actor/recipe and payload attribute.
+     *
+     * @param policyJson The operational policy json config
+     * @return The same object reference but modified
+     */
+    public static JsonElement reworkActorAttributes(JsonElement policyJson) {
+        for (JsonElement policy : policyJson.getAsJsonObject().get(POLICIES).getAsJsonArray()) {
+            JsonObject actor = policy.getAsJsonObject().get(ACTOR).getAsJsonObject();
+            policy.getAsJsonObject().remove(ACTOR);
+            String actorStr = actor.getAsJsonObject().get(ACTOR).getAsString();
+            policy.getAsJsonObject().addProperty(ACTOR, actorStr);
+            policy.getAsJsonObject().addProperty(RECIPE, getRecipe(actor));
+
+            if ("CDS".equalsIgnoreCase(actorStr)) {
+                addPayloadAttributes(actor.getAsJsonObject(ACTOR).getAsJsonObject(RECIPE), policy);
+            } else {
+                addPayloadAttributes(actor, policy);
+            }
+        }
+        return policyJson;
+    }
+
+    private static void addPayloadAttributes(JsonObject jsonObject,
+                                             JsonElement policy) {
+        JsonElement payloadElem = jsonObject.getAsJsonObject().get(PAYLOAD);
+        String payloadString = payloadElem != null ? payloadElem.getAsString() : "";
+        if (!payloadString.isEmpty()) {
+            Map<String, String> testMap = new Yaml().load(payloadString);
+            String json = new GsonBuilder().create().toJson(testMap);
+            policy.getAsJsonObject().add(PAYLOAD,
+                                         new GsonBuilder().create().fromJson(json, JsonElement.class));
+        } else {
+            policy.getAsJsonObject().addProperty(PAYLOAD, "");
+        }
+    }
+
+    private static String getRecipe(JsonObject actor) {
+        return actor.getAsJsonObject().get("type").getAsString();
+    }
 }
index 9756742..9cf5163 100644 (file)
@@ -4,6 +4,7 @@
  * ================================================================================
  * Copyright (C) 2019 AT&T Intellectual Property. All rights
  *                             reserved.
+ * Modifications Copyright (C) 2020 Huawei Technologies Co., Ltd.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -216,7 +217,7 @@ public class OperationalPolicy extends Policy implements Serializable {
         metadata.addProperty("policy-id", this.name);
 
         operationalPolicyDetails.add("properties", LegacyOperationalPolicy
-                .reworkPayloadAttributes(this.getConfigurationsJson().get("operational_policy").deepCopy()));
+                .reworkActorAttributes(this.getConfigurationsJson().get("operational_policy").deepCopy()));
 
         DumperOptions options = new DumperOptions();
         options.setIndent(2);
index 1d0d990..244f4c2 100644 (file)
@@ -4,6 +4,7 @@
  * ================================================================================
  * Copyright (C) 2019 AT&T Intellectual Property. All rights
  *                             reserved.
+ * Modifications Copyright (C) 2020 Huawei Technologies Co., Ltd.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -42,7 +43,7 @@ public class OperationalPolicyRepresentationBuilder {
      * used by ui for rendering. It uses the model (VF and VFModule) defined in the
      * loop object to do so, so it's dynamic. It also uses the operational policy
      * schema template defined in the resource folder.
-     * 
+     *
      * @param modelJson The loop model json
      * @return The json representation
      * @throws JsonSyntaxException If the schema template cannot be parsed
@@ -58,6 +59,22 @@ public class OperationalPolicyRepresentationBuilder {
                 .get("operational_policy").getAsJsonObject().get("properties").getAsJsonObject().get("policies")
                 .getAsJsonObject().get("items").getAsJsonObject().get("properties").getAsJsonObject().get("target")
                 .getAsJsonObject().get("anyOf").getAsJsonArray().addAll(createAnyOfArray(modelJson));
+
+        // update CDS recipe and payload information to schema
+        JsonArray actors = jsonSchema.get("schema").getAsJsonObject().get("items").getAsJsonObject().get("properties")
+                .getAsJsonObject().get("configurationsJson").getAsJsonObject().get("properties").getAsJsonObject()
+                .get("operational_policy").getAsJsonObject().get("properties").getAsJsonObject().get("policies")
+                .getAsJsonObject().get("items").getAsJsonObject().get("properties").getAsJsonObject().get("actor")
+                .getAsJsonObject().get("anyOf").getAsJsonArray();
+
+        for (JsonElement actor : actors) {
+            if ("CDS".equalsIgnoreCase(actor.getAsJsonObject().get("title").getAsString())) {
+                actor.getAsJsonObject().get("properties").getAsJsonObject().get("type").getAsJsonObject()
+                        .get("anyOf").getAsJsonArray()
+                        .addAll(createAnyOfArrayForCdsRecipe(modelJson.getResourceDetails()));
+            }
+        }
+
         return jsonSchema;
     }
 
@@ -143,4 +160,54 @@ public class OperationalPolicyRepresentationBuilder {
         targetOneOfStructure.addAll(createVfModuleSchema(modelJson));
         return targetOneOfStructure;
     }
+
+    private static JsonArray createAnyOfArrayForCdsRecipe(JsonObject resourceDetails) {
+        JsonArray anyOfStructure = new JsonArray();
+        anyOfStructure.addAll(createAnyOfCdsRecipe(resourceDetails.getAsJsonObject("VF")));
+        anyOfStructure.addAll(createAnyOfCdsRecipe(resourceDetails.getAsJsonObject("PNF")));
+        return anyOfStructure;
+    }
+
+    private static JsonArray createAnyOfCdsRecipe(JsonObject jsonObject) {
+        JsonArray schemaArray = new JsonArray();
+        for (Entry<String, JsonElement> entry : jsonObject.entrySet()) {
+            JsonObject controllerProperties = entry.getValue().getAsJsonObject()
+                    .getAsJsonObject("controllerProperties");
+
+            if (controllerProperties != null) {
+                JsonObject workflows = controllerProperties.getAsJsonObject("workflows");
+                for (Entry<String, JsonElement> workflowsEntry : workflows.entrySet()) {
+                    JsonObject obj = new JsonObject();
+                    obj.addProperty("title", workflowsEntry.getKey());
+                    obj.add("properties", createPayloadProperty(workflowsEntry.getValue().getAsJsonObject(),
+                                                                controllerProperties));
+                    schemaArray.add(obj);
+                }
+
+            }
+        }
+        return schemaArray;
+    }
+
+    private static JsonObject createPayloadProperty(JsonObject workFlow, JsonObject controllerProperties) {
+        JsonObject type = new JsonObject();
+        type.addProperty("title", "Payload (YAML)");
+        type.addProperty("type", "string");
+        type.addProperty("default", createDefaultStringForPayload(workFlow, controllerProperties));
+        type.addProperty("format", "textarea");
+        JsonObject properties = new JsonObject();
+        properties.add("type", type);
+        return properties;
+    }
+
+    private static String createDefaultStringForPayload(JsonObject workFlow, JsonObject controllerProperties) {
+        String artifactName = controllerProperties.get("sdnc_model_name").toString();
+        String artifactVersion = controllerProperties.get("sdnc_model_version").toString();
+        String data = workFlow.getAsJsonObject("inputs").toString();
+        StringBuilder builder = new StringBuilder("'").append("artifact_name : ").append(artifactName).append("\n")
+                .append("artifact_version : ").append(artifactVersion).append("\n")
+                .append("mode : async").append("\n")
+                .append("data : ").append("'").append("\\").append("'").append(data).append("\\").append("'").append("'");
+        return builder.toString();
+    }
 }
index e856743..ed7f4ef 100644 (file)
@@ -190,3 +190,8 @@ clamp.config.cadi.cadiX509Issuers=CN=intermediateCA_1, OU=OSAAF, O=ONAP, C=US:CN
 
 ## Tosca converter
 clamp.config.tosca.converter.templates=classpath:/clds/tosca_updates/templates.properties
+
+# Configuration settings for CDS
+clamp.config.cds.url=http4://blueprints-processor-http:8080
+clamp.config.cds.userName=ccsdkapps
+clamp.config.cds.password=ccsdkapps
\ No newline at end of file
diff --git a/src/main/resources/clds/camel/routes/cds-flows.xml b/src/main/resources/clds/camel/routes/cds-flows.xml
new file mode 100644 (file)
index 0000000..5c10a0c
--- /dev/null
@@ -0,0 +1,46 @@
+<routes xmlns="http://camel.apache.org/schema/spring">
+    <route id="get-blueprint-workflow-list">
+        <from uri="direct:get-blueprint-workflow-list"/>
+        <log loggingLevel="INFO"
+             message="Getting blueprint workflow list from CDS"/>
+        <to uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('CDS', 'Getting workflow list from CDS')"/>
+        <doTry>
+            <setHeader headerName="CamelHttpMethod">
+                <constant>GET</constant>
+            </setHeader>
+            <setHeader headerName="Content-Type">
+                <constant>application/json</constant>
+            </setHeader>
+            <log loggingLevel="INFO"
+                 message="Endpoint to query workflows from CDS : {{clamp.config.cds.url}}/api/v1/blueprint-model/workflows/blueprint-name/${exchangeProperty[blueprintName]}/version/${exchangeProperty[blueprintVersion]}"></log>
+            <toD uri="{{clamp.config.cds.url}}/api/v1/blueprint-model/workflows/blueprint-name/${exchangeProperty[blueprintName]}/version/${exchangeProperty[blueprintVersion]}?bridgeEndpoint=true&amp;useSystemProperties=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authMethod=Basic&amp;authUsername={{clamp.config.cds.userName}}&amp;authPassword={{clamp.config.cds.password}}&amp;connectionTimeToLive=5000&amp;httpClient.connectTimeout=10000&amp;httpClient.socketTimeout=30000&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+            <convertBodyTo type="java.lang.String"/>
+            <doFinally>
+                <to uri="direct:reset-raise-http-exception-flag"/>
+                <to uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+            </doFinally>
+        </doTry>
+    </route>
+    <route id="get-blueprint-workflow-input-properties">
+        <from uri="direct:get-blueprint-workflow-input-properties"/>
+        <log loggingLevel="INFO"
+             message="Getting blueprint input properties for workflow"/>
+        <to uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeLog('CDS', 'Getting input properties for workflow')"/>
+        <doTry>
+            <setHeader headerName="CamelHttpMethod">
+                <constant>POST</constant>
+            </setHeader>
+            <setHeader headerName="Content-Type">
+                <constant>application/json</constant>
+            </setHeader>
+            <log loggingLevel="INFO"
+                 message="Endpoint to query input properties for workflow from CDS : {{clamp.config.cds.url}}/api/v1/blueprint-model/workflow-spec"></log>
+            <toD uri="{{clamp.config.cds.url}}/api/v1/blueprint-model/workflow-spec?bridgeEndpoint=true&amp;useSystemProperties=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authMethod=Basic&amp;authUsername={{clamp.config.cds.userName}}&amp;authPassword={{clamp.config.cds.password}}&amp;connectionTimeToLive=5000&amp;httpClient.connectTimeout=10000&amp;httpClient.socketTimeout=30000&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+            <convertBodyTo type="java.lang.String"/>
+            <doFinally>
+                <to uri="direct:reset-raise-http-exception-flag"/>
+                <to uri="bean:org.onap.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+            </doFinally>
+        </doTry>
+    </route>
+</routes>
\ No newline at end of file
index 93738c8..ef22e81 100644 (file)
@@ -87,7 +87,6 @@
                                         "basicCategoryTitle": "recipe",
                                         "required": [
                                             "id",
-                                            "recipe",
                                             "retry",
                                             "timeout",
                                             "actor",
                                                 "title": "Policy ID",
                                                 "type": "string"
                                             },
-                                            "recipe": {
-                                                "title": "Recipe",
-                                                "type": "string",
-                                                "enum": [
-                                                    "Restart",
-                                                    "Rebuild",
-                                                    "Migrate",
-                                                    "Health-Check",
-                                                    "ModifyConfig",
-                                                    "VF Module Create",
-                                                    "VF Module Delete",
-                                                    "Reroute"
-                                                ]
-                                            },
                                             "retry": {
                                                 "default": "0",
                                                 "title": "Number of Retry",
                                                 "format": "number"
                                             },
                                             "actor": {
+                                                "type": "object",
                                                 "title": "Actor",
-                                                "type": "string",
-                                                "enum": [
-                                                    "APPC",
-                                                    "SO",
-                                                    "VFC",
-                                                    "SDNC",
-                                                    "SDNR"
+                                                "anyOf": [
+                                                    {
+                                                        "title": "APPC",
+                                                        "properties": {
+                                                            "actor": {
+                                                                "title": "actor",
+                                                                "type": "string",
+                                                                "default": "APPC",
+                                                                "options": {
+                                                                    "hidden": true
+                                                                }
+                                                            },
+                                                            "type": {
+                                                                "title": "recipe",
+                                                                "type": "string",
+                                                                "default": "",
+                                                                "enum": [
+                                                                    "Restart",
+                                                                    "Rebuild",
+                                                                    "Migrate",
+                                                                    "Health-Check",
+                                                                    "ModifyConfig"
+                                                                ]
+                                                            },
+                                                            "payload": {
+                                                                "title": "Payload (YAML)",
+                                                                "type": "string",
+                                                                "format": "textarea"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "title": "SO",
+                                                        "properties": {
+                                                            "actor": {
+                                                                "title": "actor",
+                                                                "type": "string",
+                                                                "default": "SO",
+                                                                "options": {
+                                                                    "hidden": true
+                                                                }
+                                                            },
+                                                            "type": {
+                                                                "title": "recipe",
+                                                                "type": "string",
+                                                                "default": "",
+                                                                "enum": [
+                                                                    "VF Module Create",
+                                                                    "VF Module Delete"
+                                                                ]
+                                                            },
+                                                            "payload": {
+                                                                "title": "Payload (YAML)",
+                                                                "type": "string",
+                                                                "format": "textarea"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "title": "SDNC",
+                                                        "properties": {
+                                                            "actor": {
+                                                                "title": "actor",
+                                                                "type": "string",
+                                                                "default": "SDNC",
+                                                                "options": {
+                                                                    "hidden": true
+                                                                }
+                                                            },
+                                                            "type": {
+                                                                "title": "recipe",
+                                                                "type": "string",
+                                                                "default": "",
+                                                                "enum": [
+                                                                    "Reroute",
+                                                                    "BandwidthOnDemand"
+                                                                ]
+                                                            },
+                                                            "payload": {
+                                                                "title": "Payload (YAML)",
+                                                                "type": "string",
+                                                                "format": "textarea"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "title": "VFC",
+                                                        "properties": {
+                                                            "actor": {
+                                                                "title": "actor",
+                                                                "type": "string",
+                                                                "default": "VFC",
+                                                                "options": {
+                                                                    "hidden": true
+                                                                }
+                                                            },
+                                                            "type": {
+                                                                "title": "recipe",
+                                                                "type": "string",
+                                                                "required": [
+                                                                    "payload"
+                                                                ],
+                                                                "default": "",
+                                                                "enum": [
+                                                                    "ModifyConfig"
+                                                                ]
+                                                            },
+                                                            "payload": {
+                                                                "title": "Payload (YAML)",
+                                                                "type": "string",
+                                                                "format": "textarea"
+                                                            }
+                                                        }
+                                                    },
+                                                    {
+                                                        "title": "CDS",
+                                                        "properties": {
+                                                            "actor": {
+                                                                "title": "actor",
+                                                                "type": "string",
+                                                                "default": "CDS",
+                                                                "options": {
+                                                                    "hidden": true
+                                                                }
+                                                            },
+                                                            "type": {
+                                                                "title": "recipe",
+                                                                "type": "object",
+                                                                "required": [
+                                                                    "payload"
+                                                                ],
+                                                                "anyOf": [
+                                                                    {
+                                                                        "title": "user-defined",
+                                                                        "properties": {
+                                                                            "type": {
+                                                                                "title": "Payload (YAML)",
+                                                                                "type": "string",
+                                                                                "default" : "",
+                                                                                "format" : "textarea"
+                                                                            }
+                                                                        }
+                                                                    }
+                                                                ]
+                                                            }
+                                                        }
+                                                    }
                                                 ]
                                             },
-                                            "payload": {
-                                                "title": "Payload (YAML)",
-                                                "type": "string",
-                                                "format": "textarea"
-                                            },
                                             "success": {
                                                 "default": "final_success",
                                                 "title": "When Success",
                                                 "anyOf": [
                                                     {
                                                         "title": "User Defined",
-                                                        "additionalProperties":"True",
+                                                        "additionalProperties": "True",
                                                         "properties": {
                                                             "type": {
                                                                 "title": "Target type",
index e842abd..54ba090 100644 (file)
@@ -160,4 +160,9 @@ clamp.config.security.permission.type.template=permission-type-template
 clamp.config.security.permission.type.tosca=permission-type-tosca
 #This one indicates the type of instances (dev|prod|perf...), this must be set accordingly in clds-users.properties
 clamp.config.security.permission.instance=dev
-clamp.config.security.authentication.class=org.onap.aaf.cadi.principal.X509Principal
\ No newline at end of file
+clamp.config.security.authentication.class=org.onap.aaf.cadi.principal.X509Principal
+
+# Configuration settings for CDS
+clamp.config.cds.url=http4://localhost:${docker.http-cache.port.host}
+clamp.config.cds.userName=ccsdkapps
+clamp.config.cds.password=ccsdkapps
\ No newline at end of file
index 3330dd1..ff33799 100644 (file)
Binary files a/src/test/resources/example/sdc/service_Vloadbalancerms_csar.csar and b/src/test/resources/example/sdc/service_Vloadbalancerms_csar.csar differ
diff --git a/src/test/resources/http-cache/example/api/v1/blueprint-model/workflow-spec&#63;connectionTimeToLive=5000/.file b/src/test/resources/http-cache/example/api/v1/blueprint-model/workflow-spec&#63;connectionTimeToLive=5000/.file
new file mode 100644 (file)
index 0000000..13d3fea
--- /dev/null
@@ -0,0 +1,68 @@
+{
+    "blueprintName": "baseconfiguration",
+    "version": "1.0.0",
+    "workFlowData": {
+        "workFlowName": "resource-assignment",
+        "inputs": {
+            "resource-assignment-properties": {
+                "required": true,
+                "type": "dt-resource-assignment-properties"
+            }
+        },
+        "outputs": {
+            "response-property": {
+                "type": "string",
+                "value": "executed"
+            },
+            "template-properties": {
+                "type": "json",
+                "value": {
+                    "get_attribute": [
+                        "resource-assignment",
+                        "assignment-params"
+                    ]
+                }
+            }
+        }
+    },
+    "dataTypes": {
+        "dt-resource-assignment-properties": {
+            "description": "This is Dynamically generated data type for workflow activate",
+            "version": "1.0.0",
+            "metadata": null,
+            "attributes": null,
+            "properties": {
+                "request-id": {
+                    "required": true,
+                    "type": "string"
+                },
+                "service-instance-id": {
+                    "required": true,
+                    "type": "string"
+                },
+                "vnf-id": {
+                    "required": true,
+                    "type": "string"
+                },
+                "action-name": {
+                    "required": true,
+                    "type": "string"
+                },
+                "scope-type": {
+                    "required": true,
+                    "type": "string"
+                },
+                "hostname": {
+                    "required": true,
+                    "type": "string"
+                },
+                "vnf_name": {
+                    "required": true,
+                    "type": "string"
+                }
+            },
+            "constraints": null,
+            "derived_from": "tosca.datatypes.Dynamic"
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/test/resources/http-cache/example/api/v1/blueprint-model/workflow-spec&#63;connectionTimeToLive=5000/.header b/src/test/resources/http-cache/example/api/v1/blueprint-model/workflow-spec&#63;connectionTimeToLive=5000/.header
new file mode 100644 (file)
index 0000000..6a280d9
--- /dev/null
@@ -0,0 +1 @@
+{"Transfer-Encoding": "chunked", "Set-Cookie": "JSESSIONID=158qxkdtdobkd1umr3ikkgrmlx;Path=/", "Expires": "Thu, 01 Jan 1970 00:00:00 GMT", "Server": "Jetty(9.3.21.v20170918)", "Content-Type": "application/json", "X-ECOMP-RequestID": "e2ddb3c8-994f-47df-b4dc-097d4fb55c08"}
\ No newline at end of file
diff --git a/src/test/resources/http-cache/example/api/v1/blueprint-model/workflows/blueprint-name/baseconfiguration/version/1.0.0&#63;connectionTimeToLive=5000/.file b/src/test/resources/http-cache/example/api/v1/blueprint-model/workflows/blueprint-name/baseconfiguration/version/1.0.0&#63;connectionTimeToLive=5000/.file
new file mode 100644 (file)
index 0000000..58975d8
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "blueprintName": "baseconfiguration",
+    "version": "1.0.0",
+    "workflows": [
+        "resource-assignment",
+        "activate",
+        "activate-restconf",
+        "activate-cli",
+        "assign-activate",
+        "imperative-test-wf"
+    ]
+}
\ No newline at end of file
diff --git a/src/test/resources/http-cache/example/api/v1/blueprint-model/workflows/blueprint-name/baseconfiguration/version/1.0.0&#63;connectionTimeToLive=5000/.header b/src/test/resources/http-cache/example/api/v1/blueprint-model/workflows/blueprint-name/baseconfiguration/version/1.0.0&#63;connectionTimeToLive=5000/.header
new file mode 100644 (file)
index 0000000..6a280d9
--- /dev/null
@@ -0,0 +1 @@
+{"Transfer-Encoding": "chunked", "Set-Cookie": "JSESSIONID=158qxkdtdobkd1umr3ikkgrmlx;Path=/", "Expires": "Thu, 01 Jan 1970 00:00:00 GMT", "Server": "Jetty(9.3.21.v20170918)", "Content-Type": "application/json", "X-ECOMP-RequestID": "e2ddb3c8-994f-47df-b4dc-097d4fb55c08"}
\ No newline at end of file
index e41471b..c405964 100644 (file)
                                "UUID": "b4c4f3d7-929e-4b6d-a1cd-57e952ddc3e6",
                                "version": "1.0",
                                "resourceVendorRelease": "1.0",
-                               "customizationUUID": "465246dc-7748-45f4-a013-308d92922552"
+                               "customizationUUID": "465246dc-7748-45f4-a013-308d92922552",
+                               "controllerProperties": {
+                                       "sdnc_model_name": "baseconfiguration",
+                                       "sdnc_model_version": "1.0.0",
+                                       "workflows": {
+                                               "resource-assignment": {
+                                                       "inputs": {
+                                                               "resource-assignment-properties": {
+                                                                       "request-id": "",
+                                                                       "service-instance-id": "",
+                                                                       "vnf-id": "",
+                                                                       "action-name": "",
+                                                                       "scope-type": "",
+                                                                       "hostname": "",
+                                                                       "vnf_name": ""
+                                                               }
+                                                       }
+                                               },
+                                               "activate": {
+                                                       "inputs": {
+                                                               "resource-assignment-properties": {
+                                                                       "request-id": "",
+                                                                       "service-instance-id": "",
+                                                                       "vnf-id": "",
+                                                                       "action-name": "",
+                                                                       "scope-type": "",
+                                                                       "hostname": "",
+                                                                       "vnf_name": ""
+                                                               }
+                                                       }
+                                               },
+                                               "activate-restconf": {
+                                                       "inputs": {
+                                                               "resource-assignment-properties": {
+                                                                       "request-id": "",
+                                                                       "service-instance-id": "",
+                                                                       "vnf-id": "",
+                                                                       "action-name": "",
+                                                                       "scope-type": "",
+                                                                       "hostname": "",
+                                                                       "vnf_name": ""
+                                                               }
+                                                       }
+                                               },
+                                               "activate-cli": {
+                                                       "inputs": {
+                                                               "resource-assignment-properties": {
+                                                                       "request-id": "",
+                                                                       "service-instance-id": "",
+                                                                       "vnf-id": "",
+                                                                       "action-name": "",
+                                                                       "scope-type": "",
+                                                                       "hostname": "",
+                                                                       "vnf_name": ""
+                                                               }
+                                                       }
+                                               },
+                                               "assign-activate": {
+                                                       "inputs": {
+                                                               "resource-assignment-properties": {
+                                                                       "request-id": "",
+                                                                       "service-instance-id": "",
+                                                                       "vnf-id": "",
+                                                                       "action-name": "",
+                                                                       "scope-type": "",
+                                                                       "hostname": "",
+                                                                       "vnf_name": ""
+                                                               }
+                                                       }
+                                               },
+                                               "imperative-test-wf": {
+                                                       "inputs": {
+                                                               "resource-assignment-properties": {
+                                                                       "request-id": "",
+                                                                       "service-instance-id": "",
+                                                                       "vnf-id": "",
+                                                                       "action-name": "",
+                                                                       "scope-type": "",
+                                                                       "hostname": "",
+                                                                       "vnf_name": ""
+                                                               }
+                                                       }
+                                               } 
+                                       }
+                               }
                        }
                },
                "CR": {
index d6870dc..b43f6f9 100644 (file)
@@ -87,7 +87,6 @@
                                                                                "basicCategoryTitle": "recipe",
                                                                                "required": [
                                                                                        "id",
-                                                                                       "recipe",
                                                                                        "retry",
                                                                                        "timeout",
                                                                                        "actor",
                                                                                                "title": "Policy ID",
                                                                                                "type": "string"
                                                                                        },
-                                                                                       "recipe": {
-                                                                                               "title": "Recipe",
-                                                                                               "type": "string",
-                                                                                               "enum": [
-                                                                                                       "Restart",
-                                                                                                       "Rebuild",
-                                                                                                       "Migrate",
-                                                                                                       "Health-Check",
-                                                                                                       "ModifyConfig",
-                                                                                                       "VF Module Create",
-                                                                                                       "VF Module Delete",
-                                                                                                       "Reroute"
-                                                                                               ]
-                                                                                       },
                                                                                        "retry": {
                                                                                                "default": "0",
                                                                                                "title": "Number of Retry",
                                                                                                "format": "number"
                                                                                        },
                                                                                        "actor": {
+                                                                                               "type": "object",
                                                                                                "title": "Actor",
-                                                                                               "type": "string",
-                                                                                               "enum": [
-                                                                                                       "APPC",
-                                                                                                       "SO",
-                                                                                                       "VFC",
-                                                                                                       "SDNC",
-                                                                                                       "SDNR"
+                                                                                               "anyOf": [
+                                                                                                       {
+                                                                                                               "title": "APPC",
+                                                                                                               "properties": {
+                                                                                                                       "actor": {
+                                                                                                                               "title": "actor",
+                                                                                                                               "type": "string",
+                                                                                                                               "default": "APPC",
+                                                                                                                               "options": {
+                                                                                                                                       "hidden": true
+                                                                                                                               }
+                                                                                                                       },
+                                                                                                                       "type": {
+                                                                                                                               "title": "recipe",
+                                                                                                                               "type": "string",
+                                                                                                                               "default": "",
+                                                                                                                               "enum": [
+                                                                                                                                       "Restart",
+                                                                                                                                       "Rebuild",
+                                                                                                                                       "Migrate",
+                                                                                                                                       "Health-Check",
+                                                                                                                                       "ModifyConfig"
+                                                                                                                               ]
+                                                                                                                       },
+                                                                                                                       "payload": {
+                                                                                                                               "title": "Payload (YAML)",
+                                                                                                                               "type": "string",
+                                                                                                                               "format": "textarea"
+                                                                                                                       }
+                                                                                                               }
+                                                                                                       },
+                                                                                                       {
+                                                                                                               "title": "SO",
+                                                                                                               "properties": {
+                                                                                                                       "actor": {
+                                                                                                                               "title": "actor",
+                                                                                                                               "type": "string",
+                                                                                                                               "default": "SO",
+                                                                                                                               "options": {
+                                                                                                                                       "hidden": true
+                                                                                                                               }
+                                                                                                                       },
+                                                                                                                       "type": {
+                                                                                                                               "title": "recipe",
+                                                                                                                               "type": "string",
+                                                                                                                               "default": "",
+                                                                                                                               "enum": [
+                                                                                                                                       "VF Module Create",
+                                                                                                                                       "VF Module Delete"
+                                                                                                                               ]
+                                                                                                                       },
+                                                                                                                       "payload": {
+                                                                                                                               "title": "Payload (YAML)",
+                                                                                                                               "type": "string",
+                                                                                                                               "format": "textarea"
+                                                                                                                       }
+                                                                                                               }
+                                                                                                       },
+                                                                                                       {
+                                                                                                               "title": "SDNC",
+                                                                                                               "properties": {
+                                                                                                                       "actor": {
+                                                                                                                               "title": "actor",
+                                                                                                                               "type": "string",
+                                                                                                                               "default": "SDNC",
+                                                                                                                               "options": {
+                                                                                                                                       "hidden": true
+                                                                                                                               }
+                                                                                                                       },
+                                                                                                                       "type": {
+                                                                                                                               "title": "recipe",
+                                                                                                                               "type": "string",
+                                                                                                                               "default": "",
+                                                                                                                               "enum": [
+                                                                                                                                       "Reroute",
+                                                                                                                                       "BandwidthOnDemand"
+                                                                                                                               ]
+                                                                                                                       },
+                                                                                                                       "payload": {
+                                                                                                                               "title": "Payload (YAML)",
+                                                                                                                               "type": "string",
+                                                                                                                               "format": "textarea"
+                                                                                                                       }
+                                                                                                               }
+                                                                                                       },
+                                                                                                       {
+                                                                                                               "title": "VFC",
+                                                                                                               "properties": {
+                                                                                                                       "actor": {
+                                                                                                                               "title": "actor",
+                                                                                                                               "type": "string",
+                                                                                                                               "default": "VFC",
+                                                                                                                               "options": {
+                                                                                                                                       "hidden": true
+                                                                                                                               }
+                                                                                                                       },
+                                                                                                                       "type": {
+                                                                                                                               "title": "recipe",
+                                                                                                                               "type": "string",
+                                                                                                                               "required": [
+                                                                                                                                       "payload"
+                                                                                                                               ],
+                                                                                                                               "default": "",
+                                                                                                                               "enum": [
+                                                                                                                                       "ModifyConfig"
+                                                                                                                               ]
+                                                                                                                       },
+                                                                                                                       "payload": {
+                                                                                                                               "title": "Payload (YAML)",
+                                                                                                                               "type": "string",
+                                                                                                                               "format": "textarea"
+                                                                                                                       }
+                                                                                                               }
+                                                                                                       },
+                                                                                                       {
+                                                                                                               "title": "CDS",
+                                                                                                               "properties": {
+                                                                                                                       "actor": {
+                                                                                                                               "title": "actor",
+                                                                                                                               "type": "string",
+                                                                                                                               "default": "CDS",
+                                                                                                                               "options": {
+                                                                                                                                       "hidden": true
+                                                                                                                               }
+                                                                                                                       },
+                                                                                                                       "type": {
+                                                                                                                               "title": "recipe",
+                                                                                                                               "type": "object",
+                                                                                                                               "required": [
+                                                                                                                                       "payload"
+                                                                                                                               ],
+                                                                                                                               "anyOf": [
+                                                                                                                                       {
+                                                                                                                                               "title": "user-defined",
+                                                                                                                                               "properties": {
+                                                                                                                                                       "type": {
+                                                                                                                                                               "title": "Payload (YAML)",
+                                                                                                                                                               "type": "string",
+                                                                                                                                                               "format": "textarea"
+                                                                                                                                                       }
+                                                                                                                                               }
+                                                                                                                                       },
+                                                                                                                                       {
+                                                                                                                                               "title": "resource-assignment",
+                                                                                                                                               "properties": {
+                                                                                                                                                       "type": {
+                                                                                                                                                               "title": "Payload (YAML)",
+                                                                                                                                                               "type": "string",
+                                                                                                                                                               "default": "'artifact_name : \"baseconfiguration\"\nartifact_version : \"1.0.0\"\nmode : async\ndata : '\\'{\"resource-assignment-properties\":{\"request-id\":\"\",\"service-instance-id\":\"\",\"vnf-id\":\"\",\"action-name\":\"\",\"scope-type\":\"\",\"hostname\":\"\",\"vnf_name\":\"\"}}\\''",
+                                                                                                                                                               "format": "textarea"
+                                                                                                                                                       }
+                                                                                                                                               }
+                                                                                                                                       },
+                                                                                                                                       {
+                                                                                                                                               "title": "activate",
+                                                                                                                                               "properties": {
+                                                                                                                                                       "type": {
+                                                                                                                                                               "title": "Payload (YAML)",
+                                                                                                                                                               "type": "string",
+                                                                                                                                                               "default": "'artifact_name : \"baseconfiguration\"\nartifact_version : \"1.0.0\"\nmode : async\ndata : '\\'{\"resource-assignment-properties\":{\"request-id\":\"\",\"service-instance-id\":\"\",\"vnf-id\":\"\",\"action-name\":\"\",\"scope-type\":\"\",\"hostname\":\"\",\"vnf_name\":\"\"}}\\''",
+                                                                                                                                                               "format": "textarea"
+                                                                                                                                                       }
+                                                                                                                                               }
+                                                                                                                                       },
+                                                                                                                                       {
+                                                                                                                                               "title": "activate-restconf",
+                                                                                                                                               "properties": {
+                                                                                                                                                       "type": {
+                                                                                                                                                               "title": "Payload (YAML)",
+                                                                                                                                                               "type": "string",
+                                                                                                                                                               "default": "'artifact_name : \"baseconfiguration\"\nartifact_version : \"1.0.0\"\nmode : async\ndata : '\\'{\"resource-assignment-properties\":{\"request-id\":\"\",\"service-instance-id\":\"\",\"vnf-id\":\"\",\"action-name\":\"\",\"scope-type\":\"\",\"hostname\":\"\",\"vnf_name\":\"\"}}\\''",
+                                                                                                                                                               "format": "textarea"
+                                                                                                                                                       }
+                                                                                                                                               }
+                                                                                                                                       },
+                                                                                                                                       {
+                                                                                                                                               "title": "activate-cli",
+                                                                                                                                               "properties": {
+                                                                                                                                                       "type": {
+                                                                                                                                                               "title": "Payload (YAML)",
+                                                                                                                                                               "type": "string",
+                                                                                                                                                               "default": "'artifact_name : \"baseconfiguration\"\nartifact_version : \"1.0.0\"\nmode : async\ndata : '\\'{\"resource-assignment-properties\":{\"request-id\":\"\",\"service-instance-id\":\"\",\"vnf-id\":\"\",\"action-name\":\"\",\"scope-type\":\"\",\"hostname\":\"\",\"vnf_name\":\"\"}}\\''",
+                                                                                                                                                               "format": "textarea"
+                                                                                                                                                       }
+                                                                                                                                               }
+                                                                                                                                       },
+                                                                                                                                       {
+                                                                                                                                               "title": "assign-activate",
+                                                                                                                                               "properties": {
+                                                                                                                                                       "type": {
+                                                                                                                                                               "title": "Payload (YAML)",
+                                                                                                                                                               "type": "string",
+                                                                                                                                                               "default": "'artifact_name : \"baseconfiguration\"\nartifact_version : \"1.0.0\"\nmode : async\ndata : '\\'{\"resource-assignment-properties\":{\"request-id\":\"\",\"service-instance-id\":\"\",\"vnf-id\":\"\",\"action-name\":\"\",\"scope-type\":\"\",\"hostname\":\"\",\"vnf_name\":\"\"}}\\''",
+                                                                                                                                                               "format": "textarea"
+                                                                                                                                                       }
+                                                                                                                                               }
+                                                                                                                                       },
+                                                                                                                                       {
+                                                                                                                                               "title": "imperative-test-wf",
+                                                                                                                                               "properties": {
+                                                                                                                                                       "type": {
+                                                                                                                                                               "title": "Payload (YAML)",
+                                                                                                                                                               "type": "string",
+                                                                                                                                                               "default": "'artifact_name : \"baseconfiguration\"\nartifact_version : \"1.0.0\"\nmode : async\ndata : '\\'{\"resource-assignment-properties\":{\"request-id\":\"\",\"service-instance-id\":\"\",\"vnf-id\":\"\",\"action-name\":\"\",\"scope-type\":\"\",\"hostname\":\"\",\"vnf_name\":\"\"}}\\''",
+                                                                                                                                                               "format": "textarea"
+                                                                                                                                                       }
+                                                                                                                                               }
+                                                                                                                                       }
+                                                                                                                               ]
+                                                                                                                       }
+                                                                                                               }
+                                                                                                       }
                                                                                                ]
                                                                                        },
-                                                                                       "payload": {
-                                                                                               "title": "Payload (YAML)",
-                                                                                               "type": "string",
-                                                                                               "format": "textarea"
-                                                                                       },
                                                                                        "success": {
                                                                                                "default": "final_success",
                                                                                                "title": "When Success",
index 4e667e5..69c86cc 100644 (file)
@@ -14,13 +14,8 @@ topology_template:
           controlLoopName: LOOP_ASJOy_v1_0_ResourceInstanceName1_tca
         policies:
         - id: policy1
-          recipe: Restart
           retry: '0'
           timeout: '0'
-          actor: APPC
-          payload:
-            requestParameters: '{"usePreload":true,"userParams":[]}'
-            configurationParameters: '[{"ip-addr":"$.vf-module-topology.vf-module-parameters.param[10].value","oam-ip-addr":"$.vf-module-topology.vf-module-parameters.param[15].value","enabled":"$.vf-module-topology.vf-module-parameters.param[22].value"}]'
           success: final_success
           failure: policy2
           failure_timeout: final_failure_timeout
@@ -30,12 +25,14 @@ topology_template:
           target:
             type: VNF
             resourceID: vLoadBalancerMS
+          actor: APPC
+          recipe: Restart
+          payload:
+            requestParameters: '{"usePreload":true,"userParams":[]}'
+            configurationParameters: '[{"ip-addr":"$.vf-module-topology.vf-module-parameters.param[10].value","oam-ip-addr":"$.vf-module-topology.vf-module-parameters.param[15].value","enabled":"$.vf-module-topology.vf-module-parameters.param[22].value"}]'
         - id: policy2
-          recipe: VF Module Create
           retry: '0'
           timeout: '0'
-          actor: SO
-          payload: ''
           success: final_success
           failure: final_failure
           failure_timeout: final_failure_timeout
@@ -50,3 +47,6 @@ topology_template:
             modelName: Vloadbalancerms..vpkg..module-1
             modelVersion: '1'
             modelCustomizationId: 1bffdc31-a37d-4dee-b65c-dde623a76e52
+          actor: SO
+          recipe: VF Module Create
+          payload: ''
index ac1314e..a2de76a 100644 (file)
@@ -8,12 +8,14 @@
     },
     "policies": [
       {
+        "actor": {
+          "actor": "APPC",
+          "type": "Restart",
+          "payload": "requestParameters: '{\"usePreload\":true,\"userParams\":[]}'\r\nconfigurationParameters: '[{\"ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[10].value\",\"oam-ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[15].value\",\"enabled\":\"$.vf-module-topology.vf-module-parameters.param[22].value\"}]'"
+        },
         "id": "policy1",
-        "recipe": "Restart",
         "retry": "0",
         "timeout": "0",
-        "actor": "APPC",
-        "payload": "requestParameters: '{\"usePreload\":true,\"userParams\":[]}'\r\nconfigurationParameters: '[{\"ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[10].value\",\"oam-ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[15].value\",\"enabled\":\"$.vf-module-topology.vf-module-parameters.param[22].value\"}]'",
         "success": "final_success",
         "failure": "policy2",
         "failure_timeout": "final_failure_timeout",
         }
       },
     {
+        "actor": {
+         "actor": "SO",
+         "type": "VF Module Create",
+         "payload": ""
+        },
         "id": "policy2",
-        "recipe": "VF Module Create",
         "retry": "0",
         "timeout": "0",
-        "actor": "SO",
-        "payload": "",
         "success": "final_success",
         "failure": "final_failure",
         "failure_timeout": "final_failure_timeout",
index 7b53f39..a638c35 100644 (file)
                        "UUID": "b4c4f3d7-929e-4b6d-a1cd-57e952ddc3e6",
                        "version": "1.0",
                        "resourceVendorRelease": "1.0",
-                       "customizationUUID": "465246dc-7748-45f4-a013-308d92922552"
+                       "customizationUUID": "465246dc-7748-45f4-a013-308d92922552",
+                               "controllerProperties": {
+                                       "sdnc_model_name": "baseconfiguration",
+                                       "sdnc_model_version": "1.0.0",
+                                       "workflows": {
+                                               "resource-assignment": {
+                                                       "inputs": {
+                                                               "resource-assignment-properties": {
+                                                                       "request-id": "",
+                                                                       "service-instance-id": "",
+                                                                       "vnf-id": "",
+                                                                       "action-name": "",
+                                                                       "scope-type": "",
+                                                                       "hostname": "",
+                                                                       "vnf_name": ""
+                                                               }
+                                                       }
+                                               },
+                                               "activate": {
+                                                       "inputs": {
+                                                               "resource-assignment-properties": {
+                                                                       "request-id": "",
+                                                                       "service-instance-id": "",
+                                                                       "vnf-id": "",
+                                                                       "action-name": "",
+                                                                       "scope-type": "",
+                                                                       "hostname": "",
+                                                                       "vnf_name": ""
+                                                               }
+                                                       }
+                                               },
+                                               "activate-restconf": {
+                                                       "inputs": {
+                                                               "resource-assignment-properties": {
+                                                                       "request-id": "",
+                                                                       "service-instance-id": "",
+                                                                       "vnf-id": "",
+                                                                       "action-name": "",
+                                                                       "scope-type": "",
+                                                                       "hostname": "",
+                                                                       "vnf_name": ""
+                                                               }
+                                                       }
+                                               },
+                                               "activate-cli": {
+                                                       "inputs": {
+                                                               "resource-assignment-properties": {
+                                                                       "request-id": "",
+                                                                       "service-instance-id": "",
+                                                                       "vnf-id": "",
+                                                                       "action-name": "",
+                                                                       "scope-type": "",
+                                                                       "hostname": "",
+                                                                       "vnf_name": ""
+                                                               }
+                                                       }
+                                               },
+                                               "assign-activate": {
+                                                       "inputs": {
+                                                               "resource-assignment-properties": {
+                                                                       "request-id": "",
+                                                                       "service-instance-id": "",
+                                                                       "vnf-id": "",
+                                                                       "action-name": "",
+                                                                       "scope-type": "",
+                                                                       "hostname": "",
+                                                                       "vnf_name": ""
+                                                               }
+                                                       }
+                                               },
+                                               "imperative-test-wf": {
+                                                       "inputs": {
+                                                               "resource-assignment-properties": {
+                                                                       "request-id": "",
+                                                                       "service-instance-id": "",
+                                                                       "vnf-id": "",
+                                                                       "action-name": "",
+                                                                       "scope-type": "",
+                                                                       "hostname": "",
+                                                                       "vnf_name": ""
+                                                               }
+                                                       }
+                                               } 
+                                }
+               }
                }
        },
        "CR": {
index 471e872..bc3f235 100644 (file)
@@ -49,6 +49,7 @@ import LoopService from './api/LoopService';
 import UploadToscaPolicyModal from './components/dialogs/Tosca/UploadToscaPolicyModal';
 import ViewToscaPolicyModal from './components/dialogs/Tosca/ViewToscaPolicyModal';
 import ViewLoopTemplatesModal from './components/dialogs/Tosca/ViewLoopTemplatesModal';
+import ManageDictionaries from './components/dialogs/ManageDictionaries/ManageDictionaries';
 import PerformAction from './components/dialogs/PerformActions';
 import RefreshStatus from './components/dialogs/RefreshStatus';
 import DeployLoopModal from './components/dialogs/Loop/DeployLoopModal';
@@ -255,6 +256,7 @@ export default class LoopUI extends React.Component {
                                <Route path="/uploadToscaPolicyModal" render={(routeProps) => (<UploadToscaPolicyModal {...routeProps} />)} />
                                <Route path="/viewToscaPolicyModal" render={(routeProps) => (<ViewToscaPolicyModal {...routeProps} />)} />
                                <Route path="/ViewLoopTemplatesModal" render={(routeProps) => (<ViewLoopTemplatesModal {...routeProps} />)} />
+                               <Route path="/ManageDictionaries" render={(routeProps) => (<ManageDictionaries {...routeProps} />)} />
                                <Route path="/operationalPolicyModal"
                                        render={(routeProps) => (<OperationalPolicyModal {...routeProps} loopCache={this.getLoopCache()} loadLoopFunction={this.loadLoop} updateLoopFunction={this.updateLoopCache} showAlert={this.showAlert}/>)} />
                                <Route path="/policyModal/:policyInstanceType/:policyName" render={(routeProps) => (<PolicyModal {...routeProps} loopCache={this.getLoopCache()} loadLoopFunction={this.loadLoop}/>)} />
index 7d2c446..9de232d 100644 (file)
@@ -16,6 +16,10 @@ exports[`Verify LoopUI Test the render method 1`] = `
     path="/ViewLoopTemplatesModal"
     render={[Function]}
   />
+  <Route
+    path="/ManageDictionaries"
+    render={[Function]}
+  />
   <Route
     path="/operationalPolicyModal"
     render={[Function]}
index e195523..91812b7 100644 (file)
@@ -41,6 +41,10 @@ exports[`Verify OnapClamp Test the render method 1`] = `
       path="/ViewLoopTemplatesModal"
       render={[Function]}
     />
+    <Route
+      path="/ManageDictionaries"
+      render={[Function]}
+    />
     <Route
       path="/operationalPolicyModal"
       render={[Function]}
index 6a65d9a..124d29c 100644 (file)
@@ -38,20 +38,159 @@ export default class TemplateService {
                        });
        }
 
-  static getBlueprintMicroServiceTemplates() {
-    return fetch('restservices/clds/v2/templates', { method: 'GET', credentials: 'same-origin', })
-      .then(function (response) {
-        console.debug("getBlueprintMicroServiceTemplates response received: ", response.status);
-        if (response.ok) {
-          return response.json();
-        } else {
-          console.error("getBlueprintMicroServiceTemplates query failed");
-          return {};
-        }
-      })
-      .catch(function (error) {
-        console.error("getBlueprintMicroServiceTemplates error received", error);
-        return {};
-      });
-  }
-}
+       static getBlueprintMicroServiceTemplates() {
+           return fetch('restservices/clds/v2/templates', { method: 'GET', credentials: 'same-origin', })
+               .then(function (response) {
+                   console.debug("getBlueprintMicroServiceTemplates response received: ", response.status);
+                   if (response.ok) {
+                       return response.json();
+                   } else {
+                       console.error("getBlueprintMicroServiceTemplates query failed");
+                       return {};
+                   }
+               })
+               .catch(function (error) {
+                   console.error("getBlueprintMicroServiceTemplates error received", error);
+                   return {};
+               });
+           }
+       
+       static getDictionary() {
+           return fetch('restservices/clds/v2/dictionary/', { method: 'GET', credentials: 'same-origin', })
+             .then(function (response) {
+               console.debug("getDictionary response received: ", response.status);
+               if (response.ok) {
+                 return response.json();
+               } else {
+                 console.error("getDictionary query failed");
+                 return {};
+               }
+             })
+             .catch(function (error) {
+               console.error("getDictionary error received", error);
+               return {};
+             });
+         }
+
+         static getDictionaryElements(dictionaryName) {
+           return fetch('restservices/clds/v2/dictionary/' + dictionaryName, {
+             method: 'GET',
+             headers: {
+               "Content-Type": "application/json",
+             },
+             credentials: 'same-origin',
+           })
+             .then(function (response) {
+               console.debug("getDictionaryElements response received: ", response.status);
+               if (response.ok) {
+                 return response.json();
+               } else {
+                 console.error("getDictionaryElements query failed");
+                 return {};
+               }
+             })
+             .catch(function (error) {
+               console.error("getDictionaryElements error received", error);
+               return {};
+             });
+         }
+
+         static insDictionary(jsonData) {
+           console.log("dictionaryName is", jsonData.name)
+           return fetch('/restservices/clds/v2/dictionary/', {
+             method: 'PUT',
+             credentials: 'same-origin',
+             headers: {
+               "Content-Type": "application/json",
+             },
+             body: JSON.stringify(jsonData)
+           })
+             .then(function (response) {
+               console.debug("insDictionary response received: ", response.status);
+               if (response.ok) {
+                 return response.status;
+               } else {
+                 var errorMessage = response.status;
+                 console.error("insDictionary query failed", response.status);
+                 return errorMessage;
+               }
+             })
+             .catch(function (error) {
+               console.error("insDictionary error received", error);
+               return "";
+             });
+         }
+
+         static insDictionaryElements(jsonData) {
+           console.log("dictionaryName is", jsonData.name)
+           return fetch('/restservices/clds/v2/dictionary/' + jsonData.name, {
+             method: 'PUT',
+             credentials: 'same-origin',
+             headers: {
+               "Content-Type": "application/json",
+             },
+             body: JSON.stringify(jsonData)
+           })
+             .then(function (response) {
+               console.debug("insDictionary response received: ", response.status);
+               if (response.ok) {
+                 return response.status;
+               } else {
+                 var errorMessage = response.status;
+                 console.error("insDictionary query failed", response.status);
+                 return errorMessage;
+               }
+             })
+             .catch(function (error) {
+               console.error("insDictionary error received", error);
+               return "";
+             });
+         }
+
+         static deleteDictionary(dictionaryName) {
+           console.log("inside templaemenu service", dictionaryName)
+           return fetch('restservices/clds/v2/dictionary/' + dictionaryName, {
+             method: 'DELETE',
+             headers: {
+               "Content-Type": "application/json",
+             },
+             credentials: 'same-origin',
+           })
+             .then(function (response) {
+               console.debug("deleteDictionary response received: ", response.status);
+               if (response.ok) {
+                 return response.status;
+               } else {
+                 console.error("deleteDictionary query failed");
+                 return {};
+               }
+             })
+             .catch(function (error) {
+               console.error("deleteDictionary error received", error);
+               return {};
+             });
+         }
+
+         static deleteDictionaryElements(dictionaryData) {
+           return fetch('restservices/clds/v2/dictionary/' + dictionaryData.name + '/elements/' + dictionaryData.shortName , {
+             method: 'DELETE',
+             headers: {
+               "Content-Type": "application/json",
+             },
+             credentials: 'same-origin',
+           })
+             .then(function (response) {
+               console.debug("deleteDictionary response received: ", response.status);
+               if (response.ok) {
+                 return response.status;
+               } else {
+                 console.error("deleteDictionary query failed");
+                 return {};
+               }
+             })
+             .catch(function (error) {
+               console.error("deleteDictionary error received", error);
+               return {};
+             });
+         }
+    }
diff --git a/ui-react/src/components/dialogs/ManageDictionaries/ManageDictionaries.js b/ui-react/src/components/dialogs/ManageDictionaries/ManageDictionaries.js
new file mode 100644 (file)
index 0000000..1895237
--- /dev/null
@@ -0,0 +1,559 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+
+import React from 'react';
+import Button from 'react-bootstrap/Button';
+import Modal from 'react-bootstrap/Modal';
+import styled from 'styled-components';
+import TemplateMenuService from '../../../api/TemplateService';
+import MaterialTable, {MTableToolbar} from "material-table";
+import IconButton from '@material-ui/core/IconButton';
+import Tooltip from '@material-ui/core/Tooltip';
+import Grid from '@material-ui/core/Grid';
+import { forwardRef }  from 'react';
+import AddBox from '@material-ui/icons/AddBox';
+import ArrowUpward from '@material-ui/icons/ArrowUpward';
+import Check from '@material-ui/icons/Check';
+import ChevronLeft from '@material-ui/icons/ChevronLeft';
+import VerticalAlignTopIcon from '@material-ui/icons/VerticalAlignTop';
+import VerticalAlignBottomIcon from '@material-ui/icons/VerticalAlignBottom';
+import ChevronRight from '@material-ui/icons/ChevronRight';
+import Clear from '@material-ui/icons/Clear';
+import DeleteOutline from '@material-ui/icons/DeleteOutline';
+import Edit from '@material-ui/icons/Edit';
+import FilterList from '@material-ui/icons/FilterList';
+import FirstPage from '@material-ui/icons/FirstPage';
+import LastPage from '@material-ui/icons/LastPage';
+import Remove from '@material-ui/icons/Remove';
+import Search from '@material-ui/icons/Search';
+import ViewColumn from '@material-ui/icons/ViewColumn';
+
+
+const ModalStyled = styled(Modal)`
+       background-color: transparent;
+`
+const cellStyle = { border: '1px solid black' };
+const headerStyle = { backgroundColor: '#ddd', border: '2px solid black'       };
+const rowHeaderStyle = {backgroundColor:'#ddd',  fontSize: '15pt', text: 'bold', border: '1px solid black'};
+var dictList = [];
+
+function SelectSubDictType(props) {
+       const {onChange} = props;
+       const selectedValues = (e) => {
+               var options = e.target.options;
+               var SelectedDictTypes = '';
+               for (var dictType = 0, values = options.length; dictType < values; dictType++) {
+                       if (options[dictType].selected) {
+                               SelectedDictTypes = SelectedDictTypes.concat(options[dictType].value);
+                               SelectedDictTypes = SelectedDictTypes.concat('|');
+                       }
+               }
+               SelectedDictTypes = SelectedDictTypes.slice(0,-1);
+               onChange(SelectedDictTypes);
+       }
+       return(
+               <div>
+                       <select multiple={true}  onChange={selectedValues}>
+                               <option value="string">string</option>
+                               <option value="number">number</option>
+                               <option value="datetime">datetime</option>
+                               <option value="map">map</option>
+                               <option value="json">json</option>
+                       </select>
+               </div>
+       )
+}
+
+function SubDict(props) {
+       const {onChange} = props;
+       const subDicts = [];
+       subDicts.push('Default');
+       for(var item in dictList) {
+               if(dictList[item].secondLevelDictionary === 1) {
+                       subDicts.push(dictList[item].name);
+               }
+       };
+       subDicts.push('');
+       var optionItems = subDicts.map(
+               (item) => <option key={item}>{item}</option>
+         );
+       function selectedValue (e) {
+               onChange(e.target.value);
+       }
+       return(
+               <select onChange={selectedValue} >
+                       {optionItems}
+               </select>
+       )
+}
+
+export default class ManageDictionaries extends React.Component {
+       constructor(props, context) {
+               super(props, context);
+               this.handleClose = this.handleClose.bind(this);
+               this.getDictionary = this.getDictionary.bind(this);
+               this.getDictionaryElements = this.getDictionaryElements.bind(this);
+               this.clickHandler = this.clickHandler.bind(this);
+               this.addDictionary = this.addDictionary.bind(this);
+               this.deleteDictionary = this.deleteDictionary.bind(this);
+               this.fileSelectedHandler = this.fileSelectedHandler.bind(this);
+               this.state = {
+                       show: true,
+                       selectedFile: '',
+                       dictNameFlag: false,
+                       exportFilename: '',
+                       content: null,
+                       newDict: '',
+                       newDictItem: '',
+                       delDictItem: '',
+                       addDict: false,
+                       delData: '',
+                       delDict: false,
+                       validImport: false,
+                       dictionaryNames: [],
+                       dictionaryElements: [],
+      tableIcons: {
+               Add: forwardRef((props, ref) => <AddBox {...props} ref={ref} />),
+        Check: forwardRef((props, ref) => <Check {...props} ref={ref} />),
+        Clear: forwardRef((props, ref) => <Clear {...props} ref={ref} />),
+        Delete: forwardRef((props, ref) => <DeleteOutline {...props} ref={ref} />),
+        DetailPanel: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />),
+        Edit: forwardRef((props, ref) => <Edit {...props} ref={ref} />),
+        Export: forwardRef((props, ref) => <VerticalAlignBottomIcon {...props} ref={ref} />),
+        Filter: forwardRef((props, ref) => <FilterList {...props} ref={ref} />),
+        FirstPage: forwardRef((props, ref) => <FirstPage {...props} ref={ref} />),
+        LastPage: forwardRef((props, ref) => <LastPage {...props} ref={ref} />),
+        NextPage: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />),
+        PreviousPage: forwardRef((props, ref) => <ChevronLeft {...props} ref={ref} />),
+        ResetSearch: forwardRef((props, ref) => <Clear {...props} ref={ref} />),
+        Search: forwardRef((props, ref) => <Search {...props} ref={ref} />),
+        SortArrow: forwardRef((props, ref) => <ArrowUpward {...props} ref={ref} />),
+        ThirdStateCheck: forwardRef((props, ref) => <Remove {...props} ref={ref} />),
+        ViewColumn: forwardRef((props, ref) => <ViewColumn {...props} ref={ref} />)
+      },
+                       dictColumns: [
+                               {
+                                       title: "Dictionary Name", field: "name",editable: 'onAdd',
+                                       cellStyle: cellStyle,
+                                       headerStyle: headerStyle
+                               },
+                               {
+                                       title: "Sub Dictionary ?", field: "secondLevelDictionary", lookup: {0: 'No', 1: 'Yes'},
+                                       cellStyle: cellStyle,
+                                       headerStyle: headerStyle
+                               },
+                               {
+                                       title: "Dictionary Type", field: "subDictionaryType",lookup: {string: 'string', number: 'number'},
+                                       cellStyle: cellStyle,
+                                       headerStyle: headerStyle
+                               },
+                               {
+                                       title: "Updated By", field: "updatedBy", editable: 'never',
+                                       cellStyle: cellStyle,
+                                       headerStyle: headerStyle
+                               },
+                               {
+                                       title: "Last Updated Date", field: "updatedDate", editable: 'never',
+                                       cellStyle: cellStyle,
+                                       headerStyle: headerStyle
+                               }
+                       ],
+                       dictElementColumns: [
+                               {
+                                       title: "Element Short Name", field: "shortName",editable: 'onAdd',
+                                       cellStyle: cellStyle,
+                                       headerStyle: headerStyle
+                               },
+        {
+                                       title: "Element Name", field: "name",
+                                       cellStyle: cellStyle,
+                                       headerStyle: headerStyle
+                               },
+                               {
+                                       title: "Element Description", field: "description",
+                                       cellStyle: cellStyle,
+                                       headerStyle: headerStyle
+                                },
+                                {
+                                       title: "Element Type", field: "type",
+                                       editComponent: props => (
+                                               <div>
+                                                       <SelectSubDictType  value={props.value} onChange={props.onChange} />
+                                               </div>
+                                       ),
+                                       cellStyle: cellStyle,
+                                       headerStyle: headerStyle
+                                },
+                                {  
+                                   title: "Sub-Dictionary", field: "subDictionary",
+                                     editComponent: props => (
+                                                <div>
+                                                        <SubDict  value={props.value} onChange={props.onChange} />
+                                                </div>
+                                     ),
+                                   cellStyle: cellStyle,
+                                   headerStyle: headerStyle
+                                },
+                               {     
+                                       title: "Updated By", field: "updatedBy", editable: 'never',
+                                       cellStyle: cellStyle,
+                                       headerStyle: headerStyle
+                               },
+                               {
+                                       title: "Updated Date", field: "updatedDate", editable: 'never',
+                                       cellStyle: cellStyle,
+                                       headerStyle: headerStyle
+                               }
+                       ]
+               }
+       }
+
+       componentWillMount() {
+        this.getDictionary();
+    }
+
+    getDictionary() {
+        TemplateMenuService.getDictionary().then(dictionaryNames => {
+            this.setState({ dictionaryNames: dictionaryNames })
+        });
+        var dictNamesingetDict = this.state.dictionaryNames;
+    }
+
+    getDictionaryElements(dictionaryName) {
+        TemplateMenuService.getDictionaryElements(dictionaryName).then(dictionaryElements => {
+            dictList = this.state.dictionaryNames;
+            this.setState({ dictionaryElements: dictionaryElements.dictionaryElements});
+        });
+    }
+
+    clickHandler(rowData)   {
+        this.setState({
+            dictNameFlag: false,
+            addDict: false,
+    });
+    }
+
+    handleClose() {
+        this.setState({ show: false });
+        this.props.history.push('/');
+    }
+
+    addDictionary() {
+        var modifiedData = [];
+        if(this.state.newDict !== '') {
+            modifiedData = this.state.newDict;
+        } else {
+            modifiedData = {"name": this.state.dictionaryName, 'dictionaryElements': this.state.newDictItem};
+        }
+        if(this.state.newDictItem === '') {
+            TemplateMenuService.insDictionary(modifiedData).then(resp => {
+            });
+        } else {
+            TemplateMenuService.insDictionaryElements(modifiedData).then(resp => {
+            });
+        }
+    }
+
+    deleteDictionary() {
+        var modifiedData = [];
+        if(this.state.delData !== '') {
+            modifiedData = this.state.delData.name;
+        } else {
+            modifiedData = {"name": this.state.dictionaryName, "shortName": this.state.delDictItem.shortName};
+        }
+        if(this.state.delDictItem === '') {
+            TemplateMenuService.deleteDictionary(modifiedData).then(resp => {
+            });
+        } else {
+            TemplateMenuService.deleteDictionaryElements(modifiedData).then(resp => {
+            });
+        }
+    }
+
+    fileSelectedHandler = (event) => {
+        const text = this;
+        var dictionaryElements = [];
+        if (event.target.files[0].type === 'text/csv' ) {
+            if (event.target.files && event.target.files[0]) {
+                let reader = new FileReader();
+                reader.onload = function(e) {
+                    var dictElems = reader.result.split('\n');
+                    var jsonObj = [];
+                    var headers = dictElems[0].split(',');
+                    for(var i = 0; i < dictElems.length; i++) {
+                        var data = dictElems[i].split(',');
+                        var obj = {};
+                        for(var j = 0; j < data.length; j++) {
+                            obj[headers[j].trim()] = data[j].trim();
+                        }
+                        jsonObj.push(obj);
+                    }
+                    JSON.stringify(jsonObj);
+                    const dictKeys = ['Element Short Name','Element Name','Element Description','Element Type','Sub-Dictionary'];
+                    const mandatoryKeys = [ 'Element Short Name', 'Element Name', 'Element Type' ];
+                    const validTypes = ['string','number','datetime','json','map'];
+                    if (!dictElems){
+                        
+                        text.setState({validData: false});
+                    } else if (headers.length !== dictKeys.length){
+                        text.setState({validImport: false});
+                    } else {
+                        var subDictionaries = [];
+                        for(var item in dictList) {
+                            if(dictList[item].secondLevelDictionary === 1) {
+                                subDictionaries.push(dictList[item].name);
+                            }
+                        };
+                        subDictionaries = subDictionaries.toString();
+                        var row = 0;
+                        for (var dictElem of jsonObj){
+                            ++row;
+                            for (var itemKey in dictElem){
+                                var value = dictElem[itemKey].trim();
+                                if (dictKeys.indexOf(itemKey) < 0){
+                                    var errorMessage = 'unknown field name of, ' + itemKey + ', found in CSV header';
+                                    text.setState({validImport: false});
+                                    alert(errorMessage);
+                                    break;
+                                } else if (value === "" && mandatoryKeys.indexOf(itemKey) >= 0){
+                                    errorMessage = 'value for ' + itemKey + ', at row #, ' + row + ', is empty but required';
+                                    text.setState({validImport: false});
+                                    alert(errorMessage);
+                                    break;
+                                } else if (itemKey === 'Element Type' && validTypes.indexOf(value) < 0 && row > 1) {
+                                    errorMessage = 'invalid dictElemenType of ' + value + ' at row #' + row;
+                                    text.setState({validImport: false});
+                                    alert(errorMessage);
+                                    break;
+                                } else if (value !== "" && itemKey === 'Sub-Dictionary' && subDictionaries.indexOf(value) < 0 && row > 1) {
+                                    errorMessage = 'invalid subDictionary of ' + value + ' at row #' + row;
+                                    text.setState({validImport: false});
+                                    alert(errorMessage);
+                                }
+                            }
+                        }
+                    }
+                    const headerKeys = ['shortName','name','description','type','subDictionary'];
+
+                    for(i = 1; i < dictElems.length; i++) {
+                        data = dictElems[i].split(',');
+                        obj = {};
+                        for(j = 0; j < data.length; j++) {
+                            obj[headerKeys[j].trim()] = data[j].trim();
+                        }
+                        dictionaryElements.push(obj);
+                    }
+                    text.setState({newDictItem: dictionaryElements, addDict: true});
+                }
+                reader.readAsText(event.target.files[0]);
+            }
+            this.setState({selectedFile: event.target.files[0]})
+        } else {
+            text.setState({validImport: false});
+            alert('Please upload .csv extention files only.');
+        }
+
+    }
+    
+    render() {
+        return (
+            <ModalStyled size="xl" show={this.state.show} onHide={this.handleClose}>
+                <Modal.Header closeButton>
+                    <Modal.Title>Manage Dictionaries</Modal.Title>
+                </Modal.Header>
+                <Modal.Body>
+                    {!this.state.dictNameFlag? <MaterialTable
+                        title={"Dictionary List"}
+                        data={this.state.dictionaryNames}
+                        columns={this.state.dictColumns}
+                        icons={this.state.tableIcons}
+                        onRowClick={(event, rowData) => {this.getDictionaryElements(rowData.name);this.setState({dictNameFlag: true, exportFilename: rowData.name, dictionaryName: rowData.name})}}
+                        options={{
+                            headerStyle: rowHeaderStyle,
+                        }}
+                        editable={{
+                            onRowAdd: newData =>
+                            new Promise((resolve, reject) => {
+                                setTimeout(() => {
+                                    {
+                                        const dictionaryNames = this.state.dictionaryNames;
+                                        var validData =  true;
+                                        if(/[^a-zA-Z0-9-_.]/.test(newData.name)) {
+                                            validData = false;
+                                            alert('Please enter alphanumberic input. Only allowed special characters are:(period, hyphen, underscore)');
+                                        }
+                                        for (var i = 0; i < this.state.dictionaryNames.length; i++) {
+                                            if (this.state.dictionaryNames[i].name === newData.name) {
+                                                validData = false;
+                                                alert(newData.name + ' dictionary name already exists')
+                                            }
+                                        }
+                                        if(validData){
+                                            dictionaryNames.push(newData);
+                                            this.setState({ dictionaryNames }, () => resolve());
+                                            this.setState({addDict: true, newDict: newData});
+                                        }
+                                    }
+                                    resolve();
+                                }, 1000);
+                            }),
+                            onRowUpdate: (newData, oldData) =>
+                            new Promise((resolve, reject) => {
+                                setTimeout(() => {
+                                    {
+                                        const dictionaryNames = this.state.dictionaryNames;
+                                        var validData =  true;
+                                        if(/[^a-zA-Z0-9-_.]/.test(newData.name)) {
+                                            validData = false;
+                                            alert('Please enter alphanumberic input. Only allowed special characters are:(period, hyphen, underscore)');
+                                        }
+                                        if(validData){
+                                            const index = dictionaryNames.indexOf(oldData);
+                                            dictionaryNames[index] = newData;
+                                            this.setState({ dictionaryNames }, () => resolve());
+                                            this.setState({addDict: true, newDict: newData});
+                                        }
+                                    }
+                                    resolve();
+                                }, 1000);
+                            }),
+                            onRowDelete: oldData =>
+                new Promise((resolve, reject) => {
+                                setTimeout(() => {
+                                    {
+                                        let data = this.state.dictionaryNames;
+                    const index = data.indexOf(oldData);
+                    data.splice(index, 1);
+                    this.setState({ data }, () => resolve());
+                                        this.setState({delDict: true, delData: oldData})
+                    }
+                    resolve()
+                }, 1000)
+                })
+                        }}
+                        />:""
+                    }
+                    {this.state.dictNameFlag? <MaterialTable
+                        title={"Dictionary Elements List"}
+                        data={this.state.dictionaryElements}
+                        columns={this.state.dictElementColumns}
+                        icons={this.state.tableIcons}
+                        options={{
+                            exportButton: true,
+                            exportFileName: this.state.exportFilename,
+                            headerStyle:{backgroundColor:'white',  fontSize: '15pt', text: 'bold', border: '1px solid black'}
+                        }}
+                        components={{
+                            Toolbar: props => (
+                                <div>
+                                    <MTableToolbar {...props} />
+                                <div>
+                                    <Grid item container xs={12} alignItems="flex-end" direction="column" justify="flex-end">
+                                        <Tooltip title="Import" placement = "bottom">
+                                            <IconButton aria-label="import" onClick={() => this.fileUpload.click()}>
+                                                <VerticalAlignTopIcon />
+                                            </IconButton>
+                                        </Tooltip>
+                                    </Grid>
+                                </div>
+                                <input type="file" ref={(fileUpload) => {this.fileUpload = fileUpload;}} style={{ visibility: 'hidden'}} onChange={this.fileSelectedHandler} />
+                                </div>
+                            )
+                        }}
+                        editable={{
+                            onRowAdd: newData =>
+                            new Promise((resolve, reject) => {
+                                setTimeout(() => {
+                                    {
+                                        const dictionaryElements = this.state.dictionaryElements;
+                                        var validData =  true;
+                                        for (var i = 0; i < this.state.dictionaryElements.length; i++) {
+                                            if (this.state.dictionaryElements[i].shortName === newData.shortName) {
+                                                validData = false;
+                                                alert(newData.shortname + 'short name already exists')
+                                            }
+                                        }
+                                        if(/[^a-zA-Z0-9-_.]/.test(newData.shortName)) {
+                                            validData = false;
+                                            alert('Please enter alphanumberic input. Only allowed special characters are:(period, hyphen, underscore)');
+                                        }
+                                        if(!newData.type){
+                                            validData = false;
+                                            alert('Element Type cannot be null');
+                                        }
+                                        if(validData){
+                                            dictionaryElements.push(newData);
+                                            this.setState({ dictionaryElements }, () => resolve());
+                                            this.setState({addDict: true, newDictItem: [newData]});
+                                        }
+                                    }
+                                    resolve();
+                                }, 1000);
+                            }),
+                            onRowUpdate: (newData, oldData) =>
+                            new Promise((resolve, reject) => {
+                                setTimeout(() => {
+                                    {
+                                        const dictionaryElements = this.state.dictionaryElements;
+                                        var validData =  true;
+                                        if(!newData.type){
+                                            validData = false;
+                                            alert('Element Type cannot be null');
+                                        }
+                                        if(validData){
+                                            const index = dictionaryElements.indexOf(oldData);
+                                            dictionaryElements[index] = newData;
+                                            this.setState({ dictionaryElements }, () => resolve());
+                                            this.setState({addDict: true, newDictItem: [newData]});
+                                        }
+                                    }
+                                    resolve();
+                                }, 1000);
+                            }),
+                            onRowDelete: oldData =>
+                new Promise((resolve, reject) => {
+                                setTimeout(() => {
+                                    {
+                                        let data = this.state.dictionaryElements;
+                    const index = data.indexOf(oldData);
+                    data.splice(index, 1);
+                    this.setState({ data }, () => resolve());
+                                        this.setState({delDict: true, delDictItem: oldData})
+                    }
+                    resolve()
+                }, 1000)
+                })
+                        }}
+                        />:""
+                    }
+                    {this.state.dictNameFlag?<button onClick={this.clickHandler} style={{marginTop: '25px'}}>Go Back to Dictionaries List</button>:""}
+                    {this.state.addDict && this.addDictionary()}
+                    {this.state.delDict && this.deleteDictionary()}
+                </Modal.Body>
+                <Modal.Footer>
+                    <Button variant="secondary" type="null" onClick={this.handleClose}>Close</Button>
+                </Modal.Footer>
+            </ModalStyled>
+        );
+    }
+}                                      
diff --git a/ui-react/src/components/dialogs/ManageDictionaries/ManageDictionaries.test.js b/ui-react/src/components/dialogs/ManageDictionaries/ManageDictionaries.test.js
new file mode 100644 (file)
index 0000000..4363da9
--- /dev/null
@@ -0,0 +1,202 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ *                             reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+import React from 'react';
+import { shallow } from 'enzyme';
+import { mount } from 'enzyme';
+import { render } from 'enzyme';
+import ManageDictionaries from './ManageDictionaries';
+import TemplateMenuService from '../../../api/TemplateService'
+
+describe('Verify ManageDictionaries', () => {
+       beforeEach(() => {
+               fetch.resetMocks();
+       });
+
+       it('Test API Successful', () => {
+               fetch.mockImplementationOnce(() => {
+                       return Promise.resolve({
+                               ok: true,
+                               status: 200,
+                               json: () => {
+                                       return Promise.resolve({
+                                               "name": "vtest",
+                                               "secondLevelDictionary": "1",
+                                               "subDictionaryType": "string",
+                                               "updatedBy": "test",
+                                               "updatedDate": "05-07-2019 19:09:42"
+                                       });
+                               }
+                       });
+               });
+               const component = shallow(<ManageDictionaries />);
+               expect(component).toMatchSnapshot();
+       });
+
+       it('Test API Exception', () => {
+               fetch.mockImplementationOnce(() => {
+                       return Promise.resolve({
+                               ok: false,
+                               status: 500,
+                               json: () => {
+                                       return Promise.resolve({
+                                               "name": "vtest",
+            "secondLevelDictionary": "1",
+                                               "subDictionaryType": "string",
+                       "updatedBy": "test",
+            "updatedDate": "05-07-2019 19:09:42"
+                                       });
+                               }
+                       });
+               });
+               const component = shallow(<ManageDictionaries />);
+       });
+
+       it('Test API Rejection', () => {
+               const myMockFunc  = fetch.mockImplementationOnce(() => Promise.reject('error'));
+               setTimeout( () => myMockFunc().catch(e => {
+                       console.log(e);
+               }),
+               100
+               );
+               new Promise(resolve => setTimeout(resolve, 200));
+               const component = shallow(<ManageDictionaries />);
+               expect(myMockFunc.mock.calls.length).toBe(1);
+       });
+
+       it('Test Table icons', () => {
+               fetch.mockImplementationOnce(() => {
+                       return Promise.resolve({
+                               ok: true,
+                               status: 200,
+                               json: () => {
+                                       return Promise.resolve({
+                                               "name": "vtest",
+                 "secondLevelDictionary": "1",
+                                               "subDictionaryType": "string",
+                       "updatedBy": "test",
+                 "updatedDate": "05-07-2019 19:09:42"
+                                       });
+                               }
+                       });
+               });
+               const component = mount(<ManageDictionaries />);
+               expect(component.find('[className="MuiSelect-icon MuiTablePagination-selectIcon"]')).toBeTruthy();
+       });
+
+       test('Test get dictionaryNames/dictionaryElements, add/delete dictionary functions', async () => {
+               const historyMock = { push: jest.fn() };
+               TemplateMenuService.getDictionary = jest.fn().mockImplementation(() => {
+                       return Promise.resolve("test");
+               });
+               TemplateMenuService.getDictionaryElements = jest.fn().mockImplementation(() => {
+                       return Promise.resolve({dictionaryElements:"testitem"});
+               });
+               TemplateMenuService.insDictionary = jest.fn().mockImplementation(() => {
+                       return Promise.resolve(200);
+               });
+               TemplateMenuService.deleteDictionary = jest.fn().mockImplementation(() => {
+                       return Promise.resolve(200);
+               });
+               const flushPromises = () => new Promise(setImmediate);
+               const component = shallow(<ManageDictionaries history={historyMock} />)
+               component.setState({ newDict: {
+                       "name": "test",
+                       "secondLevelDictionary": "0",
+                       "subDictionaryType": "string"
+                       }
+               });
+               component.setState({ delData: {
+                       "name": "test",
+                       "secondLevelDictionary": "0",
+                       "subDictionaryType": "string"
+                       }
+               });
+               const instance = component.instance();
+               instance.getDictionaryElements("test");
+               instance.clickHandler();
+               instance.addDictionary();
+               instance.deleteDictionary();
+               await flushPromises();
+               expect(component.state('dictionaryNames')).toEqual("test");
+               expect(component.state('dictionaryElements')).toEqual("testitem");
+               expect(component.state('dictNameFlag')).toEqual(false);
+       });
+
+       test('Test adding and deleting dictionaryelements', async () => {
+               const historyMock = { push: jest.fn() };
+               TemplateMenuService.getDictionary = jest.fn().mockImplementation(() => {
+                       return Promise.resolve("test");
+               });
+               TemplateMenuService.insDictionaryElements = jest.fn().mockImplementation(() => {
+                       return Promise.resolve(200);
+               });
+               TemplateMenuService.deleteDictionaryElements = jest.fn().mockImplementation(() => {
+                       return Promise.resolve(200);
+               });
+               const flushPromises = () => new Promise(setImmediate);
+               const component = shallow(<ManageDictionaries history={historyMock}/>)
+               component.setState({ newDictItem: {
+                       "name": "test",
+                       "dictionaryElements" : {
+                               "shortName": "shorttest",
+                               }
+               }});
+               component.setState({ delDictItem: {
+                       "name": "test",
+                       "dictionaryElements" : {
+                               "shortName": "shortTest",
+                               }
+               }});
+               const instance = component.instance();
+               instance.addDictionary();
+               instance.deleteDictionary();
+               await flushPromises();
+               expect(component.state('dictionaryNames')).toEqual("test");
+       });
+
+       it('Test handleClose', () => {
+               fetch.mockImplementationOnce(() => {
+                       return Promise.resolve({
+                               ok: true,
+                               status: 200,
+                               json: () => {
+                                       return Promise.resolve({
+                                               "name": "vtest",
+                       "secondLevelDictionary": "1",
+                                               "subDictionaryType": "string",
+                       "updatedBy": "test",
+                       "updatedDate": "05-07-2019 19:09:42"
+                                       });
+                               }
+                       });
+               });
+               const historyMock = { push: jest.fn() };
+               const handleClose = jest.spyOn(ManageDictionaries.prototype,'handleClose');
+               const component = shallow(<ManageDictionaries history={historyMock} />)
+               component.find('[variant="secondary"]').prop('onClick')();
+               expect(handleClose).toHaveBeenCalledTimes(1);
+               expect(component.state('show')).toEqual(false);
+               expect(historyMock.push.mock.calls[0]).toEqual([ '/']);
+               handleClose.mockClear();
+       });
+});
diff --git a/ui-react/src/components/dialogs/ManageDictionaries/__snapshots__/ManageDictionaries.test.js.snap b/ui-react/src/components/dialogs/ManageDictionaries/__snapshots__/ManageDictionaries.test.js.snap
new file mode 100644 (file)
index 0000000..e782922
--- /dev/null
@@ -0,0 +1,195 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Verify ManageDictionaries Test API Successful 1`] = `
+<Styled(Bootstrap(Modal))
+  onHide={[Function]}
+  show={true}
+  size="xl"
+>
+  <ModalHeader
+    closeButton={true}
+    closeLabel="Close"
+  >
+    <ModalTitle>
+      Manage Dictionaries
+    </ModalTitle>
+  </ModalHeader>
+  <ModalBody>
+    <WithStyles(Component)
+      columns={
+        Array [
+          Object {
+            "cellStyle": Object {
+              "border": "1px solid black",
+            },
+            "editable": "onAdd",
+            "field": "name",
+            "headerStyle": Object {
+              "backgroundColor": "#ddd",
+              "border": "2px solid black",
+            },
+            "title": "Dictionary Name",
+          },
+          Object {
+            "cellStyle": Object {
+              "border": "1px solid black",
+            },
+            "field": "secondLevelDictionary",
+            "headerStyle": Object {
+              "backgroundColor": "#ddd",
+              "border": "2px solid black",
+            },
+            "lookup": Object {
+              "0": "No",
+              "1": "Yes",
+            },
+            "title": "Sub Dictionary ?",
+          },
+          Object {
+            "cellStyle": Object {
+              "border": "1px solid black",
+            },
+            "field": "subDictionaryType",
+            "headerStyle": Object {
+              "backgroundColor": "#ddd",
+              "border": "2px solid black",
+            },
+            "lookup": Object {
+              "number": "number",
+              "string": "string",
+            },
+            "title": "Dictionary Type",
+          },
+          Object {
+            "cellStyle": Object {
+              "border": "1px solid black",
+            },
+            "editable": "never",
+            "field": "updatedBy",
+            "headerStyle": Object {
+              "backgroundColor": "#ddd",
+              "border": "2px solid black",
+            },
+            "title": "Updated By",
+          },
+          Object {
+            "cellStyle": Object {
+              "border": "1px solid black",
+            },
+            "editable": "never",
+            "field": "updatedDate",
+            "headerStyle": Object {
+              "backgroundColor": "#ddd",
+              "border": "2px solid black",
+            },
+            "title": "Last Updated Date",
+          },
+        ]
+      }
+      data={Array []}
+      editable={
+        Object {
+          "onRowAdd": [Function],
+          "onRowDelete": [Function],
+          "onRowUpdate": [Function],
+        }
+      }
+      icons={
+        Object {
+          "Add": Object {
+            "$$typeof": Symbol(react.forward_ref),
+            "render": [Function],
+          },
+          "Check": Object {
+            "$$typeof": Symbol(react.forward_ref),
+            "render": [Function],
+          },
+          "Clear": Object {
+            "$$typeof": Symbol(react.forward_ref),
+            "render": [Function],
+          },
+          "Delete": Object {
+            "$$typeof": Symbol(react.forward_ref),
+            "render": [Function],
+          },
+          "DetailPanel": Object {
+            "$$typeof": Symbol(react.forward_ref),
+            "render": [Function],
+          },
+          "Edit": Object {
+            "$$typeof": Symbol(react.forward_ref),
+            "render": [Function],
+          },
+          "Export": Object {
+            "$$typeof": Symbol(react.forward_ref),
+            "render": [Function],
+          },
+          "Filter": Object {
+            "$$typeof": Symbol(react.forward_ref),
+            "render": [Function],
+          },
+          "FirstPage": Object {
+            "$$typeof": Symbol(react.forward_ref),
+            "render": [Function],
+          },
+          "LastPage": Object {
+            "$$typeof": Symbol(react.forward_ref),
+            "render": [Function],
+          },
+          "NextPage": Object {
+            "$$typeof": Symbol(react.forward_ref),
+            "render": [Function],
+          },
+          "PreviousPage": Object {
+            "$$typeof": Symbol(react.forward_ref),
+            "render": [Function],
+          },
+          "ResetSearch": Object {
+            "$$typeof": Symbol(react.forward_ref),
+            "render": [Function],
+          },
+          "Search": Object {
+            "$$typeof": Symbol(react.forward_ref),
+            "render": [Function],
+          },
+          "SortArrow": Object {
+            "$$typeof": Symbol(react.forward_ref),
+            "render": [Function],
+          },
+          "ThirdStateCheck": Object {
+            "$$typeof": Symbol(react.forward_ref),
+            "render": [Function],
+          },
+          "ViewColumn": Object {
+            "$$typeof": Symbol(react.forward_ref),
+            "render": [Function],
+          },
+        }
+      }
+      onRowClick={[Function]}
+      options={
+        Object {
+          "headerStyle": Object {
+            "backgroundColor": "#ddd",
+            "border": "1px solid black",
+            "fontSize": "15pt",
+            "text": "bold",
+          },
+        }
+      }
+      title="Dictionary List"
+    />
+  </ModalBody>
+  <ModalFooter>
+    <Button
+      active={false}
+      disabled={false}
+      onClick={[Function]}
+      type="null"
+      variant="secondary"
+    >
+      Close
+    </Button>
+  </ModalFooter>
+</Styled(Bootstrap(Modal))>
+`;
index 92380ab..4eafaa4 100644 (file)
@@ -93,6 +93,9 @@ export default class MenuBar extends React.Component {
                                        <StyledNavDropdown title="Policy Models">
                            <NavDropdown.Item as={StyledLink} to="/uploadToscaPolicyModal">Upload Tosca Model</NavDropdown.Item>
                                <NavDropdown.Item as={StyledLink} to="/viewToscaPolicyModal">View Tosca Models</NavDropdown.Item>
+                    </StyledNavDropdown>
+                    <StyledNavDropdown title="Dictionaries">
+                            <NavDropdown.Item as={StyledLink} to="/ManageDictionaries">Manage Dictionaries</NavDropdown.Item>
                     </StyledNavDropdown>
                                        <StyledNavDropdown title="Loop Instance">
                                                <NavDropdown.Item as={StyledLink} to="/createLoop">Create</NavDropdown.Item>
index dfc6a56..9070e87 100644 (file)
@@ -163,6 +163,61 @@ exports[`Verify MenuBar Test the render method 1`] = `
       View Tosca Models
     </DropdownItem>
   </Styled(NavDropdown)>
+  <Styled(NavDropdown)
+    title="Dictionaries"
+  >
+    <DropdownItem
+      as={
+        Object {
+          "$$typeof": Symbol(react.forward_ref),
+          "attrs": Array [],
+          "componentStyle": ComponentStyle {
+            "componentId": "sc-bdVaJa",
+            "isStatic": false,
+            "rules": Array [
+              "
+       color: ",
+              [Function],
+              ";
+       background-color: ",
+              [Function],
+              ";
+       font-weight: normal;
+       display: block;
+       width: 100%;
+       padding: .25rem 1.5rem;
+       clear: both;
+       text-align: inherit;
+       white-space: nowrap;
+       border: 0;
+       :hover {
+               text-decoration: none;
+               background-color: ",
+              [Function],
+              ";
+               color:  ",
+              [Function],
+              ";
+       }
+",
+            ],
+          },
+          "displayName": "Styled(Link)",
+          "foldedComponentIds": Array [],
+          "render": [Function],
+          "styledComponentId": "sc-bdVaJa",
+          "target": [Function],
+          "toString": [Function],
+          "warnTooManyClasses": [Function],
+          "withComponent": [Function],
+        }
+      }
+      disabled={false}
+      to="/ManageDictionaries"
+    >
+      Manage Dictionaries
+    </DropdownItem>
+  </Styled(NavDropdown)>
   <Styled(NavDropdown)
     title="Loop Instance"
   >