From d4dd779aa66be0e046ecb1938fb532312cfe7680 Mon Sep 17 00:00:00 2001
From: "andre.schmid"
Date: Mon, 20 Jul 2020 17:48:48 +0100
Subject: Upload policy feature
Implements an upload feature that can be enable/disabled through
configuration properties. An upload endpoint must be provided also by
configuration.
The upload has similar feature as the download, but it sends the file
to the provided endpoint instead, converting it to TOSCA YAML.
Creates an configuration endpoint so the front-end can read it.
Introduces a pub/sub feature in the front-end so it can asynchronous
read configuration information and send configuration ready message to
components that depends on it.
Issue-ID: POLICY-2751
Signed-off-by: andre.schmid
Change-Id: I5e8e91616a7d4dc69e6739604fcd36528cce0028
---
.../policy/gui/editors/apex/rest/ApexEditor.java | 2 +
.../gui/editors/apex/rest/ApexEditorMain.java | 5 +-
.../apex/rest/UploadPluginConfigParameters.java | 81 +++++++++
.../apex/rest/handling/ApexEditorRestResource.java | 58 ++++++-
.../rest/handling/ConfigurationRestResource.java | 83 ++++++++++
.../editors/apex/rest/handling/ModelHandler.java | 2 +-
.../apex/rest/handling/PolicyUploadHandler.java | 182 +++++++++++++++++++++
.../config/PolicyUploadPluginConfigKey.java | 40 +++++
.../converter/tosca/ApexConfigProcessor.java | 117 +++++++++++++
.../converter/tosca/PolicyToscaConverter.java | 168 +++++++++++++++++++
.../converter/tosca/ProcessedTemplate.java | 60 +++++++
.../converter/tosca/ToscaTemplateProcessor.java | 179 ++++++++++++++++++++
.../exception/PolicyToscaConverterException.java | 27 +++
.../handling/plugin/upload/UploadPluginClient.java | 69 ++++++++
.../plugin/upload/UploadPolicyRequestDto.java | 40 +++++
.../main/resources/webapp/css/upload/dialog.css | 56 +++++++
.../src/main/resources/webapp/index.html | 9 +-
.../src/main/resources/webapp/js/ApexConfig.js | 58 +++++++
.../src/main/resources/webapp/js/ApexMain.js | 4 +-
.../main/resources/webapp/js/ApexPageControl.js | 2 +
.../src/main/resources/webapp/js/ApexUpload.js | 61 +++++++
.../webapp/js/lib/pubsub/ba-tiny-pubsub.min.js | 4 +
.../src/main/resources/webapp/upload/dialog.html | 64 ++++++++
23 files changed, 1361 insertions(+), 10 deletions(-)
create mode 100644 gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/UploadPluginConfigParameters.java
create mode 100644 gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/ConfigurationRestResource.java
create mode 100644 gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/PolicyUploadHandler.java
create mode 100644 gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/config/PolicyUploadPluginConfigKey.java
create mode 100644 gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/ApexConfigProcessor.java
create mode 100644 gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/PolicyToscaConverter.java
create mode 100644 gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/ProcessedTemplate.java
create mode 100644 gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/ToscaTemplateProcessor.java
create mode 100644 gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/exception/PolicyToscaConverterException.java
create mode 100644 gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/plugin/upload/UploadPluginClient.java
create mode 100644 gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/plugin/upload/UploadPolicyRequestDto.java
create mode 100644 gui-editors/gui-editor-apex/src/main/resources/webapp/css/upload/dialog.css
create mode 100644 gui-editors/gui-editor-apex/src/main/resources/webapp/js/ApexConfig.js
create mode 100644 gui-editors/gui-editor-apex/src/main/resources/webapp/js/ApexUpload.js
create mode 100644 gui-editors/gui-editor-apex/src/main/resources/webapp/js/lib/pubsub/ba-tiny-pubsub.min.js
create mode 100644 gui-editors/gui-editor-apex/src/main/resources/webapp/upload/dialog.html
(limited to 'gui-editors/gui-editor-apex/src/main')
diff --git a/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/ApexEditor.java b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/ApexEditor.java
index 4741346..d21e305 100644
--- a/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/ApexEditor.java
+++ b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/ApexEditor.java
@@ -23,6 +23,7 @@ package org.onap.policy.gui.editors.apex.rest;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.onap.policy.common.utils.validation.Assertions;
import org.slf4j.ext.XLogger;
@@ -59,6 +60,7 @@ public class ApexEditor {
// Create a resource configuration that scans for JAX-RS resources and providers
final ResourceConfig rc = new ResourceConfig().packages(parameters.getRestPackages());
+ rc.register(MultiPartFeature.class);
// create and start a new instance of grizzly http server
// exposing the Jersey application at BASE_URI
diff --git a/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/ApexEditorMain.java b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/ApexEditorMain.java
index 481f0af..9d88a2d 100644
--- a/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/ApexEditorMain.java
+++ b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/ApexEditorMain.java
@@ -22,6 +22,7 @@
package org.onap.policy.gui.editors.apex.rest;
import java.io.PrintStream;
+import org.onap.policy.common.parameters.ParameterService;
import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;
@@ -85,7 +86,6 @@ public class ApexEditorMain {
throw new ApexEditorParameterException(REST_ENDPOINT_PREFIX + this.toString() + ") parameter error, "
+ e.getMessage() + '\n' + parser.getHelp(ApexEditorMain.class.getName()), e);
}
-
if (parameters.isHelpSet()) {
throw new ApexEditorParameterException(parser.getHelp(ApexEditorMain.class.getName()));
}
@@ -97,6 +97,8 @@ public class ApexEditorMain {
+ validationMessage + '\n' + parser.getHelp(ApexEditorMain.class.getName()));
}
+ ParameterService.register(new UploadPluginConfigParameters());
+
state = EditorState.READY;
}
@@ -210,3 +212,4 @@ public class ApexEditorMain {
}
}
}
+
diff --git a/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/UploadPluginConfigParameters.java b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/UploadPluginConfigParameters.java
new file mode 100644
index 0000000..e330af7
--- /dev/null
+++ b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/UploadPluginConfigParameters.java
@@ -0,0 +1,81 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.gui.editors.apex.rest;
+
+import java.util.Optional;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.policy.common.parameters.GroupValidationResult;
+import org.onap.policy.common.parameters.ParameterGroup;
+import org.onap.policy.common.parameters.ValidationStatus;
+import org.onap.policy.gui.editors.apex.rest.handling.config.PolicyUploadPluginConfigKey;
+
+@Getter
+public class UploadPluginConfigParameters implements ParameterGroup {
+
+ public static final String GROUP_NAME = "UploadParameters";
+ @Setter
+ private String name;
+ private boolean isEnabled;
+ private String url;
+
+ public UploadPluginConfigParameters() {
+ this.name = GROUP_NAME;
+ initProperties();
+ }
+
+ private void initProperties() {
+ final String isEnabledProperty = System.getProperty(PolicyUploadPluginConfigKey.ENABLE.getKey());
+ isEnabled = Boolean.parseBoolean(isEnabledProperty);
+ url = System.getProperty(PolicyUploadPluginConfigKey.URL.getKey());
+ }
+
+ @Override
+ public GroupValidationResult validate() {
+ final GroupValidationResult result = new GroupValidationResult(this);
+ if (isEnabled && StringUtils.isEmpty(url)) {
+ result.setResult("url", ValidationStatus.INVALID,
+ String.format("The URL for the upload endpoint must be provided as the java property '%s'",
+ PolicyUploadPluginConfigKey.URL.getKey()));
+ }
+
+ return result;
+ }
+
+ /**
+ * Gets a property value based on the key and type.
+ *
+ * @param represents the class type
+ * @param key the property key
+ * @return the property value if it exists
+ */
+ public Optional getValue(final PolicyUploadPluginConfigKey key) {
+ final Class> type = key.getType();
+ if (key == PolicyUploadPluginConfigKey.URL && type.isInstance(url)) {
+ return (Optional) Optional.of(type.cast(url));
+ }
+ if (key == PolicyUploadPluginConfigKey.ENABLE && type.isInstance(isEnabled)) {
+ return (Optional) Optional.of(type.cast(isEnabled));
+ }
+ return Optional.empty();
+ }
+
+}
diff --git a/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/ApexEditorRestResource.java b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/ApexEditorRestResource.java
index ef5c57a..33aa04d 100644
--- a/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/ApexEditorRestResource.java
+++ b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/ApexEditorRestResource.java
@@ -22,6 +22,7 @@
package org.onap.policy.gui.editors.apex.rest.handling;
import java.io.IOException;
+import java.io.InputStream;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
@@ -32,9 +33,18 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
+import org.glassfish.jersey.media.multipart.FormDataParam;
import org.onap.policy.apex.model.modelapi.ApexApiResult;
import org.onap.policy.apex.model.modelapi.ApexApiResult.Result;
+import org.onap.policy.common.parameters.ParameterService;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.common.utils.coder.YamlJsonTranslator;
import org.onap.policy.common.utils.resources.TextFileUtils;
+import org.onap.policy.gui.editors.apex.rest.UploadPluginConfigParameters;
+import org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.ApexConfigProcessor;
+import org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.PolicyToscaConverter;
+import org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.ToscaTemplateProcessor;
+import org.onap.policy.gui.editors.apex.rest.handling.plugin.upload.UploadPluginClient;
import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;
@@ -61,15 +71,16 @@ import org.slf4j.ext.XLoggerFactory;
@Path("editor/{session}")
@Produces({MediaType.APPLICATION_JSON})
@Consumes({MediaType.APPLICATION_JSON})
-
public class ApexEditorRestResource implements RestCommandHandler {
+
// Get a reference to the logger
- private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexEditorRestResource.class);
+ private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexEditorRestResource.class);
// Location of the periodi event template
- private static final String PERIODIC_EVENT_TEMPLATE = "src/main/resources/templates/PeriodicEventTemplate.json";
+ private static final String PERIODIC_EVENT_TEMPLATE = "src/main/resources/templates/PeriodicEventTemplate.json";
// Recurring string constants
+
private static final String NAME = "name";
private static final String VERSION = "version";
private static final String REST_COMMAND_NOT_RECOGNISED = "REST command not recognised";
@@ -77,12 +88,12 @@ public class ApexEditorRestResource implements RestCommandHandler {
private static final String NOT_OK = ": Not OK";
private static final String SESSION_CREATE = "Session/Create";
private static final String SESSION_CREATE_NOT_OK = "Session/Create: Not OK";
-
// The session handler for sessions on the Apex editor
- private static final RestSessionHandler SESSION_HANDLER = new RestSessionHandler();
+ private static final RestSessionHandler SESSION_HANDLER = new RestSessionHandler();
// Handlers for the various parts of an Apex model
//@formatter:off
+
private static final ModelHandler MODEL_HANDLER = new ModelHandler();
private static final KeyInfoHandler KEY_INFO_HANDLER = new KeyInfoHandler();
private static final ContextSchemaHandler CONTEXT_SCHEMA_HANDLER = new ContextSchemaHandler();
@@ -90,12 +101,26 @@ public class ApexEditorRestResource implements RestCommandHandler {
private static final EventHandler EVENT_HANDLER = new EventHandler();
private static final TaskHandler TASK_HANDLER = new TaskHandler();
private static final PolicyHandler POLICY_HANDLER = new PolicyHandler();
- //@formatter:on
+ private final PolicyUploadHandler policyUploadHandler;
+ //@formatter:on
// The ID of this session. This gets injected from the URL.
+
@PathParam("session")
private int sessionId = -1;
+ /**
+ * Creates the ApexEditorRestResource instance.
+ */
+ public ApexEditorRestResource() {
+ final StandardCoder standardCoder = new StandardCoder();
+ policyUploadHandler = new PolicyUploadHandler(
+ new UploadPluginClient(), new PolicyToscaConverter(standardCoder, new YamlJsonTranslator()),
+ new ToscaTemplateProcessor(standardCoder), new ApexConfigProcessor(standardCoder),
+ ParameterService.get(UploadPluginConfigParameters.GROUP_NAME)
+ );
+ }
+
/**
* Creates a new session. Always call this method with sessionID -1, whereby a new sessionID will be allocated. If
* successful the new sessionID will be available in the first message in the result.
@@ -225,6 +250,27 @@ public class ApexEditorRestResource implements RestCommandHandler {
}
}
+ /**
+ * Uploads a Policy Model to a configured endpoint converting it to tosca based on the given apex config and tosca
+ * templates.
+ *
+ * @param toscaTemplateFileStream the tosca template file input stream
+ * @param apexConfigFileStream the apex config file input stream
+ * @return an ApexAPIResult that contains the operation status and success/error messages
+ */
+ @POST
+ @Path("Model/Upload")
+ @Consumes({MediaType.MULTIPART_FORM_DATA})
+ public ApexApiResult uploadModel(@FormDataParam("tosca-template-file") InputStream toscaTemplateFileStream,
+ @FormDataParam("apex-config-file") InputStream apexConfigFileStream) {
+ final ApexApiResult result = new ApexApiResult();
+ final RestSession session = SESSION_HANDLER.getSession(sessionId, result);
+ if (session == null) {
+ return result;
+ }
+ return policyUploadHandler.doUpload(session.getApexModel(), toscaTemplateFileStream, apexConfigFileStream);
+ }
+
/**
* Delete the model for this session.
*
diff --git a/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/ConfigurationRestResource.java b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/ConfigurationRestResource.java
new file mode 100644
index 0000000..76af06e
--- /dev/null
+++ b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/ConfigurationRestResource.java
@@ -0,0 +1,83 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.gui.editors.apex.rest.handling;
+
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import org.onap.policy.apex.model.modelapi.ApexApiResult;
+import org.onap.policy.apex.model.modelapi.ApexApiResult.Result;
+import org.onap.policy.common.parameters.ParameterService;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.gui.editors.apex.rest.UploadPluginConfigParameters;
+import org.onap.policy.gui.editors.apex.rest.handling.config.PolicyUploadPluginConfigKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Handles endpoints for the configuration properties.
+ */
+@Path("editor/config")
+@Produces({MediaType.APPLICATION_JSON})
+@Consumes({MediaType.APPLICATION_JSON})
+public class ConfigurationRestResource {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationRestResource.class);
+ private static final StandardCoder STANDARD_CODER = new StandardCoder();
+
+ private final UploadPluginConfigParameters uploadConfigParam;
+
+ public ConfigurationRestResource() {
+ uploadConfigParam = ParameterService.get(UploadPluginConfigParameters.GROUP_NAME);
+ }
+
+ /**
+ * Gets the configured properties.
+ *
+ * @return the properties as JSON in the ApexApiResult messages list.
+ */
+ @GET
+ @Path("")
+ public ApexApiResult show() {
+ final ApexApiResult result = new ApexApiResult(Result.SUCCESS);
+
+ final Map configMap = Stream.of(PolicyUploadPluginConfigKey.values())
+ .filter(key -> uploadConfigParam.getValue(key).isPresent())
+ .collect(Collectors.toMap(PolicyUploadPluginConfigKey::getKey,
+ configKey -> uploadConfigParam.getValue(configKey).get()));
+ try {
+ final String encode = STANDARD_CODER.encode(configMap);
+ result.addMessage(encode);
+ } catch (final CoderException e) {
+ result.setResult(Result.FAILED);
+ final String errorMsg = "Could not parse configuration parameters as JSON";
+ result.addMessage(errorMsg);
+ LOGGER.error(errorMsg, e);
+ }
+ return result;
+ }
+
+}
diff --git a/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/ModelHandler.java b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/ModelHandler.java
index 667d771..3bedad2 100644
--- a/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/ModelHandler.java
+++ b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/ModelHandler.java
@@ -389,7 +389,7 @@ public class ModelHandler implements RestCommandHandler {
*
* @param jsonObject the object to query
* @param fieldTag the tag of the field to condition
- * @param fieldValue the value of the field to condition
+ * @param value the default value of the field to condition
* @return field read from the json
*/
private String readFieldFromJsonObject(final JsonObject jsonObject, final String fieldTag, final String value) {
diff --git a/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/PolicyUploadHandler.java b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/PolicyUploadHandler.java
new file mode 100644
index 0000000..af8d9dd
--- /dev/null
+++ b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/PolicyUploadHandler.java
@@ -0,0 +1,182 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.gui.editors.apex.rest.handling;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.Optional;
+import javax.ws.rs.core.Response;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.modelapi.ApexApiResult;
+import org.onap.policy.apex.model.modelapi.ApexApiResult.Result;
+import org.onap.policy.apex.model.modelapi.ApexModel;
+import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel;
+import org.onap.policy.gui.editors.apex.rest.UploadPluginConfigParameters;
+import org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.ApexConfigProcessor;
+import org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.PolicyToscaConverter;
+import org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.ProcessedTemplate;
+import org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.ToscaTemplateProcessor;
+import org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.exception.PolicyToscaConverterException;
+import org.onap.policy.gui.editors.apex.rest.handling.plugin.upload.UploadPluginClient;
+import org.onap.policy.gui.editors.apex.rest.handling.plugin.upload.UploadPolicyRequestDto;
+import org.slf4j.ext.XLogger;
+import org.slf4j.ext.XLoggerFactory;
+
+/**
+ * Handles the Policy Model upload.
+ */
+public class PolicyUploadHandler {
+
+ private static final XLogger LOGGER = XLoggerFactory.getXLogger(PolicyUploadHandler.class);
+ private final PolicyToscaConverter policyToscaConverter;
+ private final ToscaTemplateProcessor toscaTemplateProcessor;
+ private final ApexConfigProcessor apexConfigProcessor;
+ private final UploadPluginClient uploadPluginClient;
+ private final UploadPluginConfigParameters uploadPluginConfigParameters;
+
+ /**
+ * Creates the upload handler with its necessary dependencies.
+ *
+ * @param uploadPluginClient the UploadPluginClient instance
+ * @param policyToscaConverter the PolicyToscaConverter instance
+ * @param toscaTemplateProcessor the ToscaTemplateProcessor instance
+ * @param apexConfigProcessor the ApexConfigProcessor instance
+ * @param uploadPluginConfigParameters the Config instance
+ */
+ public PolicyUploadHandler(final UploadPluginClient uploadPluginClient,
+ final PolicyToscaConverter policyToscaConverter,
+ final ToscaTemplateProcessor toscaTemplateProcessor,
+ final ApexConfigProcessor apexConfigProcessor,
+ final UploadPluginConfigParameters uploadPluginConfigParameters) {
+ this.uploadPluginClient = uploadPluginClient;
+ this.policyToscaConverter = policyToscaConverter;
+ this.toscaTemplateProcessor = toscaTemplateProcessor;
+ this.apexConfigProcessor = apexConfigProcessor;
+ this.uploadPluginConfigParameters = uploadPluginConfigParameters;
+ }
+
+ /**
+ * Handles the policy model upload converting it to TOSCA with given template files.
+ *
+ * @param apexModel the apex model that contains the policy model
+ * @param toscaTemplateInputStream the tosca template input stream
+ * @param apexConfigInputStream the apex config input stream
+ * @return the result of the upload process
+ */
+ public ApexApiResult doUpload(final ApexModel apexModel, final InputStream toscaTemplateInputStream,
+ final InputStream apexConfigInputStream) {
+ final ProcessedTemplate processedToscaTemplate;
+ try {
+ processedToscaTemplate = toscaTemplateProcessor.process(toscaTemplateInputStream);
+ } catch (final IOException e) {
+ final ApexApiResult result = new ApexApiResult(Result.FAILED);
+ result.addThrowable(e);
+ final String errorMsg = "Could not process the tosca template file";
+ result.addMessage(errorMsg);
+ LOGGER.error(errorMsg, e);
+ return result;
+ }
+ if (!processedToscaTemplate.isValid()) {
+ return buildResponse(processedToscaTemplate);
+ }
+
+ final ProcessedTemplate processedApexConfig;
+ try {
+ processedApexConfig = apexConfigProcessor.process(apexConfigInputStream);
+ } catch (final IOException e) {
+ final ApexApiResult result = new ApexApiResult(Result.FAILED);
+ result.addThrowable(e);
+ final String errorMsg = "Could not process the apex config file";
+ result.addMessage(errorMsg);
+ LOGGER.error(errorMsg, e);
+ return result;
+ }
+ if (!processedApexConfig.isValid()) {
+ return buildResponse(processedApexConfig);
+ }
+ return doUpload(apexModel, processedToscaTemplate.getContent(), processedApexConfig.getContent());
+ }
+
+ private ApexApiResult doUpload(final ApexModel apexModel, final String toscaTemplate, final String apexConfig) {
+ LOGGER.entry();
+ if (!isUploadPluginEnabled()) {
+ final ApexApiResult apexApiResult = new ApexApiResult(Result.FAILED);
+ apexApiResult.addMessage("Upload feature is disabled");
+ return apexApiResult;
+ }
+ final AxPolicyModel policyModel = apexModel.getPolicyModel();
+ final ApexApiResult result = apexModel.listModel();
+ final UploadPolicyRequestDto uploadPolicyRequestDto = new UploadPolicyRequestDto();
+ final AxArtifactKey policyKey = policyModel.getKeyInformation().getKey();
+ final java.util.UUID uuid = policyModel.getKeyInformation().get(policyKey).getUuid();
+ uploadPolicyRequestDto
+ .setFilename(String.format("%s.%s.%s", uuid, policyKey.getName(), policyKey.getVersion()));
+ final String apexPolicy = convert(result.getMessage(), toscaTemplate, apexConfig).orElse(null);
+ if (apexPolicy == null) {
+ final ApexApiResult apexApiResult = new ApexApiResult(Result.FAILED);
+ apexApiResult.addMessage(
+ String.format("An error has occurred while uploading the converting the Policy '%s' to YAML.",
+ policyModel.getId()));
+ LOGGER.exit("Model/Upload: NOT OK");
+ return apexApiResult;
+ }
+ uploadPolicyRequestDto.setFileData(
+ Base64.getEncoder().encodeToString(apexPolicy.getBytes(StandardCharsets.UTF_8)));
+ final Response response = uploadPluginClient.upload(uploadPolicyRequestDto);
+ if (response.getStatus() == 201) {
+ final ApexApiResult apexApiResult = new ApexApiResult(Result.SUCCESS);
+ apexApiResult.addMessage(String.format("Policy '%s' uploaded successfully", policyModel.getId()));
+ LOGGER.exit("Model/Upload: OK");
+ return apexApiResult;
+ } else {
+ final ApexApiResult apexApiResult = new ApexApiResult(Result.FAILED);
+ apexApiResult.addMessage(
+ String.format("An error has occurred while uploading the Policy '%s'. Status was %s",
+ policyModel.getId(), response.getStatus()));
+ LOGGER.exit("Model/Upload: NOT OK");
+ return apexApiResult;
+ }
+ }
+
+ private ApexApiResult buildResponse(final ProcessedTemplate processedTemplate) {
+ final ApexApiResult result = new ApexApiResult(Result.SUCCESS);
+ if (!processedTemplate.isValid()) {
+ result.setResult(Result.OTHER_ERROR);
+ processedTemplate.getErrorSet().forEach(result::addMessage);
+ }
+ return result;
+ }
+
+ private boolean isUploadPluginEnabled() {
+ return uploadPluginConfigParameters.isEnabled();
+ }
+
+ private Optional convert(final String apexPolicy, final String toscaTemplate, final String apexConfig) {
+ try {
+ return policyToscaConverter.convert(apexPolicy, apexConfig, toscaTemplate);
+ } catch (final PolicyToscaConverterException e) {
+ LOGGER.error("Could not convert policy to TOSCA", e);
+ }
+
+ return Optional.empty();
+ }
+}
diff --git a/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/config/PolicyUploadPluginConfigKey.java b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/config/PolicyUploadPluginConfigKey.java
new file mode 100644
index 0000000..02e23ff
--- /dev/null
+++ b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/config/PolicyUploadPluginConfigKey.java
@@ -0,0 +1,40 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.gui.editors.apex.rest.handling.config;
+
+import lombok.Getter;
+
+/**
+ * Represents properties related to the upload plugin.
+ */
+@Getter
+public enum PolicyUploadPluginConfigKey {
+ URL("plugin.policy.upload.url", String.class),
+ ENABLE("plugin.policy.upload.enable", Boolean.class);
+
+ private final String key;
+ private final Class> type;
+
+ PolicyUploadPluginConfigKey(final String key, final Class> type) {
+ this.key = key;
+ this.type = type;
+ }
+
+}
diff --git a/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/ApexConfigProcessor.java b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/ApexConfigProcessor.java
new file mode 100644
index 0000000..e05b833
--- /dev/null
+++ b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/ApexConfigProcessor.java
@@ -0,0 +1,117 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.gui.editors.apex.rest.handling.converter.tosca;
+
+import static org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.ApexConfigProcessor.ErrorMessage.INVALID_APEX_CONFIG;
+import static org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.ApexConfigProcessor.ErrorMessage.INVALID_ENTRY;
+import static org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.ApexConfigProcessor.ErrorMessage.MISSING_ENTRY;
+import static org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.PolicyToscaConverter.ToscaKey.ENGINE_SERVICE_PARAMETERS;
+
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.HashSet;
+import java.util.Set;
+import lombok.AllArgsConstructor;
+import org.apache.commons.io.IOUtils;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Process the Apex Config JSON template file.
+ */
+public class ApexConfigProcessor {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ApexConfigProcessor.class);
+
+ private final StandardCoder standardCoder;
+
+ public ApexConfigProcessor(final StandardCoder standardCoder) {
+ this.standardCoder = standardCoder;
+ }
+
+ /**
+ * Process the Apex Config JSON template file.
+ *
+ * @param apexConfigInputStream the input stream for the Apex Config JSON template
+ * @return the result of the processing with the read JSON and its errors.
+ */
+ public ProcessedTemplate process(final InputStream apexConfigInputStream) throws IOException {
+ final ProcessedTemplate processedTemplate = new ProcessedTemplate();
+ final String templateAsString;
+ try (final InputStream inputStream = apexConfigInputStream) {
+ templateAsString = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
+ }
+ final Set errorSet = validate(templateAsString);
+ processedTemplate.setContent(templateAsString);
+ processedTemplate.addToErrors(errorSet);
+
+ return processedTemplate;
+ }
+
+ private Set validate(final String apexConfig) {
+ final Set errorSet = new HashSet<>();
+ final JsonObject apexConfigJson;
+ try {
+ apexConfigJson = standardCoder.decode(apexConfig, JsonObject.class);
+ } catch (final CoderException e) {
+ LOGGER.debug(INVALID_APEX_CONFIG.getMessage(), e);
+ errorSet.add(INVALID_APEX_CONFIG.getMessage());
+ return errorSet;
+ }
+
+ final JsonObject topologyTemplate;
+ try {
+ topologyTemplate = apexConfigJson.getAsJsonObject(ENGINE_SERVICE_PARAMETERS.getKey());
+ } catch (final Exception e) {
+ final String errorMsg = INVALID_ENTRY.getMessage(ENGINE_SERVICE_PARAMETERS.getKey());
+ LOGGER.debug(errorMsg, e);
+ errorSet.add(errorMsg);
+ return errorSet;
+ }
+
+ if (topologyTemplate == null) {
+ errorSet.add(MISSING_ENTRY.getMessage(ENGINE_SERVICE_PARAMETERS.getKey()));
+ return errorSet;
+ }
+
+ return errorSet;
+ }
+
+ /**
+ * Stores the possible error messages for the Apex Config template validation process.
+ */
+ @AllArgsConstructor
+ public enum ErrorMessage {
+ MISSING_ENTRY("Missing '%s' entry"),
+ INVALID_ENTRY("Invalid entry '%s' provided"),
+ INVALID_APEX_CONFIG("Invalid apex config provided");
+
+ private final String messageFormat;
+
+ public String getMessage(final String... params) {
+ return String.format(this.messageFormat, params);
+ }
+ }
+
+}
diff --git a/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/PolicyToscaConverter.java b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/PolicyToscaConverter.java
new file mode 100644
index 0000000..0bacb24
--- /dev/null
+++ b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/PolicyToscaConverter.java
@@ -0,0 +1,168 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.gui.editors.apex.rest.handling.converter.tosca;
+
+import static org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.PolicyToscaConverter.ToscaKey.ENGINE_SERVICE_PARAMETERS;
+import static org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.PolicyToscaConverter.ToscaKey.POLICIES;
+import static org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.PolicyToscaConverter.ToscaKey.POLICY_TYPE_IMPL;
+import static org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.PolicyToscaConverter.ToscaKey.PROPERTIES;
+import static org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.PolicyToscaConverter.ToscaKey.TOPOLOGY_TEMPLATE;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import java.util.Map.Entry;
+import java.util.Optional;
+import lombok.Getter;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.common.utils.coder.YamlJsonTranslator;
+import org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.exception.PolicyToscaConverterException;
+
+/**
+ * Handles the conversion from policy JSON to policy YAML.
+ */
+public class PolicyToscaConverter {
+
+ private final StandardCoder standardCoder;
+ private final YamlJsonTranslator yamlJsonTranslator;
+
+ /**
+ * Creates a policy tosca converter.
+ *
+ * @param standardCoder the encoder that will handle JSON conversions
+ * @param yamlJsonTranslator the translator that will handle YAML conversions
+ */
+ public PolicyToscaConverter(final StandardCoder standardCoder, final YamlJsonTranslator yamlJsonTranslator) {
+ this.standardCoder = standardCoder;
+ this.yamlJsonTranslator = yamlJsonTranslator;
+ }
+
+ /**
+ * Converts the policy model to TOSCA, by merging the 3 given JSON models.
+ *
+ * @param policyModelJsonString the policy model JSON
+ * @param apexConfigJsonString the apex config JSON
+ * @param toscaTemplateJsonString the base TOSCA template in JSON format
+ * @return the merged policy model in YAML format
+ * @throws PolicyToscaConverterException when a JSON string could not be parsed to JsonObject or the resulting JSON
+ * could not be parsed to YAML.
+ */
+ public Optional convert(final String policyModelJsonString, final String apexConfigJsonString,
+ final String toscaTemplateJsonString) throws PolicyToscaConverterException {
+ final JsonObject apexConfigJson = decodeToJson(apexConfigJsonString);
+ final JsonObject policyModelJson = decodeToJson(policyModelJsonString);
+ final JsonObject toscaTemplateJson = decodeToJson(toscaTemplateJsonString);
+
+ final JsonObject toscaPolicyProperties = readTopologyTemplateAsJsonObject(toscaTemplateJson);
+ final JsonObject toscaPolicy = readToscaPolicyAsJsonObject(toscaPolicyProperties);
+ final JsonObject toscaProperties = readPolicyPropertiesAsJsonObject(toscaPolicy);
+
+ for (final Entry entry : apexConfigJson.entrySet()) {
+ if (ENGINE_SERVICE_PARAMETERS.getKey().equals(entry.getKey())) {
+ final JsonObject engineServiceParameters = readEngineServiceParametersAsJsonObject(entry.getValue());
+ engineServiceParameters.add(POLICY_TYPE_IMPL.getKey(), policyModelJson);
+ }
+ toscaProperties.add(entry.getKey(), entry.getValue());
+ }
+ return Optional.ofNullable(convertToYaml(toscaTemplateJson));
+ }
+
+ private JsonObject readTopologyTemplateAsJsonObject(final JsonObject toscaTemplateJson)
+ throws PolicyToscaConverterException {
+
+ try {
+ return toscaTemplateJson.get(TOPOLOGY_TEMPLATE.getKey()).getAsJsonObject();
+ } catch (final Exception e) {
+ throw new PolicyToscaConverterException(
+ String.format("Could not read the '%s' entry in the Tosca Template", TOPOLOGY_TEMPLATE.getKey()), e);
+ }
+ }
+
+ private JsonObject readEngineServiceParametersAsJsonObject(final JsonElement engineServiceParametersEntry)
+ throws PolicyToscaConverterException {
+
+ try {
+ return engineServiceParametersEntry.getAsJsonObject();
+ } catch (final Exception e) {
+ throw new PolicyToscaConverterException(
+ String.format("Could not read the '%s' in the Apex Config", ENGINE_SERVICE_PARAMETERS.getKey()), e);
+ }
+ }
+
+ private JsonObject readToscaPolicyAsJsonObject(final JsonObject toscaPolicyProperties)
+ throws PolicyToscaConverterException {
+
+ try {
+ return toscaPolicyProperties.get(POLICIES.getKey()).getAsJsonArray().get(0).getAsJsonObject();
+ } catch (final Exception e) {
+ throw new PolicyToscaConverterException(
+ String.format("Could not read the first policy in the '%s' entry under '%s'",
+ POLICIES.getKey(), TOPOLOGY_TEMPLATE.getKey()), e);
+ }
+ }
+
+ private JsonObject readPolicyPropertiesAsJsonObject(final JsonObject toscaPolicy)
+ throws PolicyToscaConverterException {
+
+ try {
+ final String policyObjectKey = toscaPolicy.keySet().iterator().next();
+ final JsonObject policyEntry = toscaPolicy.get(policyObjectKey).getAsJsonObject();
+ return policyEntry.get(PROPERTIES.getKey()).getAsJsonObject();
+ } catch (final Exception e) {
+ throw new PolicyToscaConverterException(
+ String.format("Could not read the policy '%s' entry", PROPERTIES.getKey()), e);
+ }
+ }
+
+ private String convertToYaml(final JsonObject jsonObject) throws PolicyToscaConverterException {
+ try {
+ return yamlJsonTranslator.toYaml(jsonObject);
+ } catch (final Exception e) {
+ throw new PolicyToscaConverterException(
+ String.format("Could not convert JSON Object to YAML:%n%s", jsonObject.toString()), e);
+ }
+ }
+
+ private JsonObject decodeToJson(final String jsonString) throws PolicyToscaConverterException {
+ try {
+ return standardCoder.decode(jsonString, JsonObject.class);
+ } catch (final CoderException e) {
+ throw new PolicyToscaConverterException(
+ String.format("Could not convert JSON string to JSON:%n%s", jsonString), e);
+ }
+ }
+
+ @Getter
+ public enum ToscaKey {
+ TOPOLOGY_TEMPLATE("topology_template"),
+ TOSCA_DEFINITIONS_VERSION("tosca_definitions_version"),
+ PROPERTIES("properties"),
+ ENGINE_SERVICE_PARAMETERS("engineServiceParameters"),
+ POLICY_TYPE_IMPL("policy_type_impl"),
+ POLICIES("policies");
+
+ private final String key;
+
+ ToscaKey(final String key) {
+ this.key = key;
+ }
+ }
+
+}
diff --git a/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/ProcessedTemplate.java b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/ProcessedTemplate.java
new file mode 100644
index 0000000..1b4bb97
--- /dev/null
+++ b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/ProcessedTemplate.java
@@ -0,0 +1,60 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.gui.editors.apex.rest.handling.converter.tosca;
+
+import java.util.HashSet;
+import java.util.Set;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.commons.collections4.CollectionUtils;
+
+@Getter
+@Setter
+public class ProcessedTemplate {
+
+ private String content;
+ private final Set errorSet;
+
+ public ProcessedTemplate() {
+ errorSet = new HashSet<>();
+ }
+
+ /**
+ * Adds the given error messages to the errors collection.
+ *
+ * @param errorSet a set of error messages
+ */
+ public void addToErrors(final Set errorSet) {
+ if (CollectionUtils.isEmpty(errorSet)) {
+ return;
+ }
+
+ this.errorSet.addAll(errorSet);
+ }
+
+ /**
+ * Checks if the processed template is valid.
+ *
+ * @return {@code true} if the content is valid, {@code false} otherwise
+ */
+ public boolean isValid() {
+ return CollectionUtils.isEmpty(errorSet);
+ }
+}
diff --git a/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/ToscaTemplateProcessor.java b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/ToscaTemplateProcessor.java
new file mode 100644
index 0000000..5539617
--- /dev/null
+++ b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/ToscaTemplateProcessor.java
@@ -0,0 +1,179 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.gui.editors.apex.rest.handling.converter.tosca;
+
+import static org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.PolicyToscaConverter.ToscaKey.POLICIES;
+import static org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.PolicyToscaConverter.ToscaKey.PROPERTIES;
+import static org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.PolicyToscaConverter.ToscaKey.TOPOLOGY_TEMPLATE;
+import static org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.PolicyToscaConverter.ToscaKey.TOSCA_DEFINITIONS_VERSION;
+import static org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.ToscaTemplateProcessor.ErrorMessage.INVALID_ENTRY;
+import static org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.ToscaTemplateProcessor.ErrorMessage.INVALID_POLICY;
+import static org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.ToscaTemplateProcessor.ErrorMessage.INVALID_TOSCA_TEMPLATE;
+import static org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.ToscaTemplateProcessor.ErrorMessage.MISSING_ENTRY;
+import static org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.ToscaTemplateProcessor.ErrorMessage.MISSING_POLICY;
+import static org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.ToscaTemplateProcessor.ErrorMessage.ONLY_ONE_POLICY_ALLOWED;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import lombok.AllArgsConstructor;
+import org.apache.commons.io.IOUtils;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.PolicyToscaConverter.ToscaKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Process the TOSCA JSON template file, base for the Policy Model TOSCA conversion.
+ */
+public class ToscaTemplateProcessor {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ToscaTemplateProcessor.class);
+
+ private final StandardCoder jsonCoder;
+
+ public ToscaTemplateProcessor(final StandardCoder jsonCoder) {
+ this.jsonCoder = jsonCoder;
+ }
+
+ /**
+ * Process the TOSCA JSON template file.
+ *
+ * @param toscaTemplateInputStream the input stream for the TOSCA JSON template file
+ * @return the result of the processing with the read JSON and its errors.
+ */
+ public ProcessedTemplate process(final InputStream toscaTemplateInputStream) throws IOException {
+ final ProcessedTemplate processedTemplate = new ProcessedTemplate();
+
+ final String templateAsString;
+ try (final InputStream inputStream = toscaTemplateInputStream) {
+ templateAsString = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
+ }
+
+ final Set errorSet = validate(templateAsString);
+ processedTemplate.setContent(templateAsString);
+ processedTemplate.addToErrors(errorSet);
+
+ return processedTemplate;
+ }
+
+ private Set validate(final String toscaTemplate) {
+ final Set errorSet = new HashSet<>();
+ final JsonObject toscaTemplateJson;
+ try {
+ toscaTemplateJson = jsonCoder.decode(toscaTemplate, JsonObject.class);
+ } catch (final CoderException e) {
+ LOGGER.debug(INVALID_TOSCA_TEMPLATE.getMessage(), e);
+ errorSet.add(INVALID_TOSCA_TEMPLATE.getMessage());
+ return errorSet;
+ }
+
+ final Optional toscaDefinitionVersionOpt =
+ readJsonEntry(TOSCA_DEFINITIONS_VERSION, toscaTemplateJson::getAsJsonPrimitive, errorSet);
+ if (toscaDefinitionVersionOpt.isEmpty()) {
+ return errorSet;
+ }
+
+ final Optional topologyTemplate =
+ readJsonEntry(TOPOLOGY_TEMPLATE, toscaTemplateJson::getAsJsonObject, errorSet);
+ if (topologyTemplate.isEmpty()) {
+ return errorSet;
+ }
+
+ final Optional policiesOpt =
+ readJsonEntry(POLICIES, topologyTemplate.get()::getAsJsonArray, errorSet);
+ if (policiesOpt.isEmpty()) {
+ return errorSet;
+ }
+ final JsonArray policies = policiesOpt.get();
+
+ if (policies.size() == 0) {
+ errorSet.add(MISSING_POLICY.getMessage());
+ return errorSet;
+ }
+
+ if (policies.size() > 1) {
+ errorSet.add(ONLY_ONE_POLICY_ALLOWED.getMessage());
+ return errorSet;
+ }
+
+ final JsonObject firstPolicy;
+ try {
+ final JsonObject firstPolicyObj = policies.get(0).getAsJsonObject();
+ firstPolicy = firstPolicyObj.entrySet().iterator().next().getValue().getAsJsonObject();
+ } catch (final Exception e) {
+ final String errorMsg = INVALID_POLICY.getMessage();
+ LOGGER.debug(errorMsg, e);
+ errorSet.add(errorMsg);
+ return errorSet;
+ }
+
+ readJsonEntry(PROPERTIES, firstPolicy::getAsJsonObject, errorSet);
+
+ return errorSet;
+ }
+
+ private Optional readJsonEntry(final ToscaKey toscaKey,
+ final Function jsonFunction, final Set errorSet) {
+ try {
+ final T json = jsonFunction.apply(toscaKey.getKey());
+ if (json == null) {
+ errorSet.add(MISSING_ENTRY.getMessage(toscaKey.getKey()));
+ }
+ return Optional.ofNullable(json);
+ } catch (final Exception e) {
+ final String errorMsg = INVALID_ENTRY.getMessage(toscaKey.getKey());
+ LOGGER.debug(errorMsg, e);
+ errorSet.add(errorMsg);
+ return Optional.empty();
+ }
+
+ }
+
+ /**
+ * Stores the possible error messages for the Tosca template validation process.
+ */
+ @AllArgsConstructor
+ public enum ErrorMessage {
+ MISSING_ENTRY("Missing '%s' entry"),
+ MISSING_POLICY("No policy was provided in the 'policies' list"),
+ INVALID_POLICY("Invalid policy was provided in the 'policies' list"),
+ ONLY_ONE_POLICY_ALLOWED("Only one policy entry is allowed in the 'policies' list"),
+ INVALID_TOSCA_TEMPLATE("Invalid tosca template provided"),
+ INVALID_ENTRY("Invalid entry '%s' provided"),
+ MISSING_PROPERTIES_ENTRY("Missing properties entry in '%s'");
+
+ private final String messageFormat;
+
+ public String getMessage(final String... params) {
+ return String.format(this.messageFormat, params);
+ }
+ }
+
+
+}
diff --git a/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/exception/PolicyToscaConverterException.java b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/exception/PolicyToscaConverterException.java
new file mode 100644
index 0000000..a24c393
--- /dev/null
+++ b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/exception/PolicyToscaConverterException.java
@@ -0,0 +1,27 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.exception;
+
+public class PolicyToscaConverterException extends Exception {
+
+ public PolicyToscaConverterException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/plugin/upload/UploadPluginClient.java b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/plugin/upload/UploadPluginClient.java
new file mode 100644
index 0000000..d0c97c9
--- /dev/null
+++ b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/plugin/upload/UploadPluginClient.java
@@ -0,0 +1,69 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.gui.editors.apex.rest.handling.plugin.upload;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.onap.policy.common.parameters.ParameterService;
+import org.onap.policy.gui.editors.apex.rest.UploadPluginConfigParameters;
+
+/**
+ * Client for the Policy Model upload endpoint.
+ */
+public class UploadPluginClient {
+
+ private final Client client;
+ private final UploadPluginConfigParameters uploadConfigParam;
+
+ /**
+ * Create a upload plugin client.
+ */
+ public UploadPluginClient() {
+ this(ClientBuilder.newClient(), ParameterService.get(UploadPluginConfigParameters.GROUP_NAME));
+ }
+
+ /**
+ * Create a upload plugin client.
+ * @param client the http client
+ * @param uploadConfigParam the upload configuration parameters
+ */
+ UploadPluginClient(final Client client,
+ final UploadPluginConfigParameters uploadConfigParam) {
+ this.client = client;
+ this.uploadConfigParam = uploadConfigParam;
+ }
+
+ /**
+ * Uploads the policy to the configured endpoint.
+ *
+ * @param uploadPolicyRequestDto the policy DTO to upload
+ * @return the request response
+ */
+ public Response upload(final UploadPolicyRequestDto uploadPolicyRequestDto) {
+ return client
+ .target(uploadConfigParam.getUrl())
+ .request(MediaType.APPLICATION_JSON)
+ .post(Entity.entity(uploadPolicyRequestDto, MediaType.APPLICATION_JSON));
+ }
+
+}
diff --git a/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/plugin/upload/UploadPolicyRequestDto.java b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/plugin/upload/UploadPolicyRequestDto.java
new file mode 100644
index 0000000..dbd15a0
--- /dev/null
+++ b/gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/plugin/upload/UploadPolicyRequestDto.java
@@ -0,0 +1,40 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.gui.editors.apex.rest.handling.plugin.upload;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+import lombok.Data;
+
+/**
+ * DTO to a policy upload endpoint.
+ */
+@XmlRootElement(name = "policy")
+@XmlAccessorType(XmlAccessType.FIELD)
+@Data
+public class UploadPolicyRequestDto {
+
+ private Long id;
+ private String userId;
+ private String filename;
+ private String fileData;
+
+}
diff --git a/gui-editors/gui-editor-apex/src/main/resources/webapp/css/upload/dialog.css b/gui-editors/gui-editor-apex/src/main/resources/webapp/css/upload/dialog.css
new file mode 100644
index 0000000..95f29b1
--- /dev/null
+++ b/gui-editors/gui-editor-apex/src/main/resources/webapp/css/upload/dialog.css
@@ -0,0 +1,56 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+.upload-dialog {
+ font-size: 16px;
+ line-height: 19px;
+}
+
+.upload-dialog .ui-button {
+ position: relative;
+ display: inline-block;
+ vertical-align: middle;
+ color: #333333;
+ background-color: #ffffff;
+ border: none;
+ min-width: 60px;
+ box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2);
+ border-radius: 3px;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ background-image: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.1) 100%);
+ padding: 0 8px;
+ height: 2.4rem;
+ font-size: 1.2rem;
+ white-space: nowrap;
+ text-decoration: none;
+ text-align: center;
+ cursor: pointer;
+}
+
+.upload-dialog #upload-form {
+ width: 100%;
+ font-size: 16px;
+ line-height: 19px;
+}
+
+.upload-dialog #upload-form input {
+ width: 100%;
+}
\ No newline at end of file
diff --git a/gui-editors/gui-editor-apex/src/main/resources/webapp/index.html b/gui-editors/gui-editor-apex/src/main/resources/webapp/index.html
index 20a15ff..53e205e 100644
--- a/gui-editors/gui-editor-apex/src/main/resources/webapp/index.html
+++ b/gui-editors/gui-editor-apex/src/main/resources/webapp/index.html
@@ -43,6 +43,8 @@
+
+
@@ -82,6 +84,7 @@
New Ctrl+N
Open... Ctrl+O
Download Ctrl+S
+
Upload Ctrl+U
ClearCtrl+D
New SessionCtrl+R
@@ -172,6 +175,7 @@
+
@@ -212,7 +216,8 @@
-
+
+
@@ -234,6 +239,8 @@
+
+
+
+
Provide the following files to compose the policy TOSCA
+
+
+
+
+
+
+
+
diff --git a/gui-editors/gui-editor-apex/src/main/resources/webapp/js/ApexConfig.js b/gui-editors/gui-editor-apex/src/main/resources/webapp/js/ApexConfig.js
new file mode 100644
index 0000000..a7f41d2
--- /dev/null
+++ b/gui-editors/gui-editor-apex/src/main/resources/webapp/js/ApexConfig.js
@@ -0,0 +1,58 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+const configObj = {
+ configMap: {},
+ getConfig: function (configKey) {
+ return this.configMap[configKey];
+ },
+ setConfig: function (configKey, configValue) {
+ return this.configMap[configKey] = configValue;
+ },
+ readySignal: function () {
+ $.publish("/config/ready");
+ }
+}
+
+$(document).ready(function () {
+ $("#menuFileUpload").hide();
+
+ const rootUrl = location.protocol
+ + "//"
+ + window.location.hostname
+ + (location.port ? ':' + location.port : '');
+
+ const configUrl = rootUrl + "/apexservices/editor/config";
+
+ function loadConfiguration() {
+ ajax_get(configUrl, function (data) {
+ for (let i = 0; i < data.messages.message.length; i++) {
+ const configEntry = JSON.parse(data.messages.message[i]);
+ Object.keys(configEntry).forEach(key => {
+ configObj.setConfig(key, configEntry[key]);
+ });
+ }
+ configObj.readySignal();
+ });
+ }
+
+ loadConfiguration();
+});
+
+
diff --git a/gui-editors/gui-editor-apex/src/main/resources/webapp/js/ApexMain.js b/gui-editors/gui-editor-apex/src/main/resources/webapp/js/ApexMain.js
index e8ad0de..57433d6 100644
--- a/gui-editors/gui-editor-apex/src/main/resources/webapp/js/ApexMain.js
+++ b/gui-editors/gui-editor-apex/src/main/resources/webapp/js/ApexMain.js
@@ -40,10 +40,12 @@ $("#menu li").not(".emptyMessage").click(function() {
case "menuFileOpen":
files_fileOpen();
break;
-
case "menuFileDownload":
files_fileDownload();
break;
+ case "menuFileUpload":
+ uploadPlugin.openDialog();
+ break;
case "menuFileClear":
if (confirm("Clear the current model?")) {
diff --git a/gui-editors/gui-editor-apex/src/main/resources/webapp/js/ApexPageControl.js b/gui-editors/gui-editor-apex/src/main/resources/webapp/js/ApexPageControl.js
index 4904f30..c2cb45c 100644
--- a/gui-editors/gui-editor-apex/src/main/resources/webapp/js/ApexPageControl.js
+++ b/gui-editors/gui-editor-apex/src/main/resources/webapp/js/ApexPageControl.js
@@ -27,6 +27,7 @@ function pageControl_modelMode(name, version, fileName) {
$("#menuFileNew").addClass("disabled");
$("#menuFileOpen").addClass("disabled");
$("#menuFileDownload").removeClass("disabled");
+ $("#menuFileUpload").removeClass("disabled");
$("#menuFileClear").removeClass("disabled");
$("#menuModelAnalyse").removeClass("disabled");
$("#menuModelValidate").removeClass("disabled");
@@ -77,6 +78,7 @@ function pageControl_noModelMode() {
$("#menuFileNew").removeClass("disabled");
$("#menuFileOpen").removeClass("disabled");
$("#menuFileDownload").addClass("disabled");
+ $("#menuFileUpload").addClass("disabled");
$("#menuFileClear").addClass("disabled");
$("#menuModelAnalyse").addClass("disabled");
$("#menuModelValidate").addClass("disabled");
diff --git a/gui-editors/gui-editor-apex/src/main/resources/webapp/js/ApexUpload.js b/gui-editors/gui-editor-apex/src/main/resources/webapp/js/ApexUpload.js
new file mode 100644
index 0000000..a71853c
--- /dev/null
+++ b/gui-editors/gui-editor-apex/src/main/resources/webapp/js/ApexUpload.js
@@ -0,0 +1,61 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Nordix Foundation
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+$(document).ready(function () {
+ $.subscribe("/config/ready", enableUpload);
+
+ function enableUpload() {
+ const menuFileUpload = $('#menuFileUpload');
+ const isUploadEnabled = configObj.getConfig("plugin.policy.upload.enable");
+ if (isUploadEnabled === "true" || isUploadEnabled === true) {
+ menuFileUpload.show();
+ } else {
+ menuFileUpload.hide();
+ }
+ }
+
+});
+
+const uploadPlugin = {
+ dialogDiv: $('#main-dialog'),
+ openDialog: function () {
+ this.dialogDiv.load('../upload/dialog.html');
+ },
+
+ upload: function (data, successCallback, errorCallback) {
+ const requestURL = restRootURL + "/Model/Upload";
+ $.ajax({
+ type: 'POST',
+ url: requestURL,
+ data: data,
+ contentType: false,
+ processData: false
+ }).done(function (data) {
+ pageControl_successStatus(data);
+ if (typeof successCallback === typeof Function) {
+ successCallback(data);
+ }
+ }).fail(function (jqXHR, textStatus, errorThrown) {
+ pageControl_restError(requestURL, jqXHR, textStatus, errorThrown);
+ if (typeof errorCallback === typeof Function) {
+ errorCallback(jqXHR, textStatus, errorThrown);
+ }
+ });
+ }
+}
diff --git a/gui-editors/gui-editor-apex/src/main/resources/webapp/js/lib/pubsub/ba-tiny-pubsub.min.js b/gui-editors/gui-editor-apex/src/main/resources/webapp/js/lib/pubsub/ba-tiny-pubsub.min.js
new file mode 100644
index 0000000..635ab34
--- /dev/null
+++ b/gui-editors/gui-editor-apex/src/main/resources/webapp/js/lib/pubsub/ba-tiny-pubsub.min.js
@@ -0,0 +1,4 @@
+/*! Tiny Pub/Sub - v0.7.0 - 2013-01-29
+* https://github.com/cowboy/jquery-tiny-pubsub
+* Copyright (c) 2013 "Cowboy" Ben Alman; Licensed MIT */
+(function(n){var u=n({});n.subscribe=function(){u.on.apply(u,arguments)},n.unsubscribe=function(){u.off.apply(u,arguments)},n.publish=function(){u.trigger.apply(u,arguments)}})(jQuery);
\ No newline at end of file
diff --git a/gui-editors/gui-editor-apex/src/main/resources/webapp/upload/dialog.html b/gui-editors/gui-editor-apex/src/main/resources/webapp/upload/dialog.html
new file mode 100644
index 0000000..aac7762
--- /dev/null
+++ b/gui-editors/gui-editor-apex/src/main/resources/webapp/upload/dialog.html
@@ -0,0 +1,64 @@
+
+
+
+
+