diff options
Diffstat (limited to 'src/main/java/org/openecomp/modelloader/entity/model')
11 files changed, 1108 insertions, 297 deletions
diff --git a/src/main/java/org/openecomp/modelloader/entity/model/AbstractModelArtifact.java b/src/main/java/org/openecomp/modelloader/entity/model/AbstractModelArtifact.java new file mode 100644 index 0000000..2add53e --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/entity/model/AbstractModelArtifact.java @@ -0,0 +1,85 @@ +/** + * ============LICENSE_START======================================================= + * Model Loader + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ +package org.openecomp.modelloader.entity.model; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.openecomp.modelloader.config.ModelLoaderConfig; +import org.openecomp.modelloader.entity.Artifact; +import org.openecomp.modelloader.entity.ArtifactType; +import org.openecomp.modelloader.restclient.AaiRestClient; + +public abstract class AbstractModelArtifact extends Artifact { + + private String modelNamespace; + private String modelNamespaceVersion; + private Set<String> referencedModelIds = new HashSet<String>(); + + public AbstractModelArtifact(ArtifactType type) { + super(type); + } + + public Set<String> getDependentModelIds() { + return referencedModelIds; + } + + public void addDependentModelId(String dependentModelId) { + this.referencedModelIds.add(dependentModelId); + } + + public String getModelNamespace() { + return modelNamespace; + } + + public void setModelNamespace(String modelNamespace) { + this.modelNamespace = modelNamespace; + + // Get the version from the namespace (in format 'http://org.openecomp.aai.inventory/v9') + String[] parts = modelNamespace.split("/"); + modelNamespaceVersion = parts[parts.length-1].trim(); + } + + public String getModelNamespaceVersion() { + return modelNamespaceVersion; + } + + public abstract String getUniqueIdentifier(); + + public abstract boolean push(AaiRestClient aaiClient, ModelLoaderConfig config, String distId, List<AbstractModelArtifact> addedModels); + + public abstract void rollbackModel(AaiRestClient aaiClient, ModelLoaderConfig config, String distId); + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("\nType=" + getType().toString() +"\nId=" + getUniqueIdentifier() +"\nVersion=" + getModelNamespaceVersion() + "\nDependant models: "); + for (String dep : referencedModelIds) { + sb.append(dep + " "); + } + + return sb.toString(); + } + + +} diff --git a/src/main/java/org/openecomp/modelloader/entity/model/IModelParser.java b/src/main/java/org/openecomp/modelloader/entity/model/IModelParser.java new file mode 100644 index 0000000..3a31756 --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/entity/model/IModelParser.java @@ -0,0 +1,31 @@ +/** + * ============LICENSE_START======================================================= + * Model Loader + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ +package org.openecomp.modelloader.entity.model; + +import java.util.List; + +import org.openecomp.modelloader.entity.Artifact; + +public interface IModelParser { + public List<Artifact> parse(byte[] artifactPayload, String artifactName); +} diff --git a/src/main/java/org/openecomp/modelloader/entity/model/ModelArtifact.java b/src/main/java/org/openecomp/modelloader/entity/model/ModelArtifact.java index 904dba9..f316e28 100644 --- a/src/main/java/org/openecomp/modelloader/entity/model/ModelArtifact.java +++ b/src/main/java/org/openecomp/modelloader/entity/model/ModelArtifact.java @@ -1,60 +1,210 @@ -/*- +/** * ============LICENSE_START======================================================= - * MODEL LOADER SERVICE + * Model Loader * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============LICENSE_END========================================================= + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. */ - package org.openecomp.modelloader.entity.model; -import org.openecomp.modelloader.entity.Artifact; +import java.io.StringWriter; +import java.util.List; -import java.util.HashSet; -import java.util.Set; +import javax.ws.rs.core.Response; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; -public class ModelArtifact extends Artifact { +import org.openecomp.cl.api.Logger; +import org.openecomp.cl.eelf.LoggerFactory; +import org.openecomp.modelloader.config.ModelLoaderConfig; +import org.openecomp.modelloader.entity.ArtifactType; +import org.openecomp.modelloader.restclient.AaiRestClient; +import org.openecomp.modelloader.service.ModelLoaderMsgs; +import org.w3c.dom.Node; - String nameVersionId; - Set<String> referencedModelIds = new HashSet<String>(); +import com.sun.jersey.api.client.ClientResponse; - public String getNameVersionId() { - return nameVersionId; - } +public class ModelArtifact extends AbstractModelArtifact { - public void setNameVersionId(String nameVersionId) { - this.nameVersionId = nameVersionId; - } + private static final String AAI_MODEL_VER_SUB_URL = "/model-vers/model-ver"; + + private static Logger logger = LoggerFactory.getInstance().getLogger(ModelArtifact.class.getName()); + + private String modelVerId; + private String modelInvariantId; + private Node modelVer; + private boolean firstVersionOfModel = false; - public Set<String> getDependentModelIds() { - return referencedModelIds; - } + public ModelArtifact() { + super(ArtifactType.MODEL); + } - public void addDependentModelId(String dependentModelId) { - this.referencedModelIds.add(dependentModelId); + public String getModelVerId() { + return modelVerId; + } + + public void setModelVerId(String modelVerId) { + this.modelVerId = modelVerId; + } + + public String getModelInvariantId() { + return modelInvariantId; + } + + public void setModelInvariantId(String modelInvariantId) { + this.modelInvariantId = modelInvariantId; + } + + public Node getModelVer() { + return modelVer; + } + + public void setModelVer(Node modelVer) { + this.modelVer = modelVer; + } + + @Override + public String getUniqueIdentifier() { + return getModelInvariantId() + "|" + getModelVerId(); } @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("NameVersId=" + nameVersionId + "(" + getType().toString() + ") ==> "); - for (String dep : referencedModelIds) { - sb.append(dep + " "); + public boolean push(AaiRestClient aaiClient, ModelLoaderConfig config, String distId, List<AbstractModelArtifact> addedModels) { + ClientResponse getResponse = aaiClient.getResource(getModelUrl(config), distId, AaiRestClient.MimeType.XML); + if ( (getResponse == null) || (getResponse.getStatus() != Response.Status.OK.getStatusCode()) ) { + // Only attempt the PUT if the model doesn't already exist + ClientResponse putResponse = aaiClient.putResource(getModelUrl(config), getPayload(), distId, AaiRestClient.MimeType.XML); + if ( (putResponse != null) && (putResponse.getStatus() == Response.Status.CREATED.getStatusCode()) ) { + addedModels.add(this); + + // Flag this as the first version of the model that has been added. + firstVersionOfModel = true; + + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, getType().toString() + " " + getUniqueIdentifier() + " successfully ingested."); + } + else { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, "Ingestion failed for " + getType().toString() + " " + getUniqueIdentifier() + + ". Rolling back distribution."); + return false; + } } + else { + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, getType().toString() + " " + getModelInvariantId() + " already exists. Skipping ingestion."); + getResponse = aaiClient.getResource(getModelVerUrl(config), distId, AaiRestClient.MimeType.XML); + if ( (getResponse == null) || (getResponse.getStatus() != Response.Status.OK.getStatusCode()) ) { + // Only attempt the PUT if the model-ver doesn't already exist + ClientResponse putResponse = null; - return sb.toString(); + try { + putResponse = aaiClient.putResource(getModelVerUrl(config), nodeToString(getModelVer()), distId, AaiRestClient.MimeType.XML); + } catch (TransformerException e) { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, "Ingestion failed for " + getType().toString() + " " + getUniqueIdentifier() + + ": " + e.getMessage() + ". Rolling back distribution."); + return false; + } + if ( (putResponse != null) && (putResponse.getStatus() == Response.Status.CREATED.getStatusCode()) ) { + addedModels.add(this); + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, getType().toString() + " " + getUniqueIdentifier() + " successfully ingested."); + } + else { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, "Ingestion failed for " + getType().toString() + " " + + getUniqueIdentifier() + ". Rolling back distribution."); + return false; + } + } + else { + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, getType().toString() + " " + getUniqueIdentifier() + " already exists. Skipping ingestion."); + } + } + + return true; } + + @Override + public void rollbackModel(AaiRestClient aaiClient, ModelLoaderConfig config, String distId) { + String url = getModelVerUrl(config); + if (firstVersionOfModel) { + // If this was the first version of the model which was added, we want to remove the entire + // model rather than just the version. + url = getModelUrl(config); + } + + // Best effort to delete. Nothing we can do in the event this fails. + aaiClient.getAndDeleteResource(url, distId); + } + + private String getModelUrl(ModelLoaderConfig config) { + String baseURL = config.getAaiBaseUrl().trim(); + String subURL = null; + String instance = null; + + subURL = config.getAaiModelUrl(getModelNamespaceVersion()).trim(); + instance = getModelInvariantId(); + + if ( (!baseURL.endsWith("/")) && (!subURL.startsWith("/")) ) { + baseURL = baseURL + "/"; + } + + if ( baseURL.endsWith("/") && subURL.startsWith("/") ) { + baseURL = baseURL.substring(0, baseURL.length()-1); + } + if (!subURL.endsWith("/")) { + subURL = subURL + "/"; + } + + String url = baseURL + subURL + instance; + return url; + } + + private String getModelVerUrl(ModelLoaderConfig config) { + String baseURL = config.getAaiBaseUrl().trim(); + String subURL = null; + String instance = null; + + subURL = config.getAaiModelUrl(getModelNamespaceVersion()).trim() + getModelInvariantId() + AAI_MODEL_VER_SUB_URL; + instance = getModelVerId(); + + if ( (!baseURL.endsWith("/")) && (!subURL.startsWith("/")) ) { + baseURL = baseURL + "/"; + } + + if ( baseURL.endsWith("/") && subURL.startsWith("/") ) { + baseURL = baseURL.substring(0, baseURL.length()-1); + } + + if (!subURL.endsWith("/")) { + subURL = subURL + "/"; + } + + String url = baseURL + subURL + instance; + return url; + } + + private String nodeToString(Node node) throws TransformerException { + StringWriter sw = new StringWriter(); + Transformer t = TransformerFactory.newInstance().newTransformer(); + t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + t.transform(new DOMSource(node), new StreamResult(sw)); + return sw.toString(); + } } diff --git a/src/main/java/org/openecomp/modelloader/entity/model/ModelArtifactHandler.java b/src/main/java/org/openecomp/modelloader/entity/model/ModelArtifactHandler.java index fb269b1..13ef1b1 100644 --- a/src/main/java/org/openecomp/modelloader/entity/model/ModelArtifactHandler.java +++ b/src/main/java/org/openecomp/modelloader/entity/model/ModelArtifactHandler.java @@ -1,127 +1,79 @@ -/*- +/** * ============LICENSE_START======================================================= - * MODEL LOADER SERVICE + * Model Loader * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============LICENSE_END========================================================= + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. */ - package org.openecomp.modelloader.entity.model; -import com.sun.jersey.api.client.ClientResponse; - import org.openecomp.cl.api.Logger; import org.openecomp.cl.eelf.LoggerFactory; import org.openecomp.modelloader.config.ModelLoaderConfig; import org.openecomp.modelloader.entity.Artifact; import org.openecomp.modelloader.entity.ArtifactHandler; -import org.openecomp.modelloader.entity.ArtifactType; import org.openecomp.modelloader.restclient.AaiRestClient; import org.openecomp.modelloader.service.ModelLoaderMsgs; import java.util.ArrayList; import java.util.List; -import javax.ws.rs.core.Response; public class ModelArtifactHandler extends ArtifactHandler { - private static Logger logger = LoggerFactory.getInstance() - .getLogger(ArtifactHandler.class.getName()); - + private static Logger logger = LoggerFactory.getInstance().getLogger(ModelArtifactHandler.class.getName()); + public ModelArtifactHandler(ModelLoaderConfig config) { super(config); } @Override - public boolean pushArtifacts(List<Artifact> artifacts, String distributionId) { + public boolean pushArtifacts(List<Artifact> artifacts, String distributionID) { ModelSorter modelSorter = new ModelSorter(); - List<Artifact> sortedModelArtifacts = modelSorter.sort(artifacts); - - // Push the ordered list of model artifacts to A&AI. If one fails, we need - // to roll back + List<Artifact> sortedModelArtifacts; + try { + sortedModelArtifacts = modelSorter.sort(artifacts); + } + catch (RuntimeException ex) { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, "Unable to resolve models: " + ex.getMessage()); + return false; + } + + // Push the ordered list of model artifacts to A&AI. If one fails, we need to roll back // the changes. - List<ModelArtifact> completedModels = new ArrayList<ModelArtifact>(); + List<AbstractModelArtifact> completedModels = new ArrayList<AbstractModelArtifact>(); AaiRestClient aaiClient = new AaiRestClient(config); for (Artifact art : sortedModelArtifacts) { - ModelArtifact model = (ModelArtifact) art; - ClientResponse getResponse = aaiClient.getResource(getUrl(model), distributionId, - AaiRestClient.MimeType.XML); - if ((getResponse == null) - || (getResponse.getStatus() != Response.Status.OK.getStatusCode())) { - // Only attempt the PUT if the model doesn't already exist - ClientResponse putResponse = aaiClient.putResource(getUrl(model), model.getPayload(), - distributionId, AaiRestClient.MimeType.XML); - if ((putResponse != null) - && (putResponse.getStatus() == Response.Status.CREATED.getStatusCode())) { - completedModels.add(model); - logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, model.getType().toString() + " " - + model.getNameVersionId() + " successfully ingested."); - } else { - logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, - "Ingestion failed for " + model.getType().toString() + " " + model.getNameVersionId() - + ". Rolling back distribution."); - - for (ModelArtifact modelToDelete : completedModels) { - // Best effort to delete. Nothing we can do in the event this fails. - aaiClient.getAndDeleteResource(getUrl(modelToDelete), distributionId); - } - - return false; + AbstractModelArtifact model = (AbstractModelArtifact)art; + if (model.push(aaiClient, config, distributionID, completedModels) != true) { + for (AbstractModelArtifact modelToDelete : completedModels) { + modelToDelete.rollbackModel(aaiClient, config, distributionID); } - } else { - logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, model.getType().toString() + " " - + model.getNameVersionId() + " already exists. Skipping ingestion."); + + return false; } } return true; } - private String getUrl(ModelArtifact model) { - String baseUrl = config.getAaiBaseUrl().trim(); - String subUrl = null; - if (model.getType().equals(ArtifactType.MODEL)) { - subUrl = config.getAaiModelUrl().trim(); - } else { - subUrl = config.getAaiNamedQueryUrl().trim(); - } - - if ((!baseUrl.endsWith("/")) && (!subUrl.startsWith("/"))) { - baseUrl = baseUrl + "/"; - } - - if (baseUrl.endsWith("/") && subUrl.startsWith("/")) { - baseUrl = baseUrl.substring(0, baseUrl.length() - 1); - } - - if (!subUrl.endsWith("/")) { - subUrl = subUrl + "/"; - } - - String url = baseUrl + subUrl + model.getNameVersionId(); - return url; - } - - /** - * This method is used for the test REST interface to load models without an - * ASDC. - * - * @param payload content of the request - */ + // This method is used for the test REST interface to load models without an ASDC public void loadModelTest(byte[] payload) { List<Artifact> modelArtifacts = new ArrayList<Artifact>(); ModelArtifactParser parser = new ModelArtifactParser(); diff --git a/src/main/java/org/openecomp/modelloader/entity/model/ModelArtifactParser.java b/src/main/java/org/openecomp/modelloader/entity/model/ModelArtifactParser.java index 625145f..d81539c 100644 --- a/src/main/java/org/openecomp/modelloader/entity/model/ModelArtifactParser.java +++ b/src/main/java/org/openecomp/modelloader/entity/model/ModelArtifactParser.java @@ -1,197 +1,194 @@ -/*- +/** * ============LICENSE_START======================================================= - * MODEL LOADER SERVICE + * Model Loader * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============LICENSE_END========================================================= + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. */ - package org.openecomp.modelloader.entity.model; import org.openecomp.cl.api.Logger; import org.openecomp.cl.eelf.LoggerFactory; import org.openecomp.modelloader.entity.Artifact; -import org.openecomp.modelloader.entity.ArtifactType; import org.openecomp.modelloader.service.ModelLoaderMsgs; -import org.openecomp.modelloader.util.JsonXmlConverter; + import org.w3c.dom.Document; +import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import java.io.StringReader; -import java.io.StringWriter; import java.util.ArrayList; import java.util.List; +import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -public class ModelArtifactParser { - - private static String MODELS_ELEMENT = "models"; - private static String MODEL_ELEMENT = "model"; - private static String NAMED_QUERIES_ELEMENT = "named-queries"; - private static String NAMED_QUERY_ELEMENT = "named-query"; - private static String MODEL_NAME_VERSION_ID = "model-name-version-id"; - private static String NAMED_QUERY_VERSION_ID = "named-query-uuid"; - private static String RELATIONSHIP_DATA = "relationship-data"; - private static String RELATIONSHIP_KEY = "relationship-key"; - private static String RELATIONSHIP_VALUE = "relationship-value"; - private static String MODEL_ELEMENT_RELATIONSHIP_KEY = "model.model-name-version-id"; - - private static Logger logger = LoggerFactory.getInstance() - .getLogger(ModelArtifactParser.class.getName()); - - /** - * This method parses the given artifact payload in byte array format and - * generates a list of model artifacts according to the content. - * - * @param artifactPayload - * artifact content to be parsed - * @param artifactName - * name of the artifact - * @return a list of model artifacts - */ - public List<Artifact> parse(byte[] artifactPayload, String artifactName) { - String payload = new String(artifactPayload); - List<Artifact> modelList = new ArrayList<Artifact>(); - - try { - // Artifact could be JSON or XML - if (JsonXmlConverter.isValidJson(payload)) { - payload = JsonXmlConverter.convertJsonToXml(payload); - } - - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - InputSource is = new InputSource(new StringReader(payload)); - Document doc = builder.parse(is); - - if ((doc.getDocumentElement().getNodeName().equalsIgnoreCase(MODEL_ELEMENT)) - || (doc.getDocumentElement().getNodeName().equalsIgnoreCase(NAMED_QUERY_ELEMENT))) { - ModelArtifact model = parseModel(doc.getDocumentElement(), payload); - if (model != null) { - modelList.add(model); - } else { - // TODO: A WARN message? - logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, - "Unable to parse artifact " + artifactName); - } - } else if ((doc.getDocumentElement().getNodeName().equalsIgnoreCase(MODELS_ELEMENT)) - || (doc.getDocumentElement().getNodeName().equalsIgnoreCase(NAMED_QUERIES_ELEMENT))) { - // The complete set of models/named-queries were contained in this - // artifact - NodeList nodeList = doc.getDocumentElement().getChildNodes(); - for (int i = 0; i < nodeList.getLength(); i++) { - Node childNode = nodeList.item(i); - if ((childNode.getNodeName().equalsIgnoreCase(MODEL_ELEMENT)) - || (childNode.getNodeName().equalsIgnoreCase(NAMED_QUERY_ELEMENT))) { - String modelPayload = nodeToString(childNode); - ModelArtifact model = parseModel(childNode, modelPayload); - if (model != null) { - modelList.add(model); - } else { - // TODO: A WARN message? - logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, - "Unable to parse artifact " + artifactName); - modelList.clear(); - break; - } - } - } - } - } catch (Exception ex) { - // This may not be an error. We may be receiving an artifact that is - // unrelated - // to models. In this case, we just ignore it. - // TODO: A WARN message? - logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, - "Unable to parse artifact " + artifactName + ": " + ex.getLocalizedMessage()); - } - - return modelList; - } - - private ModelArtifact parseModel(Node modelNode, String payload) { - ModelArtifact model = new ModelArtifact(); - model.setPayload(payload); - - if (modelNode.getNodeName().equalsIgnoreCase(MODEL_ELEMENT)) { - model.setType(ArtifactType.MODEL); - } else { - model.setType(ArtifactType.NAMED_QUERY); - } - - parseNode(modelNode, model); - - if (model.getNameVersionId() == null) { - return null; - } - - return model; - } - - private void parseNode(Node node, ModelArtifact model) { - if (node.getNodeName().equalsIgnoreCase(MODEL_NAME_VERSION_ID)) { - model.setNameVersionId(node.getTextContent().trim()); - } else if (node.getNodeName().equalsIgnoreCase(NAMED_QUERY_VERSION_ID)) { - model.setNameVersionId(node.getTextContent().trim()); - } else if (node.getNodeName().equalsIgnoreCase(RELATIONSHIP_DATA)) { - parseRelationshipNode(node, model); - } else { - NodeList nodeList = node.getChildNodes(); - for (int i = 0; i < nodeList.getLength(); i++) { - Node childNode = nodeList.item(i); - parseNode(childNode, model); - } - } - } - - private void parseRelationshipNode(Node node, ModelArtifact model) { - String key = null; - String value = null; - - NodeList nodeList = node.getChildNodes(); - for (int i = 0; i < nodeList.getLength(); i++) { - Node childNode = nodeList.item(i); - if (childNode.getNodeName().equalsIgnoreCase(RELATIONSHIP_KEY)) { - key = childNode.getTextContent().trim(); - } else if (childNode.getNodeName().equalsIgnoreCase(RELATIONSHIP_VALUE)) { - value = childNode.getTextContent().trim(); - } - } - - if ((key != null) && (key.equalsIgnoreCase(MODEL_ELEMENT_RELATIONSHIP_KEY))) { - if (value != null) { - model.addDependentModelId(value); - } - } - } - - private String nodeToString(Node node) throws TransformerException { - StringWriter sw = new StringWriter(); - Transformer transfomer = TransformerFactory.newInstance().newTransformer(); - transfomer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); - transfomer.transform(new DOMSource(node), new StreamResult(sw)); - return sw.toString(); - } + + +public class ModelArtifactParser implements IModelParser { + + private static String MODEL_VER = "model-ver"; + private static String MODEL_VERSION_ID = "model-version-id"; + private static String MODEL_INVARIANT_ID = "model-invariant-id"; + private static String RELATIONSHIP = "relationship"; + private static String RELATIONSHIP_DATA = "relationship-data"; + private static String RELATIONSHIP_KEY = "relationship-key"; + private static String RELATIONSHIP_VALUE = "relationship-value"; + private static String MODEL_ELEMENT_RELATIONSHIP_KEY = "model.model-invariant-id"; + private static String MODEL_VER_ELEMENT_RELATIONSHIP_KEY = "model-ver.model-version-id"; + + private static Logger logger = LoggerFactory.getInstance().getLogger(ModelArtifactParser.class.getName()); + + public List<Artifact> parse(byte[] artifactPayload, String artifactName) { + String payload = new String(artifactPayload); + List<Artifact> modelList = new ArrayList<Artifact>(); + + try { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + InputSource is = new InputSource(new StringReader(payload)); + Document doc = builder.parse(is); + + ModelArtifact model = parseModel(doc.getDocumentElement(), payload); + + if (model != null) { + logger.info( ModelLoaderMsgs.DISTRIBUTION_EVENT, "Model parsed =====>>>> " + + "Model-invariant-Id: "+ model.getModelInvariantId() + + " Model-Version-Id: "+ model.getModelVerId()); + modelList.add(model); + } + else { + logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, "Unable to parse artifact " + artifactName); + return null; + } + } + catch (Exception ex) { + logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, "Unable to parse artifact " + artifactName + ": " + ex.getLocalizedMessage()); + } + + return modelList; + } + + private ModelArtifact parseModel(Node modelNode, String payload) { + ModelArtifact model = new ModelArtifact(); + model.setPayload(payload); + + Element e = (Element)modelNode; + model.setModelNamespace(e.getAttribute("xmlns")); + + parseNode(modelNode, model); + + if ( (model.getModelInvariantId() == null) || (model.getModelVerId() == null) ){ + return null; + } + + return model; + } + + private void parseNode(Node node, ModelArtifact model) { + if (node.getNodeName().equalsIgnoreCase(MODEL_INVARIANT_ID)) { + model.setModelInvariantId(node.getTextContent().trim()); + } + else if (node.getNodeName().equalsIgnoreCase(MODEL_VERSION_ID)) { + model.setModelVerId(node.getTextContent().trim()); + } + else if (node.getNodeName().equalsIgnoreCase(RELATIONSHIP)) { + String dependentModelKey = parseRelationshipNode(node, model); + if (dependentModelKey != null) { + model.addDependentModelId(dependentModelKey); + } + } + else { + if (node.getNodeName().equalsIgnoreCase(MODEL_VER)) { + model.setModelVer(node); + if ( (model.getModelNamespace() != null) && (!model.getModelNamespace().isEmpty()) ) { + Element e = (Element) node; + e.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns", model.getModelNamespace()); + } + } + + NodeList nodeList = node.getChildNodes(); + + for (int i = 0; i < nodeList.getLength(); i++) { + Node childNode = nodeList.item(i); + parseNode(childNode, model); + } + } + } + + private String parseRelationshipNode(Node node, ModelArtifact model) { + String currentKey = null; + String currentValue = null; + String modelVersionIdValue = null; + String modelInvariantIdValue = null; + + NodeList nodeList = node.getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node childNode = nodeList.item(i); + + if (childNode.getNodeName().equalsIgnoreCase(RELATIONSHIP_DATA)) { + NodeList relDataChildList = childNode.getChildNodes(); + + for (int j = 0; j < relDataChildList.getLength(); j++) { + Node relDataChildNode = relDataChildList.item(j); + + if (relDataChildNode.getNodeName().equalsIgnoreCase(RELATIONSHIP_KEY)) { + currentKey = relDataChildNode.getTextContent().trim(); + + if (currentValue != null) { + if (currentKey.equalsIgnoreCase(MODEL_VER_ELEMENT_RELATIONSHIP_KEY)) { + modelVersionIdValue = currentValue; + } + else if (currentKey.equalsIgnoreCase(MODEL_ELEMENT_RELATIONSHIP_KEY)) { + modelInvariantIdValue = currentValue; + } + + currentKey = null; + currentValue = null; + } + } + else if (relDataChildNode.getNodeName().equalsIgnoreCase(RELATIONSHIP_VALUE)) { + currentValue = relDataChildNode.getTextContent().trim(); + + if (currentKey != null) { + if (currentKey.equalsIgnoreCase(MODEL_VER_ELEMENT_RELATIONSHIP_KEY)) { + modelVersionIdValue = currentValue; + } + else if (currentKey.equalsIgnoreCase(MODEL_ELEMENT_RELATIONSHIP_KEY)) { + modelInvariantIdValue = currentValue; + } + + currentKey = null; + currentValue = null; + } + } + } + } + } + + if ( (modelVersionIdValue != null) && (modelInvariantIdValue != null) ) { + return modelInvariantIdValue + "|" + modelVersionIdValue; + } + + return null; + + } + } diff --git a/src/main/java/org/openecomp/modelloader/entity/model/ModelParserFactory.java b/src/main/java/org/openecomp/modelloader/entity/model/ModelParserFactory.java new file mode 100644 index 0000000..aa3283f --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/entity/model/ModelParserFactory.java @@ -0,0 +1,87 @@ +/** + * ============LICENSE_START======================================================= + * Model Loader + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ +package org.openecomp.modelloader.entity.model; + +import java.io.StringReader; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.openecomp.cl.api.Logger; +import org.openecomp.cl.eelf.LoggerFactory; +import org.openecomp.modelloader.service.ModelLoaderMsgs; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.InputSource; + +public class ModelParserFactory { + private static Logger logger = LoggerFactory.getInstance().getLogger(ModelParserFactory.class.getName()); + + private static String MODEL_ELEMENT = "model"; + private static String NAMED_QUERY_ELEMENT = "named-query"; + + public static IModelParser createModelParser(byte[] artifactPayload, String artifactName) { + Document doc = null; + + try { + String payload = new String(artifactPayload); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder; + builder = factory.newDocumentBuilder(); + InputSource is = new InputSource(new StringReader(payload)); + doc = builder.parse(is); + } catch (Exception e) { + logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, "Unable to parse artifact " + artifactName); + return null; + } + + if (doc.getDocumentElement().getNodeName().equalsIgnoreCase(NAMED_QUERY_ELEMENT)) { + return new NamedQueryArtifactParser(); + } + + if (!doc.getDocumentElement().getNodeName().equalsIgnoreCase(MODEL_ELEMENT)) { + logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, "Unable to parse artifact " + artifactName + + ": Invalid root element: " + doc.getDocumentElement().getNodeName()); + return null; + } + + Element e = doc.getDocumentElement(); + String ns = e.getAttribute("xmlns"); + String[] parts = ns.split("/"); + + if (parts.length < 1) { + logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, "Unable to parse artifact " + artifactName + + ": Could not parse namespace version"); + return null; + } + + String modelNamespaceVersion = parts[parts.length-1].trim().replace("v", ""); + int version = Integer.parseInt(modelNamespaceVersion); + + if (version > 8) { + return new ModelArtifactParser(); + } + + return new ModelV8ArtifactParser(); + } +} diff --git a/src/main/java/org/openecomp/modelloader/entity/model/ModelSorter.java b/src/main/java/org/openecomp/modelloader/entity/model/ModelSorter.java index 4dcda71..274b18f 100644 --- a/src/main/java/org/openecomp/modelloader/entity/model/ModelSorter.java +++ b/src/main/java/org/openecomp/modelloader/entity/model/ModelSorter.java @@ -1,23 +1,25 @@ -/*- +/** * ============LICENSE_START======================================================= - * MODEL LOADER SERVICE + * Model Loader * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============LICENSE_END========================================================= + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. */ - package org.openecomp.modelloader.entity.model; import jline.internal.Log; @@ -42,11 +44,11 @@ public class ModelSorter { * Wraps a Model object to form dependencies other Models using Edges. */ static class Node { - private final ModelArtifact model; + private final AbstractModelArtifact model; private final HashSet<Edge> inEdges; private final HashSet<Edge> outEdges; - public Node(ModelArtifact model) { + public Node(AbstractModelArtifact model) { this.model = model; inEdges = new HashSet<Edge>(); outEdges = new HashSet<Edge>(); @@ -61,19 +63,18 @@ public class ModelSorter { @Override public String toString() { - return model.getNameVersionId(); + return model.getUniqueIdentifier(); } @Override public boolean equals(Object other) { - ModelArtifact otherModel = ((Node) other).model; - return this.model.getNameVersionId().equals(otherModel.getNameVersionId()); + AbstractModelArtifact otherModel = ((Node) other).model; + return this.model.getUniqueIdentifier().equals(otherModel.getUniqueIdentifier()); } @Override public int hashCode() { - return this.model.getNameVersionId().hashCode(); - + return this.model.getUniqueIdentifier().hashCode(); } } @@ -111,7 +112,7 @@ public class ModelSorter { Collection<Node> nodes = createNodes(originalList); Collection<Node> sortedNodes = sortNodes(nodes); - + List<Artifact> sortedModelsList = new ArrayList<Artifact>(sortedNodes.size()); for (Node node : sortedNodes) { sortedModelsList.add(node.model); @@ -131,23 +132,24 @@ public class ModelSorter { // load list of models into a map, so we can later replace referenceIds with // real Models - HashMap<String, ModelArtifact> versionIdToModelMap = new HashMap<String, ModelArtifact>(); + HashMap<String, AbstractModelArtifact> versionIdToModelMap = new HashMap<String, AbstractModelArtifact>(); for (Artifact art : models) { - ModelArtifact ma = (ModelArtifact) art; - versionIdToModelMap.put(ma.getNameVersionId(), ma); + AbstractModelArtifact ma = (AbstractModelArtifact) art; + versionIdToModelMap.put(ma.getUniqueIdentifier(), ma); } HashMap<String, Node> nodes = new HashMap<String, Node>(); // create a node for each model and its referenced models for (Artifact art : models) { - ModelArtifact model = (ModelArtifact) art; + AbstractModelArtifact model = (AbstractModelArtifact) art; + // node might have been created by another model referencing it - Node node = nodes.get(model.getNameVersionId()); + Node node = nodes.get(model.getUniqueIdentifier()); if (null == node) { node = new Node(model); - nodes.put(model.getNameVersionId(), node); + nodes.put(model.getUniqueIdentifier(), node); } for (String referencedModelId : model.getDependentModelIds()) { @@ -156,7 +158,7 @@ public class ModelSorter { if (null == referencedNode) { // create node - ModelArtifact referencedModel = versionIdToModelMap.get(referencedModelId); + AbstractModelArtifact referencedModel = versionIdToModelMap.get(referencedModelId); if (referencedModel == null) { Log.debug("ignoring " + referencedModelId); continue; // referenced model not supplied, no need to sort it @@ -179,7 +181,6 @@ public class ModelSorter { * @return a sorted collection of the given nodes */ private Collection<Node> sortNodes(Collection<Node> unsortedNodes) { - // L <- Empty list that will contain the sorted elements ArrayList<Node> nodeList = new ArrayList<Node>(); @@ -230,4 +231,5 @@ public class ModelSorter { return nodeList; } + } diff --git a/src/main/java/org/openecomp/modelloader/entity/model/ModelV8Artifact.java b/src/main/java/org/openecomp/modelloader/entity/model/ModelV8Artifact.java new file mode 100644 index 0000000..847f880 --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/entity/model/ModelV8Artifact.java @@ -0,0 +1,122 @@ +/** + * ============LICENSE_START======================================================= + * Model Loader + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ +package org.openecomp.modelloader.entity.model; + +import java.util.List; + +import javax.ws.rs.core.Response; + +import org.openecomp.cl.api.Logger; +import org.openecomp.cl.eelf.LoggerFactory; +import org.openecomp.modelloader.config.ModelLoaderConfig; +import org.openecomp.modelloader.entity.Artifact; +import org.openecomp.modelloader.entity.ArtifactType; +import org.openecomp.modelloader.restclient.AaiRestClient; +import org.openecomp.modelloader.service.ModelLoaderMsgs; + +import com.sun.jersey.api.client.ClientResponse; + +public class ModelV8Artifact extends AbstractModelArtifact { + private static String AAI_CONVERSION_URL = "/aai/tools/modeltransform"; + + private static Logger logger = LoggerFactory.getInstance().getLogger(ModelArtifact.class.getName()); + + private String modelNameVersionId; + private ModelArtifact translatedModel; + + public ModelV8Artifact() { + super(ArtifactType.MODEL_V8); + } + + public String getModelNameVersionId() { + return modelNameVersionId; + } + + public void setModelNameVersionId(String modelNameVersionId) { + this.modelNameVersionId = modelNameVersionId; + } + + @Override + public String getUniqueIdentifier() { + return getModelNameVersionId(); + } + + @Override + public boolean push(AaiRestClient aaiClient, ModelLoaderConfig config, String distId, List<AbstractModelArtifact> addedModels) { + // For a legacy model (version <= v8), we need to call out to an A&AI endpoint to convert to the proper format + ClientResponse response = aaiClient.postResource(getConversionUrl(config), constructTransformPayload(), distId, AaiRestClient.MimeType.XML); + if ( (response == null) || (response.getStatus() != Response.Status.OK.getStatusCode()) ) { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, "Ingestion failed for " + + getType().toString() + " " + getModelNameVersionId() + ". Unable to convert model. Rolling back distribution."); + return false; + } + + String translatedPayload = response.getEntity(String.class); + + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Translated artifact payload:\n" + translatedPayload); + + ModelArtifactParser parser = new ModelArtifactParser(); + + List<Artifact> parsedArtifacts = parser.parse(translatedPayload.getBytes(), "translated-payload"); + if (parsedArtifacts == null || parsedArtifacts.isEmpty()) { + return false; + } + + translatedModel = (ModelArtifact)parsedArtifacts.get(0); + return translatedModel.push(aaiClient, config, distId, addedModels); + } + + @Override + public void rollbackModel(AaiRestClient aaiClient, ModelLoaderConfig config, String distId) { + if (translatedModel != null) { + translatedModel.rollbackModel(aaiClient, config, distId); + } + } + + + private String constructTransformPayload() { + // A&AI requires that to transform a legacy model, we need to use the v8 namespace (even + // if the version < 8) + return getPayload().replaceFirst("aai.inventory/v.", "aai.inventory/v8"); + } + + private String getConversionUrl(ModelLoaderConfig config) { + String baseUrl = config.getAaiBaseUrl().trim(); + String subUrl = AAI_CONVERSION_URL; + + if ( (!baseUrl.endsWith("/")) && (!subUrl.startsWith("/")) ) { + baseUrl = baseUrl + "/"; + } + + if ( baseUrl.endsWith("/") && subUrl.startsWith("/") ) { + baseUrl = baseUrl.substring(0, baseUrl.length()-1); + } + + if (!subUrl.endsWith("/")) { + subUrl = subUrl + "/"; + } + + String url = baseUrl + subUrl; + return url; + } +} diff --git a/src/main/java/org/openecomp/modelloader/entity/model/ModelV8ArtifactParser.java b/src/main/java/org/openecomp/modelloader/entity/model/ModelV8ArtifactParser.java new file mode 100644 index 0000000..f5ecb2b --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/entity/model/ModelV8ArtifactParser.java @@ -0,0 +1,136 @@ +/** + * ============LICENSE_START======================================================= + * Model Loader + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ +package org.openecomp.modelloader.entity.model; + +import org.openecomp.cl.api.Logger; +import org.openecomp.cl.eelf.LoggerFactory; +import org.openecomp.modelloader.entity.Artifact; +import org.openecomp.modelloader.service.ModelLoaderMsgs; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + + +public class ModelV8ArtifactParser implements IModelParser { + + private static String MODEL_NAME_VERSION_ID = "model-name-version-id"; + private static String RELATIONSHIP_DATA = "relationship-data"; + private static String RELATIONSHIP_KEY = "relationship-key"; + private static String RELATIONSHIP_VALUE = "relationship-value"; + private static String MODEL_ELEMENT_RELATIONSHIP_KEY = "model.model-name-version-id"; + + + private static Logger logger = LoggerFactory.getInstance().getLogger(ModelV8ArtifactParser.class.getName()); + + public List<Artifact> parse(byte[] artifactPayload, String artifactName) { + String payload = new String(artifactPayload); + List<Artifact> modelList = new ArrayList<Artifact>(); + + try { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + InputSource is = new InputSource(new StringReader(payload)); + Document doc = builder.parse(is); + + ModelV8Artifact model = parseModel(doc.getDocumentElement(), payload); + + if (model != null) { + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Model parsed =====>>>> " + "Model-Named-Version-Id: "+ model.getModelNameVersionId()); + modelList.add(model); + } + else { + logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, "Unable to parse legacy model artifact " + artifactName); + return null; + } + } + catch (Exception ex) { + logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, "Unable to parse legacy model artifact " + artifactName + ": " + ex.getLocalizedMessage()); + } + + return modelList; + } + + private ModelV8Artifact parseModel(Node modelNode, String payload) { + ModelV8Artifact model = new ModelV8Artifact(); + model.setPayload(payload); + + Element e = (Element)modelNode; + model.setModelNamespace(e.getAttribute("xmlns")); + + parseNode(modelNode, model); + + if (model.getModelNameVersionId() == null) { + return null; + } + + return model; + } + + private void parseNode(Node node, ModelV8Artifact model) { + if (node.getNodeName().equalsIgnoreCase(MODEL_NAME_VERSION_ID)) { + model.setModelNameVersionId(node.getTextContent().trim()); + } + else if (node.getNodeName().equalsIgnoreCase(RELATIONSHIP_DATA)) { + parseRelationshipNode(node, model); + } + else { + NodeList nodeList = node.getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node childNode = nodeList.item(i); + parseNode(childNode, model); + } + } + } + + private void parseRelationshipNode(Node node, ModelV8Artifact model) { + String key = null; + String value = null; + + NodeList nodeList = node.getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node childNode = nodeList.item(i); + if (childNode.getNodeName().equalsIgnoreCase(RELATIONSHIP_KEY)) { + key = childNode.getTextContent().trim(); + } + else if (childNode.getNodeName().equalsIgnoreCase(RELATIONSHIP_VALUE)) { + value = childNode.getTextContent().trim(); + } + } + + if ( (key != null) && (key.equalsIgnoreCase(MODEL_ELEMENT_RELATIONSHIP_KEY )) ) { + if (value != null) { + model.addDependentModelId(value); + } + } + } +} diff --git a/src/main/java/org/openecomp/modelloader/entity/model/NamedQueryArtifact.java b/src/main/java/org/openecomp/modelloader/entity/model/NamedQueryArtifact.java new file mode 100644 index 0000000..1a4ceaa --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/entity/model/NamedQueryArtifact.java @@ -0,0 +1,113 @@ +/** + * ============LICENSE_START======================================================= + * Model Loader + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ +package org.openecomp.modelloader.entity.model; + +import java.util.List; + +import javax.ws.rs.core.Response; + +import org.openecomp.cl.api.Logger; +import org.openecomp.cl.eelf.LoggerFactory; +import org.openecomp.modelloader.config.ModelLoaderConfig; +import org.openecomp.modelloader.entity.ArtifactType; +import org.openecomp.modelloader.restclient.AaiRestClient; +import org.openecomp.modelloader.service.ModelLoaderMsgs; + +import com.sun.jersey.api.client.ClientResponse; + +public class NamedQueryArtifact extends AbstractModelArtifact { + + private Logger logger = LoggerFactory.getInstance().getLogger(NamedQueryArtifact.class.getName()); + + private String namedQueryUuid; + + public NamedQueryArtifact() { + super(ArtifactType.NAMED_QUERY); + } + + public String getNamedQueryUuid() { + return namedQueryUuid; + } + + public void setNamedQueryUuid(String namedQueryUuid) { + this.namedQueryUuid = namedQueryUuid; + } + + @Override + public String getUniqueIdentifier() { + return getNamedQueryUuid(); + } + + @Override + public boolean push(AaiRestClient aaiClient, ModelLoaderConfig config, String distId, List<AbstractModelArtifact> addedModels) { + ClientResponse getResponse = aaiClient.getResource(getNamedQueryUrl(config), distId, AaiRestClient.MimeType.XML); + if ( (getResponse == null) || (getResponse.getStatus() != Response.Status.OK.getStatusCode()) ) { + // Only attempt the PUT if the model doesn't already exist + ClientResponse putResponse = aaiClient.putResource(getNamedQueryUrl(config), getPayload(), distId, AaiRestClient.MimeType.XML); + if ( (putResponse != null) && (putResponse.getStatus() == Response.Status.CREATED.getStatusCode()) ) { + addedModels.add(this); + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, getType().toString() + " " + getUniqueIdentifier() + " successfully ingested."); + } + else { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, "Ingestion failed for " + getType().toString() + " " + getUniqueIdentifier() + + ". Rolling back distribution."); + return false; + } + } + else { + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, getType().toString() + " " + getUniqueIdentifier() + " already exists. Skipping ingestion."); + } + + return true; + } + + @Override + public void rollbackModel(AaiRestClient aaiClient, ModelLoaderConfig config, String distId) { + // Best effort to delete. Nothing we can do in the event this fails. + aaiClient.getAndDeleteResource(getNamedQueryUrl(config), distId); + } + + private String getNamedQueryUrl(ModelLoaderConfig config) { + String baseURL = config.getAaiBaseUrl().trim(); + String subURL = null; + String instance = null; + + subURL = config.getAaiNamedQueryUrl(getModelNamespaceVersion()).trim(); + instance = this.getNamedQueryUuid(); + + if ( (!baseURL.endsWith("/")) && (!subURL.startsWith("/")) ) { + baseURL = baseURL + "/"; + } + + if ( baseURL.endsWith("/") && subURL.startsWith("/") ) { + baseURL = baseURL.substring(0, baseURL.length()-1); + } + + if (!subURL.endsWith("/")) { + subURL = subURL + "/"; + } + + String url = baseURL + subURL + instance; + return url; + } +} diff --git a/src/main/java/org/openecomp/modelloader/entity/model/NamedQueryArtifactParser.java b/src/main/java/org/openecomp/modelloader/entity/model/NamedQueryArtifactParser.java new file mode 100644 index 0000000..3643f18 --- /dev/null +++ b/src/main/java/org/openecomp/modelloader/entity/model/NamedQueryArtifactParser.java @@ -0,0 +1,136 @@ +/** + * ============LICENSE_START======================================================= + * Model Loader + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ +package org.openecomp.modelloader.entity.model; + +import org.openecomp.cl.api.Logger; +import org.openecomp.cl.eelf.LoggerFactory; +import org.openecomp.modelloader.entity.Artifact; +import org.openecomp.modelloader.service.ModelLoaderMsgs; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + + +public class NamedQueryArtifactParser implements IModelParser { + + private static String NAMED_QUERY_VERSION_ID = "named-query-uuid"; + private static String RELATIONSHIP_DATA = "relationship-data"; + private static String RELATIONSHIP_KEY = "relationship-key"; + private static String RELATIONSHIP_VALUE = "relationship-value"; + private static String MODEL_ELEMENT_RELATIONSHIP_KEY = "model.model-invariant-id"; + + + private static Logger logger = LoggerFactory.getInstance().getLogger(NamedQueryArtifactParser.class.getName()); + + public List<Artifact> parse(byte[] artifactPayload, String artifactName) { + String payload = new String(artifactPayload); + List<Artifact> modelList = new ArrayList<Artifact>(); + + try { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + InputSource is = new InputSource(new StringReader(payload)); + Document doc = builder.parse(is); + + NamedQueryArtifact model = parseModel(doc.getDocumentElement(), payload); + + if (model != null) { + logger.info(ModelLoaderMsgs.DISTRIBUTION_EVENT, "Named-Query parsed =====>>>> " + "Named-Query-UUID: "+ model.getNamedQueryUuid()); + modelList.add(model); + } + else { + logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, "Unable to parse named-query artifact " + artifactName); + return null; + } + } + catch (Exception ex) { + logger.error(ModelLoaderMsgs.ARTIFACT_PARSE_ERROR, "Unable to parse named-query artifact " + artifactName + ": " + ex.getLocalizedMessage()); + } + + return modelList; + } + + private NamedQueryArtifact parseModel(Node modelNode, String payload) { + NamedQueryArtifact model = new NamedQueryArtifact(); + model.setPayload(payload); + + Element e = (Element)modelNode; + model.setModelNamespace(e.getAttribute("xmlns")); + + parseNode(modelNode, model); + + if (model.getNamedQueryUuid() == null) { + return null; + } + + return model; + } + + private void parseNode(Node node, NamedQueryArtifact model) { + if (node.getNodeName().equalsIgnoreCase(NAMED_QUERY_VERSION_ID)) { + model.setNamedQueryUuid(node.getTextContent().trim()); + } + else if (node.getNodeName().equalsIgnoreCase(RELATIONSHIP_DATA)) { + parseRelationshipNode(node, model); + } + else { + NodeList nodeList = node.getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node childNode = nodeList.item(i); + parseNode(childNode, model); + } + } + } + + private void parseRelationshipNode(Node node, NamedQueryArtifact model) { + String key = null; + String value = null; + + NodeList nodeList = node.getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node childNode = nodeList.item(i); + if (childNode.getNodeName().equalsIgnoreCase(RELATIONSHIP_KEY)) { + key = childNode.getTextContent().trim(); + } + else if (childNode.getNodeName().equalsIgnoreCase(RELATIONSHIP_VALUE)) { + value = childNode.getTextContent().trim(); + } + } + + if ( (key != null) && (key.equalsIgnoreCase(MODEL_ELEMENT_RELATIONSHIP_KEY )) ) { + if (value != null) { + model.addDependentModelId(value); + } + } + } +} |