aboutsummaryrefslogtreecommitdiffstats
path: root/gui-editors/gui-editor-apex/src/main/java
diff options
context:
space:
mode:
authorAjith Sreekumar <ajith.sreekumar@bell.ca>2020-08-10 14:33:18 +0000
committerGerrit Code Review <gerrit@onap.org>2020-08-10 14:33:18 +0000
commit864811238d7d44933df2c4f59f31947a83310587 (patch)
tree9e6bbf6894e040c20c5d5840fd1582a46ed73aae /gui-editors/gui-editor-apex/src/main/java
parent6b61be2310929f155dcd38478df13fe1a0d81fad (diff)
parentd4dd779aa66be0e046ecb1938fb532312cfe7680 (diff)
Merge "Upload policy feature"
Diffstat (limited to 'gui-editors/gui-editor-apex/src/main/java')
-rw-r--r--gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/ApexEditor.java2
-rw-r--r--gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/ApexEditorMain.java5
-rw-r--r--gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/UploadPluginConfigParameters.java81
-rw-r--r--gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/ApexEditorRestResource.java58
-rw-r--r--gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/ConfigurationRestResource.java83
-rw-r--r--gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/ModelHandler.java2
-rw-r--r--gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/PolicyUploadHandler.java182
-rw-r--r--gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/config/PolicyUploadPluginConfigKey.java40
-rw-r--r--gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/ApexConfigProcessor.java117
-rw-r--r--gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/PolicyToscaConverter.java168
-rw-r--r--gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/ProcessedTemplate.java60
-rw-r--r--gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/ToscaTemplateProcessor.java179
-rw-r--r--gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/converter/tosca/exception/PolicyToscaConverterException.java27
-rw-r--r--gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/plugin/upload/UploadPluginClient.java69
-rw-r--r--gui-editors/gui-editor-apex/src/main/java/org/onap/policy/gui/editors/apex/rest/handling/plugin/upload/UploadPolicyRequestDto.java40
15 files changed, 1105 insertions, 8 deletions
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 <T> represents the class type
+ * @param key the property key
+ * @return the property value if it exists
+ */
+ public <T> Optional<T> getValue(final PolicyUploadPluginConfigKey key) {
+ final Class<?> type = key.getType();
+ if (key == PolicyUploadPluginConfigKey.URL && type.isInstance(url)) {
+ return (Optional<T>) Optional.of(type.cast(url));
+ }
+ if (key == PolicyUploadPluginConfigKey.ENABLE && type.isInstance(isEnabled)) {
+ return (Optional<T>) 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,13 +101,27 @@ 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.
*
@@ -226,6 +251,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.
*
* @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
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<String, Object> 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<String> 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<String> errorSet = validate(templateAsString);
+ processedTemplate.setContent(templateAsString);
+ processedTemplate.addToErrors(errorSet);
+
+ return processedTemplate;
+ }
+
+ private Set<String> validate(final String apexConfig) {
+ final Set<String> 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<String> 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<String, JsonElement> 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<String> 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<String> 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<String> errorSet = validate(templateAsString);
+ processedTemplate.setContent(templateAsString);
+ processedTemplate.addToErrors(errorSet);
+
+ return processedTemplate;
+ }
+
+ private Set<String> validate(final String toscaTemplate) {
+ final Set<String> 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<JsonPrimitive> toscaDefinitionVersionOpt =
+ readJsonEntry(TOSCA_DEFINITIONS_VERSION, toscaTemplateJson::getAsJsonPrimitive, errorSet);
+ if (toscaDefinitionVersionOpt.isEmpty()) {
+ return errorSet;
+ }
+
+ final Optional<JsonObject> topologyTemplate =
+ readJsonEntry(TOPOLOGY_TEMPLATE, toscaTemplateJson::getAsJsonObject, errorSet);
+ if (topologyTemplate.isEmpty()) {
+ return errorSet;
+ }
+
+ final Optional<JsonArray> 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 <T> Optional<T> readJsonEntry(final ToscaKey toscaKey,
+ final Function<String, T> jsonFunction, final Set<String> 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;
+
+}