2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 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=========================================================
21 package org.openecomp.aai.util;
23 import java.io.BufferedWriter;
25 import java.io.FileInputStream;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.lang.reflect.Field;
29 import java.nio.charset.Charset;
30 import java.nio.file.Files;
31 import java.nio.file.Path;
32 import java.nio.file.Paths;
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.Collection;
36 import java.util.Collections;
37 import java.util.HashMap;
38 import java.util.Iterator;
39 import java.util.List;
41 import java.util.Scanner;
42 import java.util.StringTokenizer;
43 import java.util.Vector;
45 import javax.xml.XMLConstants;
46 import javax.xml.parsers.DocumentBuilder;
47 import javax.xml.parsers.DocumentBuilderFactory;
48 import javax.xml.xpath.XPath;
49 import javax.xml.xpath.XPathConstants;
50 import javax.xml.xpath.XPathExpression;
51 import javax.xml.xpath.XPathExpressionException;
52 import javax.xml.xpath.XPathFactory;
54 import org.openecomp.aai.dbmodel.DbEdgeRules;
55 import org.openecomp.aai.introspection.Version;
56 import org.openecomp.aai.serialization.db.EdgeProperty;
57 import org.w3c.dom.Attr;
58 import org.w3c.dom.Document;
59 import org.w3c.dom.Element;
60 import org.w3c.dom.NamedNodeMap;
61 import org.w3c.dom.NodeList;
63 import com.google.common.base.Joiner;
64 import com.google.common.collect.Multimap;
65 import com.jayway.jsonpath.JsonPath;
69 public class GenerateXsd {
71 static String apiVersion = null;
72 static String apiVersionFmt = null;
73 static boolean useAnnotationsInXsd = false;
74 static String responsesUrl = null;
75 static String responsesLabel = null;
76 static String jsonEdges = null;
78 static Map<String, String> generatedJavaType;
79 static Map<String, String> appliedPaths;
80 static NodeList javaTypeNodes;
81 static Class<?> versionedClass;
84 public static final int VALUE_NONE = 0;
85 public static final int VALUE_DESCRIPTION = 1;
86 public static final int VALUE_INDEXED_PROPS = 2;
88 private static final String generateTypeXSD = "xsd";
89 private static final String generateTypeYAML = "yaml";
91 private static final String root = "../aai-schema/src/main/resources";
92 private static final String xsd_dir = root + "/aai_schema";
93 private static final String yaml_dir = root + "/aai_swagger_yaml";
95 private static int annotationsStartVersion = 9; // minimum version to support annotations in xsd
96 private static int swaggerSupportStartsVersion = 7; // minimum version to support swagger documentation
98 private static XPath xpath = XPathFactory.newInstance().newXPath();
101 private enum LineageType {
102 PARENT, CHILD, UNRELATED;
104 private class EdgeDescription {
106 private String ruleKey;
107 private LineageType type = LineageType.UNRELATED;
108 private String direction;
109 private String multiplicity;
110 private boolean hasDelTarget = false;
112 public String getRuleKey() {
115 public String getMultiplicity() {
118 public String getDirection() {
121 public void setRuleKey(String val) {
124 public void setType(LineageType val) {
127 public void setDirection(String val) {
128 this.direction = val;
130 public void setMultiplicity(String val) {
131 this.multiplicity=val;
133 public void setHasDelTarget(String val) {
134 hasDelTarget = Boolean.parseBoolean(val);
137 public String getRelationshipDescription(String fromTo, String otherNodeName) {
141 if ("FROM".equals(fromTo)) {
142 if ("OUT".equals(direction)) {
143 if (LineageType.PARENT == type) {
144 result = " (is composed of "+otherNodeName;
148 if (LineageType.CHILD == type) {
149 result = " (comprises "+otherNodeName;
151 else if (LineageType.PARENT == type) {
152 result = " (comprises "+otherNodeName;
156 if ("OUT".equals(direction)) {
157 if (LineageType.PARENT == type) {
158 result = " (comprises "+otherNodeName;
161 if (LineageType.PARENT == type) {
162 result = " (is composed of "+otherNodeName;
167 // if (type != null) {
168 // if (LineageType.PARENT.equals(type) && "FROM".equals(fromTo)) {
169 // if ("OUT".equals(direction)) {
170 // result = " (is composed of "+otherNodeName;
172 // result = " (comprises "+otherNodeName;
175 // result = " (comprises " + otherNodeName;
176 // // if (!(multiplicity.startsWith("One"))) {
177 // // System.err.println("Surprised to find multiplicity "+multiplicity+" with comprises for "+ruleKey);
181 if ("TO".equals(fromTo)) {
182 if (result.length() == 0) result = result + " (";
183 else result = result + ", ";
185 result = result + mapMultiplicity(fromTo);
186 if (hasDelTarget) result = result + ", will delete target node";
189 if (result.length() > 0) result = result + ")";
194 private String mapMultiplicity(String fromTo) {
195 String result = multiplicity;
196 // Below logic works if an IN switches multiplicity, which it doesn't today.
197 // if ("TO".equals(fromTo)) {
198 // if (direction.equals("OUT")) {
199 // result = multiplicity;
201 // result = switchMultiplicity(multiplicity);
204 // if (direction.equals("OUT")) {
205 // result = multiplicity;
207 // result = switchMultiplicity(multiplicity);
213 // private String switchMultiplicity(String val) throws IllegalArgumentException
215 // String result = null;
222 // result = "One2Many";
225 // result = "Many2One";
228 // throw new IllegalArgumentException("Multiplicity cannot be "+val);
230 // System.out.println("Switched Multiplicity from "+val+" to "+result);
235 private static boolean validVersion(String versionToGen) {
237 if ("ALL".equalsIgnoreCase(versionToGen)) {
241 for (Version v : Version.values()) {
242 if (v.name().equals(versionToGen)) {
250 private static boolean versionUsesAnnotations( String version) {
251 if (new Integer(version.substring(1)).intValue() >= annotationsStartVersion ) {
257 private static boolean versionSupportsSwagger( String version) {
258 if (new Integer(version.substring(1)).intValue() >= swaggerSupportStartsVersion ) {
264 public static void main(String[] args) throws IOException {
265 String versionToGen = System.getProperty("gen_version").toLowerCase();
266 String fileTypeToGen = System.getProperty("gen_type").toLowerCase();
267 if ( fileTypeToGen == null ) {
268 fileTypeToGen = generateTypeXSD;
271 if ( !fileTypeToGen.equals( generateTypeXSD ) && !fileTypeToGen.equals( generateTypeYAML )) {
272 System.err.println("Invalid gen_type passed. " + fileTypeToGen);
277 if ( versionToGen == null ) {
278 System.err.println("Version is required, ie v<n> or ALL.");
282 responsesUrl = System.getProperty("yamlresponses_url");
283 String responsesLabel = System.getProperty("yamlresponses_label");
284 List<Version> versionsToGen = new ArrayList<>();
287 if (!"ALL".equalsIgnoreCase(versionToGen) && !versionToGen.matches("v\\d+") && !validVersion(versionToGen)) {
288 System.err.println("Invalid version passed. " + versionToGen);
292 if ("ALL".equalsIgnoreCase(versionToGen)) {
293 versionsToGen = Arrays.asList(Version.values());
294 Collections.sort(versionsToGen);
295 Collections.reverse(versionsToGen);
297 versionsToGen.add(Version.valueOf(versionToGen));
300 if ( fileTypeToGen.equals(generateTypeYAML) ) {
301 if ( responsesUrl == null || responsesUrl.length() < 1
302 || responsesLabel == null || responsesLabel.length() < 1 ) {
303 System.err.println("generating swagger yaml file requires yamlresponses_url and yamlresponses_label properties" );
306 responsesUrl = "description: "+ responsesLabel+ "(" + responsesUrl + ").\n";
308 String oxmPath = root + "/oxm/";
314 for (Version v : versionsToGen) {
315 apiVersion = v.toString();
316 System.out.println("Generating " + apiVersion + " " + fileTypeToGen);
317 File oxm_file = new File(oxmPath + "aai_oxm_" + apiVersion + ".xml");
318 apiVersionFmt = "." + apiVersion + ".";
319 generatedJavaType = new HashMap<String, String>();
320 appliedPaths = new HashMap<String, String>();
321 if ( fileTypeToGen.equals(generateTypeXSD) ) {
322 useAnnotationsInXsd = versionUsesAnnotations(apiVersion);
323 outfileName = xsd_dir + "/aai_schema_" + apiVersion + "." + generateTypeXSD;
324 fileContent = processOxmFile(oxm_file, v);
325 } else if ( versionSupportsSwagger(apiVersion )) {
326 outfileName = yaml_dir + "/aai_swagger_" + apiVersion + "." + generateTypeYAML;
327 fileContent = generateSwaggerFromOxmFile( oxm_file);
331 outfile = new File(outfileName);
332 File parentDir = outfile.getParentFile();
333 if(! parentDir.exists())
337 outfile.createNewFile();
338 } catch (IOException e) {
339 System.out.println( "Exception creating output file " + outfileName);
342 BufferedWriter bw = null;
344 Charset charset = Charset.forName("UTF-8");
345 Path path = Paths.get(outfileName);
346 bw = Files.newBufferedWriter(path, charset);
347 bw.write(fileContent);
348 } catch ( IOException e) {
349 System.out.println( "Exception writing output file " + outfileName);
356 System.out.println( "GeneratedXSD successful, saved in " + outfileName);
362 public static String processJavaTypeElement( String javaTypeName, Element javaTypeElement) {
364 String xmlRootElementName = null;
366 NodeList parentNodes = javaTypeElement.getElementsByTagName("java-attributes");
367 StringBuffer sb = new StringBuffer();
368 if ( parentNodes.getLength() == 0 ) {
369 //System.out.println( "no java-attributes for java-type " + javaTypeName);
374 NamedNodeMap attributes;
376 NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
377 Element valElement = (Element) valNodes.item(0);
378 attributes = valElement.getAttributes();
379 for ( int i = 0; i < attributes.getLength(); ++i ) {
380 Attr attr = (Attr) attributes.item(i);
381 String attrName = attr.getNodeName();
383 String attrValue = attr.getNodeValue();
384 //System.out.println("Found xml-root-element attribute: " + attrName + " with value: " + attrValue);
385 if ( attrName.equals("name"))
386 xmlRootElementName = attrValue;
389 if ( javaTypeName.equals("RelationshipList")) {
390 System.out.println( "Skipping " + javaTypeName);
391 generatedJavaType.put(javaTypeName, null);
396 Element parentElement = (Element)parentNodes.item(0);
397 NodeList xmlElementNodes = parentElement.getElementsByTagName("xml-element");
399 Element childElement;
400 String xmlElementWrapper;
402 Element xmlElementElement;
404 String elementName, elementType, elementIsKey, elementIsRequired, elementContainerType;
405 StringBuffer sb1 = new StringBuffer();
406 if ( xmlElementNodes.getLength() > 0 ) {
407 sb1.append(" <xs:element name=\"" + xmlRootElementName + "\">\n");
408 sb1.append(" <xs:complexType>\n");
409 NodeList properties = GenerateXsd.locateXmlProperties(javaTypeElement);
410 if (properties != null && useAnnotationsInXsd) {
411 //System.out.println("properties found for: " + xmlRootElementName);
412 sb1.append(" <xs:annotation>\r\n");
413 insertAnnotation(properties, false, "class", sb1, " ");
415 sb1.append(" </xs:annotation>\r\n");
417 System.out.println("no properties found for: " + xmlRootElementName);
419 sb1.append(" <xs:sequence>\n");
420 for ( int i = 0; i < xmlElementNodes.getLength(); ++i ) {
422 xmlElementElement = (Element)xmlElementNodes.item(i);
423 childNodes = xmlElementElement.getElementsByTagName("xml-element-wrapper");
425 xmlElementWrapper = null;
426 if ( childNodes.getLength() > 0 ) {
427 childElement = (Element)childNodes.item(0);
429 attributes = childElement.getAttributes();
430 for ( int k = 0; k < attributes.getLength(); ++k ) {
431 Attr attr = (Attr) attributes.item(k);
432 String attrName = attr.getNodeName();
433 String attrValue = attr.getNodeValue();
434 if ( attrName.equals("name")) {
435 xmlElementWrapper = attrValue;
436 //System.out.println("found xml-element-wrapper " + xmlElementWrapper);
441 attributes = xmlElementElement.getAttributes();
445 elementName = elementType = elementIsKey = elementIsRequired = elementContainerType = null;
446 for ( int j = 0; j < attributes.getLength(); ++j ) {
447 Attr attr = (Attr) attributes.item(j);
448 String attrName = attr.getNodeName();
450 String attrValue = attr.getNodeValue();
451 //System.out.println("For " + xmlRootElementName + " Found xml-element attribute: " + attrName + " with value: " + attrValue);
452 if ( attrName.equals("name")) {
453 elementName = attrValue;
455 if ( attrName.equals("type")) {
456 elementType = attrValue;
457 if ( attrValue.contains(apiVersionFmt) ) {
458 addType = attrValue.substring(attrValue.lastIndexOf('.')+1);
459 if ( !generatedJavaType.containsKey(addType) ) {
460 generatedJavaType.put(addType, attrValue);
461 sb.append(processJavaTypeElement( addType, getJavaTypeElement(addType) ));
467 if ( attrName.equals("xml-key")) {
468 elementIsKey = attrValue;
470 if ( attrName.equals("required")) {
471 elementIsRequired = attrValue;
473 if ( attrName.equals("container-type")) {
474 elementContainerType = attrValue;
478 if ( xmlElementWrapper != null ) {
479 sb1.append(" <xs:element name=\"" + xmlElementWrapper +"\"");
480 if ( elementIsRequired == null || !elementIsRequired.equals("true")||addType != null) {
481 sb1.append(" minOccurs=\"0\"");
484 sb1.append(" <xs:complexType>\n");
485 properties = GenerateXsd.locateXmlProperties(javaTypeElement);
486 if (properties != null && useAnnotationsInXsd) {
487 sb1.append(" <xs:annotation>\r\n");
488 insertAnnotation(properties, false, "class", sb1, " ");
489 sb1.append(" </xs:annotation>\r\n");
491 System.out.println("no properties found for: " + xmlElementWrapper);
493 sb1.append(" <xs:sequence>\n");
496 if ("Nodes".equals(addType)) {
497 //System.out.println ("Skipping nodes, temporary testing");
500 if ( addType != null ) {
501 //sb1.append(" <xs:element ref=\"tns:" + elementName +"\"");
502 sb1.append(" <xs:element ref=\"tns:" + getXmlRootElementName(addType) +"\"");
504 sb1.append(" <xs:element name=\"" + elementName +"\"");
506 if ( elementType.equals("java.lang.String"))
507 sb1.append(" type=\"xs:string\"");
508 //if ( elementType.equals("java.lang.String"))
509 //sb1.append(" type=\"xs:string\"");
510 if ( elementType.equals("java.lang.Long"))
511 sb1.append(" type=\"xs:unsignedInt\"");
512 if ( elementType.equals("java.lang.Integer"))
513 sb1.append(" type=\"xs:int\"");
514 if ( elementType.equals("java.lang.Boolean"))
515 sb1.append(" type=\"xs:boolean\"");
516 //if ( elementIsRequired != null && elementIsRequired.equals("true")||addType != null) {
517 if ( elementIsRequired == null || !elementIsRequired.equals("true")||addType != null) {
518 sb1.append(" minOccurs=\"0\"");
520 if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) {
521 sb1.append(" maxOccurs=\"unbounded\"");
523 properties = GenerateXsd.locateXmlProperties(xmlElementElement);
524 if (properties != null || elementIsKey != null) {
526 if ( useAnnotationsInXsd ) {
527 sb1.append(" <xs:annotation>\r\n");
528 insertAnnotation(properties, elementIsKey != null, "field", sb1, " ");
529 sb1.append(" </xs:annotation>\r\n");
531 if (xmlElementWrapper== null) {
532 sb1.append(" </xs:element>\n");
537 if ( xmlElementWrapper != null ) {
538 sb1.append(" </xs:sequence>\n");
539 sb1.append(" </xs:complexType>\n");
540 sb1.append(" </xs:element>\n");
544 if ( xmlRootElementName.equals("notify") ||
545 xmlRootElementName.equals("relationship") ||
546 xmlRootElementName.equals("relationship-data") ||
547 xmlRootElementName.equals("related-to-property") )
549 sb1.append(" <xs:any namespace=\"##other\" processContents=\"lax\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n");
551 sb1.append(" </xs:sequence>\n");
552 sb1.append(" </xs:complexType>\n");
553 sb1.append(" </xs:element>\n");
556 NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
557 Element valElement = (Element) valNodes.item(0);
558 attributes = valElement.getAttributes();
559 for ( int i = 0; i < attributes.getLength(); ++i ) {
560 Attr attr = (Attr) attributes.item(i);
561 String attrName = attr.getNodeName();
563 String attrValue = attr.getNodeValue();
564 System.out.println("Found xml-root-element attribute: " + attrName + " with value: " + attrValue);
565 if ( attrValue.equals("name"))
566 xmlRootElementName = attrValue;
570 if ( xmlElementNodes.getLength() < 1 ) {
571 sb.append(" <xs:element name=\"" + xmlRootElementName + "\">\n");
572 sb.append(" <xs:complexType>\n");
573 sb.append(" <xs:sequence/>\n");
574 sb.append(" </xs:complexType>\n");
575 sb.append(" </xs:element>\n");
576 generatedJavaType.put(javaTypeName, null);
577 return sb.toString();
582 return sb.toString();
585 private static void insertAnnotation(NodeList items, boolean isKey, String target, StringBuffer sb1, String indentation) {
586 if (items != null || isKey) {
587 List<String> metadata = new ArrayList<>();
593 metadata.add("isKey=true");
596 for (int i = 0; i < items.getLength(); i++) {
597 item = (Element)items.item(i);
598 name = item.getAttribute("name");
599 value = item.getAttribute("value");
600 if (name.equals("abstract")) {
602 } else if (name.equals("extends")) {
603 name = "extendsFrom";
605 metadata.add(name + "=\"" + value.replaceAll("&", "&") + "\"");
606 //System.out.println("property name: " + name);
611 indentation + " <xs:appinfo>\r\n" +
612 indentation + " <annox:annotate target=\""+target+"\">@org.openecomp.aai.annotations.Metadata(" + Joiner.on(",").join(metadata) + ")</annox:annotate>\r\n" +
613 indentation + " </xs:appinfo>\r\n");
618 private static Element getJavaTypeElement( String javaTypeName )
621 String attrName, attrValue;
623 Element javaTypeElement;
624 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
625 javaTypeElement = (Element) javaTypeNodes.item(i);
626 NamedNodeMap attributes = javaTypeElement.getAttributes();
627 for ( int j = 0; j < attributes.getLength(); ++j ) {
628 attr = (Attr) attributes.item(j);
629 attrName = attr.getNodeName();
630 attrValue = attr.getNodeValue();
631 if ( attrName.equals("name") && attrValue.equals(javaTypeName))
632 return javaTypeElement;
635 System.out.println( "oxm file format error, missing java-type " + javaTypeName);
636 return (Element) null;
639 private static Element getJavaTypeElementSwagger( String javaTypeName )
642 String attrName, attrValue;
644 Element javaTypeElement;
645 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
646 javaTypeElement = (Element) javaTypeNodes.item(i);
647 NamedNodeMap attributes = javaTypeElement.getAttributes();
648 for ( int j = 0; j < attributes.getLength(); ++j ) {
649 attr = (Attr) attributes.item(j);
650 attrName = attr.getNodeName();
651 attrValue = attr.getNodeValue();
652 if ( attrName.equals("name") && attrValue.equals(javaTypeName))
653 return javaTypeElement;
656 System.out.println( "oxm file format error, missing java-type " + javaTypeName);
657 return (Element) null;
659 private static String getXmlRootElementName( String javaTypeName )
662 String attrName, attrValue;
664 Element javaTypeElement;
665 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
666 javaTypeElement = (Element) javaTypeNodes.item(i);
667 NamedNodeMap attributes = javaTypeElement.getAttributes();
668 for ( int j = 0; j < attributes.getLength(); ++j ) {
669 attr = (Attr) attributes.item(j);
670 attrName = attr.getNodeName();
671 attrValue = attr.getNodeValue();
672 if ( attrName.equals("name") && attrValue.equals(javaTypeName)) {
673 NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
674 Element valElement = (Element) valNodes.item(0);
675 attributes = valElement.getAttributes();
676 for ( int k = 0; k < attributes.getLength(); ++k ) {
677 attr = (Attr) attributes.item(k);
678 attrName = attr.getNodeName();
680 attrValue = attr.getNodeValue();
681 //System.out.println("Found xml-root-element attribute: " + attrName + " with value: " + attrValue);
682 if ( attrName.equals("name"))
688 System.out.println( "oxm file format error, missing java-type " + javaTypeName);
693 public static String processOxmFile( File oxmFile, Version v )
695 StringBuilder sb = new StringBuilder();
696 sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");
697 String namespace = "org.openecomp";
698 if ( useAnnotationsInXsd ) {
699 sb.append("<xs:schema elementFormDefault=\"qualified\" version=\"1.0\" targetNamespace=\"http://" + namespace + ".aai.inventory/"
700 + apiVersion + "\" xmlns:tns=\"http://" + namespace + ".aai.inventory/" + apiVersion + "\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
702 + "xmlns:jaxb=\"http://java.sun.com/xml/ns/jaxb\"\r\n" +
703 " jaxb:version=\"2.1\" \r\n" +
704 " xmlns:annox=\"http://annox.dev.java.net\" \r\n" +
705 " jaxb:extensionBindingPrefixes=\"annox\">\n\n");
707 sb.append("<xs:schema elementFormDefault=\"qualified\" version=\"1.0\" targetNamespace=\"http://" + namespace + ".aai.inventory/"
708 + apiVersion + "\" xmlns:tns=\"http://" + namespace + ".aai.inventory/" + apiVersion + "\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n\n");
713 DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
714 dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
715 DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
716 Document doc = dBuilder.parse(oxmFile);
718 NodeList bindingsNodes = doc.getElementsByTagName("xml-bindings");
719 Element bindingElement;
720 NodeList javaTypesNodes;
721 Element javaTypesElement;
723 Element javaTypeElement;
726 if ( bindingsNodes == null || bindingsNodes.getLength() == 0 ) {
727 System.out.println( "missing <binding-nodes> in " + oxmFile );
731 bindingElement = (Element) bindingsNodes.item(0);
732 javaTypesNodes = bindingElement.getElementsByTagName("java-types");
733 if ( javaTypesNodes.getLength() < 1 ) {
734 System.out.println( "missing <binding-nodes><java-types> in " + oxmFile );
737 javaTypesElement = (Element) javaTypesNodes.item(0);
738 javaTypeNodes = javaTypesElement.getElementsByTagName("java-type");
739 if ( javaTypeNodes.getLength() < 1 ) {
740 System.out.println( "missing <binding-nodes><java-types><java-type> in " + oxmFile );
745 String attrName, attrValue;
747 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
748 javaTypeElement = (Element) javaTypeNodes.item(i);
749 NamedNodeMap attributes = javaTypeElement.getAttributes();
751 for ( int j = 0; j < attributes.getLength(); ++j ) {
752 attr = (Attr) attributes.item(j);
753 attrName = attr.getNodeName();
754 attrValue = attr.getNodeValue();
755 if ( attrName.equals("name"))
756 javaTypeName = attrValue;
758 if ( javaTypeName == null ) {
759 System.out.println( "<java-type> has no name attribute in " + oxmFile );
762 if ("Nodes".equals(javaTypeName)) {
763 //System.out.println("skipping Nodes entry (temporary feature)");
766 if ( !generatedJavaType.containsKey(javaTypeName) ) {
767 generatedJavaType.put(javaTypeName, null);
768 sb.append(processJavaTypeElement( javaTypeName, javaTypeElement ));
772 } catch (Exception e) {
776 sb.append("</xs:schema>\n");
777 return sb.toString();
780 private static boolean isStandardType( String elementType )
782 switch ( elementType ) {
783 case "java.lang.String":
784 case "java.lang.Long":
785 case "java.lang.Integer":
786 case"java.lang.Boolean":
792 private static Vector<String> getIndexedProps( String attrValue )
794 if ( attrValue == null )
796 StringTokenizer st = new StringTokenizer( attrValue, ",");
797 if ( st.countTokens() == 0 )
799 Vector<String> result = new Vector<String>();
800 while ( st.hasMoreTokens()) {
801 result.add(st.nextToken());
806 private static Class<?> getEdgeRulesClass() throws ClassNotFoundException {
807 Class<?> result = null;
809 // If a class matching the apiVersion exists, we are generating documentation for a prior release
810 // Otherwise, we're generated documentation for the current release.
812 result = Class.forName("org.openecomp.aai.dbmodel." + apiVersion +".gen.DbEdgeRules");
813 } catch (ClassNotFoundException ex) {
814 result = Class.forName("org.openecomp.aai.dbmodel.DbEdgeRules");
820 * Guaranteed to at least return non null but empty collection of edge descriptions
821 * @param nodeName name of the vertex whose edge relationships to return
822 * @return collection of node neighbors based on DbEdgeRules
824 private static Collection<EdgeDescription> getEdgeRulesFromJson( String path, boolean skipMatch )
827 ArrayList<EdgeDescription> result = new ArrayList<>();
828 Iterator<Map<String, Object>> edgeRulesIterator;
831 GenerateXsd x = new GenerateXsd();
833 List<Map<String, Object>> inEdges = JsonPath.parse(jsonEdges).read(path);
835 edgeRulesIterator = inEdges.iterator();
836 Map<String, Object> edgeMap;
844 EdgeDescription edgeDes;
846 while( edgeRulesIterator.hasNext() ){
847 edgeMap = edgeRulesIterator.next();
848 fromNode = (String)edgeMap.get("from");
849 toNode = (String)edgeMap.get("to");
851 if ( fromNode.equals(toNode)) {
855 edgeDes = x.new EdgeDescription();
856 edgeDes.setRuleKey(fromNode + "|" + toNode);
857 direction = (String)edgeMap.get("direction");
858 edgeDes.setDirection(direction);
859 multiplicity = (String)edgeMap.get("multiplicity");
860 edgeDes.setMultiplicity(multiplicity);
861 isParent = (String)edgeMap.get(EdgeProperty.CONTAINS.toString());
862 if ( "${direction}".equals(isParent)) {
863 edgeDes.setType(LineageType.PARENT);
865 edgeDes.setType(LineageType.UNRELATED);
867 hasDelTarget = (String)edgeMap.get(EdgeProperty.DELETE_OTHER_V.toString());
868 edgeDes.setHasDelTarget(hasDelTarget);
872 } catch (Exception ex) {
873 ex.printStackTrace();
880 * Guaranteed to at least return non null but empty collection of edge descriptions
881 * @param nodeName name of the vertex whose edge relationships to return
882 * @return collection of node neighbors based on DbEdgeRules
884 private static Collection<EdgeDescription> getEdgeRules( String nodeName )
886 String fromRulesPath = "$['rules'][?(@['from']=='" + nodeName + "')]";
887 String toRulesPath = "$['rules'][?(@['to']=='" + nodeName + "')]";
888 Collection<EdgeDescription> fromEdges = getEdgeRulesFromJson( fromRulesPath, false );
889 Collection<EdgeDescription> edges = getEdgeRulesFromJson( toRulesPath, true );
890 edges.addAll(fromEdges);
895 * Finds the default delete scope from DBEdgeRules
896 * @param nodeName name of vertex whose delete scope to return
897 * @return default delete scope of the input nodeName, null if none.
899 private static String getDeleteRules( String nodeName )
901 String result = null;
902 Iterator<String> delRulesIterator;
906 Field mapfield = versionedClass.getField("DefaultDeleteScope");
907 Object map = mapfield.get(null);
908 if (map instanceof Multimap<?,?>) {
909 delRulesIterator = ((Multimap<String,String>) map).keySet().iterator();
911 throw new NoSuchFieldException ("Didn't get back the multimap field expected");
914 while( delRulesIterator.hasNext() ){
915 String ruleKey = delRulesIterator.next();
916 if ( ruleKey.equals(nodeName)) {
917 Collection <String> deRuleColl = DbEdgeRules.DefaultDeleteScope.get(ruleKey);
918 Iterator <String> ruleItr = deRuleColl.iterator();
919 if( ruleItr.hasNext() ){
920 result = ruleItr.next();
925 } catch (Exception ex) {
926 ex.printStackTrace();
931 public static String processJavaTypeElementSwagger( String javaTypeName, Element javaTypeElement,
932 StringBuffer pathSb, StringBuffer definitionsSb, String path, String tag, String opId,
933 String getItemName, StringBuffer pathParams, String queryParams, String validEdges) {
935 String xmlRootElementName = null;
937 //Map<String, String> addJavaType = new HashMap<String, String>();
938 String useTag = null;
939 String useOpId = null;
944 case "ServiceDesignAndCreation":
946 case "LicenseManagement":
947 case "CloudInfrastructure":
955 System.out.println( "processJavaTypeElementSwagger called with null path for javaTypeName " + javaTypeName);
958 if ( path == null || !(path.contains("cloud-infrastructure")))
959 switch ( javaTypeName) {
964 case "CloudInfrastructure":
967 case "ServiceDesignAndCreation":
968 case "LicenseManagement":
971 useTag = javaTypeName;
980 if ( !javaTypeName.equals("Inventory") ) {
981 if ( javaTypeName.equals("AaiInternal"))
984 useOpId = javaTypeName;
986 useOpId = opId + javaTypeName;
988 useTag = javaTypeName;
992 if ( javaTypeName.equals("GenericVnf"))
993 System.out.println( "Processing " + javaTypeName);
994 else if ( javaTypeName.equals("Service"))
995 System.out.println( "Processing " + javaTypeName);
996 else if ( javaTypeName.equals("SitePair"))
997 System.out.println( "Processing " + javaTypeName);
999 NodeList parentNodes = javaTypeElement.getElementsByTagName("java-attributes");
1001 if ( parentNodes.getLength() == 0 ) {
1002 //System.out.println( "no java-attributes for java-type " + javaTypeName);
1007 NamedNodeMap attributes;
1009 NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
1010 Element valElement = (Element) valNodes.item(0);
1011 attributes = valElement.getAttributes();
1012 for ( int i = 0; i < attributes.getLength(); ++i ) {
1013 Attr attr = (Attr) attributes.item(i);
1014 String attrName = attr.getNodeName();
1016 String attrValue = attr.getNodeValue();
1017 //System.out.println("Found xml-root-element attribute: " + attrName + " with value: " + attrValue);
1018 if ( attrName.equals("name"))
1019 xmlRootElementName = attrValue;
1022 if ( xmlRootElementName.equals("oam-networks"))
1023 System.out.println( "xmlRootElement oam-networks with getItemData [" + getItemName + "]");
1027 if ( generatedJavaType.containsKey(xmlRootElementName) ) {
1031 NodeList childNodes;
1032 Element childElement;
1033 NodeList xmlPropNodes = javaTypeElement.getElementsByTagName("xml-properties");
1034 Element xmlPropElement;
1035 String pathDescriptionProperty = null;
1038 Vector<String> indexedProps = null;
1040 /*System.out.println( "javaTypeName " + javaTypeName + " has xml-properties length " + xmlPropNodes.getLength());
1041 if ( path != null && path.equals("/network/generic-vnfs"))
1042 System.out.println("path is " + "/network/generic-vnfs with getItemName " + getItemName);
1044 if ( xmlPropNodes.getLength() > 0 ) {
1046 for ( int i = 0; i < xmlPropNodes.getLength(); ++i ) {
1047 xmlPropElement = (Element)xmlPropNodes.item(i);
1048 if ( !xmlPropElement.getParentNode().isSameNode(javaTypeElement))
1050 childNodes = xmlPropElement.getElementsByTagName("xml-property");
1052 if ( childNodes.getLength() > 0 ) {
1053 for ( int j = 0; j < childNodes.getLength(); ++j ) {
1054 childElement = (Element)childNodes.item(j);
1056 int useValue = VALUE_NONE;
1057 attributes = childElement.getAttributes();
1058 for ( int k = 0; k < attributes.getLength(); ++k ) {
1059 Attr attr = (Attr) attributes.item(k);
1060 String attrName = attr.getNodeName();
1061 String attrValue = attr.getNodeValue();
1062 if ( attrName == null || attrValue == null )
1064 if ( attrName.equals("name") && attrValue.equals("description")) {
1065 useValue = VALUE_DESCRIPTION;
1067 if ( useValue == VALUE_DESCRIPTION && attrName.equals("value")) {
1068 pathDescriptionProperty = attrValue;
1070 //System.out.println("found xml-element-wrapper " + xmlElementWrapper);
1072 if ( attrValue.equals("indexedProps")) {
1073 useValue = VALUE_INDEXED_PROPS;
1075 if ( useValue == VALUE_INDEXED_PROPS && attrName.equals("value")) {
1076 indexedProps = getIndexedProps( attrValue );
1083 //System.out.println("javaTypeName " + javaTypeName + " description " + pathDescriptionProperty);
1086 if ( javaTypeName.equals("RelationshipList")) {
1087 System.out.println( "Skipping " + javaTypeName);
1088 generatedJavaType.put(javaTypeName, null);
1093 Element parentElement = (Element)parentNodes.item(0);
1094 NodeList xmlElementNodes = parentElement.getElementsByTagName("xml-element");
1097 String attrDescription = null;
1099 Element xmlElementElement;
1100 String addType = null;
1101 String elementType = null, elementIsKey = null, elementIsRequired, elementContainerType = null;
1102 String elementName = null;
1103 StringBuffer sbParameters = new StringBuffer();
1105 StringBuffer sbRequired = new StringBuffer();
1106 int requiredCnt = 0;
1107 int propertyCnt = 0;
1108 StringBuffer sbProperties = new StringBuffer();
1109 StringBuffer sbIndexedParams = new StringBuffer();
1113 if ( xmlRootElementName.equals("inventory"))
1115 else if ( path == null )
1116 //path = "/aai/" + apiVersion;
1117 path = "/" + xmlRootElementName;
1119 path += "/" + xmlRootElementName;
1120 st = new StringTokenizer(path, "/");
1122 if ( path.equals("/business/customers/customer/{global-customer-id}/service-subscriptions/service-subscription"))
1123 System.out.println("processing path /business/customers/customer/{global-customer-id}/service-subscriptions with tag " + tag);
1125 boolean genPath = false;
1127 if ( path != null && path.equals("/network/generic-vnfs/generic-vnf"))
1128 System.out.println("path is " + "/network/generic-vnfs/generic-vnf");
1130 if ( st.countTokens() > 1 && getItemName == null ) {
1131 if ( appliedPaths.containsKey(path))
1133 appliedPaths.put(path, null);
1135 if ( path.contains("/relationship/") ) { // filter paths with relationship-list
1138 if ( path.endsWith("/relationship-list")) {
1144 Vector<String> addTypeV = null;
1145 if ( xmlElementNodes.getLength() > 0 ) {
1147 for ( int i = 0; i < xmlElementNodes.getLength(); ++i ) {
1148 xmlElementElement = (Element)xmlElementNodes.item(i);
1149 if ( !xmlElementElement.getParentNode().isSameNode(parentElement))
1151 /*childNodes = xmlElementElement.getElementsByTagName("xml-element-wrapper");
1152 if ( childNodes.getLength() > 0 ) {
1153 childElement = (Element)childNodes.item(0);
1155 attributes = childElement.getAttributes();
1156 for ( int k = 0; k < attributes.getLength(); ++k ) {
1157 Attr attr = (Attr) attributes.item(k);
1158 String attrName = attr.getNodeName();
1159 String attrValue = attr.getNodeValue();
1160 if ( attrName.equals("name")) {
1161 xmlElementWrapper = attrValue;
1162 //System.out.println("found xml-element-wrapper " + xmlElementWrapper);
1168 valNodes = xmlElementElement.getElementsByTagName("xml-properties");
1169 attrDescription = null;
1170 if ( valNodes.getLength() > 0 ) {
1171 for ( int j = 0; j < valNodes.getLength(); ++j ) {
1172 valElement = (Element)valNodes.item(j);
1173 if ( !valElement.getParentNode().isSameNode(xmlElementElement))
1175 childNodes = valElement.getElementsByTagName("xml-property");
1176 if ( childNodes.getLength() > 0 ) {
1177 childElement = (Element)childNodes.item(0);
1179 attributes = childElement.getAttributes();
1180 attrDescription = null;
1181 boolean useValue = false;
1182 for ( int k = 0; k < attributes.getLength(); ++k ) {
1183 Attr attr = (Attr) attributes.item(k);
1184 String attrName = attr.getNodeName();
1185 String attrValue = attr.getNodeValue();
1186 if ( attrName.equals("name") && attrValue.equals("description")) {
1189 if ( useValue && attrName.equals("value")) {
1190 attrDescription = attrValue;
1191 //System.out.println("found xml-element-wrapper " + xmlElementWrapper);
1199 attributes = xmlElementElement.getAttributes();
1200 addTypeV = null; // vector of 1
1203 elementName = elementType = elementIsKey = elementIsRequired = elementContainerType = null;
1204 for ( int j = 0; j < attributes.getLength(); ++j ) {
1205 Attr attr = (Attr) attributes.item(j);
1206 String attrName = attr.getNodeName();
1208 String attrValue = attr.getNodeValue();
1209 //System.out.println("For " + xmlRootElementName + " Found xml-element attribute: " + attrName + " with value: " + attrValue);
1210 if ( attrName.equals("name")) {
1211 elementName = attrValue;
1214 if ( attrName.equals("type") && getItemName == null ) {
1215 elementType = attrValue;
1216 if ( attrValue.contains(apiVersionFmt) ) {
1217 addType = attrValue.substring(attrValue.lastIndexOf('.')+1);
1218 if ( addTypeV == null )
1219 addTypeV = new Vector<String>();
1220 addTypeV.add(addType);
1224 if ( attrName.equals("xml-key")) {
1225 elementIsKey = attrValue;
1226 path += "/{" + elementName + "}";
1228 if ( attrName.equals("required")) {
1229 elementIsRequired = attrValue;
1231 if ( attrName.equals("container-type")) {
1232 elementContainerType = attrValue;
1235 if ( getItemName != null ) {
1236 if ( getItemName.equals("array") ) {
1237 if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) {
1238 //System.out.println( " returning array " + elementName );
1242 } else { // not an array check
1243 if ( elementContainerType == null || !elementContainerType.equals("java.util.ArrayList")) {
1244 //System.out.println( " returning object " + elementName );
1249 //System.out.println( " returning null" );
1252 if ( elementIsRequired != null ) {
1253 if ( requiredCnt == 0 )
1254 sbRequired.append(" required:\n");
1256 if ( addTypeV != null ) {
1257 for ( int k = 0; k < addTypeV.size(); ++i ) {
1258 sbRequired.append(" - " + getXmlRootElementName(addTypeV.elementAt(k)) + ":\n");
1261 sbRequired.append(" - " + elementName + "\n");
1265 if ( elementIsKey != null ) {
1266 sbParameters.append((" - name: " + elementName + "\n"));
1267 sbParameters.append((" in: path\n"));
1268 if ( attrDescription != null && attrDescription.length() > 0 )
1269 sbParameters.append((" description: " + attrDescription + "\n"));
1270 sbParameters.append((" required: true\n"));
1271 if ( elementType.equals("java.lang.String"))
1272 sbParameters.append(" type: string\n");
1273 if ( elementType.equals("java.lang.Long")) {
1274 sbParameters.append(" type: integer\n");
1275 sbParameters.append(" format: int64\n");
1277 if ( elementType.equals("java.lang.Integer")) {
1278 sbParameters.append(" type: integer\n");
1279 sbParameters.append(" format: int32\n");
1281 if ( elementType.equals("java.lang.Boolean"))
1282 sbParameters.append(" type: boolean\n");
1285 } else if ( indexedProps != null
1286 && indexedProps.contains(elementName ) ) {
1287 sbIndexedParams.append((" - name: " + elementName + "\n"));
1288 sbIndexedParams.append((" in: query\n"));
1289 if ( attrDescription != null && attrDescription.length() > 0 )
1290 sbIndexedParams.append((" description: " + attrDescription + "\n"));
1291 sbIndexedParams.append((" required: false\n"));
1292 if ( elementType.equals("java.lang.String"))
1293 sbIndexedParams.append(" type: string\n");
1294 if ( elementType.equals("java.lang.Long")) {
1295 sbIndexedParams.append(" type: integer\n");
1296 sbIndexedParams.append(" format: int64\n");
1298 if ( elementType.equals("java.lang.Integer")) {
1299 sbIndexedParams.append(" type: integer\n");
1300 sbIndexedParams.append(" format: int32\n");
1302 if ( elementType.equals("java.lang.Boolean"))
1303 sbIndexedParams.append(" type: boolean\n");
1307 if ( elementName != null && elementName.equals("inventory-item"))
1308 System.out.println( "processing inventory-item elementName");
1311 if ( isStandardType(elementType)) {
1312 sbProperties.append(" " + elementName + ":\n");
1314 sbProperties.append(" type: ");
1316 if ( elementType.equals("java.lang.String"))
1317 sbProperties.append("string\n");
1318 else if ( elementType.equals("java.lang.Long")) {
1319 sbProperties.append("integer\n");
1320 sbProperties.append(" format: int64\n");
1322 else if ( elementType.equals("java.lang.Integer")){
1323 sbProperties.append("integer\n");
1324 sbProperties.append(" format: int32\n");
1326 else if ( elementType.equals("java.lang.Boolean"))
1327 sbProperties.append("boolean\n");
1328 if ( attrDescription != null && attrDescription.length() > 0 )
1329 sbProperties.append(" description: " + attrDescription + "\n");
1332 //if ( addType != null && elementContainerType != null && elementContainerType.equals("java.util.ArrayList") ) {
1334 if ( addTypeV != null ) {
1335 StringBuffer newPathParams = null;
1336 if ( pathParams != null ) {
1337 newPathParams = new StringBuffer();
1338 newPathParams.append(pathParams);
1340 if ( sbParameters.toString().length() > 0 ) {
1341 if ( newPathParams == null )
1342 newPathParams = new StringBuffer();
1343 newPathParams.append(sbParameters);
1345 String newQueryParams = null;
1346 if ( sbIndexedParams.toString().length() > 0 ) {
1347 if ( queryParams == null )
1348 newQueryParams = sbIndexedParams.toString();
1350 newQueryParams = queryParams + sbIndexedParams.toString();
1352 newQueryParams = queryParams;
1354 for ( int k = 0; k < addTypeV.size(); ++k ) {
1355 addType = addTypeV.elementAt(k);
1357 if ( opId == null || !opId.contains(addType)) {
1358 processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
1359 pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId, null,
1360 newPathParams, newQueryParams, validEdges);
1362 // need item name of array
1363 String itemName = processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
1364 pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId,
1365 "array", null, null, null );
1367 if ( itemName != null ) {
1368 if ( addType.equals("AaiInternal") ) {
1369 //System.out.println( "addType AaiInternal, skip properties");
1371 } else if ( getItemName == null) {
1373 sbProperties.append(" " + getXmlRootElementName(addType) + ":\n");
1374 sbProperties.append(" type: array\n items:\n");
1375 sbProperties.append(" $ref: \"#/definitions/" + itemName + "\"\n");
1376 if ( attrDescription != null && attrDescription.length() > 0 )
1377 sbProperties.append(" description: " + attrDescription + "\n");
1380 /*itemName = processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
1381 pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId, "other" );
1382 if ( itemName != null ) {
1384 if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) {
1385 // need properties for getXmlRootElementName(addType)
1386 newPathParams = null;
1387 if ( pathParams != null ) {
1388 newPathParams = new StringBuffer();
1389 newPathParams.append(pathParams);
1391 if ( sbParameters.toString().length() > 0 ) {
1392 if ( newPathParams == null )
1393 newPathParams = new StringBuffer();
1394 newPathParams.append(sbParameters);
1396 newQueryParams = null;
1397 if ( sbIndexedParams.toString().length() > 0 ) {
1398 if ( queryParams == null )
1399 newQueryParams = sbIndexedParams.toString();
1401 newQueryParams = queryParams + sbIndexedParams.toString();
1403 newQueryParams = queryParams;
1405 processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
1406 pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId,
1407 null, newPathParams, newQueryParams, validEdges );
1408 sbProperties.append(" " + getXmlRootElementName(addType) + ":\n");
1409 sbProperties.append(" type: array\n items: \n");
1410 sbProperties.append(" $ref: \"#/definitions/" + getXmlRootElementName(addType) + "\"\n");
1412 sbProperties.append(" " + getXmlRootElementName(addType) + ":\n");
1413 sbProperties.append(" type: object\n");
1414 sbProperties.append(" $ref: \"#/definitions/" + getXmlRootElementName(addType) + "\"\n");
1416 if ( attrDescription != null && attrDescription.length() > 0 )
1417 sbProperties.append(" description: " + attrDescription + "\n");
1421 System.out.println(" unable to define swagger object for " + addType);
1425 //if ( getItemName == null) looking for missing properties
1426 //generatedJavaType.put(addType, null);
1433 if ( useOpId.equals("CloudInfrastructureComplexesComplexCtagPools"))
1434 System.out.println( "adding path CloudInfrastructureComplexesComplexCtagPools");
1437 if ( !path.endsWith("/relationship") ) {
1438 pathSb.append(" " + path + ":\n" );
1439 pathSb.append(" get:\n");
1440 pathSb.append(" tags:\n");
1441 pathSb.append(" - " + tag + "\n");
1442 pathSb.append(" summary: returns " + xmlRootElementName + "\n");
1444 pathSb.append(" description: returns " + xmlRootElementName + "\n");
1445 pathSb.append(" operationId: get" + useOpId + "\n");
1446 pathSb.append(" produces:\n");
1447 pathSb.append(" - application/json\n");
1448 pathSb.append(" - application/xml\n");
1450 pathSb.append(" responses:\n");
1451 pathSb.append(" \"200\":\n");
1452 pathSb.append(" description: successful operation\n");
1453 pathSb.append(" schema:\n");
1454 pathSb.append(" $ref: \"#/definitions/" + xmlRootElementName + "\"\n");
1455 pathSb.append(" \"default\":\n");
1456 pathSb.append(" " + responsesUrl);
1458 pathSb.append(" \"200\":\n");
1459 pathSb.append(" description: successful operation\n");
1460 pathSb.append(" schema:\n");
1461 pathSb.append(" $ref: \"#/definitions/" + xmlRootElementName + "\"\n");
1462 pathSb.append(" \"404\":\n");
1463 pathSb.append(" description: resource was not found\n");
1464 pathSb.append(" \"400\":\n");
1465 pathSb.append(" description: bad request\n");
1467 if ( path.indexOf('{') > 0 ) {
1469 if ( sbParameters.toString().length() > 0 ) {
1470 if ( pathParams == null )
1471 pathParams = new StringBuffer();
1472 pathParams.append(sbParameters);
1474 if ( pathParams != null) {
1475 pathSb.append(" parameters:\n");
1476 pathSb.append(pathParams);
1478 System.out.println( "null pathParams for " + useOpId);
1479 if ( sbIndexedParams.toString().length() > 0 ) {
1480 if ( queryParams == null )
1481 queryParams = sbIndexedParams.toString();
1483 queryParams = queryParams + sbIndexedParams.toString();
1485 if ( queryParams != null ) {
1486 if ( pathParams == null ) {
1487 pathSb.append(" parameters:\n");
1489 pathSb.append(queryParams);
1493 boolean skipPutDelete = false; // no put or delete for "all"
1494 if ( !path.endsWith("/relationship") ) {
1495 if ( !path.endsWith("}") ){
1496 skipPutDelete = true;
1500 if ( path.indexOf('{') > 0 && !opId.startsWith("Search") &&!skipPutDelete) {
1502 if ( path.endsWith("/relationship") ) {
1503 pathSb.append(" " + path + ":\n" );
1505 pathSb.append(" put:\n");
1506 pathSb.append(" tags:\n");
1507 pathSb.append(" - " + tag + "\n");
1509 if ( path.endsWith("/relationship") ) {
1510 pathSb.append(" summary: see node definition for valid relationships\n");
1512 pathSb.append(" summary: create or update an existing " + xmlRootElementName + "\n");
1513 pathSb.append(" description: create or update an existing " + xmlRootElementName + "\n");
1515 pathSb.append(" operationId: createOrUpdate" + useOpId + "\n");
1516 pathSb.append(" consumes:\n");
1517 pathSb.append(" - application/json\n");
1518 pathSb.append(" - application/xml\n");
1519 pathSb.append(" produces:\n");
1520 pathSb.append(" - application/json\n");
1521 pathSb.append(" - application/xml\n");
1522 pathSb.append(" responses:\n");
1523 pathSb.append(" \"default\":\n");
1524 pathSb.append(" " + responsesUrl);
1526 pathSb.append(" responses:\n");
1527 pathSb.append(" \"200\":\n");
1528 pathSb.append(" description: existing resource has been modified and there is a response buffer\n");
1529 pathSb.append(" \"201\":\n");
1530 pathSb.append(" description: new resource is created\n");
1531 pathSb.append(" \"202\":\n");
1532 pathSb.append(" description: action requested but may have taken other actions as well, which are returned in the response payload\n");
1533 pathSb.append(" \"204\":\n");
1534 pathSb.append(" description: existing resource has been modified and there is no response buffer\n");
1535 pathSb.append(" \"400\":\n");
1536 pathSb.append(" description: Bad Request will be returned if headers are missing\n");
1537 pathSb.append(" \"404\":\n");
1538 pathSb.append(" description: Not Found will be returned if an unknown URL is used\n");
1540 pathSb.append(" parameters:\n");
1541 //pathSb.append(" - in: path\n");
1542 pathSb.append(pathParams); // for nesting
1543 pathSb.append(" - name: body\n");
1544 pathSb.append(" in: body\n");
1545 pathSb.append(" description: " + xmlRootElementName + " object that needs to be created or updated\n");
1546 pathSb.append(" required: true\n");
1547 pathSb.append(" schema:\n");
1548 pathSb.append(" $ref: \"#/definitions/" + xmlRootElementName + "\"\n");
1550 if ( queryParams != null ) {
1551 pathSb.append(queryParams);
1555 pathSb.append(" delete:\n");
1556 pathSb.append(" tags:\n");
1557 pathSb.append(" - " + tag + "\n");
1558 pathSb.append(" summary: delete an existing " + xmlRootElementName + "\n");
1560 pathSb.append(" description: delete an existing " + xmlRootElementName + "\n");
1562 pathSb.append(" operationId: delete" + useOpId + "\n");
1563 pathSb.append(" consumes:\n");
1564 pathSb.append(" - application/json\n");
1565 pathSb.append(" - application/xml\n");
1566 pathSb.append(" produces:\n");
1567 pathSb.append(" - application/json\n");
1568 pathSb.append(" - application/xml\n");
1569 pathSb.append(" responses:\n");
1570 pathSb.append(" \"default\":\n");
1571 pathSb.append(" " + responsesUrl);
1573 pathSb.append(" responses:\n");
1574 pathSb.append(" \"200\":\n");
1575 pathSb.append(" description: successful, the response includes an entity describing the status\n");
1576 pathSb.append(" \"204\":\n");
1577 pathSb.append(" description: successful, action has been enacted but the response does not include an entity\n");
1578 pathSb.append(" \"400\":\n");
1579 pathSb.append(" description: Bad Request will be returned if headers are missing\n");
1580 pathSb.append(" \"404\":\n");
1581 pathSb.append(" description: Not Found will be returned if an unknown URL is used\n");
1583 pathSb.append(" parameters:\n");
1584 //pathSb.append(" - in: path\n");
1585 pathSb.append(pathParams); // for nesting
1586 if ( !path.endsWith("/relationship") ) {
1587 pathSb.append(" - name: resource-version\n");
1589 pathSb.append(" in: query\n");
1590 pathSb.append(" description: resource-version for concurrency\n");
1591 pathSb.append(" required: true\n");
1592 pathSb.append(" type: string\n");
1595 if ( queryParams != null ) {
1596 pathSb.append(queryParams);
1602 if ( generatedJavaType.containsKey(xmlRootElementName) ) {
1606 definitionsSb.append(" " + xmlRootElementName + ":\n");
1607 Collection<EdgeDescription> edges = getEdgeRules(xmlRootElementName );
1608 if ( edges.size() > 0 ) {
1609 StringBuffer sbEdge = new StringBuffer();
1610 sbEdge.append(" ###### Related Nodes\n");
1611 for (EdgeDescription ed : edges) {
1612 if ( ed.getRuleKey().startsWith(xmlRootElementName)) {
1613 sbEdge.append(" - TO ").append(ed.getRuleKey().substring(ed.getRuleKey().indexOf("|")+1));
1614 sbEdge.append(ed.getRelationshipDescription("TO", xmlRootElementName));
1615 sbEdge.append("\n");
1618 for (EdgeDescription ed : edges) {
1619 if ( ed.getRuleKey().endsWith(xmlRootElementName)) {
1620 sbEdge.append(" - FROM ").append(ed.getRuleKey().substring(0, ed.getRuleKey().indexOf("|")));
1621 sbEdge.append(ed.getRelationshipDescription("FROM", xmlRootElementName));
1622 sbEdge.append("\n");
1625 validEdges = sbEdge.toString();
1628 String deleteRule = getDeleteRules(xmlRootElementName);
1629 // Handle description property. Might have a description OR valid edges OR both OR neither.
1630 // Only put a description: tag if there is at least one.
1631 if (pathDescriptionProperty != null || deleteRule != null || validEdges != null) {
1632 definitionsSb.append(" description: |\n");
1634 if ( pathDescriptionProperty != null )
1635 definitionsSb.append(" " + pathDescriptionProperty + "\n" );
1636 if (deleteRule != null)
1637 definitionsSb.append(" ###### Default Delete Scope\n ").append(deleteRule).append("\n");
1638 if (validEdges != null)
1639 definitionsSb.append(validEdges);
1642 if ( requiredCnt > 0 )
1643 definitionsSb.append(sbRequired);
1644 if ( propertyCnt > 0 ) {
1645 definitionsSb.append(" properties:\n");
1646 definitionsSb.append(sbProperties);
1648 generatedJavaType.put(xmlRootElementName, null);
1652 public static String generateSwaggerFromOxmFile( File oxmFile )
1655 StringBuffer sb = new StringBuffer();
1656 sb.append("swagger: \"2.0\"\ninfo:\n description: |\n Copyright © 2017 AT&T Intellectual Property. All rights reserved.\n\n Licensed under the Creative Commons License, Attribution 4.0 Intl. (the "License"); you may not use this documentation except in compliance with the License.\n\n You may obtain a copy of the License at\n\n (https://creativecommons.org/licenses/by/4.0/)\n\n 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.\n\n ECOMP and OpenECOMP are trademarks and service marks of AT&T Intellectual Property.\n\n This document is best viewed with Firefox or Chrome. Nodes can be found by appending /#/definitions/node-type-to-find to the path to this document. Edge definitions can be found with the node definitions.\n version: \"" + apiVersion +"\"\n");
1657 sb.append(" title: Active and Available Inventory REST API\n");
1658 sb.append(" license:\n name: Apache 2.0\n url: http://www.apache.org/licenses/LICENSE-2.0.html\n");
1659 sb.append(" contact:\n name:\n url:\n email:\n");
1660 sb.append("host:\nbasePath: /aai/" + apiVersion + "\n");
1661 sb.append("schemes:\n - https\npaths:\n");
1663 sb.append("responses:\n");
1664 sb.append(" \"200\":\n");
1665 sb.append(" description: successful operation\n");
1666 sb.append(" \"404\":\n");
1667 sb.append(" description: resource was not found\n");
1668 sb.append(" \"400\":\n");
1669 sb.append(" description: bad request\n");
1672 versionedClass = getEdgeRulesClass();
1673 File initialFile = new File("src/main/resources/dbedgerules/DbEdgeRules_" + apiVersion + ".json");
1674 InputStream is = new FileInputStream(initialFile);
1676 Scanner scanner = new Scanner(is);
1677 jsonEdges = scanner.useDelimiter("\\Z").next();
1681 DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
1682 dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
1683 DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
1684 Document doc = dBuilder.parse(oxmFile);
1686 NodeList bindingsNodes = doc.getElementsByTagName("xml-bindings");
1687 Element bindingElement;
1688 NodeList javaTypesNodes;
1689 Element javaTypesElement;
1691 Element javaTypeElement;
1694 if ( bindingsNodes == null || bindingsNodes.getLength() == 0 ) {
1695 System.out.println( "missing <binding-nodes> in " + oxmFile );
1699 bindingElement = (Element) bindingsNodes.item(0);
1700 javaTypesNodes = bindingElement.getElementsByTagName("java-types");
1701 if ( javaTypesNodes.getLength() < 1 ) {
1702 System.out.println( "missing <binding-nodes><java-types> in " + oxmFile );
1705 javaTypesElement = (Element) javaTypesNodes.item(0);
1707 javaTypeNodes = javaTypesElement.getElementsByTagName("java-type");
1708 if ( javaTypeNodes.getLength() < 1 ) {
1709 System.out.println( "missing <binding-nodes><java-types><java-type> in " + oxmFile );
1713 String javaTypeName;
1714 String attrName, attrValue;
1716 StringBuffer pathSb = new StringBuffer();
1718 StringBuffer definitionsSb = new StringBuffer("definitions:\n");
1720 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
1721 javaTypeElement = (Element) javaTypeNodes.item(i);
1722 NamedNodeMap attributes = javaTypeElement.getAttributes();
1723 javaTypeName = null;
1724 for ( int j = 0; j < attributes.getLength(); ++j ) {
1725 attr = (Attr) attributes.item(j);
1726 attrName = attr.getNodeName();
1727 attrValue = attr.getNodeValue();
1728 if ( attrName.equals("name"))
1729 javaTypeName = attrValue;
1731 if ( javaTypeName == null ) {
1732 System.out.println( "<java-type> has no name attribute in " + oxmFile );
1735 if ( !generatedJavaType.containsKey(getXmlRootElementName(javaTypeName)) ) {
1737 //generatedJavaType.put(javaTypeName, null);
1738 //if ( javaTypeName.equals("search")||javaTypeName.equals("actions"))
1740 processJavaTypeElementSwagger( javaTypeName, javaTypeElement, pathSb,
1741 definitionsSb, null, null, null, null, null, null, null);
1745 //System.out.println( "definitions block\n" + definitionsSb.toString());
1746 sb.append(definitionsSb.toString());
1747 //sb.append(definitionsSb);
1749 } catch (Exception e) {
1750 e.printStackTrace();
1753 //System.out.println("generated " + sb.toString());
1754 return sb.toString();
1757 private static NodeList locateXmlProperties(Element element) {
1758 XPathExpression expr;
1759 NodeList result = null;
1761 expr = xpath.compile("xml-properties");
1763 Object nodeset = expr.evaluate(element, XPathConstants.NODESET);
1764 if (nodeset != null) {
1765 NodeList nodes = (NodeList) nodeset;
1766 if (nodes.getLength() > 0) {
1767 Element xmlProperty = (Element)nodes.item(0);
1768 result = xmlProperty.getElementsByTagName("xml-property");
1772 } catch (XPathExpressionException e) {
1773 e.printStackTrace();