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":
948 case "ExternalSystem":
956 System.out.println( "processJavaTypeElementSwagger called with null path for javaTypeName " + javaTypeName);
959 if ( path == null || !(path.contains("cloud-infrastructure")))
960 switch ( javaTypeName) {
965 case "CloudInfrastructure":
968 case "ServiceDesignAndCreation":
969 case "LicenseManagement":
972 useTag = javaTypeName;
981 if ( !javaTypeName.equals("Inventory") ) {
982 if ( javaTypeName.equals("AaiInternal"))
985 useOpId = javaTypeName;
987 useOpId = opId + javaTypeName;
989 useTag = javaTypeName;
993 if ( javaTypeName.equals("GenericVnf"))
994 System.out.println( "Processing " + javaTypeName);
995 else if ( javaTypeName.equals("Service"))
996 System.out.println( "Processing " + javaTypeName);
997 else if ( javaTypeName.equals("SitePair"))
998 System.out.println( "Processing " + javaTypeName);
1000 NodeList parentNodes = javaTypeElement.getElementsByTagName("java-attributes");
1002 if ( parentNodes.getLength() == 0 ) {
1003 //System.out.println( "no java-attributes for java-type " + javaTypeName);
1008 NamedNodeMap attributes;
1010 NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
1011 Element valElement = (Element) valNodes.item(0);
1012 attributes = valElement.getAttributes();
1013 for ( int i = 0; i < attributes.getLength(); ++i ) {
1014 Attr attr = (Attr) attributes.item(i);
1015 String attrName = attr.getNodeName();
1017 String attrValue = attr.getNodeValue();
1018 //System.out.println("Found xml-root-element attribute: " + attrName + " with value: " + attrValue);
1019 if ( attrName.equals("name"))
1020 xmlRootElementName = attrValue;
1023 if ( xmlRootElementName.equals("oam-networks"))
1024 System.out.println( "xmlRootElement oam-networks with getItemData [" + getItemName + "]");
1028 if ( generatedJavaType.containsKey(xmlRootElementName) ) {
1032 NodeList childNodes;
1033 Element childElement;
1034 NodeList xmlPropNodes = javaTypeElement.getElementsByTagName("xml-properties");
1035 Element xmlPropElement;
1036 String pathDescriptionProperty = null;
1039 Vector<String> indexedProps = null;
1041 /*System.out.println( "javaTypeName " + javaTypeName + " has xml-properties length " + xmlPropNodes.getLength());
1042 if ( path != null && path.equals("/network/generic-vnfs"))
1043 System.out.println("path is " + "/network/generic-vnfs with getItemName " + getItemName);
1045 if ( xmlPropNodes.getLength() > 0 ) {
1047 for ( int i = 0; i < xmlPropNodes.getLength(); ++i ) {
1048 xmlPropElement = (Element)xmlPropNodes.item(i);
1049 if ( !xmlPropElement.getParentNode().isSameNode(javaTypeElement))
1051 childNodes = xmlPropElement.getElementsByTagName("xml-property");
1053 if ( childNodes.getLength() > 0 ) {
1054 for ( int j = 0; j < childNodes.getLength(); ++j ) {
1055 childElement = (Element)childNodes.item(j);
1057 int useValue = VALUE_NONE;
1058 attributes = childElement.getAttributes();
1059 for ( int k = 0; k < attributes.getLength(); ++k ) {
1060 Attr attr = (Attr) attributes.item(k);
1061 String attrName = attr.getNodeName();
1062 String attrValue = attr.getNodeValue();
1063 if ( attrName == null || attrValue == null )
1065 if ( attrName.equals("name") && attrValue.equals("description")) {
1066 useValue = VALUE_DESCRIPTION;
1068 if ( useValue == VALUE_DESCRIPTION && attrName.equals("value")) {
1069 pathDescriptionProperty = attrValue;
1071 //System.out.println("found xml-element-wrapper " + xmlElementWrapper);
1073 if ( attrValue.equals("indexedProps")) {
1074 useValue = VALUE_INDEXED_PROPS;
1076 if ( useValue == VALUE_INDEXED_PROPS && attrName.equals("value")) {
1077 indexedProps = getIndexedProps( attrValue );
1084 //System.out.println("javaTypeName " + javaTypeName + " description " + pathDescriptionProperty);
1087 if ( javaTypeName.equals("RelationshipList")) {
1088 System.out.println( "Skipping " + javaTypeName);
1089 generatedJavaType.put(javaTypeName, null);
1094 Element parentElement = (Element)parentNodes.item(0);
1095 NodeList xmlElementNodes = parentElement.getElementsByTagName("xml-element");
1098 String attrDescription = null;
1100 Element xmlElementElement;
1101 String addType = null;
1102 String elementType = null, elementIsKey = null, elementIsRequired, elementContainerType = null;
1103 String elementName = null;
1104 StringBuffer sbParameters = new StringBuffer();
1106 StringBuffer sbRequired = new StringBuffer();
1107 int requiredCnt = 0;
1108 int propertyCnt = 0;
1109 StringBuffer sbProperties = new StringBuffer();
1110 StringBuffer sbIndexedParams = new StringBuffer();
1114 if ( xmlRootElementName.equals("inventory"))
1116 else if ( path == null )
1117 //path = "/aai/" + apiVersion;
1118 path = "/" + xmlRootElementName;
1120 path += "/" + xmlRootElementName;
1121 st = new StringTokenizer(path, "/");
1123 if ( path.equals("/business/customers/customer/{global-customer-id}/service-subscriptions/service-subscription"))
1124 System.out.println("processing path /business/customers/customer/{global-customer-id}/service-subscriptions with tag " + tag);
1126 boolean genPath = false;
1128 if ( path != null && path.equals("/network/generic-vnfs/generic-vnf"))
1129 System.out.println("path is " + "/network/generic-vnfs/generic-vnf");
1131 if ( st.countTokens() > 1 && getItemName == null ) {
1132 if ( appliedPaths.containsKey(path))
1134 appliedPaths.put(path, null);
1136 if ( path.contains("/relationship/") ) { // filter paths with relationship-list
1139 if ( path.endsWith("/relationship-list")) {
1145 Vector<String> addTypeV = null;
1146 if ( xmlElementNodes.getLength() > 0 ) {
1148 for ( int i = 0; i < xmlElementNodes.getLength(); ++i ) {
1149 xmlElementElement = (Element)xmlElementNodes.item(i);
1150 if ( !xmlElementElement.getParentNode().isSameNode(parentElement))
1152 /*childNodes = xmlElementElement.getElementsByTagName("xml-element-wrapper");
1153 if ( childNodes.getLength() > 0 ) {
1154 childElement = (Element)childNodes.item(0);
1156 attributes = childElement.getAttributes();
1157 for ( int k = 0; k < attributes.getLength(); ++k ) {
1158 Attr attr = (Attr) attributes.item(k);
1159 String attrName = attr.getNodeName();
1160 String attrValue = attr.getNodeValue();
1161 if ( attrName.equals("name")) {
1162 xmlElementWrapper = attrValue;
1163 //System.out.println("found xml-element-wrapper " + xmlElementWrapper);
1169 valNodes = xmlElementElement.getElementsByTagName("xml-properties");
1170 attrDescription = null;
1171 if ( valNodes.getLength() > 0 ) {
1172 for ( int j = 0; j < valNodes.getLength(); ++j ) {
1173 valElement = (Element)valNodes.item(j);
1174 if ( !valElement.getParentNode().isSameNode(xmlElementElement))
1176 childNodes = valElement.getElementsByTagName("xml-property");
1177 if ( childNodes.getLength() > 0 ) {
1178 childElement = (Element)childNodes.item(0);
1180 attributes = childElement.getAttributes();
1181 attrDescription = null;
1182 boolean useValue = false;
1183 for ( int k = 0; k < attributes.getLength(); ++k ) {
1184 Attr attr = (Attr) attributes.item(k);
1185 String attrName = attr.getNodeName();
1186 String attrValue = attr.getNodeValue();
1187 if ( attrName.equals("name") && attrValue.equals("description")) {
1190 if ( useValue && attrName.equals("value")) {
1191 attrDescription = attrValue;
1192 //System.out.println("found xml-element-wrapper " + xmlElementWrapper);
1200 attributes = xmlElementElement.getAttributes();
1201 addTypeV = null; // vector of 1
1204 elementName = elementType = elementIsKey = elementIsRequired = elementContainerType = null;
1205 for ( int j = 0; j < attributes.getLength(); ++j ) {
1206 Attr attr = (Attr) attributes.item(j);
1207 String attrName = attr.getNodeName();
1209 String attrValue = attr.getNodeValue();
1210 //System.out.println("For " + xmlRootElementName + " Found xml-element attribute: " + attrName + " with value: " + attrValue);
1211 if ( attrName.equals("name")) {
1212 elementName = attrValue;
1215 if ( attrName.equals("type") && getItemName == null ) {
1216 elementType = attrValue;
1217 if ( attrValue.contains(apiVersionFmt) ) {
1218 addType = attrValue.substring(attrValue.lastIndexOf('.')+1);
1219 if ( addTypeV == null )
1220 addTypeV = new Vector<String>();
1221 addTypeV.add(addType);
1225 if ( attrName.equals("xml-key")) {
1226 elementIsKey = attrValue;
1227 path += "/{" + elementName + "}";
1229 if ( attrName.equals("required")) {
1230 elementIsRequired = attrValue;
1232 if ( attrName.equals("container-type")) {
1233 elementContainerType = attrValue;
1236 if ( getItemName != null ) {
1237 if ( getItemName.equals("array") ) {
1238 if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) {
1239 //System.out.println( " returning array " + elementName );
1243 } else { // not an array check
1244 if ( elementContainerType == null || !elementContainerType.equals("java.util.ArrayList")) {
1245 //System.out.println( " returning object " + elementName );
1250 //System.out.println( " returning null" );
1253 if ( elementIsRequired != null ) {
1254 if ( requiredCnt == 0 )
1255 sbRequired.append(" required:\n");
1257 if ( addTypeV != null ) {
1258 for ( int k = 0; k < addTypeV.size(); ++i ) {
1259 sbRequired.append(" - " + getXmlRootElementName(addTypeV.elementAt(k)) + ":\n");
1262 sbRequired.append(" - " + elementName + "\n");
1266 if ( elementIsKey != null ) {
1267 sbParameters.append((" - name: " + elementName + "\n"));
1268 sbParameters.append((" in: path\n"));
1269 if ( attrDescription != null && attrDescription.length() > 0 )
1270 sbParameters.append((" description: " + attrDescription + "\n"));
1271 sbParameters.append((" required: true\n"));
1272 if ( elementType.equals("java.lang.String"))
1273 sbParameters.append(" type: string\n");
1274 if ( elementType.equals("java.lang.Long")) {
1275 sbParameters.append(" type: integer\n");
1276 sbParameters.append(" format: int64\n");
1278 if ( elementType.equals("java.lang.Integer")) {
1279 sbParameters.append(" type: integer\n");
1280 sbParameters.append(" format: int32\n");
1282 if ( elementType.equals("java.lang.Boolean"))
1283 sbParameters.append(" type: boolean\n");
1286 } else if ( indexedProps != null
1287 && indexedProps.contains(elementName ) ) {
1288 sbIndexedParams.append((" - name: " + elementName + "\n"));
1289 sbIndexedParams.append((" in: query\n"));
1290 if ( attrDescription != null && attrDescription.length() > 0 )
1291 sbIndexedParams.append((" description: " + attrDescription + "\n"));
1292 sbIndexedParams.append((" required: false\n"));
1293 if ( elementType.equals("java.lang.String"))
1294 sbIndexedParams.append(" type: string\n");
1295 if ( elementType.equals("java.lang.Long")) {
1296 sbIndexedParams.append(" type: integer\n");
1297 sbIndexedParams.append(" format: int64\n");
1299 if ( elementType.equals("java.lang.Integer")) {
1300 sbIndexedParams.append(" type: integer\n");
1301 sbIndexedParams.append(" format: int32\n");
1303 if ( elementType.equals("java.lang.Boolean"))
1304 sbIndexedParams.append(" type: boolean\n");
1308 if ( elementName != null && elementName.equals("inventory-item"))
1309 System.out.println( "processing inventory-item elementName");
1312 if ( isStandardType(elementType)) {
1313 sbProperties.append(" " + elementName + ":\n");
1315 sbProperties.append(" type: ");
1317 if ( elementType.equals("java.lang.String"))
1318 sbProperties.append("string\n");
1319 else if ( elementType.equals("java.lang.Long")) {
1320 sbProperties.append("integer\n");
1321 sbProperties.append(" format: int64\n");
1323 else if ( elementType.equals("java.lang.Integer")){
1324 sbProperties.append("integer\n");
1325 sbProperties.append(" format: int32\n");
1327 else if ( elementType.equals("java.lang.Boolean"))
1328 sbProperties.append("boolean\n");
1329 if ( attrDescription != null && attrDescription.length() > 0 )
1330 sbProperties.append(" description: " + attrDescription + "\n");
1333 //if ( addType != null && elementContainerType != null && elementContainerType.equals("java.util.ArrayList") ) {
1335 if ( addTypeV != null ) {
1336 StringBuffer newPathParams = null;
1337 if ( pathParams != null ) {
1338 newPathParams = new StringBuffer();
1339 newPathParams.append(pathParams);
1341 if ( sbParameters.toString().length() > 0 ) {
1342 if ( newPathParams == null )
1343 newPathParams = new StringBuffer();
1344 newPathParams.append(sbParameters);
1346 String newQueryParams = null;
1347 if ( sbIndexedParams.toString().length() > 0 ) {
1348 if ( queryParams == null )
1349 newQueryParams = sbIndexedParams.toString();
1351 newQueryParams = queryParams + sbIndexedParams.toString();
1353 newQueryParams = queryParams;
1355 for ( int k = 0; k < addTypeV.size(); ++k ) {
1356 addType = addTypeV.elementAt(k);
1358 if ( opId == null || !opId.contains(addType)) {
1359 processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
1360 pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId, null,
1361 newPathParams, newQueryParams, validEdges);
1363 // need item name of array
1364 String itemName = processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
1365 pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId,
1366 "array", null, null, null );
1368 if ( itemName != null ) {
1369 if ( addType.equals("AaiInternal") ) {
1370 //System.out.println( "addType AaiInternal, skip properties");
1372 } else if ( getItemName == null) {
1374 sbProperties.append(" " + getXmlRootElementName(addType) + ":\n");
1375 sbProperties.append(" type: array\n items:\n");
1376 sbProperties.append(" $ref: \"#/definitions/" + itemName + "\"\n");
1377 if ( attrDescription != null && attrDescription.length() > 0 )
1378 sbProperties.append(" description: " + attrDescription + "\n");
1381 /*itemName = processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
1382 pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId, "other" );
1383 if ( itemName != null ) {
1385 if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) {
1386 // need properties for getXmlRootElementName(addType)
1387 newPathParams = null;
1388 if ( pathParams != null ) {
1389 newPathParams = new StringBuffer();
1390 newPathParams.append(pathParams);
1392 if ( sbParameters.toString().length() > 0 ) {
1393 if ( newPathParams == null )
1394 newPathParams = new StringBuffer();
1395 newPathParams.append(sbParameters);
1397 newQueryParams = null;
1398 if ( sbIndexedParams.toString().length() > 0 ) {
1399 if ( queryParams == null )
1400 newQueryParams = sbIndexedParams.toString();
1402 newQueryParams = queryParams + sbIndexedParams.toString();
1404 newQueryParams = queryParams;
1406 processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
1407 pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId,
1408 null, newPathParams, newQueryParams, validEdges );
1409 sbProperties.append(" " + getXmlRootElementName(addType) + ":\n");
1410 sbProperties.append(" type: array\n items: \n");
1411 sbProperties.append(" $ref: \"#/definitions/" + getXmlRootElementName(addType) + "\"\n");
1413 sbProperties.append(" " + getXmlRootElementName(addType) + ":\n");
1414 sbProperties.append(" type: object\n");
1415 sbProperties.append(" $ref: \"#/definitions/" + getXmlRootElementName(addType) + "\"\n");
1417 if ( attrDescription != null && attrDescription.length() > 0 )
1418 sbProperties.append(" description: " + attrDescription + "\n");
1422 System.out.println(" unable to define swagger object for " + addType);
1426 //if ( getItemName == null) looking for missing properties
1427 //generatedJavaType.put(addType, null);
1434 if ( useOpId.equals("CloudInfrastructureComplexesComplexCtagPools"))
1435 System.out.println( "adding path CloudInfrastructureComplexesComplexCtagPools");
1438 if ( !path.endsWith("/relationship") ) {
1439 pathSb.append(" " + path + ":\n" );
1440 pathSb.append(" get:\n");
1441 pathSb.append(" tags:\n");
1442 pathSb.append(" - " + tag + "\n");
1443 pathSb.append(" summary: returns " + xmlRootElementName + "\n");
1445 pathSb.append(" description: returns " + xmlRootElementName + "\n");
1446 pathSb.append(" operationId: get" + useOpId + "\n");
1447 pathSb.append(" produces:\n");
1448 pathSb.append(" - application/json\n");
1449 pathSb.append(" - application/xml\n");
1451 pathSb.append(" responses:\n");
1452 pathSb.append(" \"200\":\n");
1453 pathSb.append(" description: successful operation\n");
1454 pathSb.append(" schema:\n");
1455 pathSb.append(" $ref: \"#/definitions/" + xmlRootElementName + "\"\n");
1456 pathSb.append(" \"default\":\n");
1457 pathSb.append(" " + responsesUrl);
1459 pathSb.append(" \"200\":\n");
1460 pathSb.append(" description: successful operation\n");
1461 pathSb.append(" schema:\n");
1462 pathSb.append(" $ref: \"#/definitions/" + xmlRootElementName + "\"\n");
1463 pathSb.append(" \"404\":\n");
1464 pathSb.append(" description: resource was not found\n");
1465 pathSb.append(" \"400\":\n");
1466 pathSb.append(" description: bad request\n");
1468 if ( path.indexOf('{') > 0 ) {
1470 if ( sbParameters.toString().length() > 0 ) {
1471 if ( pathParams == null )
1472 pathParams = new StringBuffer();
1473 pathParams.append(sbParameters);
1475 if ( pathParams != null) {
1476 pathSb.append(" parameters:\n");
1477 pathSb.append(pathParams);
1479 System.out.println( "null pathParams for " + useOpId);
1480 if ( sbIndexedParams.toString().length() > 0 ) {
1481 if ( queryParams == null )
1482 queryParams = sbIndexedParams.toString();
1484 queryParams = queryParams + sbIndexedParams.toString();
1486 if ( queryParams != null ) {
1487 if ( pathParams == null ) {
1488 pathSb.append(" parameters:\n");
1490 pathSb.append(queryParams);
1494 boolean skipPutDelete = false; // no put or delete for "all"
1495 if ( !path.endsWith("/relationship") ) {
1496 if ( !path.endsWith("}") ){
1497 skipPutDelete = true;
1501 if ( path.indexOf('{') > 0 && !opId.startsWith("Search") &&!skipPutDelete) {
1503 if ( path.endsWith("/relationship") ) {
1504 pathSb.append(" " + path + ":\n" );
1506 pathSb.append(" put:\n");
1507 pathSb.append(" tags:\n");
1508 pathSb.append(" - " + tag + "\n");
1510 if ( path.endsWith("/relationship") ) {
1511 pathSb.append(" summary: see node definition for valid relationships\n");
1513 pathSb.append(" summary: create or update an existing " + xmlRootElementName + "\n");
1514 pathSb.append(" description: create or update an existing " + xmlRootElementName + "\n");
1516 pathSb.append(" operationId: createOrUpdate" + useOpId + "\n");
1517 pathSb.append(" consumes:\n");
1518 pathSb.append(" - application/json\n");
1519 pathSb.append(" - application/xml\n");
1520 pathSb.append(" produces:\n");
1521 pathSb.append(" - application/json\n");
1522 pathSb.append(" - application/xml\n");
1523 pathSb.append(" responses:\n");
1524 pathSb.append(" \"default\":\n");
1525 pathSb.append(" " + responsesUrl);
1527 pathSb.append(" responses:\n");
1528 pathSb.append(" \"200\":\n");
1529 pathSb.append(" description: existing resource has been modified and there is a response buffer\n");
1530 pathSb.append(" \"201\":\n");
1531 pathSb.append(" description: new resource is created\n");
1532 pathSb.append(" \"202\":\n");
1533 pathSb.append(" description: action requested but may have taken other actions as well, which are returned in the response payload\n");
1534 pathSb.append(" \"204\":\n");
1535 pathSb.append(" description: existing resource has been modified and there is no response buffer\n");
1536 pathSb.append(" \"400\":\n");
1537 pathSb.append(" description: Bad Request will be returned if headers are missing\n");
1538 pathSb.append(" \"404\":\n");
1539 pathSb.append(" description: Not Found will be returned if an unknown URL is used\n");
1541 pathSb.append(" parameters:\n");
1542 //pathSb.append(" - in: path\n");
1543 pathSb.append(pathParams); // for nesting
1544 pathSb.append(" - name: body\n");
1545 pathSb.append(" in: body\n");
1546 pathSb.append(" description: " + xmlRootElementName + " object that needs to be created or updated\n");
1547 pathSb.append(" required: true\n");
1548 pathSb.append(" schema:\n");
1549 pathSb.append(" $ref: \"#/definitions/" + xmlRootElementName + "\"\n");
1551 if ( queryParams != null ) {
1552 pathSb.append(queryParams);
1556 pathSb.append(" delete:\n");
1557 pathSb.append(" tags:\n");
1558 pathSb.append(" - " + tag + "\n");
1559 pathSb.append(" summary: delete an existing " + xmlRootElementName + "\n");
1561 pathSb.append(" description: delete an existing " + xmlRootElementName + "\n");
1563 pathSb.append(" operationId: delete" + useOpId + "\n");
1564 pathSb.append(" consumes:\n");
1565 pathSb.append(" - application/json\n");
1566 pathSb.append(" - application/xml\n");
1567 pathSb.append(" produces:\n");
1568 pathSb.append(" - application/json\n");
1569 pathSb.append(" - application/xml\n");
1570 pathSb.append(" responses:\n");
1571 pathSb.append(" \"default\":\n");
1572 pathSb.append(" " + responsesUrl);
1574 pathSb.append(" responses:\n");
1575 pathSb.append(" \"200\":\n");
1576 pathSb.append(" description: successful, the response includes an entity describing the status\n");
1577 pathSb.append(" \"204\":\n");
1578 pathSb.append(" description: successful, action has been enacted but the response does not include an entity\n");
1579 pathSb.append(" \"400\":\n");
1580 pathSb.append(" description: Bad Request will be returned if headers are missing\n");
1581 pathSb.append(" \"404\":\n");
1582 pathSb.append(" description: Not Found will be returned if an unknown URL is used\n");
1584 pathSb.append(" parameters:\n");
1585 //pathSb.append(" - in: path\n");
1586 pathSb.append(pathParams); // for nesting
1587 if ( !path.endsWith("/relationship") ) {
1588 pathSb.append(" - name: resource-version\n");
1590 pathSb.append(" in: query\n");
1591 pathSb.append(" description: resource-version for concurrency\n");
1592 pathSb.append(" required: true\n");
1593 pathSb.append(" type: string\n");
1596 if ( queryParams != null ) {
1597 pathSb.append(queryParams);
1603 if ( generatedJavaType.containsKey(xmlRootElementName) ) {
1607 definitionsSb.append(" " + xmlRootElementName + ":\n");
1608 Collection<EdgeDescription> edges = getEdgeRules(xmlRootElementName );
1609 if ( edges.size() > 0 ) {
1610 StringBuffer sbEdge = new StringBuffer();
1611 sbEdge.append(" ###### Related Nodes\n");
1612 for (EdgeDescription ed : edges) {
1613 if ( ed.getRuleKey().startsWith(xmlRootElementName)) {
1614 sbEdge.append(" - TO ").append(ed.getRuleKey().substring(ed.getRuleKey().indexOf("|")+1));
1615 sbEdge.append(ed.getRelationshipDescription("TO", xmlRootElementName));
1616 sbEdge.append("\n");
1619 for (EdgeDescription ed : edges) {
1620 if ( ed.getRuleKey().endsWith(xmlRootElementName)) {
1621 sbEdge.append(" - FROM ").append(ed.getRuleKey().substring(0, ed.getRuleKey().indexOf("|")));
1622 sbEdge.append(ed.getRelationshipDescription("FROM", xmlRootElementName));
1623 sbEdge.append("\n");
1626 validEdges = sbEdge.toString();
1629 String deleteRule = getDeleteRules(xmlRootElementName);
1630 // Handle description property. Might have a description OR valid edges OR both OR neither.
1631 // Only put a description: tag if there is at least one.
1632 if (pathDescriptionProperty != null || deleteRule != null || validEdges != null) {
1633 definitionsSb.append(" description: |\n");
1635 if ( pathDescriptionProperty != null )
1636 definitionsSb.append(" " + pathDescriptionProperty + "\n" );
1637 if (deleteRule != null)
1638 definitionsSb.append(" ###### Default Delete Scope\n ").append(deleteRule).append("\n");
1639 if (validEdges != null)
1640 definitionsSb.append(validEdges);
1643 if ( requiredCnt > 0 )
1644 definitionsSb.append(sbRequired);
1645 if ( propertyCnt > 0 ) {
1646 definitionsSb.append(" properties:\n");
1647 definitionsSb.append(sbProperties);
1649 generatedJavaType.put(xmlRootElementName, null);
1653 public static String generateSwaggerFromOxmFile( File oxmFile )
1656 StringBuffer sb = new StringBuffer();
1657 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");
1658 sb.append(" title: Active and Available Inventory REST API\n");
1659 sb.append(" license:\n name: Apache 2.0\n url: http://www.apache.org/licenses/LICENSE-2.0.html\n");
1660 sb.append(" contact:\n name:\n url:\n email:\n");
1661 sb.append("host:\nbasePath: /aai/" + apiVersion + "\n");
1662 sb.append("schemes:\n - https\npaths:\n");
1664 sb.append("responses:\n");
1665 sb.append(" \"200\":\n");
1666 sb.append(" description: successful operation\n");
1667 sb.append(" \"404\":\n");
1668 sb.append(" description: resource was not found\n");
1669 sb.append(" \"400\":\n");
1670 sb.append(" description: bad request\n");
1673 versionedClass = getEdgeRulesClass();
1674 File initialFile = new File("src/main/resources/dbedgerules/DbEdgeRules_" + apiVersion + ".json");
1675 InputStream is = new FileInputStream(initialFile);
1677 Scanner scanner = new Scanner(is);
1678 jsonEdges = scanner.useDelimiter("\\Z").next();
1682 DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
1683 dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
1684 DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
1685 Document doc = dBuilder.parse(oxmFile);
1687 NodeList bindingsNodes = doc.getElementsByTagName("xml-bindings");
1688 Element bindingElement;
1689 NodeList javaTypesNodes;
1690 Element javaTypesElement;
1692 Element javaTypeElement;
1695 if ( bindingsNodes == null || bindingsNodes.getLength() == 0 ) {
1696 System.out.println( "missing <binding-nodes> in " + oxmFile );
1700 bindingElement = (Element) bindingsNodes.item(0);
1701 javaTypesNodes = bindingElement.getElementsByTagName("java-types");
1702 if ( javaTypesNodes.getLength() < 1 ) {
1703 System.out.println( "missing <binding-nodes><java-types> in " + oxmFile );
1706 javaTypesElement = (Element) javaTypesNodes.item(0);
1708 javaTypeNodes = javaTypesElement.getElementsByTagName("java-type");
1709 if ( javaTypeNodes.getLength() < 1 ) {
1710 System.out.println( "missing <binding-nodes><java-types><java-type> in " + oxmFile );
1714 String javaTypeName;
1715 String attrName, attrValue;
1717 StringBuffer pathSb = new StringBuffer();
1719 StringBuffer definitionsSb = new StringBuffer("definitions:\n");
1721 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
1722 javaTypeElement = (Element) javaTypeNodes.item(i);
1723 NamedNodeMap attributes = javaTypeElement.getAttributes();
1724 javaTypeName = null;
1725 for ( int j = 0; j < attributes.getLength(); ++j ) {
1726 attr = (Attr) attributes.item(j);
1727 attrName = attr.getNodeName();
1728 attrValue = attr.getNodeValue();
1729 if ( attrName.equals("name"))
1730 javaTypeName = attrValue;
1732 if ( javaTypeName == null ) {
1733 System.out.println( "<java-type> has no name attribute in " + oxmFile );
1736 if ( !generatedJavaType.containsKey(getXmlRootElementName(javaTypeName)) ) {
1738 //generatedJavaType.put(javaTypeName, null);
1739 //if ( javaTypeName.equals("search")||javaTypeName.equals("actions"))
1741 processJavaTypeElementSwagger( javaTypeName, javaTypeElement, pathSb,
1742 definitionsSb, null, null, null, null, null, null, null);
1746 //System.out.println( "definitions block\n" + definitionsSb.toString());
1747 sb.append(definitionsSb.toString());
1748 //sb.append(definitionsSb);
1750 } catch (Exception e) {
1751 e.printStackTrace();
1754 //System.out.println("generated " + sb.toString());
1755 return sb.toString();
1758 private static NodeList locateXmlProperties(Element element) {
1759 XPathExpression expr;
1760 NodeList result = null;
1762 expr = xpath.compile("xml-properties");
1764 Object nodeset = expr.evaluate(element, XPathConstants.NODESET);
1765 if (nodeset != null) {
1766 NodeList nodes = (NodeList) nodeset;
1767 if (nodes.getLength() > 0) {
1768 Element xmlProperty = (Element)nodes.item(0);
1769 result = xmlProperty.getElementsByTagName("xml-property");
1773 } catch (XPathExpressionException e) {
1774 e.printStackTrace();