X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Forg%2Fonap%2Faai%2Fmodelloader%2Futil%2FGizmoTranslator.java;fp=src%2Fmain%2Fjava%2Forg%2Fonap%2Faai%2Fmodelloader%2Futil%2FGizmoTranslator.java;h=69e59719a8ebc90f8d11c6acace37262f72c5e8d;hb=270656abb1ed24930b2f9e57f5bef659494f5e8e;hp=0000000000000000000000000000000000000000;hpb=5209f42102348d19a389017c1717f0edc3733b36;p=aai%2Fmodel-loader.git diff --git a/src/main/java/org/onap/aai/modelloader/util/GizmoTranslator.java b/src/main/java/org/onap/aai/modelloader/util/GizmoTranslator.java new file mode 100644 index 0000000..69e5971 --- /dev/null +++ b/src/main/java/org/onap/aai/modelloader/util/GizmoTranslator.java @@ -0,0 +1,288 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + */ +package org.onap.aai.modelloader.util; + +import java.io.IOException; +import java.io.StringReader; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.modelloader.gizmo.GizmoBulkPayload; +import org.onap.aai.modelloader.gizmo.GizmoEdge; +import org.onap.aai.modelloader.gizmo.GizmoEdgeOperation; +import org.onap.aai.modelloader.gizmo.GizmoVertex; +import org.onap.aai.modelloader.gizmo.GizmoVertexOperation; +import org.onap.aai.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 org.xml.sax.SAXException; + +public class GizmoTranslator { + + private enum NodeType { + VERTEX, + ATTRIBUTE, + CONTAINER, + RELATIONSHIP_LIST, + RELATIONSHIP, + RELATED_TO, + RELATIONSHIP_DATA, + RELATIONSHIP_KEY, + RELATIONSHIP_VALUE, + MODEL_ELEMENT_VERTEX, + NQ_ELEMENT_VERTEX, + UNKNOWN + } + + private static Logger logger = LoggerFactory.getInstance().getLogger(GizmoTranslator.class.getName()); + + public static String translate(String xmlPayload) throws ParserConfigurationException, SAXException, IOException { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + DocumentBuilder builder = factory.newDocumentBuilder(); + InputSource is = new InputSource(new StringReader(xmlPayload)); + Document doc = builder.parse(is); + + GizmoBulkPayload gizmoPayload = new GizmoBulkPayload(); + + processNode(doc.getDocumentElement(), null, null, gizmoPayload); + + return gizmoPayload.toJson(); + } + + private static void processNode(Node node, Node parentNode, GizmoVertexOperation parentVertexOp, GizmoBulkPayload gizmoPayload) { + if (!(node instanceof Element)) { + return; + } + + Node newParent = null; + NodeType nodeType = getNodeType(node); + + switch (nodeType) { + case VERTEX: + case MODEL_ELEMENT_VERTEX: + case NQ_ELEMENT_VERTEX: + parentVertexOp = createGizmoVertexOp(node, GizmoBulkPayload.ADD_OP); + gizmoPayload.addVertexOperation(parentVertexOp); + if (parentNode != null) { + gizmoPayload.addEdgeOperation(createGizmoEdgeOp(node, parentNode)); + } + newParent = node; + break; + case RELATIONSHIP: + processRelationship((Element)node, parentVertexOp, gizmoPayload); + newParent = parentNode; + break; + default: + newParent = parentNode; + break; + } + + NodeList childNodes = node.getChildNodes(); + for (int ix = 0; ix < childNodes.getLength(); ix++) { + processNode(childNodes.item(ix), newParent, parentVertexOp, gizmoPayload); + } + } + + private static void processRelationship(Element relationshipNode, GizmoVertexOperation sourceNode, GizmoBulkPayload gizmoPayload) { + NodeList relatedToList = relationshipNode.getElementsByTagName("related-to"); + if (relatedToList.getLength() != 1) { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, "Unable to resolve relationship"); + return; + } + + GizmoVertex targetVertex = new GizmoVertex(); + targetVertex.setType(relatedToList.item(0).getTextContent().trim()); + + NodeList relationData = relationshipNode.getElementsByTagName("relationship-data"); + for (int ix = 0; ix < relationData.getLength(); ix++) { + Element relationNode = (Element)relationData.item(ix); + NodeList keyList = relationNode.getElementsByTagName("relationship-key"); + NodeList valueList = relationNode.getElementsByTagName("relationship-value"); + + if ( (keyList.getLength() != 1) || (valueList.getLength() != 1) ) { + logger.error(ModelLoaderMsgs.DISTRIBUTION_EVENT_ERROR, "Unable to resolve relationship. Missing key/value."); + return; + } + + String[] keyBits = keyList.item(0).getTextContent().trim().split("\\."); + String value = valueList.item(0).getTextContent().trim(); + + if (keyBits[0].equalsIgnoreCase(targetVertex.getType())) { + targetVertex.setProperty(keyBits[1], value); + } + } + + gizmoPayload.addVertexOperation(new GizmoVertexOperation(GizmoBulkPayload.EXISTS_OP, getVertexId(targetVertex), targetVertex)); + + GizmoEdge edge = new GizmoEdge(); + + edge.setSource("$" + getVertexId(sourceNode.getVertex())); + edge.setTarget("$" + getVertexId(targetVertex)); + + gizmoPayload.addEdgeOperation(new GizmoEdgeOperation(GizmoBulkPayload.ADD_OP, edge.getSource() + "_" + edge.getTarget(), edge)); + } + + private static GizmoEdgeOperation createGizmoEdgeOp(Node node, Node parentNode) { + GizmoEdge edge = new GizmoEdge(); + + edge.setSource("$" + getVertexId(createGizmoVertex(node))); + edge.setTarget("$" + getVertexId(createGizmoVertex(parentNode))); + + GizmoEdgeOperation edgeOp = new GizmoEdgeOperation(GizmoBulkPayload.ADD_OP, edge.getSource() + "_" + edge.getTarget(), edge); + + return edgeOp; + } + + private static GizmoVertexOperation createGizmoVertexOp(Node node, String operationType) { + GizmoVertex vertex = createGizmoVertex(node); + GizmoVertexOperation addOp = new GizmoVertexOperation(operationType, getVertexId(vertex), vertex); + return addOp; + } + + private static String getVertexId(GizmoVertex vertex) { + StringBuilder sb = new StringBuilder(); + sb.append(vertex.getType()); + for (Map.Entry entry : vertex.getProperties().entrySet()) { + sb.append("-" + entry.getValue()); + } + + return sb.toString(); + } + + private static GizmoVertex createGizmoVertex(Node node) { + GizmoVertex vertex = new GizmoVertex(); + vertex.setType(node.getNodeName().trim()); + + NodeList childNodes = node.getChildNodes(); + + for (int ix = 0; ix < childNodes.getLength(); ix++) { + if (getNodeType(childNodes.item(ix)).equals(NodeType.ATTRIBUTE)) { + vertex.setProperty(childNodes.item(ix).getNodeName().trim(), childNodes.item(ix).getTextContent().trim()); + } + } + + // Special case for model-element, where we need to generate an id field + if (getNodeType(node).equals(NodeType.MODEL_ELEMENT_VERTEX)) { + vertex.setProperty("model-element-uuid", generateModelElementId((Element)node)); + } + + // Special case for nq-element, where we need to generate an id field + if (getNodeType(node).equals(NodeType.NQ_ELEMENT_VERTEX)) { + vertex.setProperty("named-query-element-uuid", generateModelElementId((Element)node)); + } + + return vertex; + } + + // Generate a unique hash to store as the id for this node + private static String generateModelElementId(Element node) { + Set elemSet = new HashSet(); + + NodeList childNodes = node.getElementsByTagName("*"); + for (int ix = 0; ix < childNodes.getLength(); ix++) { + NodeType nt = getNodeType(childNodes.item(ix)); + if ( nt.equals(NodeType.ATTRIBUTE) || nt.equals(NodeType.RELATIONSHIP_KEY) || nt.equals(NodeType.RELATIONSHIP_VALUE) ) { + elemSet.add(childNodes.item(ix).getTextContent().trim()); + } + } + + return Integer.toString(elemSet.hashCode()); + } + + private static NodeType getNodeType(Node node) { + if (!(node instanceof Element)) { + return NodeType.UNKNOWN; + } + + if (node.getNodeName().equalsIgnoreCase("relationship-list")) { + return NodeType.RELATIONSHIP_LIST; + } + + if (node.getNodeName().equalsIgnoreCase("relationship")) { + return NodeType.RELATIONSHIP; + } + + if (node.getNodeName().equalsIgnoreCase("relationship-data")) { + return NodeType.RELATIONSHIP_DATA; + } + + if (node.getNodeName().equalsIgnoreCase("related-to")) { + return NodeType.RELATED_TO; + } + + if (node.getNodeName().equalsIgnoreCase("relationship-key")) { + return NodeType.RELATIONSHIP_KEY; + } + + if (node.getNodeName().equalsIgnoreCase("relationship-value")) { + return NodeType.RELATIONSHIP_VALUE; + } + + if (node.getNodeName().equalsIgnoreCase("model-element")) { + return NodeType.MODEL_ELEMENT_VERTEX; + } + + if (node.getNodeName().equalsIgnoreCase("named-query-element")) { + return NodeType.NQ_ELEMENT_VERTEX; + } + + NodeList childNodes = node.getChildNodes(); + int childElements = countChildElements(childNodes); + + if ( (childElements == 0) && (node.getTextContent() != null) && (!node.getTextContent().trim().isEmpty()) ) { + return NodeType.ATTRIBUTE; + } + + for (int ix = 0; ix < childNodes.getLength(); ix++) { + if (getNodeType(childNodes.item(ix)) == NodeType.ATTRIBUTE) { + return NodeType.VERTEX; + } + } + + if (childElements > 0) { + return NodeType.CONTAINER; + } + + return NodeType.UNKNOWN; + } + + static int countChildElements(NodeList nodes) { + int count = 0; + for (int ix = 0; ix < nodes.getLength(); ix++) { + if (nodes.item(ix) instanceof Element) { + count++; + } + } + + return count; + } +}