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.FileWriter;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.FileInputStream;
29 import java.nio.file.Path;
30 import java.nio.file.Paths;
31 import java.nio.charset.Charset;
32 import java.nio.file.Files;
33 import java.lang.reflect.Field;
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.Collection;
37 import java.util.HashMap;
38 import java.util.HashSet;
39 import java.util.Iterator;
40 import java.util.Collections;
41 import java.util.List;
43 import java.util.Scanner;
45 import java.util.StringTokenizer;
46 import java.util.Vector;
48 import javax.xml.XMLConstants;
49 import javax.xml.bind.JAXBContext;
50 import javax.xml.bind.JAXBException;
51 import javax.xml.bind.SchemaOutputResolver;
52 import javax.xml.parsers.DocumentBuilder;
53 import javax.xml.parsers.DocumentBuilderFactory;
54 import javax.xml.transform.Result;
55 import javax.xml.transform.stream.StreamResult;
56 import javax.xml.xpath.XPath;
57 import javax.xml.xpath.XPathConstants;
58 import javax.xml.xpath.XPathExpression;
59 import javax.xml.xpath.XPathExpressionException;
60 import javax.xml.xpath.XPathFactory;
62 import org.w3c.dom.Attr;
63 import org.w3c.dom.Document;
64 import org.w3c.dom.Element;
65 import org.w3c.dom.NamedNodeMap;
66 import org.w3c.dom.NodeList;
68 import org.openecomp.aai.dbmodel.DbEdgeRules;
69 import org.openecomp.aai.db.props.AAIProperties;
70 import org.openecomp.aai.introspection.Version;
71 import org.openecomp.aai.serialization.db.EdgeRule;
72 import org.openecomp.aai.serialization.db.EdgeRules;
74 import com.google.common.base.Joiner;
75 import com.google.common.collect.Multimap;
76 import com.jayway.jsonpath.Criteria;
77 import com.jayway.jsonpath.DocumentContext;
78 import com.jayway.jsonpath.JsonPath;
82 public class GenerateXsd {
84 static String apiVersion = null;
85 static String apiVersionFmt = null;
86 static boolean useAnnotationsInXsd = false;
87 static String responsesUrl = null;
88 static String responsesLabel = null;
89 static String jsonEdges = null;
91 static Map<String, String> generatedJavaType;
92 static Map<String, String> appliedPaths;
93 static NodeList javaTypeNodes;
94 static Class<?> versionedClass;
97 public static final int VALUE_NONE = 0;
98 public static final int VALUE_DESCRIPTION = 1;
99 public static final int VALUE_INDEXED_PROPS = 2;
101 private static final String generateTypeXSD = "xsd";
102 private static final String generateTypeYAML = "yaml";
104 private static final String root = "../aai-schema/src/main/resources";
105 private static final String xsd_dir = root + "/aai_schema";
106 private static final String yaml_dir = root + "/aai_swagger_yaml";
108 private static int annotationsStartVersion = 9; // minimum version to support annotations in xsd
109 private static int swaggerSupportStartsVersion = 7; // minimum version to support swagger documentation
111 private static XPath xpath = XPathFactory.newInstance().newXPath();
114 private enum LineageType {
115 PARENT, CHILD, UNRELATED;
117 private class EdgeDescription {
119 private String ruleKey;
120 private LineageType type = LineageType.UNRELATED;
121 private String direction;
122 private String multiplicity;
123 private boolean hasDelTarget = false;
125 public String getRuleKey() {
128 public String getMultiplicity() {
131 public String getDirection() {
134 public void setRuleKey(String val) {
137 public void setType(LineageType val) {
140 public void setDirection(String val) {
141 this.direction = val;
143 public void setMultiplicity(String val) {
144 this.multiplicity=val;
146 public void setHasDelTarget(String val) {
147 hasDelTarget = Boolean.parseBoolean(val);
150 public String getRelationshipDescription(String fromTo, String otherNodeName) {
154 if ("FROM".equals(fromTo)) {
155 if ("OUT".equals(direction)) {
156 if (LineageType.PARENT == type) {
157 result = " (is composed of "+otherNodeName;
161 if (LineageType.CHILD == type) {
162 result = " (comprises "+otherNodeName;
164 else if (LineageType.PARENT == type) {
165 result = " (comprises "+otherNodeName;
169 if ("OUT".equals(direction)) {
170 if (LineageType.PARENT == type) {
171 result = " (comprises "+otherNodeName;
174 if (LineageType.PARENT == type) {
175 result = " (is composed of "+otherNodeName;
180 // if (type != null) {
181 // if (LineageType.PARENT.equals(type) && "FROM".equals(fromTo)) {
182 // if ("OUT".equals(direction)) {
183 // result = " (is composed of "+otherNodeName;
185 // result = " (comprises "+otherNodeName;
188 // result = " (comprises " + otherNodeName;
189 // // if (!(multiplicity.startsWith("One"))) {
190 // // System.err.println("Surprised to find multiplicity "+multiplicity+" with comprises for "+ruleKey);
194 if ("TO".equals(fromTo)) {
195 if (result.length() == 0) result = result + " (";
196 else result = result + ", ";
198 result = result + mapMultiplicity(fromTo);
199 if (hasDelTarget) result = result + ", will delete target node";
202 if (result.length() > 0) result = result + ")";
207 private String mapMultiplicity(String fromTo) {
208 String result = multiplicity;
209 // Below logic works if an IN switches multiplicity, which it doesn't today.
210 // if ("TO".equals(fromTo)) {
211 // if (direction.equals("OUT")) {
212 // result = multiplicity;
214 // result = switchMultiplicity(multiplicity);
217 // if (direction.equals("OUT")) {
218 // result = multiplicity;
220 // result = switchMultiplicity(multiplicity);
226 // private String switchMultiplicity(String val) throws IllegalArgumentException
228 // String result = null;
235 // result = "One2Many";
238 // result = "Many2One";
241 // throw new IllegalArgumentException("Multiplicity cannot be "+val);
243 // System.out.println("Switched Multiplicity from "+val+" to "+result);
248 private static boolean validVersion(String versionToGen) {
250 if ("ALL".equalsIgnoreCase(versionToGen)) {
254 for (Version v : Version.values()) {
255 if (v.name().equals(versionToGen)) {
263 private static boolean versionUsesAnnotations( String version) {
264 if (new Integer(version.substring(1)).intValue() >= annotationsStartVersion ) {
270 private static boolean versionSupportsSwagger( String version) {
271 if (new Integer(version.substring(1)).intValue() >= swaggerSupportStartsVersion ) {
277 public static void main(String[] args) throws IOException {
278 String versionToGen = System.getProperty("gen_version").toLowerCase();
279 String fileTypeToGen = System.getProperty("gen_type").toLowerCase();
280 if ( fileTypeToGen == null ) {
281 fileTypeToGen = generateTypeXSD;
284 if ( !fileTypeToGen.equals( generateTypeXSD ) && !fileTypeToGen.equals( generateTypeYAML )) {
285 System.err.println("Invalid gen_type passed. " + fileTypeToGen);
290 if ( versionToGen == null ) {
291 System.err.println("Version is required, ie v<n> or ALL.");
295 responsesUrl = System.getProperty("yamlresponses_url");
296 String responsesLabel = System.getProperty("yamlresponses_label");
297 List<Version> versionsToGen = new ArrayList<>();
300 if (!"ALL".equalsIgnoreCase(versionToGen) && !versionToGen.matches("v\\d+") && !validVersion(versionToGen)) {
301 System.err.println("Invalid version passed. " + versionToGen);
305 if ("ALL".equalsIgnoreCase(versionToGen)) {
306 versionsToGen = Arrays.asList(Version.values());
307 Collections.sort(versionsToGen);
308 Collections.reverse(versionsToGen);
310 versionsToGen.add(Version.valueOf(versionToGen));
313 if ( fileTypeToGen.equals(generateTypeYAML) ) {
314 if ( responsesUrl == null || responsesUrl.length() < 1
315 || responsesLabel == null || responsesLabel.length() < 1 ) {
316 System.err.println("generating swagger yaml file requires yamlresponses_url and yamlresponses_label properties" );
319 responsesUrl = "description: "+ responsesLabel+ "(" + responsesUrl + ").\n";
321 String oxmPath = root + "/oxm/";
327 for (Version v : versionsToGen) {
328 apiVersion = v.toString();
329 System.out.println("Generating " + apiVersion + " " + fileTypeToGen);
330 File oxm_file = new File(oxmPath + "aai_oxm_" + apiVersion + ".xml");
331 apiVersionFmt = "." + apiVersion + ".";
332 generatedJavaType = new HashMap<String, String>();
333 appliedPaths = new HashMap<String, String>();
334 if ( fileTypeToGen.equals(generateTypeXSD) ) {
335 useAnnotationsInXsd = versionUsesAnnotations(apiVersion);
336 outfileName = xsd_dir + "/aai_schema_" + apiVersion + "." + generateTypeXSD;
337 fileContent = processOxmFile( oxm_file);
338 } else if ( versionSupportsSwagger(apiVersion )) {
339 outfileName = yaml_dir + "/aai_swagger_" + apiVersion + "." + generateTypeYAML;
340 fileContent = generateSwaggerFromOxmFile( oxm_file);
344 outfile = new File(outfileName);
345 File parentDir = outfile.getParentFile();
346 if(! parentDir.exists())
350 outfile.createNewFile();
351 } catch (IOException e) {
352 System.out.println( "Exception creating output file " + outfileName);
355 BufferedWriter bw = null;
357 Charset charset = Charset.forName("UTF-8");
358 Path path = Paths.get(outfileName);
359 bw = Files.newBufferedWriter(path, charset);
360 bw.write(fileContent);
361 } catch ( IOException e) {
362 System.out.println( "Exception writing output file " + outfileName);
369 System.out.println( "GeneratedXSD successful, saved in " + outfileName);
375 public static String processJavaTypeElement( String javaTypeName, Element javaTypeElement) {
377 String xmlRootElementName = null;
379 NodeList parentNodes = javaTypeElement.getElementsByTagName("java-attributes");
380 StringBuffer sb = new StringBuffer();
381 if ( parentNodes.getLength() == 0 ) {
382 //System.out.println( "no java-attributes for java-type " + javaTypeName);
387 NamedNodeMap attributes;
389 NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
390 Element valElement = (Element) valNodes.item(0);
391 attributes = valElement.getAttributes();
392 for ( int i = 0; i < attributes.getLength(); ++i ) {
393 Attr attr = (Attr) attributes.item(i);
394 String attrName = attr.getNodeName();
396 String attrValue = attr.getNodeValue();
397 //System.out.println("Found xml-root-element attribute: " + attrName + " with value: " + attrValue);
398 if ( attrName.equals("name"))
399 xmlRootElementName = attrValue;
402 if ( javaTypeName.equals("RelationshipList")) {
403 System.out.println( "Skipping " + javaTypeName);
404 generatedJavaType.put(javaTypeName, null);
409 Element parentElement = (Element)parentNodes.item(0);
410 NodeList xmlElementNodes = parentElement.getElementsByTagName("xml-element");
412 Element childElement;
413 String xmlElementWrapper;
415 Element xmlElementElement;
417 String elementName, elementType, elementIsKey, elementIsRequired, elementContainerType;
418 StringBuffer sb1 = new StringBuffer();
419 if ( xmlElementNodes.getLength() > 0 ) {
420 sb1.append(" <xs:element name=\"" + xmlRootElementName + "\">\n");
421 sb1.append(" <xs:complexType>\n");
422 NodeList properties = GenerateXsd.locateXmlProperties(javaTypeElement);
423 if (properties != null && useAnnotationsInXsd) {
424 //System.out.println("properties found for: " + xmlRootElementName);
425 sb1.append(" <xs:annotation>\r\n");
426 insertAnnotation(properties, false, "class", sb1, " ");
428 sb1.append(" </xs:annotation>\r\n");
430 System.out.println("no properties found for: " + xmlRootElementName);
432 sb1.append(" <xs:sequence>\n");
433 for ( int i = 0; i < xmlElementNodes.getLength(); ++i ) {
435 xmlElementElement = (Element)xmlElementNodes.item(i);
436 childNodes = xmlElementElement.getElementsByTagName("xml-element-wrapper");
438 xmlElementWrapper = null;
439 if ( childNodes.getLength() > 0 ) {
440 childElement = (Element)childNodes.item(0);
442 attributes = childElement.getAttributes();
443 for ( int k = 0; k < attributes.getLength(); ++k ) {
444 Attr attr = (Attr) attributes.item(k);
445 String attrName = attr.getNodeName();
446 String attrValue = attr.getNodeValue();
447 if ( attrName.equals("name")) {
448 xmlElementWrapper = attrValue;
449 //System.out.println("found xml-element-wrapper " + xmlElementWrapper);
454 attributes = xmlElementElement.getAttributes();
458 elementName = elementType = elementIsKey = elementIsRequired = elementContainerType = null;
459 for ( int j = 0; j < attributes.getLength(); ++j ) {
460 Attr attr = (Attr) attributes.item(j);
461 String attrName = attr.getNodeName();
463 String attrValue = attr.getNodeValue();
464 //System.out.println("For " + xmlRootElementName + " Found xml-element attribute: " + attrName + " with value: " + attrValue);
465 if ( attrName.equals("name")) {
466 elementName = attrValue;
468 if ( attrName.equals("type")) {
469 elementType = attrValue;
470 if ( attrValue.contains(apiVersionFmt) ) {
471 addType = attrValue.substring(attrValue.lastIndexOf('.')+1);
472 if ( !generatedJavaType.containsKey(addType) ) {
473 generatedJavaType.put(addType, attrValue);
474 sb.append(processJavaTypeElement( addType, getJavaTypeElement(addType) ));
480 if ( attrName.equals("xml-key")) {
481 elementIsKey = attrValue;
483 if ( attrName.equals("required")) {
484 elementIsRequired = attrValue;
486 if ( attrName.equals("container-type")) {
487 elementContainerType = attrValue;
491 if ( xmlElementWrapper != null ) {
492 sb1.append(" <xs:element name=\"" + xmlElementWrapper +"\"");
493 if ( elementIsRequired == null || !elementIsRequired.equals("true")||addType != null) {
494 sb1.append(" minOccurs=\"0\"");
497 sb1.append(" <xs:complexType>\n");
498 properties = GenerateXsd.locateXmlProperties(javaTypeElement);
499 if (properties != null && useAnnotationsInXsd) {
500 sb1.append(" <xs:annotation>\r\n");
501 insertAnnotation(properties, false, "class", sb1, " ");
502 sb1.append(" </xs:annotation>\r\n");
504 System.out.println("no properties found for: " + xmlElementWrapper);
506 sb1.append(" <xs:sequence>\n");
509 if ("Nodes".equals(addType)) {
510 //System.out.println ("Skipping nodes, temporary testing");
513 if ( addType != null ) {
514 //sb1.append(" <xs:element ref=\"tns:" + elementName +"\"");
515 sb1.append(" <xs:element ref=\"tns:" + getXmlRootElementName(addType) +"\"");
517 sb1.append(" <xs:element name=\"" + elementName +"\"");
519 if ( elementType.equals("java.lang.String"))
520 sb1.append(" type=\"xs:string\"");
521 //if ( elementType.equals("java.lang.String"))
522 //sb1.append(" type=\"xs:string\"");
523 if ( elementType.equals("java.lang.Long"))
524 sb1.append(" type=\"xs:unsignedInt\"");
525 if ( elementType.equals("java.lang.Integer"))
526 sb1.append(" type=\"xs:int\"");
527 if ( elementType.equals("java.lang.Boolean"))
528 sb1.append(" type=\"xs:boolean\"");
529 //if ( elementIsRequired != null && elementIsRequired.equals("true")||addType != null) {
530 if ( elementIsRequired == null || !elementIsRequired.equals("true")||addType != null) {
531 sb1.append(" minOccurs=\"0\"");
533 if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) {
534 sb1.append(" maxOccurs=\"unbounded\"");
536 properties = GenerateXsd.locateXmlProperties(xmlElementElement);
537 if (properties != null || elementIsKey != null) {
539 if ( useAnnotationsInXsd ) {
540 sb1.append(" <xs:annotation>\r\n");
541 insertAnnotation(properties, elementIsKey != null, "field", sb1, " ");
542 sb1.append(" </xs:annotation>\r\n");
544 if (xmlElementWrapper== null) {
545 sb1.append(" </xs:element>\n");
550 if ( xmlElementWrapper != null ) {
551 sb1.append(" </xs:sequence>\n");
552 sb1.append(" </xs:complexType>\n");
553 sb1.append(" </xs:element>\n");
557 if ( xmlRootElementName.equals("notify") ||
558 xmlRootElementName.equals("relationship") ||
559 xmlRootElementName.equals("relationship-data") ||
560 xmlRootElementName.equals("related-to-property") )
562 sb1.append(" <xs:any namespace=\"##other\" processContents=\"lax\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n");
564 sb1.append(" </xs:sequence>\n");
565 sb1.append(" </xs:complexType>\n");
566 sb1.append(" </xs:element>\n");
569 NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
570 Element valElement = (Element) valNodes.item(0);
571 attributes = valElement.getAttributes();
572 for ( int i = 0; i < attributes.getLength(); ++i ) {
573 Attr attr = (Attr) attributes.item(i);
574 String attrName = attr.getNodeName();
576 String attrValue = attr.getNodeValue();
577 System.out.println("Found xml-root-element attribute: " + attrName + " with value: " + attrValue);
578 if ( attrValue.equals("name"))
579 xmlRootElementName = attrValue;
583 if ( xmlElementNodes.getLength() < 1 ) {
584 sb.append(" <xs:element name=\"" + xmlRootElementName + "\">\n");
585 sb.append(" <xs:complexType>\n");
586 sb.append(" <xs:sequence/>\n");
587 sb.append(" </xs:complexType>\n");
588 sb.append(" </xs:element>\n");
589 generatedJavaType.put(javaTypeName, null);
590 return sb.toString();
595 return sb.toString();
598 private static void insertAnnotation(NodeList items, boolean isKey, String target, StringBuffer sb1, String indentation) {
599 if (items != null || isKey) {
600 List<String> metadata = new ArrayList<>();
606 metadata.add("isKey=true");
609 for (int i = 0; i < items.getLength(); i++) {
610 item = (Element)items.item(i);
611 name = item.getAttribute("name");
612 value = item.getAttribute("value");
613 if (name.equals("abstract")) {
615 } else if (name.equals("extends")) {
616 name = "extendsFrom";
618 metadata.add(name + "=\"" + value.replaceAll("&", "&") + "\"");
619 //System.out.println("property name: " + name);
624 indentation + " <xs:appinfo>\r\n" +
625 indentation + " <annox:annotate target=\""+target+"\">@org.openecomp.aai.annotations.Metadata(" + Joiner.on(",").join(metadata) + ")</annox:annotate>\r\n" +
626 indentation + " </xs:appinfo>\r\n");
631 private static Element getJavaTypeElement( String javaTypeName )
634 String attrName, attrValue;
636 Element javaTypeElement;
637 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
638 javaTypeElement = (Element) javaTypeNodes.item(i);
639 NamedNodeMap attributes = javaTypeElement.getAttributes();
640 for ( int j = 0; j < attributes.getLength(); ++j ) {
641 attr = (Attr) attributes.item(j);
642 attrName = attr.getNodeName();
643 attrValue = attr.getNodeValue();
644 if ( attrName.equals("name") && attrValue.equals(javaTypeName))
645 return javaTypeElement;
648 System.out.println( "oxm file format error, missing java-type " + javaTypeName);
649 return (Element) null;
652 private static Element getJavaTypeElementSwagger( String javaTypeName )
655 String attrName, attrValue;
657 Element javaTypeElement;
658 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
659 javaTypeElement = (Element) javaTypeNodes.item(i);
660 NamedNodeMap attributes = javaTypeElement.getAttributes();
661 for ( int j = 0; j < attributes.getLength(); ++j ) {
662 attr = (Attr) attributes.item(j);
663 attrName = attr.getNodeName();
664 attrValue = attr.getNodeValue();
665 if ( attrName.equals("name") && attrValue.equals(javaTypeName))
666 return javaTypeElement;
669 System.out.println( "oxm file format error, missing java-type " + javaTypeName);
670 return (Element) null;
672 private static String getXmlRootElementName( String javaTypeName )
675 String attrName, attrValue;
677 Element javaTypeElement;
678 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
679 javaTypeElement = (Element) javaTypeNodes.item(i);
680 NamedNodeMap attributes = javaTypeElement.getAttributes();
681 for ( int j = 0; j < attributes.getLength(); ++j ) {
682 attr = (Attr) attributes.item(j);
683 attrName = attr.getNodeName();
684 attrValue = attr.getNodeValue();
685 if ( attrName.equals("name") && attrValue.equals(javaTypeName)) {
686 NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
687 Element valElement = (Element) valNodes.item(0);
688 attributes = valElement.getAttributes();
689 for ( int k = 0; k < attributes.getLength(); ++k ) {
690 attr = (Attr) attributes.item(k);
691 attrName = attr.getNodeName();
693 attrValue = attr.getNodeValue();
694 //System.out.println("Found xml-root-element attribute: " + attrName + " with value: " + attrValue);
695 if ( attrName.equals("name"))
701 System.out.println( "oxm file format error, missing java-type " + javaTypeName);
706 public static String processOxmFile( File oxmFile )
708 StringBuffer sb = new StringBuffer();
709 sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");
710 String namespace = "org.openecomp";
711 if ( useAnnotationsInXsd ) {
712 sb.append("<xs:schema elementFormDefault=\"qualified\" version=\"1.0\" targetNamespace=\"http://" + namespace + ".aai.inventory/"
713 + apiVersion + "\" xmlns:tns=\"http://" + namespace + ".aai.inventory/" + apiVersion + "\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
715 + "xmlns:jaxb=\"http://java.sun.com/xml/ns/jaxb\"\r\n" +
716 " jaxb:version=\"2.1\" \r\n" +
717 " xmlns:annox=\"http://annox.dev.java.net\" \r\n" +
718 " jaxb:extensionBindingPrefixes=\"annox\">\n\n");
720 sb.append("<xs:schema elementFormDefault=\"qualified\" version=\"1.0\" targetNamespace=\"http://" + namespace + ".aai.inventory/"
721 + apiVersion + "\" xmlns:tns=\"http://" + namespace + ".aai.inventory/" + apiVersion + "\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n\n");
726 DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
727 dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
728 DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
729 Document doc = dBuilder.parse(oxmFile);
731 NodeList bindingsNodes = doc.getElementsByTagName("xml-bindings");
732 Element bindingElement;
733 NodeList javaTypesNodes;
734 Element javaTypesElement;
736 Element javaTypeElement;
739 if ( bindingsNodes == null || bindingsNodes.getLength() == 0 ) {
740 System.out.println( "missing <binding-nodes> in " + oxmFile );
744 bindingElement = (Element) bindingsNodes.item(0);
745 javaTypesNodes = bindingElement.getElementsByTagName("java-types");
746 if ( javaTypesNodes.getLength() < 1 ) {
747 System.out.println( "missing <binding-nodes><java-types> in " + oxmFile );
750 javaTypesElement = (Element) javaTypesNodes.item(0);
751 javaTypeNodes = javaTypesElement.getElementsByTagName("java-type");
752 if ( javaTypeNodes.getLength() < 1 ) {
753 System.out.println( "missing <binding-nodes><java-types><java-type> in " + oxmFile );
758 String attrName, attrValue;
760 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
761 javaTypeElement = (Element) javaTypeNodes.item(i);
762 NamedNodeMap attributes = javaTypeElement.getAttributes();
764 for ( int j = 0; j < attributes.getLength(); ++j ) {
765 attr = (Attr) attributes.item(j);
766 attrName = attr.getNodeName();
767 attrValue = attr.getNodeValue();
768 if ( attrName.equals("name"))
769 javaTypeName = attrValue;
771 if ( javaTypeName == null ) {
772 System.out.println( "<java-type> has no name attribute in " + oxmFile );
775 if ("Nodes".equals(javaTypeName)) {
776 //System.out.println("skipping Nodes entry (temporary feature)");
779 if ( !generatedJavaType.containsKey(javaTypeName) ) {
780 generatedJavaType.put(javaTypeName, null);
781 sb.append(processJavaTypeElement( javaTypeName, javaTypeElement ));
785 } catch (Exception e) {
789 sb.append("</xs:schema>\n");
790 return sb.toString();
793 private static boolean isStandardType( String elementType )
795 switch ( elementType ) {
796 case "java.lang.String":
797 case "java.lang.Long":
798 case "java.lang.Integer":
799 case"java.lang.Boolean":
805 private static Vector<String> getIndexedProps( String attrValue )
807 if ( attrValue == null )
809 StringTokenizer st = new StringTokenizer( attrValue, ",");
810 if ( st.countTokens() == 0 )
812 Vector<String> result = new Vector<String>();
813 while ( st.hasMoreTokens()) {
814 result.add(st.nextToken());
819 private static Class<?> getEdgeRulesClass() throws ClassNotFoundException {
820 Class<?> result = null;
822 // If a class matching the apiVersion exists, we are generating documentation for a prior release
823 // Otherwise, we're generated documentation for the current release.
825 result = Class.forName("org.openecomp.aai.dbmodel." + apiVersion +".gen.DbEdgeRules");
826 } catch (ClassNotFoundException ex) {
827 result = Class.forName("org.openecomp.aai.dbmodel.DbEdgeRules");
833 * Guaranteed to at least return non null but empty collection of edge descriptions
834 * @param nodeName name of the vertex whose edge relationships to return
835 * @return collection of node neighbors based on DbEdgeRules
837 private static Collection<EdgeDescription> getEdgeRulesFromJson( String path, boolean skipMatch )
840 ArrayList<EdgeDescription> result = new ArrayList<>();
841 Iterator<Map<String, Object>> edgeRulesIterator;
844 GenerateXsd x = new GenerateXsd();
846 List<Map<String, Object>> inEdges = JsonPath.parse(jsonEdges).read(path);
848 edgeRulesIterator = inEdges.iterator();
849 Map<String, Object> edgeMap;
857 EdgeDescription edgeDes;
859 while( edgeRulesIterator.hasNext() ){
860 edgeMap = edgeRulesIterator.next();
861 fromNode = (String)edgeMap.get("from");
862 toNode = (String)edgeMap.get("to");
864 if ( fromNode.equals(toNode)) {
868 edgeDes = x.new EdgeDescription();
869 edgeDes.setRuleKey(fromNode + "|" + toNode);
870 direction = (String)edgeMap.get("direction");
871 edgeDes.setDirection(direction);
872 multiplicity = (String)edgeMap.get("multiplicity");
873 edgeDes.setMultiplicity(multiplicity);
874 isParent = (String)edgeMap.get("isParent");
875 if ( isParent != null && isParent.equals("true")) {
876 edgeDes.setType(LineageType.PARENT);
878 edgeDes.setType(LineageType.UNRELATED);
880 hasDelTarget = (String)edgeMap.get("hasDelTarget");
881 edgeDes.setHasDelTarget(hasDelTarget);
885 } catch (Exception ex) {
886 ex.printStackTrace();
893 * Guaranteed to at least return non null but empty collection of edge descriptions
894 * @param nodeName name of the vertex whose edge relationships to return
895 * @return collection of node neighbors based on DbEdgeRules
897 private static Collection<EdgeDescription> getEdgeRules( String nodeName )
899 String fromRulesPath = "$['rules'][?(@['from']=='" + nodeName + "')]";
900 String toRulesPath = "$['rules'][?(@['to']=='" + nodeName + "')]";
901 Collection<EdgeDescription> fromEdges = getEdgeRulesFromJson( fromRulesPath, false );
902 Collection<EdgeDescription> edges = getEdgeRulesFromJson( toRulesPath, true );
903 edges.addAll(fromEdges);
908 * Finds the default delete scope from DBEdgeRules
909 * @param nodeName name of vertex whose delete scope to return
910 * @return default delete scope of the input nodeName, null if none.
912 private static String getDeleteRules( String nodeName )
914 String result = null;
915 Iterator<String> delRulesIterator;
919 Field mapfield = versionedClass.getField("DefaultDeleteScope");
920 Object map = mapfield.get(null);
921 if (map instanceof Multimap<?,?>) {
922 delRulesIterator = ((Multimap<String,String>) map).keySet().iterator();
924 throw new NoSuchFieldException ("Didn't get back the multimap field expected");
927 while( delRulesIterator.hasNext() ){
928 String ruleKey = delRulesIterator.next();
929 if ( ruleKey.equals(nodeName)) {
930 Collection <String> deRuleColl = DbEdgeRules.DefaultDeleteScope.get(ruleKey);
931 Iterator <String> ruleItr = deRuleColl.iterator();
932 if( ruleItr.hasNext() ){
933 result = ruleItr.next();
938 } catch (Exception ex) {
939 ex.printStackTrace();
944 public static String processJavaTypeElementSwagger( String javaTypeName, Element javaTypeElement,
945 StringBuffer pathSb, StringBuffer definitionsSb, String path, String tag, String opId,
946 String getItemName, StringBuffer pathParams, String queryParams, String validEdges) {
948 String xmlRootElementName = null;
950 //Map<String, String> addJavaType = new HashMap<String, String>();
951 String useTag = null;
952 String useOpId = null;
957 case "ServiceDesignAndCreation":
959 case "LicenseManagement":
960 case "CloudInfrastructure":
968 System.out.println( "processJavaTypeElementSwagger called with null path for javaTypeName " + javaTypeName);
971 if ( path == null || !(path.contains("cloud-infrastructure")))
972 switch ( javaTypeName) {
977 case "CloudInfrastructure":
980 case "ServiceDesignAndCreation":
981 case "LicenseManagement":
984 useTag = javaTypeName;
993 if ( !javaTypeName.equals("Inventory") ) {
994 if ( javaTypeName.equals("AaiInternal"))
997 useOpId = javaTypeName;
999 useOpId = opId + javaTypeName;
1001 useTag = javaTypeName;
1005 if ( javaTypeName.equals("GenericVnf"))
1006 System.out.println( "Processing " + javaTypeName);
1007 else if ( javaTypeName.equals("Service"))
1008 System.out.println( "Processing " + javaTypeName);
1009 else if ( javaTypeName.equals("SitePair"))
1010 System.out.println( "Processing " + javaTypeName);
1012 NodeList parentNodes = javaTypeElement.getElementsByTagName("java-attributes");
1014 if ( parentNodes.getLength() == 0 ) {
1015 //System.out.println( "no java-attributes for java-type " + javaTypeName);
1020 NamedNodeMap attributes;
1022 NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
1023 Element valElement = (Element) valNodes.item(0);
1024 attributes = valElement.getAttributes();
1025 for ( int i = 0; i < attributes.getLength(); ++i ) {
1026 Attr attr = (Attr) attributes.item(i);
1027 String attrName = attr.getNodeName();
1029 String attrValue = attr.getNodeValue();
1030 //System.out.println("Found xml-root-element attribute: " + attrName + " with value: " + attrValue);
1031 if ( attrName.equals("name"))
1032 xmlRootElementName = attrValue;
1035 if ( xmlRootElementName.equals("oam-networks"))
1036 System.out.println( "xmlRootElement oam-networks with getItemData [" + getItemName + "]");
1040 if ( generatedJavaType.containsKey(xmlRootElementName) ) {
1044 NodeList childNodes;
1045 Element childElement;
1046 NodeList xmlPropNodes = javaTypeElement.getElementsByTagName("xml-properties");
1047 Element xmlPropElement;
1048 String pathDescriptionProperty = null;
1051 Vector<String> indexedProps = null;
1053 /*System.out.println( "javaTypeName " + javaTypeName + " has xml-properties length " + xmlPropNodes.getLength());
1054 if ( path != null && path.equals("/network/generic-vnfs"))
1055 System.out.println("path is " + "/network/generic-vnfs with getItemName " + getItemName);
1057 if ( xmlPropNodes.getLength() > 0 ) {
1059 for ( int i = 0; i < xmlPropNodes.getLength(); ++i ) {
1060 xmlPropElement = (Element)xmlPropNodes.item(i);
1061 if ( !xmlPropElement.getParentNode().isSameNode(javaTypeElement))
1063 childNodes = xmlPropElement.getElementsByTagName("xml-property");
1065 if ( childNodes.getLength() > 0 ) {
1066 for ( int j = 0; j < childNodes.getLength(); ++j ) {
1067 childElement = (Element)childNodes.item(j);
1069 int useValue = VALUE_NONE;
1070 attributes = childElement.getAttributes();
1071 for ( int k = 0; k < attributes.getLength(); ++k ) {
1072 Attr attr = (Attr) attributes.item(k);
1073 String attrName = attr.getNodeName();
1074 String attrValue = attr.getNodeValue();
1075 if ( attrName == null || attrValue == null )
1077 if ( attrName.equals("name") && attrValue.equals("description")) {
1078 useValue = VALUE_DESCRIPTION;
1080 if ( useValue == VALUE_DESCRIPTION && attrName.equals("value")) {
1081 pathDescriptionProperty = attrValue;
1083 //System.out.println("found xml-element-wrapper " + xmlElementWrapper);
1085 if ( attrValue.equals("indexedProps")) {
1086 useValue = VALUE_INDEXED_PROPS;
1088 if ( useValue == VALUE_INDEXED_PROPS && attrName.equals("value")) {
1089 indexedProps = getIndexedProps( attrValue );
1096 //System.out.println("javaTypeName " + javaTypeName + " description " + pathDescriptionProperty);
1099 if ( javaTypeName.equals("RelationshipList")) {
1100 System.out.println( "Skipping " + javaTypeName);
1101 generatedJavaType.put(javaTypeName, null);
1106 Element parentElement = (Element)parentNodes.item(0);
1107 NodeList xmlElementNodes = parentElement.getElementsByTagName("xml-element");
1110 String attrDescription = null;
1112 Element xmlElementElement;
1113 String addType = null;
1114 String elementType = null, elementIsKey = null, elementIsRequired, elementContainerType = null;
1115 String elementName = null;
1116 StringBuffer sbParameters = new StringBuffer();
1118 StringBuffer sbRequired = new StringBuffer();
1119 int requiredCnt = 0;
1120 int propertyCnt = 0;
1121 StringBuffer sbProperties = new StringBuffer();
1122 StringBuffer sbIndexedParams = new StringBuffer();
1126 if ( xmlRootElementName.equals("inventory"))
1128 else if ( path == null )
1129 //path = "/aai/" + apiVersion;
1130 path = "/" + xmlRootElementName;
1132 path += "/" + xmlRootElementName;
1133 st = new StringTokenizer(path, "/");
1135 if ( path.equals("/business/customers/customer/{global-customer-id}/service-subscriptions/service-subscription"))
1136 System.out.println("processing path /business/customers/customer/{global-customer-id}/service-subscriptions with tag " + tag);
1138 boolean genPath = false;
1140 if ( path != null && path.equals("/network/generic-vnfs/generic-vnf"))
1141 System.out.println("path is " + "/network/generic-vnfs/generic-vnf");
1143 if ( st.countTokens() > 1 && getItemName == null ) {
1144 if ( appliedPaths.containsKey(path))
1146 appliedPaths.put(path, null);
1148 if ( path.contains("/relationship/") ) { // filter paths with relationship-list
1151 if ( path.endsWith("/relationship-list")) {
1157 Vector<String> addTypeV = null;
1158 if ( xmlElementNodes.getLength() > 0 ) {
1160 for ( int i = 0; i < xmlElementNodes.getLength(); ++i ) {
1161 xmlElementElement = (Element)xmlElementNodes.item(i);
1162 if ( !xmlElementElement.getParentNode().isSameNode(parentElement))
1164 /*childNodes = xmlElementElement.getElementsByTagName("xml-element-wrapper");
1165 if ( childNodes.getLength() > 0 ) {
1166 childElement = (Element)childNodes.item(0);
1168 attributes = childElement.getAttributes();
1169 for ( int k = 0; k < attributes.getLength(); ++k ) {
1170 Attr attr = (Attr) attributes.item(k);
1171 String attrName = attr.getNodeName();
1172 String attrValue = attr.getNodeValue();
1173 if ( attrName.equals("name")) {
1174 xmlElementWrapper = attrValue;
1175 //System.out.println("found xml-element-wrapper " + xmlElementWrapper);
1181 valNodes = xmlElementElement.getElementsByTagName("xml-properties");
1182 attrDescription = null;
1183 if ( valNodes.getLength() > 0 ) {
1184 for ( int j = 0; j < valNodes.getLength(); ++j ) {
1185 valElement = (Element)valNodes.item(j);
1186 if ( !valElement.getParentNode().isSameNode(xmlElementElement))
1188 childNodes = valElement.getElementsByTagName("xml-property");
1189 if ( childNodes.getLength() > 0 ) {
1190 childElement = (Element)childNodes.item(0);
1192 attributes = childElement.getAttributes();
1193 attrDescription = null;
1194 boolean useValue = false;
1195 for ( int k = 0; k < attributes.getLength(); ++k ) {
1196 Attr attr = (Attr) attributes.item(k);
1197 String attrName = attr.getNodeName();
1198 String attrValue = attr.getNodeValue();
1199 if ( attrName.equals("name") && attrValue.equals("description")) {
1202 if ( useValue && attrName.equals("value")) {
1203 attrDescription = attrValue;
1204 //System.out.println("found xml-element-wrapper " + xmlElementWrapper);
1212 attributes = xmlElementElement.getAttributes();
1213 addTypeV = null; // vector of 1
1216 elementName = elementType = elementIsKey = elementIsRequired = elementContainerType = null;
1217 for ( int j = 0; j < attributes.getLength(); ++j ) {
1218 Attr attr = (Attr) attributes.item(j);
1219 String attrName = attr.getNodeName();
1221 String attrValue = attr.getNodeValue();
1222 //System.out.println("For " + xmlRootElementName + " Found xml-element attribute: " + attrName + " with value: " + attrValue);
1223 if ( attrName.equals("name")) {
1224 elementName = attrValue;
1227 if ( attrName.equals("type") && getItemName == null ) {
1228 elementType = attrValue;
1229 if ( attrValue.contains(apiVersionFmt) ) {
1230 addType = attrValue.substring(attrValue.lastIndexOf('.')+1);
1231 if ( addTypeV == null )
1232 addTypeV = new Vector<String>();
1233 addTypeV.add(addType);
1237 if ( attrName.equals("xml-key")) {
1238 elementIsKey = attrValue;
1239 path += "/{" + elementName + "}";
1241 if ( attrName.equals("required")) {
1242 elementIsRequired = attrValue;
1244 if ( attrName.equals("container-type")) {
1245 elementContainerType = attrValue;
1248 if ( getItemName != null ) {
1249 if ( getItemName.equals("array") ) {
1250 if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) {
1251 //System.out.println( " returning array " + elementName );
1255 } else { // not an array check
1256 if ( elementContainerType == null || !elementContainerType.equals("java.util.ArrayList")) {
1257 //System.out.println( " returning object " + elementName );
1262 //System.out.println( " returning null" );
1265 if ( elementIsRequired != null ) {
1266 if ( requiredCnt == 0 )
1267 sbRequired.append(" required:\n");
1269 if ( addTypeV != null ) {
1270 for ( int k = 0; k < addTypeV.size(); ++i ) {
1271 sbRequired.append(" - " + getXmlRootElementName(addTypeV.elementAt(k)) + ":\n");
1274 sbRequired.append(" - " + elementName + "\n");
1278 if ( elementIsKey != null ) {
1279 sbParameters.append((" - name: " + elementName + "\n"));
1280 sbParameters.append((" in: path\n"));
1281 if ( attrDescription != null && attrDescription.length() > 0 )
1282 sbParameters.append((" description: " + attrDescription + "\n"));
1283 sbParameters.append((" required: true\n"));
1284 if ( elementType.equals("java.lang.String"))
1285 sbParameters.append(" type: string\n");
1286 if ( elementType.equals("java.lang.Long")) {
1287 sbParameters.append(" type: integer\n");
1288 sbParameters.append(" format: int64\n");
1290 if ( elementType.equals("java.lang.Integer")) {
1291 sbParameters.append(" type: integer\n");
1292 sbParameters.append(" format: int32\n");
1294 if ( elementType.equals("java.lang.Boolean"))
1295 sbParameters.append(" type: boolean\n");
1298 } else if ( indexedProps != null
1299 && indexedProps.contains(elementName ) ) {
1300 sbIndexedParams.append((" - name: " + elementName + "\n"));
1301 sbIndexedParams.append((" in: query\n"));
1302 if ( attrDescription != null && attrDescription.length() > 0 )
1303 sbIndexedParams.append((" description: " + attrDescription + "\n"));
1304 sbIndexedParams.append((" required: false\n"));
1305 if ( elementType.equals("java.lang.String"))
1306 sbIndexedParams.append(" type: string\n");
1307 if ( elementType.equals("java.lang.Long")) {
1308 sbIndexedParams.append(" type: integer\n");
1309 sbIndexedParams.append(" format: int64\n");
1311 if ( elementType.equals("java.lang.Integer")) {
1312 sbIndexedParams.append(" type: integer\n");
1313 sbIndexedParams.append(" format: int32\n");
1315 if ( elementType.equals("java.lang.Boolean"))
1316 sbIndexedParams.append(" type: boolean\n");
1320 if ( elementName != null && elementName.equals("inventory-item"))
1321 System.out.println( "processing inventory-item elementName");
1324 if ( isStandardType(elementType)) {
1325 sbProperties.append(" " + elementName + ":\n");
1327 sbProperties.append(" type: ");
1329 if ( elementType.equals("java.lang.String"))
1330 sbProperties.append("string\n");
1331 else if ( elementType.equals("java.lang.Long")) {
1332 sbProperties.append("integer\n");
1333 sbProperties.append(" format: int64\n");
1335 else if ( elementType.equals("java.lang.Integer")){
1336 sbProperties.append("integer\n");
1337 sbProperties.append(" format: int32\n");
1339 else if ( elementType.equals("java.lang.Boolean"))
1340 sbProperties.append("boolean\n");
1341 if ( attrDescription != null && attrDescription.length() > 0 )
1342 sbProperties.append(" description: " + attrDescription + "\n");
1345 //if ( addType != null && elementContainerType != null && elementContainerType.equals("java.util.ArrayList") ) {
1347 if ( addTypeV != null ) {
1348 StringBuffer newPathParams = null;
1349 if ( pathParams != null ) {
1350 newPathParams = new StringBuffer();
1351 newPathParams.append(pathParams);
1353 if ( sbParameters.toString().length() > 0 ) {
1354 if ( newPathParams == null )
1355 newPathParams = new StringBuffer();
1356 newPathParams.append(sbParameters);
1358 String newQueryParams = null;
1359 if ( sbIndexedParams.toString().length() > 0 ) {
1360 if ( queryParams == null )
1361 newQueryParams = sbIndexedParams.toString();
1363 newQueryParams = queryParams + sbIndexedParams.toString();
1365 newQueryParams = queryParams;
1367 for ( int k = 0; k < addTypeV.size(); ++k ) {
1368 addType = addTypeV.elementAt(k);
1370 if ( opId == null || !opId.contains(addType)) {
1371 processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
1372 pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId, null,
1373 newPathParams, newQueryParams, validEdges);
1375 // need item name of array
1376 String itemName = processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
1377 pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId,
1378 "array", null, null, null );
1380 if ( itemName != null ) {
1381 if ( addType.equals("AaiInternal") ) {
1382 //System.out.println( "addType AaiInternal, skip properties");
1384 } else if ( getItemName == null) {
1386 sbProperties.append(" " + getXmlRootElementName(addType) + ":\n");
1387 sbProperties.append(" type: array\n items:\n");
1388 sbProperties.append(" $ref: \"#/definitions/" + itemName + "\"\n");
1389 if ( attrDescription != null && attrDescription.length() > 0 )
1390 sbProperties.append(" description: " + attrDescription + "\n");
1393 /*itemName = processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
1394 pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId, "other" );
1395 if ( itemName != null ) {
1397 if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) {
1398 // need properties for getXmlRootElementName(addType)
1399 newPathParams = null;
1400 if ( pathParams != null ) {
1401 newPathParams = new StringBuffer();
1402 newPathParams.append(pathParams);
1404 if ( sbParameters.toString().length() > 0 ) {
1405 if ( newPathParams == null )
1406 newPathParams = new StringBuffer();
1407 newPathParams.append(sbParameters);
1409 newQueryParams = null;
1410 if ( sbIndexedParams.toString().length() > 0 ) {
1411 if ( queryParams == null )
1412 newQueryParams = sbIndexedParams.toString();
1414 newQueryParams = queryParams + sbIndexedParams.toString();
1416 newQueryParams = queryParams;
1418 processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
1419 pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId,
1420 null, newPathParams, newQueryParams, validEdges );
1421 sbProperties.append(" " + getXmlRootElementName(addType) + ":\n");
1422 sbProperties.append(" type: array\n items: \n");
1423 sbProperties.append(" $ref: \"#/definitions/" + getXmlRootElementName(addType) + "\"\n");
1425 sbProperties.append(" " + getXmlRootElementName(addType) + ":\n");
1426 sbProperties.append(" type: object\n");
1427 sbProperties.append(" $ref: \"#/definitions/" + getXmlRootElementName(addType) + "\"\n");
1429 if ( attrDescription != null && attrDescription.length() > 0 )
1430 sbProperties.append(" description: " + attrDescription + "\n");
1434 System.out.println(" unable to define swagger object for " + addType);
1438 //if ( getItemName == null) looking for missing properties
1439 //generatedJavaType.put(addType, null);
1446 if ( useOpId.equals("CloudInfrastructureComplexesComplexCtagPools"))
1447 System.out.println( "adding path CloudInfrastructureComplexesComplexCtagPools");
1450 if ( !path.endsWith("/relationship") ) {
1451 pathSb.append(" " + path + ":\n" );
1452 pathSb.append(" get:\n");
1453 pathSb.append(" tags:\n");
1454 pathSb.append(" - " + tag + "\n");
1455 pathSb.append(" summary: returns " + xmlRootElementName + "\n");
1457 pathSb.append(" description: returns " + xmlRootElementName + "\n");
1458 pathSb.append(" operationId: get" + useOpId + "\n");
1459 pathSb.append(" produces:\n");
1460 pathSb.append(" - application/json\n");
1461 pathSb.append(" - application/xml\n");
1463 pathSb.append(" responses:\n");
1464 pathSb.append(" \"200\":\n");
1465 pathSb.append(" description: successful operation\n");
1466 pathSb.append(" schema:\n");
1467 pathSb.append(" $ref: \"#/definitions/" + xmlRootElementName + "\"\n");
1468 pathSb.append(" \"default\":\n");
1469 pathSb.append(" " + responsesUrl);
1471 pathSb.append(" \"200\":\n");
1472 pathSb.append(" description: successful operation\n");
1473 pathSb.append(" schema:\n");
1474 pathSb.append(" $ref: \"#/definitions/" + xmlRootElementName + "\"\n");
1475 pathSb.append(" \"404\":\n");
1476 pathSb.append(" description: resource was not found\n");
1477 pathSb.append(" \"400\":\n");
1478 pathSb.append(" description: bad request\n");
1480 if ( path.indexOf('{') > 0 ) {
1482 if ( sbParameters.toString().length() > 0 ) {
1483 if ( pathParams == null )
1484 pathParams = new StringBuffer();
1485 pathParams.append(sbParameters);
1487 if ( pathParams != null) {
1488 pathSb.append(" parameters:\n");
1489 pathSb.append(pathParams);
1491 System.out.println( "null pathParams for " + useOpId);
1492 if ( sbIndexedParams.toString().length() > 0 ) {
1493 if ( queryParams == null )
1494 queryParams = sbIndexedParams.toString();
1496 queryParams = queryParams + sbIndexedParams.toString();
1498 if ( queryParams != null ) {
1499 if ( pathParams == null ) {
1500 pathSb.append(" parameters:\n");
1502 pathSb.append(queryParams);
1506 boolean skipPutDelete = false; // no put or delete for "all"
1507 if ( !path.endsWith("/relationship") ) {
1508 if ( !path.endsWith("}") ){
1509 skipPutDelete = true;
1513 if ( path.indexOf('{') > 0 && !opId.startsWith("Search") &&!skipPutDelete) {
1515 if ( path.endsWith("/relationship") ) {
1516 pathSb.append(" " + path + ":\n" );
1518 pathSb.append(" put:\n");
1519 pathSb.append(" tags:\n");
1520 pathSb.append(" - " + tag + "\n");
1522 if ( path.endsWith("/relationship") ) {
1523 pathSb.append(" summary: see node definition for valid relationships\n");
1525 pathSb.append(" summary: create or update an existing " + xmlRootElementName + "\n");
1526 pathSb.append(" description: create or update an existing " + xmlRootElementName + "\n");
1528 pathSb.append(" operationId: createOrUpdate" + useOpId + "\n");
1529 pathSb.append(" consumes:\n");
1530 pathSb.append(" - application/json\n");
1531 pathSb.append(" - application/xml\n");
1532 pathSb.append(" produces:\n");
1533 pathSb.append(" - application/json\n");
1534 pathSb.append(" - application/xml\n");
1535 pathSb.append(" responses:\n");
1536 pathSb.append(" \"default\":\n");
1537 pathSb.append(" " + responsesUrl);
1539 pathSb.append(" responses:\n");
1540 pathSb.append(" \"200\":\n");
1541 pathSb.append(" description: existing resource has been modified and there is a response buffer\n");
1542 pathSb.append(" \"201\":\n");
1543 pathSb.append(" description: new resource is created\n");
1544 pathSb.append(" \"202\":\n");
1545 pathSb.append(" description: action requested but may have taken other actions as well, which are returned in the response payload\n");
1546 pathSb.append(" \"204\":\n");
1547 pathSb.append(" description: existing resource has been modified and there is no response buffer\n");
1548 pathSb.append(" \"400\":\n");
1549 pathSb.append(" description: Bad Request will be returned if headers are missing\n");
1550 pathSb.append(" \"404\":\n");
1551 pathSb.append(" description: Not Found will be returned if an unknown URL is used\n");
1553 pathSb.append(" parameters:\n");
1554 //pathSb.append(" - in: path\n");
1555 pathSb.append(pathParams); // for nesting
1556 pathSb.append(" - name: body\n");
1557 pathSb.append(" in: body\n");
1558 pathSb.append(" description: " + xmlRootElementName + " object that needs to be created or updated\n");
1559 pathSb.append(" required: true\n");
1560 pathSb.append(" schema:\n");
1561 pathSb.append(" $ref: \"#/definitions/" + xmlRootElementName + "\"\n");
1563 if ( queryParams != null ) {
1564 pathSb.append(queryParams);
1568 pathSb.append(" delete:\n");
1569 pathSb.append(" tags:\n");
1570 pathSb.append(" - " + tag + "\n");
1571 pathSb.append(" summary: delete an existing " + xmlRootElementName + "\n");
1573 pathSb.append(" description: delete an existing " + xmlRootElementName + "\n");
1575 pathSb.append(" operationId: delete" + useOpId + "\n");
1576 pathSb.append(" consumes:\n");
1577 pathSb.append(" - application/json\n");
1578 pathSb.append(" - application/xml\n");
1579 pathSb.append(" produces:\n");
1580 pathSb.append(" - application/json\n");
1581 pathSb.append(" - application/xml\n");
1582 pathSb.append(" responses:\n");
1583 pathSb.append(" \"default\":\n");
1584 pathSb.append(" " + responsesUrl);
1586 pathSb.append(" responses:\n");
1587 pathSb.append(" \"200\":\n");
1588 pathSb.append(" description: successful, the response includes an entity describing the status\n");
1589 pathSb.append(" \"204\":\n");
1590 pathSb.append(" description: successful, action has been enacted but the response does not include an entity\n");
1591 pathSb.append(" \"400\":\n");
1592 pathSb.append(" description: Bad Request will be returned if headers are missing\n");
1593 pathSb.append(" \"404\":\n");
1594 pathSb.append(" description: Not Found will be returned if an unknown URL is used\n");
1596 pathSb.append(" parameters:\n");
1597 //pathSb.append(" - in: path\n");
1598 pathSb.append(pathParams); // for nesting
1599 if ( !path.endsWith("/relationship") ) {
1600 pathSb.append(" - name: resource-version\n");
1602 pathSb.append(" in: query\n");
1603 pathSb.append(" description: resource-version for concurrency\n");
1604 pathSb.append(" required: true\n");
1605 pathSb.append(" type: string\n");
1608 if ( queryParams != null ) {
1609 pathSb.append(queryParams);
1615 if ( generatedJavaType.containsKey(xmlRootElementName) ) {
1619 definitionsSb.append(" " + xmlRootElementName + ":\n");
1620 Collection<EdgeDescription> edges = getEdgeRules(xmlRootElementName );
1621 if ( edges.size() > 0 ) {
1622 StringBuffer sbEdge = new StringBuffer();
1623 sbEdge.append(" ###### Related Nodes\n");
1624 for (EdgeDescription ed : edges) {
1625 if ( ed.getRuleKey().startsWith(xmlRootElementName)) {
1626 sbEdge.append(" - TO ").append(ed.getRuleKey().substring(ed.getRuleKey().indexOf("|")+1));
1627 sbEdge.append(ed.getRelationshipDescription("TO", xmlRootElementName));
1628 sbEdge.append("\n");
1631 for (EdgeDescription ed : edges) {
1632 if ( ed.getRuleKey().endsWith(xmlRootElementName)) {
1633 sbEdge.append(" - FROM ").append(ed.getRuleKey().substring(0, ed.getRuleKey().indexOf("|")));
1634 sbEdge.append(ed.getRelationshipDescription("FROM", xmlRootElementName));
1635 sbEdge.append("\n");
1638 validEdges = sbEdge.toString();
1641 String deleteRule = getDeleteRules(xmlRootElementName);
1642 // Handle description property. Might have a description OR valid edges OR both OR neither.
1643 // Only put a description: tag if there is at least one.
1644 if (pathDescriptionProperty != null || deleteRule != null || validEdges != null) {
1645 definitionsSb.append(" description: |\n");
1647 if ( pathDescriptionProperty != null )
1648 definitionsSb.append(" " + pathDescriptionProperty + "\n" );
1649 if (deleteRule != null)
1650 definitionsSb.append(" ###### Default Delete Scope\n ").append(deleteRule).append("\n");
1651 if (validEdges != null)
1652 definitionsSb.append(validEdges);
1655 if ( requiredCnt > 0 )
1656 definitionsSb.append(sbRequired);
1657 if ( propertyCnt > 0 ) {
1658 definitionsSb.append(" properties:\n");
1659 definitionsSb.append(sbProperties);
1661 generatedJavaType.put(xmlRootElementName, null);
1665 public static String generateSwaggerFromOxmFile( File oxmFile )
1668 StringBuffer sb = new StringBuffer();
1669 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");
1670 sb.append(" title: Active and Available Inventory REST API\n");
1671 sb.append(" license:\n name: Apache 2.0\n url: http://www.apache.org/licenses/LICENSE-2.0.html\n");
1672 sb.append(" contact:\n name:\n url:\n email:\n");
1673 sb.append("host:\nbasePath: /aai/" + apiVersion + "\n");
1674 sb.append("schemes:\n - https\npaths:\n");
1676 sb.append("responses:\n");
1677 sb.append(" \"200\":\n");
1678 sb.append(" description: successful operation\n");
1679 sb.append(" \"404\":\n");
1680 sb.append(" description: resource was not found\n");
1681 sb.append(" \"400\":\n");
1682 sb.append(" description: bad request\n");
1685 versionedClass = getEdgeRulesClass();
1686 File initialFile = new File("src/main/resources/dbedgerules/DbEdgeRules_" + apiVersion + ".json");
1687 InputStream is = new FileInputStream(initialFile);
1689 Scanner scanner = new Scanner(is);
1690 jsonEdges = scanner.useDelimiter("\\Z").next();
1694 DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
1695 dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
1696 DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
1697 Document doc = dBuilder.parse(oxmFile);
1699 NodeList bindingsNodes = doc.getElementsByTagName("xml-bindings");
1700 Element bindingElement;
1701 NodeList javaTypesNodes;
1702 Element javaTypesElement;
1704 Element javaTypeElement;
1707 if ( bindingsNodes == null || bindingsNodes.getLength() == 0 ) {
1708 System.out.println( "missing <binding-nodes> in " + oxmFile );
1712 bindingElement = (Element) bindingsNodes.item(0);
1713 javaTypesNodes = bindingElement.getElementsByTagName("java-types");
1714 if ( javaTypesNodes.getLength() < 1 ) {
1715 System.out.println( "missing <binding-nodes><java-types> in " + oxmFile );
1718 javaTypesElement = (Element) javaTypesNodes.item(0);
1720 javaTypeNodes = javaTypesElement.getElementsByTagName("java-type");
1721 if ( javaTypeNodes.getLength() < 1 ) {
1722 System.out.println( "missing <binding-nodes><java-types><java-type> in " + oxmFile );
1726 String javaTypeName;
1727 String attrName, attrValue;
1729 StringBuffer pathSb = new StringBuffer();
1731 StringBuffer definitionsSb = new StringBuffer("definitions:\n");
1733 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
1734 javaTypeElement = (Element) javaTypeNodes.item(i);
1735 NamedNodeMap attributes = javaTypeElement.getAttributes();
1736 javaTypeName = null;
1737 for ( int j = 0; j < attributes.getLength(); ++j ) {
1738 attr = (Attr) attributes.item(j);
1739 attrName = attr.getNodeName();
1740 attrValue = attr.getNodeValue();
1741 if ( attrName.equals("name"))
1742 javaTypeName = attrValue;
1744 if ( javaTypeName == null ) {
1745 System.out.println( "<java-type> has no name attribute in " + oxmFile );
1748 if ( !generatedJavaType.containsKey(getXmlRootElementName(javaTypeName)) ) {
1750 //generatedJavaType.put(javaTypeName, null);
1751 //if ( javaTypeName.equals("search")||javaTypeName.equals("actions"))
1753 processJavaTypeElementSwagger( javaTypeName, javaTypeElement, pathSb,
1754 definitionsSb, null, null, null, null, null, null, null);
1758 //System.out.println( "definitions block\n" + definitionsSb.toString());
1759 sb.append(definitionsSb.toString());
1760 //sb.append(definitionsSb);
1762 } catch (Exception e) {
1763 e.printStackTrace();
1766 //System.out.println("generated " + sb.toString());
1767 return sb.toString();
1770 private static NodeList locateXmlProperties(Element element) {
1771 XPathExpression expr;
1772 NodeList result = null;
1774 expr = xpath.compile("xml-properties");
1776 Object nodeset = expr.evaluate(element, XPathConstants.NODESET);
1777 if (nodeset != null) {
1778 NodeList nodes = (NodeList) nodeset;
1779 if (nodes != null && nodes.getLength() > 0) {
1780 Element xmlProperty = (Element)nodes.item(0);
1781 result = xmlProperty.getElementsByTagName("xml-property");
1785 } catch (XPathExpressionException e) {
1786 e.printStackTrace();