2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
20 package org.onap.aai.util.genxsd;
23 import java.io.FileNotFoundException;
24 import java.io.IOException;
25 import java.io.StringReader;
26 import java.io.StringWriter;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.HashMap;
30 import java.util.HashSet;
31 import java.util.List;
35 import javax.xml.XMLConstants;
36 import javax.xml.parsers.DocumentBuilder;
37 import javax.xml.parsers.DocumentBuilderFactory;
38 import javax.xml.parsers.ParserConfigurationException;
39 import javax.xml.transform.OutputKeys;
40 import javax.xml.transform.Transformer;
41 import javax.xml.transform.TransformerException;
42 import javax.xml.transform.TransformerFactory;
43 import javax.xml.transform.dom.DOMSource;
44 import javax.xml.transform.stream.StreamResult;
47 import org.onap.aai.edges.EdgeIngestor;
48 import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException;
49 import org.onap.aai.exceptions.AAIException;
51 import org.onap.aai.setup.SchemaVersion;
52 import org.onap.aai.setup.SchemaVersions;
53 import org.onap.aai.nodes.NodeIngestor;
54 import org.w3c.dom.Attr;
55 import org.w3c.dom.Document;
56 import org.w3c.dom.Element;
57 import org.w3c.dom.NamedNodeMap;
58 import org.w3c.dom.Node;
59 import org.w3c.dom.NodeList;
60 import org.xml.sax.SAXException;
62 import org.xml.sax.InputSource;
64 public abstract class OxmFileProcessor {
66 public static final String LINE_SEPARATOR = System.getProperty("line.separator");
67 public static final String DOUBLE_LINE_SEPARATOR = System.getProperty("line.separator") + System.getProperty("line.separator");
71 protected Set<String> namespaceFilter;
72 protected File oxmFile;
74 protected SchemaVersion v;
75 protected Document doc = null;
76 protected String apiVersion = null;
77 protected SchemaVersions schemaVersions;
79 protected Map combinedJavaTypes;
82 protected static int annotationsStartVersion = 9; // minimum version to support annotations in xsd
83 protected static int annotationsMinVersion = 6; // lower versions support annotations in xsd
84 protected static int swaggerSupportStartsVersion = 1; // minimum version to support swagger documentation
85 protected static int swaggerDiffStartVersion = 1; // minimum version to support difference
86 protected static int swaggerMinBasepath = 6; // minimum version to support difference
89 protected String apiVersionFmt = null;
90 protected HashMap<String, String> generatedJavaType = new HashMap<String, String>();
91 protected HashMap<String, String> appliedPaths = new HashMap<String, String>();
92 protected NodeList javaTypeNodes = null;
94 protected Map<String,String> javaTypeDefinitions = createJavaTypeDefinitions();
95 private Map<String, String> createJavaTypeDefinitions()
97 StringBuffer aaiInternal = new StringBuffer();
98 StringBuffer nodes = new StringBuffer();
99 Map<String,String> javaTypeDefinitions = new HashMap<String, String>();
100 aaiInternal.append(" aai-internal:\n");
101 aaiInternal.append(" properties:\n");
102 aaiInternal.append(" property-name:\n");
103 aaiInternal.append(" type: string\n");
104 aaiInternal.append(" property-value:\n");
105 aaiInternal.append(" type: string\n");
106 // javaTypeDefinitions.put("aai-internal", aaiInternal.toString());
107 nodes.append(" nodes:\n");
108 nodes.append(" properties:\n");
109 nodes.append(" inventory-item-data:\n");
110 nodes.append(" type: array\n");
111 nodes.append(" items:\n");
112 nodes.append(" $ref: \"#/definitions/inventory-item-data\"\n");
113 javaTypeDefinitions.put("nodes", nodes.toString());
114 return javaTypeDefinitions;
116 static List<String> nodeFilter = createNodeFilter();
117 private static List<String> createNodeFilter()
119 List<String> list = Arrays.asList("search", "actions", "aai-internal", "nodes");
123 public OxmFileProcessor(SchemaVersions schemaVersions, NodeIngestor ni, EdgeIngestor ei){
124 this.schemaVersions = schemaVersions;
131 public void setOxmVersion(File oxmFile, SchemaVersion v) {
132 this.oxmFile = oxmFile;
136 public void setXmlVersion(String xml, SchemaVersion v) {
141 public void setVersion(SchemaVersion v) {
146 public void setNodeIngestor(NodeIngestor ni) {
150 public void setEdgeIngestor(EdgeIngestor ei) {
154 public SchemaVersions getSchemaVersions() {
155 return schemaVersions;
158 public void setSchemaVersions(SchemaVersions schemaVersions) {
159 this.schemaVersions = schemaVersions;
162 protected void init() throws ParserConfigurationException, SAXException, IOException, AAIException, EdgeRuleNotFoundException {
163 if(this.xml != null || this.oxmFile != null ) {
166 if(this.doc == null) {
167 this.doc = ni.getSchema(v);
169 namespaceFilter = new HashSet<>();
171 NodeList bindingsNodes = doc.getElementsByTagName("xml-bindings");
172 Element bindingElement;
173 NodeList javaTypesNodes;
174 Element javaTypesElement;
176 if ( bindingsNodes == null || bindingsNodes.getLength() == 0 ) {
177 throw new AAIException("OXM file error: missing <binding-nodes> in " + oxmFile);
180 bindingElement = (Element) bindingsNodes.item(0);
181 javaTypesNodes = bindingElement.getElementsByTagName("java-types");
182 if ( javaTypesNodes.getLength() < 1 ) {
183 throw new AAIException("OXM file error: missing <binding-nodes><java-types> in " + oxmFile);
185 javaTypesElement = (Element) javaTypesNodes.item(0);
187 javaTypeNodes = javaTypesElement.getElementsByTagName("java-type");
188 if ( javaTypeNodes.getLength() < 1 ) {
189 throw new AAIException("OXM file error: missing <binding-nodes><java-types><java-type> in " + oxmFile );
193 private void createDocument() throws ParserConfigurationException, SAXException, IOException, AAIException {
194 DocumentBuilder dBuilder = null;
196 DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
197 dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
198 dBuilder = dbFactory.newDocumentBuilder();
199 } catch (ParserConfigurationException e) {
204 doc = dBuilder.parse(oxmFile);
206 InputSource isInput = new InputSource(new StringReader(xml));
207 doc = dBuilder.parse(isInput);
209 } catch (SAXException e) {
211 } catch (IOException e) {
216 public abstract String getDocumentHeader();
217 public abstract String process() throws ParserConfigurationException, SAXException, IOException, AAIException, FileNotFoundException, EdgeRuleNotFoundException ;
219 public String getXMLRootElementName(Element javaTypeElement) {
220 String xmlRootElementName=null;
221 NamedNodeMap attributes;
223 NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
224 Element valElement = (Element) valNodes.item(0);
225 attributes = valElement.getAttributes();
226 for ( int i = 0; i < attributes.getLength(); ++i ) {
227 Attr attr = (Attr) attributes.item(i);
228 String attrName = attr.getNodeName();
230 String attrValue = attr.getNodeValue();
231 if ( attrName.equals("name"))
232 xmlRootElementName = attrValue;
234 return xmlRootElementName;
237 public String getXmlRootElementName( String javaTypeName )
239 String attrName, attrValue;
241 Element javaTypeElement;
242 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
243 javaTypeElement = (Element) javaTypeNodes.item(i);
244 NamedNodeMap attributes = javaTypeElement.getAttributes();
245 for ( int j = 0; j < attributes.getLength(); ++j ) {
246 attr = (Attr) attributes.item(j);
247 attrName = attr.getNodeName();
248 attrValue = attr.getNodeValue();
249 if ( attrName.equals("name") && attrValue.equals(javaTypeName)) {
250 NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
251 Element valElement = (Element) valNodes.item(0);
252 attributes = valElement.getAttributes();
253 for ( int k = 0; k < attributes.getLength(); ++k ) {
254 attr = (Attr) attributes.item(k);
255 attrName = attr.getNodeName();
257 attrValue = attr.getNodeValue();
258 if ( attrName.equals("name"))
267 public Map getCombinedJavaTypes() {
268 return combinedJavaTypes;
271 public void setCombinedJavaTypes(Map combinedJavaTypes) {
272 this.combinedJavaTypes = combinedJavaTypes;
275 public Element getJavaTypeElementSwagger( String javaTypeName )
278 String attrName, attrValue;
280 Element javaTypeElement;
282 List<Element> combineElementList = new ArrayList<Element>();
283 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
284 javaTypeElement = (Element) javaTypeNodes.item(i);
285 NamedNodeMap attributes = javaTypeElement.getAttributes();
286 for ( int j = 0; j < attributes.getLength(); ++j ) {
287 attr = (Attr) attributes.item(j);
288 attrName = attr.getNodeName();
289 attrValue = attr.getNodeValue();
290 if ( attrName.equals("name") && attrValue.equals(javaTypeName)) {
291 combineElementList.add(javaTypeElement);
295 if ( combineElementList.size() == 0 ) {
296 return (Element) null;
297 } else if ( combineElementList.size() > 1 ) {
298 // need to combine java-attributes
299 return combineElements( javaTypeName, combineElementList);
301 return combineElementList.get(0);
304 public boolean versionSupportsSwaggerDiff( String version) {
305 int ver = new Integer(version.substring(1)).intValue();
306 if ( ver >= HTMLfromOXM.swaggerDiffStartVersion ) {
312 public boolean versionSupportsBasePathProperty( String version) {
313 int ver = new Integer(version.substring(1)).intValue();
314 if ( ver <= HTMLfromOXM.swaggerMinBasepath ) {
320 protected void updateParentXmlElements(Element parentElement, NodeList moreXmlElementNodes) {
325 Node refChild = null;
326 // find childNode with attributes and no children, insert children before that node
327 childNodes = parentElement.getChildNodes();
328 if ( childNodes == null || childNodes.getLength() == 0 ) {
329 // should not happen since the base parent was chosen if it had children
333 for ( int i = 0; i < childNodes.getLength(); ++i ) {
334 refChild = childNodes.item(i);
335 if ( refChild.hasAttributes() && !refChild.hasChildNodes()) {
341 for ( int i = 0; i < moreXmlElementNodes.getLength(); ++i ) {
342 xmlElement = (Element)moreXmlElementNodes.item(i);
343 childNode = xmlElement.cloneNode(true);
344 parentElement.insertBefore(childNode, refChild);
348 protected Node getXmlPropertiesNode(Element javaTypeElement ) {
349 NodeList nl = javaTypeElement.getChildNodes();
351 for ( int i = 0; i < nl.getLength(); ++i ) {
353 if ( "xml-properties".equals(child.getNodeName())) {
360 protected Node merge( NodeList nl, Node mergeNode ) {
361 NamedNodeMap nnm = mergeNode.getAttributes();
363 NamedNodeMap childNnm;
365 String mergeName = nnm.getNamedItem("name").getNodeValue();
366 String mergeValue = nnm.getNamedItem("value").getNodeValue();
369 for ( int j = 0; j < nl.getLength(); ++j ) {
370 childNode = nl.item(j);
371 if ( "xml-property".equals(childNode.getNodeName())) {
372 childNnm = childNode.getAttributes();
373 childName = childNnm.getNamedItem("name").getNodeValue();
374 childValue = childNnm.getNamedItem("value").getNodeValue();
375 if ( childName.equals(mergeName)) {
377 // keep, replace or update
378 if ( childValue.contains(mergeValue) ) {
381 if ( mergeValue.contains(childValue) ) {
382 childNnm.getNamedItem("value").setTextContent(mergeValue);
385 childNnm.getNamedItem("value").setTextContent(mergeValue + "," + childValue);
390 childNode = mergeNode.cloneNode(true);
394 protected void mergeXmlProperties(Node useChildProperties, NodeList propertiesToMerge ) {
395 NodeList nl = useChildProperties.getChildNodes();
398 for ( int i = 0; i < propertiesToMerge.getLength(); ++i ) {
399 childNode = propertiesToMerge.item(i);
400 if ( "xml-property".equals(childNode.getNodeName()) ) {
401 newNode = merge(nl, childNode);
402 if ( newNode != null ) {
403 useChildProperties.appendChild(newNode);
410 protected void combineXmlProperties(int useElement, List<Element> combineElementList) {
411 // add or update xml-properties to the referenced element from the combined list
412 Element javaTypeElement = combineElementList.get(useElement);
413 NodeList nl = javaTypeElement.getChildNodes();
414 Node useChildProperties = getXmlPropertiesNode( javaTypeElement);
416 Node childProperties;
417 if ( useChildProperties == null ) {
418 // find xml-properties to clone
419 for ( int i = 0; i < combineElementList.size(); ++i ) {
420 if ( i == useElement ) {
423 childProperties = getXmlPropertiesNode(combineElementList.get(i));
424 if ( childProperties != null ) {
425 useChildProperties = childProperties.cloneNode(true);
426 javaTypeElement.appendChild(useChildProperties);
432 // find other xml-properties
433 for ( int i = 0; i < combineElementList.size(); ++i ) {
434 if ( i == useElement|| ( cloneChild >= 0 && i <= cloneChild )) {
437 childProperties = getXmlPropertiesNode(combineElementList.get(i));
438 if ( childProperties == null ) {
441 cnl = childProperties.getChildNodes();
442 mergeXmlProperties( useChildProperties, cnl);
447 protected Element combineElements( String javaTypeName, List<Element> combineElementList ) {
448 Element javaTypeElement;
449 NodeList parentNodes;
450 Element parentElement = null;
451 NodeList xmlElementNodes;
454 if ( combinedJavaTypes.containsKey( javaTypeName) ) {
455 return combineElementList.get((int)combinedJavaTypes.get(javaTypeName));
457 for ( int i = 0; i < combineElementList.size(); ++i ) {
458 javaTypeElement = combineElementList.get(i);
459 parentNodes = javaTypeElement.getElementsByTagName("java-attributes");
460 if ( parentNodes.getLength() == 0 ) {
463 parentElement = (Element)parentNodes.item(0);
464 xmlElementNodes = parentElement.getElementsByTagName("xml-element");
465 if ( xmlElementNodes.getLength() <= 0 ) {
471 boolean doCombineElements = true;
472 if ( useElement < 0 ) {
474 doCombineElements = false;
475 } else if ( useElement == combineElementList.size() - 1) {
476 doCombineElements = false;
478 if ( doCombineElements ) {
479 // get xml-element from other javaTypeElements
480 Element otherParentElement = null;
481 for ( int i = 0; i < combineElementList.size(); ++i ) {
482 if ( i == useElement ) {
485 javaTypeElement = combineElementList.get(i);
486 parentNodes = javaTypeElement.getElementsByTagName("java-attributes");
487 if ( parentNodes.getLength() == 0 ) {
490 otherParentElement = (Element)parentNodes.item(0);
491 xmlElementNodes = otherParentElement.getElementsByTagName("xml-element");
492 if ( xmlElementNodes.getLength() <= 0 ) {
495 // xml-element that are not present
496 updateParentXmlElements( parentElement, xmlElementNodes);
500 // need to combine xml-properties
501 combineXmlProperties(useElement, combineElementList );
502 combinedJavaTypes.put( javaTypeName, useElement);
503 return combineElementList.get(useElement);
507 private static void prettyPrint(Node node, String tab)
511 // Set up the output transformer
512 TransformerFactory transfac = TransformerFactory.newInstance();
513 Transformer trans = transfac.newTransformer();
514 trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
515 trans.setOutputProperty(OutputKeys.INDENT, "yes");
516 StringWriter sw = new StringWriter();
517 StreamResult result = new StreamResult(sw);
518 DOMSource source = new DOMSource(node);
519 trans.transform(source, result);
520 String xmlString = sw.toString();
521 System.out.println(xmlString);
523 catch (TransformerException e) {