a1668886e551b8f111b7f2ddfa378aefe008ee06
[aai/aai-common.git] / aai-core / src / main / java / org / openecomp / aai / util / GenerateXsd.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * org.openecomp.aai
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
10
11      http://www.apache.org/licenses/LICENSE-2.0
12
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=========================================================
19  */
20
21 package org.openecomp.aai.util;
22
23 import java.io.BufferedWriter;
24 import java.io.File;
25 import java.io.FileWriter;
26 import java.io.IOException;
27 import java.lang.reflect.Field;
28 import java.util.ArrayList;
29 import java.util.Collection;
30 import java.util.HashMap;
31 import java.util.Iterator;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.StringTokenizer;
35 import java.util.Vector;
36
37 import javax.xml.XMLConstants;
38 import javax.xml.bind.JAXBContext;
39 import javax.xml.bind.JAXBException;
40 import javax.xml.bind.SchemaOutputResolver;
41 import javax.xml.parsers.DocumentBuilder;
42 import javax.xml.parsers.DocumentBuilderFactory;
43 import javax.xml.transform.Result;
44 import javax.xml.transform.stream.StreamResult;
45 import javax.xml.xpath.XPath;
46 import javax.xml.xpath.XPathConstants;
47 import javax.xml.xpath.XPathExpression;
48 import javax.xml.xpath.XPathExpressionException;
49 import javax.xml.xpath.XPathFactory;
50
51 import org.w3c.dom.Attr;
52 import org.w3c.dom.Document;
53 import org.w3c.dom.Element;
54 import org.w3c.dom.NamedNodeMap;
55 import org.w3c.dom.NodeList;
56
57 import org.openecomp.aai.dbmodel.DbEdgeRules;
58 import com.google.common.base.Joiner;
59 import com.google.common.collect.Multimap;
60
61
62 public class GenerateXsd {
63         static String apiVersion = null;
64         static String apiVersionFmt = null;
65         static String responsesUrl = null;
66         static String responsesLabel = null;
67         static Map<String, String> generatedJavaType = new HashMap<String, String>();
68         static Map<String, String> appliedPaths = new HashMap<String, String>();
69         static NodeList javaTypeNodes;
70         static Class<?> versionedClass;
71
72         
73         public static final int VALUE_NONE = 0;
74         public static final int VALUE_DESCRIPTION = 1;
75         public static final int VALUE_INDEXED_PROPS = 2;
76         
77         private static XPath xpath = XPathFactory.newInstance().newXPath();
78         
79
80         private enum LineageType {
81                 PARENT, CHILD, UNRELATED;
82         }
83         private class EdgeDescription {
84                 
85                 private String ruleKey;
86                 private LineageType type = LineageType.UNRELATED;
87                 private String direction;
88                 private String multiplicity;
89                 private boolean hasDelTarget = false;
90
91                 public String getRuleKey() {
92                         return ruleKey;
93                 }
94                 public String getMultiplicity() {
95                         return multiplicity;
96                 }
97                 public String getDirection() {
98                         return direction;
99                 }
100                 public void setRuleKey(String val) {
101                         this.ruleKey=val;
102                 }
103                 public void setType(LineageType val) {
104                         this.type=val;
105                 }
106                 public void setDirection(String val) {
107                         this.direction = val;
108                 }
109                 public void setMultiplicity(String val) {
110                         this.multiplicity=val;
111                 }
112                 public void setHasDelTarget(String val) {
113                         hasDelTarget = Boolean.parseBoolean(val);
114                 }
115
116                 public String getRelationshipDescription(String fromTo, String otherNodeName) {
117                         
118                         String result = "";             
119
120                         if ("FROM".equals(fromTo)) {
121                                 if ("OUT".equals(direction)) {
122                                         if (LineageType.PARENT == type) {
123                                                 result = " (is composed of "+otherNodeName;
124                                         } 
125                                 } 
126                                 else {
127                                         if (LineageType.CHILD == type) {
128                                                 result = " (comprises "+otherNodeName;
129                                         } 
130                                         else if (LineageType.PARENT == type) {
131                                                 result = " (comprises "+otherNodeName;
132                                         }
133                                 }
134                         } else {
135                                 if ("OUT".equals(direction)) {
136                                         if (LineageType.PARENT == type) {
137                                                 result = " (comprises "+otherNodeName;
138                                         } 
139                                 } else {
140                                         if (LineageType.PARENT == type) {
141                                                 result = " (is composed of "+otherNodeName;
142                                         }
143                                 }
144                         }
145
146 //                      if (type != null) {
147 //                              if (LineageType.PARENT.equals(type) && "FROM".equals(fromTo)) {
148 //                                      if ("OUT".equals(direction)) {
149 //                                              result = " (is composed of "+otherNodeName;
150 //                                      } else {
151 //                                              result = " (comprises "+otherNodeName;
152 //                                      }
153 //                              } else {
154 //                                      result = " (comprises " + otherNodeName;
155 //                                      //                                      if (!(multiplicity.startsWith("One"))) {
156 //                                      //                                              System.err.println("Surprised to find multiplicity "+multiplicity+" with comprises for "+ruleKey);
157 //                                      //                                      }
158 //                              }
159 //                      }
160                         if ("TO".equals(fromTo)) {
161                                 if (result.length() == 0) result = result + " (";
162                                 else result = result + ", ";
163
164                                 result = result + mapMultiplicity(fromTo);
165                                 if (hasDelTarget) result = result + ", will delete target node";
166                         }
167
168                         if (result.length() > 0) result = result + ")";
169                         
170                         return result;
171                 }
172
173                 private String mapMultiplicity(String fromTo) {
174                         String result = multiplicity;
175 // Below logic works if an IN switches multiplicity, which it doesn't today.
176 //                      if ("TO".equals(fromTo)) {
177 //                              if (direction.equals("OUT")) {
178 //                                      result = multiplicity;
179 //                              } else {
180 //                                      result = switchMultiplicity(multiplicity);
181 //                              }
182 //                      } else {
183 //                              if (direction.equals("OUT")) {
184 //                                      result = multiplicity;
185 //                              } else {
186 //                                      result = switchMultiplicity(multiplicity);
187 //                              }
188 //                      } 
189                         return result;
190                 }
191
192 //              private String switchMultiplicity(String val) throws IllegalArgumentException
193 //              {
194 //                      String result = null;
195 //                      switch (val) {
196 //                      case "Many2Many":
197 //                      case "One2One":
198 //                              result = val;
199 //                              break;
200 //                      case "Many2One":
201 //                              result = "One2Many";
202 //                              break;
203 //                      case "One2Many":
204 //                              result = "Many2One";
205 //                              break;
206 //                      default:
207 //                              throw new IllegalArgumentException("Multiplicity cannot be "+val);
208 //                      }
209 //                      System.out.println("Switched Multiplicity from "+val+" to "+result);
210 //                      return result;
211 //              }
212         }
213         
214         public static void main(String[] args) throws IOException {
215         
216                 if (args.length > 0) { 
217                         if (args[0] != null) {
218                                 apiVersion = args[0];
219                         }
220                 }
221                 boolean genDoc = false;
222                 if ( args.length > 1 ) {
223                         genDoc = true;
224                         int index = args[1].indexOf("|");
225                         if ( index > 0 ) {
226                                 responsesUrl = args[1].substring(0, index);
227                                 responsesLabel = args[1].substring(index+1);
228                                 //System.out.println( "response URL " + responsesUrl);
229                                 //System.out.println( "response label " + responsesLabel);
230                                 responsesUrl = "description: "+ responsesLabel + "(" +
231                                                 responsesUrl + ").\n";
232                                 //System.out.println( "operation described with " + responsesUrl);
233                         } else { // default
234                                 responsesUrl = "";
235                         }
236                 }
237                 String oxmPath = null;
238                 if ( apiVersion == null ) { 
239                         // to run from eclipse, set these env, e.g. v7, \sources\aai\aaimastergit\bundleconfig-local\etc\oxm\
240                         String envRev= System.getenv("OXM_REV");
241                         if ( envRev != null )
242                                 apiVersion = envRev;
243                         
244                 }
245                 oxmPath = System.getenv("OXM_PATH");    
246                 String outfileName;
247                 if ( genDoc ) {
248                         outfileName = "c:\\temp\\aai.yaml";
249                 } else
250                         outfileName = "c:\\temp\\aai_schema.xsd";
251                 if ( apiVersion != null ) { // generate from oxm
252                         apiVersionFmt = "." + apiVersion + ".";
253                         if ( oxmPath == null ) {
254                                 oxmPath = AAIConstants.AAI_HOME_ETC_OXM + AAIConstants.AAI_FILESEP;
255                                 //oxmPath = "\\sources\\aai\\aaimastergit\\bundleconfig-local\\etc\\oxm\\";
256                         }
257                                 
258                         File oxm_file = new File(oxmPath + "aai_oxm_" + apiVersion + ".xml");
259                         String xsd;
260                         File outfile;
261                         if ( genDoc ) {
262                                 xsd = generateSwaggerFromOxmFile( oxm_file);
263                                 outfile =new File(outfileName);                         
264                         } else {
265                                 xsd = processOxmFile( oxm_file);
266                                 outfile =new File(outfileName);
267                         }
268                         
269                         
270                     try {
271                         outfile.createNewFile();
272                     } catch (IOException e) {
273                         System.out.println( "Exception creating output file " + outfileName);
274                         e.printStackTrace();
275                     }
276                 try {
277                         FileWriter fw = new FileWriter(outfile.getAbsoluteFile());
278                         BufferedWriter bw = new BufferedWriter(fw);
279                         bw.write(xsd);
280                         bw.close();
281
282                 } catch ( IOException e) {
283                         System.out.println( "Exception writing output file " + outfileName);
284                         e.printStackTrace();
285                 }
286                         System.out.println( "GeneratedXSD successful, saved in " + outfileName);
287                         return;
288                 }
289                 
290                 JAXBContext jaxbContext = null;
291                 try {
292                         jaxbContext = JAXBContext.newInstance(org.openecomp.aai.domain.yang.Vce.class);
293                 } catch (JAXBException e) {
294
295                         e.printStackTrace();
296                 }
297                 SchemaOutputResolver sor = new MySchemaOutputResolver();
298                 jaxbContext.generateSchema(sor);
299                 
300         }
301
302         public static class MySchemaOutputResolver extends SchemaOutputResolver {
303
304                 public Result createOutput(String namespaceURI, String suggestedFileName) throws IOException {
305                         File file = new File("c:\\temp\\aai_schema.xsd");
306                         StreamResult result = new StreamResult(file);
307                         result.setSystemId(file.toURI().toURL().toString());
308                         return result;
309                 }
310
311         }
312         
313         public static String processJavaTypeElement( String javaTypeName, Element javaTypeElement) {
314                 
315                 String xmlRootElementName = null;
316
317                 NodeList parentNodes = javaTypeElement.getElementsByTagName("java-attributes");
318                 StringBuffer sb = new StringBuffer();
319                 if ( parentNodes.getLength() == 0 ) {
320                         System.out.println( "no java-attributes for java-type " + javaTypeName);
321                         return "";
322
323                 }
324                 
325                 NamedNodeMap attributes;
326                 
327                 NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
328                 Element valElement = (Element) valNodes.item(0);
329                 attributes = valElement.getAttributes();
330                 for ( int i = 0; i < attributes.getLength(); ++i ) {
331             Attr attr = (Attr) attributes.item(i);
332             String attrName = attr.getNodeName();
333
334             String attrValue = attr.getNodeValue();
335             //System.out.println("Found xml-root-element attribute: " + attrName + " with value: " + attrValue);
336             if ( attrName.equals("name"))
337                 xmlRootElementName = attrValue;
338                 }
339                 /*
340                 if ( javaTypeName.equals("RelationshipList")) {
341                         System.out.println( "Skipping " + javaTypeName);
342                         generatedJavaType.put(javaTypeName, null);
343                         return "";
344                 }
345                 */
346                 
347                 Element parentElement = (Element)parentNodes.item(0);
348                 NodeList xmlElementNodes = parentElement.getElementsByTagName("xml-element");
349                 NodeList childNodes;
350                 Element childElement;
351                 String xmlElementWrapper;
352
353                 Element xmlElementElement;
354                 String addType;
355                 String elementName, elementType, elementIsKey, elementIsRequired, elementContainerType;
356                 StringBuffer sb1 = new StringBuffer();
357                 if ( xmlElementNodes.getLength() > 0 ) {
358                         sb1.append("  <xs:element name=\"" + xmlRootElementName + "\">\n");
359                         sb1.append("    <xs:complexType>\n");
360                         NodeList properties = GenerateXsd.locateXmlProperties(javaTypeElement);
361                         if (properties != null) {
362                                 System.out.println("properties found for: " + xmlRootElementName);
363                                 sb1.append("      <xs:annotation>\r\n");
364                                 insertAnnotation(properties, false, "class", sb1, "      ");
365                                 
366                                 sb1.append("      </xs:annotation>\r\n");
367                         } else {
368                                 System.out.println("no properties found for: " + xmlRootElementName);
369                         }
370                         sb1.append("      <xs:sequence>\n");
371                         for ( int i = 0; i < xmlElementNodes.getLength(); ++i ) {
372                                 
373                                 xmlElementElement = (Element)xmlElementNodes.item(i);
374                                 childNodes = xmlElementElement.getElementsByTagName("xml-element-wrapper");
375                                 
376                                 xmlElementWrapper = null;
377                                 if ( childNodes.getLength() > 0 ) {
378                                         childElement = (Element)childNodes.item(0);
379                                         // get name
380                                         attributes = childElement.getAttributes();
381                                         for ( int k = 0; k < attributes.getLength(); ++k ) {
382                                                 Attr attr = (Attr) attributes.item(k);
383                                                 String attrName = attr.getNodeName();
384                                                 String attrValue = attr.getNodeValue();
385                                                 if ( attrName.equals("name")) {
386                                                         xmlElementWrapper = attrValue;
387                                                         //System.out.println("found xml-element-wrapper " + xmlElementWrapper);
388                                                 }
389                                         }
390
391                                 }
392                                 attributes = xmlElementElement.getAttributes();
393                                 addType = null;
394         
395          
396                                 elementName = elementType = elementIsKey = elementIsRequired = elementContainerType = null;
397                                 for ( int j = 0; j < attributes.getLength(); ++j ) {
398                             Attr attr = (Attr) attributes.item(j);
399                             String attrName = attr.getNodeName();
400         
401                             String attrValue = attr.getNodeValue();
402                             //System.out.println("For " + xmlRootElementName + " Found xml-element attribute: " + attrName + " with value: " + attrValue);
403                             if ( attrName.equals("name")) {
404                                 elementName = attrValue;
405                             }
406                             if ( attrName.equals("type")) {
407                                 elementType = attrValue;
408                                 if ( attrValue.contains(apiVersionFmt) ) {
409                                         addType = attrValue.substring(attrValue.lastIndexOf('.')+1);
410                                         if ( !generatedJavaType.containsKey(addType) ) {
411                                                 generatedJavaType.put(addType, attrValue);
412                                                 sb.append(processJavaTypeElement( addType, getJavaTypeElement(addType) ));      
413                                         }
414                                 }
415                                         
416                             }
417
418                             if ( attrName.equals("xml-key")) {
419                                 elementIsKey = attrValue;
420                             }
421                             if ( attrName.equals("required")) {
422                                 elementIsRequired = attrValue;
423                             }
424                             if ( attrName.equals("container-type")) {
425                                 elementContainerType = attrValue;
426                             }   
427                                 }
428         
429                                 if ( xmlElementWrapper != null ) {
430                                         sb1.append("        <xs:element name=\"" + xmlElementWrapper +"\"");
431                                         if ( elementIsRequired == null || !elementIsRequired.equals("true")||addType != null) { 
432                                                 sb1.append(" minOccurs=\"0\""); 
433                                         } 
434                                         sb1.append(">\n");
435                                         sb1.append("          <xs:complexType>\n");
436                                         properties = GenerateXsd.locateXmlProperties(javaTypeElement);
437                                         if (properties != null) {
438                                                 sb1.append("            <xs:annotation>\r\n");
439                                                 insertAnnotation(properties, false, "class", sb1, "            ");
440                                                 sb1.append("            </xs:annotation>\r\n");
441                                         } else {
442                                                 System.out.println("no properties found for: " + xmlElementWrapper);
443                                         }
444                                         sb1.append("            <xs:sequence>\n");
445                                         sb1.append("      ");
446                                 }
447                 if ("Nodes".equals(addType)) {
448                         System.out.println ("Skipping nodes, temporary testing");
449                         continue;
450                 }
451                                 if ( addType != null ) {
452                                         //sb1.append("        <xs:element ref=\"tns:" + elementName +"\"");
453                                         sb1.append("        <xs:element ref=\"tns:" + getXmlRootElementName(addType) +"\"");
454                                 } else {
455                                         sb1.append("        <xs:element name=\"" + elementName +"\"");
456                                 }
457                                 if ( elementType.equals("java.lang.String"))
458                                         sb1.append(" type=\"xs:string\"");
459                                 //if ( elementType.equals("java.lang.String"))
460                                         //sb1.append(" type=\"xs:string\"");
461                                 if ( elementType.equals("java.lang.Long"))
462                                         sb1.append(" type=\"xs:unsignedInt\"");
463                                 if ( elementType.equals("java.lang.Integer"))
464                                         sb1.append(" type=\"xs:int\"");
465                                 if ( elementType.equals("java.lang.Boolean"))
466                                         sb1.append(" type=\"xs:boolean\"");
467                                 //if ( elementIsRequired != null && elementIsRequired.equals("true")||addType != null) {
468                                 if ( elementIsRequired == null || !elementIsRequired.equals("true")||addType != null) { 
469                                         sb1.append(" minOccurs=\"0\"");
470                                 } 
471                                 if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) {
472                                         sb1.append(" maxOccurs=\"unbounded\"");
473                                 }
474                                 properties = GenerateXsd.locateXmlProperties(xmlElementElement);
475                                 if (properties != null || elementIsKey != null) {
476                                         sb1.append(">\n");
477                                         sb1.append("          <xs:annotation>\r\n");
478                                         insertAnnotation(properties, elementIsKey != null, "field", sb1, "          ");
479                                         sb1.append("          </xs:annotation>\r\n");
480
481                                         if (xmlElementWrapper== null) {
482                                                 sb1.append("        </xs:element>\n");
483                                         }
484                                 } else {
485                                         sb1.append("/>\n");
486                                 }
487                                 if ( xmlElementWrapper != null ) {
488                                         sb1.append("            </xs:sequence>\n");
489                                         sb1.append("          </xs:complexType>\n");
490                                         sb1.append("        </xs:element>\n");
491                                 }
492                         }
493                         /*
494                 if (  xmlRootElementName.equals("notify") ||
495                         xmlRootElementName.equals("relationship") ||
496                         xmlRootElementName.equals("relationship-data") ||
497                         xmlRootElementName.equals("related-to-property") )
498                         
499                         sb1.append("        <xs:any namespace=\"##other\" processContents=\"lax\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n");
500                 */      
501                 sb1.append("      </xs:sequence>\n");
502                 sb1.append("    </xs:complexType>\n");
503                 sb1.append("  </xs:element>\n");
504                 }
505                 /*
506                 NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
507                 Element valElement = (Element) valNodes.item(0);
508                 attributes = valElement.getAttributes();
509                 for ( int i = 0; i < attributes.getLength(); ++i ) {
510             Attr attr = (Attr) attributes.item(i);
511             String attrName = attr.getNodeName();
512
513             String attrValue = attr.getNodeValue();
514             System.out.println("Found xml-root-element attribute: " + attrName + " with value: " + attrValue);
515             if ( attrValue.equals("name"))
516                 xmlRootElementName = attrValue;
517                 }
518                 */
519                 
520                 if ( xmlElementNodes.getLength() < 1 ) {
521                         sb.append("  <xs:element name=\"" + xmlRootElementName + "\">\n");
522                         sb.append("    <xs:complexType>\n");
523                         sb.append("      <xs:sequence/>\n");
524                         sb.append("    </xs:complexType>\n");
525                         sb.append("  </xs:element>\n");
526                         generatedJavaType.put(javaTypeName, null);
527                         return sb.toString();                   
528                 }
529                 
530                 sb.append( sb1 );
531
532                 return sb.toString();
533         }
534         
535         private static void insertAnnotation(NodeList items, boolean isKey, String target, StringBuffer sb1, String indentation) {
536                 if (items != null || isKey) {
537                         List<String> metadata = new ArrayList<>();
538                         
539                         String name = "";
540                         String value = "";
541                         Element item = null;
542                         if (isKey) {
543                                 metadata.add("isKey=true");
544                         }
545                         if (items != null) {
546                                 for (int i = 0; i < items.getLength(); i++) {
547                                         item = (Element)items.item(i);
548                                         name = item.getAttribute("name");
549                                         value = item.getAttribute("value");
550                                         if (name.equals("abstract")) {
551                                                 name = "isAbstract";
552                                         } else if (name.equals("extends")) {
553                                                 name = "extendsFrom";
554                                         }
555                                         metadata.add(name + "=\"" + value.replaceAll("&",  "&amp;") + "\"");
556                                         System.out.println("property name: " + name);
557         
558                                 }
559                         }
560                         sb1.append(
561                                         indentation + "  <xs:appinfo>\r\n" + 
562                                                         indentation + "    <annox:annotate target=\""+target+"\">@org.openecomp.aai.annotations.Metadata(" + Joiner.on(",").join(metadata) + ")</annox:annotate>\r\n" + 
563                                                         indentation + "  </xs:appinfo>\r\n");
564                 }
565
566         }
567
568         private static Element getJavaTypeElement( String javaTypeName )
569         {
570                 
571                 String attrName, attrValue;
572                 Attr attr;
573                 Element javaTypeElement;
574                 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
575                         javaTypeElement = (Element) javaTypeNodes.item(i);
576                         NamedNodeMap attributes = javaTypeElement.getAttributes();
577                         for ( int j = 0; j < attributes.getLength(); ++j ) {
578                     attr = (Attr) attributes.item(j);
579                     attrName = attr.getNodeName();
580                     attrValue = attr.getNodeValue();
581                     if ( attrName.equals("name") && attrValue.equals(javaTypeName))
582                         return javaTypeElement;
583                         }
584                 }
585                 System.out.println( "oxm file format error, missing java-type " + javaTypeName);
586                 return (Element) null;
587         }
588         
589         private static Element getJavaTypeElementSwagger( String javaTypeName )
590         {
591                 
592                 String attrName, attrValue;
593                 Attr attr;
594                 Element javaTypeElement;
595                 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
596                         javaTypeElement = (Element) javaTypeNodes.item(i);
597                         NamedNodeMap attributes = javaTypeElement.getAttributes();
598                         for ( int j = 0; j < attributes.getLength(); ++j ) {
599                     attr = (Attr) attributes.item(j);
600                     attrName = attr.getNodeName();
601                     attrValue = attr.getNodeValue();
602                     if ( attrName.equals("name") && attrValue.equals(javaTypeName))
603                         return javaTypeElement;
604                         }
605                 }
606                 System.out.println( "oxm file format error, missing java-type " + javaTypeName);
607                 return (Element) null;
608         }
609         private static String getXmlRootElementName( String javaTypeName )
610         {
611                 
612                 String attrName, attrValue;
613                 Attr attr;
614                 Element javaTypeElement;
615                 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
616                         javaTypeElement = (Element) javaTypeNodes.item(i);
617                         NamedNodeMap attributes = javaTypeElement.getAttributes();
618                         for ( int j = 0; j < attributes.getLength(); ++j ) {
619                     attr = (Attr) attributes.item(j);
620                     attrName = attr.getNodeName();
621                     attrValue = attr.getNodeValue();
622                     if ( attrName.equals("name") && attrValue.equals(javaTypeName)) {
623                                 NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
624                                 Element valElement = (Element) valNodes.item(0);
625                                 attributes = valElement.getAttributes();
626                                 for ( int k = 0; k < attributes.getLength(); ++k ) {
627                             attr = (Attr) attributes.item(k);
628                             attrName = attr.getNodeName();
629
630                             attrValue = attr.getNodeValue();
631                             //System.out.println("Found xml-root-element attribute: " + attrName + " with value: " + attrValue);
632                             if ( attrName.equals("name"))
633                                 return (attrValue);
634                                 }
635                     }
636                         }
637                 }
638                 System.out.println( "oxm file format error, missing java-type " + javaTypeName);
639                 return null;
640         }       
641         
642         
643         public static String processOxmFile( File oxmFile )
644         {
645                 StringBuffer sb = new StringBuffer();
646                 sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");
647                 String namespace = "org.openecomp";
648                 sb.append("<xs:schema elementFormDefault=\"qualified\" version=\"1.0\" targetNamespace=\"http://" + namespace + ".aai.inventory/" 
649                                 + apiVersion + "\" xmlns:tns=\"http://" + namespace + ".aai.inventory/" + apiVersion + "\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
650                                                 + "\n"
651                                                 + "xmlns:jaxb=\"http://java.sun.com/xml/ns/jaxb\"\r\n" + 
652                                                 "    jaxb:version=\"2.1\" \r\n" + 
653                                                 "    xmlns:annox=\"http://annox.dev.java.net\" \r\n" + 
654                                                 "    jaxb:extensionBindingPrefixes=\"annox\">\n\n");
655
656                 try {
657                     
658                     DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
659                     dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
660                     DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
661                     Document doc = dBuilder.parse(oxmFile);
662
663                     NodeList bindingsNodes = doc.getElementsByTagName("xml-bindings");
664                         Element bindingElement;
665                         NodeList javaTypesNodes;
666                         Element javaTypesElement;
667                         
668                         Element javaTypeElement;
669
670                         
671                         if ( bindingsNodes == null || bindingsNodes.getLength() == 0 ) {
672                                 System.out.println( "missing <binding-nodes> in " + oxmFile );
673                                 return null;
674                         }           
675                         
676                         bindingElement = (Element) bindingsNodes.item(0);
677                         javaTypesNodes = bindingElement.getElementsByTagName("java-types");
678                         if ( javaTypesNodes.getLength() < 1 ) {
679                                 System.out.println( "missing <binding-nodes><java-types> in " + oxmFile );
680                                 return null;
681                         }
682                         javaTypesElement = (Element) javaTypesNodes.item(0);
683                         javaTypeNodes = javaTypesElement.getElementsByTagName("java-type");
684                         if ( javaTypeNodes.getLength() < 1 ) {
685                                 System.out.println( "missing <binding-nodes><java-types><java-type> in " + oxmFile );
686                                 return null;
687                         }
688
689                         String javaTypeName;
690                         String attrName, attrValue;
691                         Attr attr;
692                         for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
693                                 javaTypeElement = (Element) javaTypeNodes.item(i);
694                                 NamedNodeMap attributes = javaTypeElement.getAttributes();
695                                 javaTypeName = null;
696                                 for ( int j = 0; j < attributes.getLength(); ++j ) {
697                             attr = (Attr) attributes.item(j);
698                             attrName = attr.getNodeName();
699                             attrValue = attr.getNodeValue();
700                             if ( attrName.equals("name"))
701                                 javaTypeName = attrValue;
702                                 }
703                                 if ( javaTypeName == null ) {
704                                         System.out.println( "<java-type> has no name attribute in " + oxmFile );
705                                         return null;
706                                 }
707                                 if ("Nodes".equals(javaTypeName)) {
708                                         System.out.println("skipping Nodes entry (temporary feature)");
709                                         continue;
710                                 }
711                                 if ( !generatedJavaType.containsKey(javaTypeName) ) {
712                                         generatedJavaType.put(javaTypeName, null);
713                                         sb.append(processJavaTypeElement( javaTypeName, javaTypeElement ));
714                                 }
715                         }
716                                 
717                 } catch (Exception e) {
718                         e.printStackTrace();
719                         return null;
720                 }
721                 sb.append("</xs:schema>\n");
722                 return sb.toString();
723         }
724
725         private static boolean isStandardType( String elementType )
726         {
727                 switch ( elementType ) {
728                 case "java.lang.String":
729                 case "java.lang.Long":
730                 case "java.lang.Integer":
731                 case"java.lang.Boolean":
732                         return true;
733                 }
734                 return false;
735         }
736         
737         private static Vector<String> getIndexedProps( String attrValue )
738         {
739                 if ( attrValue == null )
740                         return null;
741                 StringTokenizer st = new StringTokenizer( attrValue, ",");
742                 if ( st.countTokens() ==  0 )
743                         return null;
744                 Vector<String> result = new Vector<String>();
745                 while ( st.hasMoreTokens()) {
746                         result.add(st.nextToken());
747                 }
748                 return result;
749         }
750         
751         private static Class<?> getEdgeRulesClass() throws ClassNotFoundException {
752                 Class<?> result = null;
753                 
754                 // If a class matching the apiVersion exists, we are generating documentation for a prior release
755                 // Otherwise, we're generated documentation for the current release.
756                 try {
757                         result = Class.forName("org.openecomp.aai.dbmodel." + apiVersion +".gen.DbEdgeRules");
758                 } catch (ClassNotFoundException  ex) {
759                         result = Class.forName("org.openecomp.aai.dbmodel.DbEdgeRules");
760                 }
761                 return result;
762         }
763         
764         /**
765          * Guaranteed to at least return non null but empty collection of edge descriptions
766          * @param nodeName name of the vertex whose edge relationships to return
767          * @return collection of node neighbors based on DbEdgeRules
768          */
769         private static Collection<EdgeDescription> getEdgeRules( String nodeName ) 
770         {
771
772                 ArrayList<EdgeDescription> result = new ArrayList<>();
773                 Iterator<String> edgeRulesIterator;
774
775                 try {
776
777                         Field mapfield = versionedClass.getField("EdgeRules");
778                         Object map = mapfield.get(null);
779                         if (map instanceof Multimap<?,?>) {
780                                 edgeRulesIterator = ((Multimap<String,String>) map).keySet().iterator();
781                         } else {
782                                 throw new NoSuchFieldException ("Didn't get back the multimap field expected");
783                         }
784                         GenerateXsd x = new GenerateXsd();
785
786                         while( edgeRulesIterator.hasNext() ){
787                                 String ruleKey = edgeRulesIterator.next();
788                                 if ( ruleKey.startsWith(nodeName + "|" ) ||
789                                                 ruleKey.endsWith("|" + nodeName)) {
790                                         Collection <String> edRuleColl = DbEdgeRules.EdgeRules.get(ruleKey);
791                                         Iterator <String> ruleItr = edRuleColl.iterator();
792                                         while( ruleItr.hasNext() ){             
793                                                 EdgeDescription edgeDes = x.new EdgeDescription();
794                                                 edgeDes.setRuleKey(ruleKey);
795                                                 String fullRuleString = ruleItr.next();
796                                                 String[] toks = fullRuleString.split(",");
797                                                 if (toks != null) {
798                                                         if (toks.length > 1) {
799                                                                 edgeDes.setDirection(toks[1]);
800                                                         }
801                                                         if (toks.length > 2) {
802                                                                 edgeDes.setMultiplicity(toks[2]);
803                                                         }
804                                                         if (toks.length > 3) {
805                                                                 if (toks[3].equals("true")) 
806                                                                         edgeDes.setType(LineageType.PARENT);
807                                                                 else if (toks[3].equals("parent")) 
808                                                                         edgeDes.setType(LineageType.PARENT);
809                                                                 else if (toks[3].equals("child")) 
810                                                                         edgeDes.setType(LineageType.CHILD);
811                                                                 else 
812                                                                         edgeDes.setType(LineageType.UNRELATED);
813                                                         }
814                                                         if (toks.length > 5) {
815                                                                 edgeDes.setHasDelTarget(toks[5]);;
816                                                         }
817                                                 }
818
819                                                 //System.out.println( "nodeName " + nodeName + " ruleKey "  + ruleKey + " ruleString " + fullRuleString);
820                                                 //result.add(ruleKey + "-" + fullRuleString);
821                                                 result.add(edgeDes);
822                                         }
823                                 }
824                         }
825                 } catch (Exception ex) {
826                         ex.printStackTrace();
827                 }
828                 return result;
829         }
830         
831         /**
832          * Finds the default delete scope from DBEdgeRules
833          * @param nodeName name of vertex whose delete scope to return
834          * @return default delete scope of the input nodeName, null if none.
835          */
836         private static String getDeleteRules( String nodeName )
837         {
838                 String result = null;
839                 Iterator<String> delRulesIterator;
840
841                 try {
842
843                         Field mapfield = versionedClass.getField("DefaultDeleteScope");
844                         Object map = mapfield.get(null);
845                         if (map instanceof Multimap<?,?>) {
846                                 delRulesIterator = ((Multimap<String,String>) map).keySet().iterator();
847                         } else {
848                                 throw new NoSuchFieldException ("Didn't get back the multimap field expected");
849                         }
850
851                         while( delRulesIterator.hasNext() ){
852                                 String ruleKey = delRulesIterator.next();
853                                 if ( ruleKey.equals(nodeName)) {
854                                         Collection <String> deRuleColl = DbEdgeRules.DefaultDeleteScope.get(ruleKey);
855                                         Iterator <String> ruleItr = deRuleColl.iterator();
856                                         if( ruleItr.hasNext() ){                
857                                                 result = ruleItr.next();
858                                         }
859                                 }
860                         }
861
862                 } catch (Exception ex) {
863                         ex.printStackTrace();
864                 }
865                 return result;
866         }
867         
868         public static String processJavaTypeElementSwagger( String javaTypeName, Element javaTypeElement, 
869                         StringBuffer pathSb, StringBuffer definitionsSb, String path, String tag, String opId,
870                         String getItemName, StringBuffer pathParams, String queryParams, String validEdges) {
871                 
872                 String xmlRootElementName = null;
873
874                 //Map<String, String> addJavaType = new HashMap<String, String>();
875                 String useTag = null;
876                 String useOpId = null;
877                 
878                 if ( tag != null ) {
879                         switch ( tag ) {
880                         case "Network":
881                         case "ServiceDesignAndCreation":
882                         case "Business":
883                         case "CloudInfrastructure":
884                                 break;
885                         default:
886                                 return null;
887                         }
888                 }
889
890                 if ( !javaTypeName.equals("Inventory") ) {
891                         if ( javaTypeName.equals("AaiInternal"))
892                                 return null;
893                         if ( opId == null )
894                                 useOpId = javaTypeName;
895                         else
896                                 useOpId = opId + javaTypeName;
897                         if ( tag == null )
898                                 useTag = javaTypeName;
899                 }
900                 
901                 NodeList parentNodes = javaTypeElement.getElementsByTagName("java-attributes");
902
903                 if ( parentNodes.getLength() == 0 ) {
904                         System.out.println( "no java-attributes for java-type " + javaTypeName);
905                         return "";
906
907                 }
908                 
909                 NamedNodeMap attributes;
910                 
911                 NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
912                 Element valElement = (Element) valNodes.item(0);
913                 attributes = valElement.getAttributes();
914                 for ( int i = 0; i < attributes.getLength(); ++i ) {
915             Attr attr = (Attr) attributes.item(i);
916             String attrName = attr.getNodeName();
917
918             String attrValue = attr.getNodeValue();
919             //System.out.println("Found xml-root-element attribute: " + attrName + " with value: " + attrValue);
920             if ( attrName.equals("name"))
921                 xmlRootElementName = attrValue;
922                 }
923                 /*
924                 if ( xmlRootElementName.equals("oam-networks"))
925                         System.out.println( "xmlRootElement oam-networks with getItemData [" + getItemName + "]");
926                 */
927                 //already processed
928                 /*
929                 if ( generatedJavaType.containsKey(xmlRootElementName) ) {
930                         return null;
931                 }
932                 */
933                 NodeList childNodes;
934                 Element childElement;
935                 NodeList xmlPropNodes = javaTypeElement.getElementsByTagName("xml-properties");
936                 Element xmlPropElement;
937                 String pathDescriptionProperty = null;
938                 
939                 
940                 Vector<String> indexedProps = null;
941                 
942                 /*System.out.println( "javaTypeName " + javaTypeName + " has xml-properties length " + xmlPropNodes.getLength());
943                 if ( path != null && path.equals("/network/generic-vnfs"))
944                         System.out.println("path is " + "/network/generic-vnfs with getItemName " + getItemName);
945                 */
946                 if ( xmlPropNodes.getLength() > 0 ) {
947
948                         for ( int i = 0; i < xmlPropNodes.getLength(); ++i ) {
949                                 xmlPropElement = (Element)xmlPropNodes.item(i);
950                                 if ( !xmlPropElement.getParentNode().isSameNode(javaTypeElement))
951                                         continue;
952                                 childNodes = xmlPropElement.getElementsByTagName("xml-property");
953                                 
954                                 if ( childNodes.getLength() > 0 ) {
955                                         for ( int j = 0; j < childNodes.getLength(); ++j ) {
956                                                 childElement = (Element)childNodes.item(j);
957                                                 // get name
958                                                 int useValue = VALUE_NONE;
959                                                 attributes = childElement.getAttributes();
960                                                 for ( int k = 0; k < attributes.getLength(); ++k ) {
961                                                         Attr attr = (Attr) attributes.item(k);
962                                                         String attrName = attr.getNodeName();
963                                                         String attrValue = attr.getNodeValue();
964                                                         if ( attrName == null || attrValue == null )
965                                                                 continue;
966                                                         if ( attrName.equals("name") && attrValue.equals("description")) {
967                                                                 useValue = VALUE_DESCRIPTION;
968                                                         }
969                                                         if ( useValue == VALUE_DESCRIPTION && attrName.equals("value")) {
970                                                                 pathDescriptionProperty = attrValue;
971                                                                 //break;
972                                                                 //System.out.println("found xml-element-wrapper " + xmlElementWrapper);
973                                                         }
974                                                         if ( attrValue.equals("indexedProps")) {
975                                                                 useValue = VALUE_INDEXED_PROPS;
976                                                         }
977                                                         if ( useValue == VALUE_INDEXED_PROPS && attrName.equals("value")) {
978                                                                 indexedProps = getIndexedProps( attrValue );
979                                                         }
980                                                 }
981                                         }
982                                 }
983                         }
984                 }
985                 //System.out.println("javaTypeName " + javaTypeName + " description " + pathDescriptionProperty);
986
987                 /*
988                 if ( javaTypeName.equals("RelationshipList")) {
989                         System.out.println( "Skipping " + javaTypeName);
990                         generatedJavaType.put(javaTypeName, null);
991                         return "";
992                 }
993                 */
994                 
995                 Element parentElement = (Element)parentNodes.item(0);
996                 NodeList xmlElementNodes = parentElement.getElementsByTagName("xml-element");
997
998         
999                 String attrDescription = null;
1000
1001                 Element xmlElementElement;
1002                 String addType = null;
1003                 String elementType = null, elementIsKey = null, elementIsRequired, elementContainerType = null;
1004                 String elementName = null;
1005                 StringBuffer sbParameters = new StringBuffer();
1006
1007                 StringBuffer sbRequired = new StringBuffer();
1008                 int requiredCnt = 0;
1009                 int propertyCnt = 0;
1010                 StringBuffer sbProperties = new StringBuffer();
1011                 StringBuffer sbIndexedParams = new StringBuffer();
1012
1013                 
1014                 StringTokenizer st;
1015                 if ( xmlRootElementName.equals("inventory"))
1016                         path = "";
1017                 else if ( path == null )
1018                         //path = "/aai/" + apiVersion;
1019                         path = "/" + xmlRootElementName;
1020                 else
1021                         path += "/" + xmlRootElementName;
1022                 st = new StringTokenizer(path, "/");
1023                 /*
1024                 if ( path.equals("/business/customers/customer/{global-customer-id}/service-subscriptions/service-subscription"))
1025                         System.out.println("processing path /business/customers/customer/{global-customer-id}/service-subscriptions with tag " + tag);
1026                 */
1027                 boolean genPath = false;
1028                 /*
1029                 if ( path != null && path.equals("/network/generic-vnfs/generic-vnf"))
1030                         System.out.println("path is " + "/network/generic-vnfs/generic-vnf");
1031                 */
1032                 if ( st.countTokens() > 1 && getItemName == null ) {
1033                         if ( appliedPaths.containsKey(path)) 
1034                                 return null;
1035                         appliedPaths.put(path, null);
1036                         genPath = true;
1037                         if ( path.contains("/relationship/") ) { // filter paths with relationship-list
1038                                 genPath = false;
1039                         }
1040                         if ( path.endsWith("/relationship-list")) {
1041                                 genPath = false;
1042                         }
1043                                         
1044                 }
1045                 
1046                 Vector<String> addTypeV = null;
1047                 if (  xmlElementNodes.getLength() > 0 ) {
1048                         
1049                         for ( int i = 0; i < xmlElementNodes.getLength(); ++i ) {
1050                                 xmlElementElement = (Element)xmlElementNodes.item(i);
1051                                 if ( !xmlElementElement.getParentNode().isSameNode(parentElement))
1052                                         continue;
1053                                 /*childNodes = xmlElementElement.getElementsByTagName("xml-element-wrapper");
1054                                 if ( childNodes.getLength() > 0 ) {
1055                                         childElement = (Element)childNodes.item(0);
1056                                         // get name
1057                                         attributes = childElement.getAttributes();
1058                                         for ( int k = 0; k < attributes.getLength(); ++k ) {
1059                                                 Attr attr = (Attr) attributes.item(k);
1060                                                 String attrName = attr.getNodeName();
1061                                                 String attrValue = attr.getNodeValue();
1062                                                 if ( attrName.equals("name")) {
1063                                                         xmlElementWrapper = attrValue;
1064                                                         //System.out.println("found xml-element-wrapper " + xmlElementWrapper);
1065                                                 }
1066                                         }
1067
1068                                 }
1069                                 */
1070                                 valNodes = xmlElementElement.getElementsByTagName("xml-properties");
1071                                 attrDescription = null;
1072                                 if ( valNodes.getLength() > 0 ) {
1073                                         for ( int j = 0; j < valNodes.getLength(); ++j ) {
1074                                                 valElement = (Element)valNodes.item(j);
1075                                                 if ( !valElement.getParentNode().isSameNode(xmlElementElement))
1076                                                         continue;
1077                                                 childNodes = valElement.getElementsByTagName("xml-property");
1078                                                 if ( childNodes.getLength() > 0 ) {
1079                                                         childElement = (Element)childNodes.item(0);
1080                                                         // get name
1081                                                         attributes = childElement.getAttributes();
1082                                                         attrDescription = null;
1083                                                         boolean useValue = false;
1084                                                         for ( int k = 0; k < attributes.getLength(); ++k ) {
1085                                                                 Attr attr = (Attr) attributes.item(k);
1086                                                                 String attrName = attr.getNodeName();
1087                                                                 String attrValue = attr.getNodeValue();
1088                                                                 if ( attrName.equals("name") && attrValue.equals("description")) {
1089                                                                         useValue = true;
1090                                                                 }
1091                                                                 if ( useValue && attrName.equals("value")) {
1092                                                                         attrDescription = attrValue;
1093                                                                         //System.out.println("found xml-element-wrapper " + xmlElementWrapper);
1094                                                                 }
1095                                                         }
1096
1097                                                 }
1098                                         }
1099                                 }
1100                                 
1101                                 attributes = xmlElementElement.getAttributes();
1102                                 addTypeV = null; // vector of 1
1103                                 addType = null;
1104                                 
1105                                 elementName = elementType = elementIsKey = elementIsRequired = elementContainerType = null;
1106                                 for ( int j = 0; j < attributes.getLength(); ++j ) {
1107                             Attr attr = (Attr) attributes.item(j);
1108                             String attrName = attr.getNodeName();
1109         
1110                             String attrValue = attr.getNodeValue();
1111                             //System.out.println("For " + xmlRootElementName + " Found xml-element attribute: " + attrName + " with value: " + attrValue);
1112                             if ( attrName.equals("name")) {
1113                                 elementName = attrValue;
1114
1115                             }
1116                             if ( attrName.equals("type") && getItemName == null ) {
1117                                 elementType = attrValue;
1118                                 if ( attrValue.contains(apiVersionFmt) ) {
1119                                         addType = attrValue.substring(attrValue.lastIndexOf('.')+1);
1120                                         if ( addTypeV == null ) 
1121                                                 addTypeV = new Vector<String>();
1122                                         addTypeV.add(addType);
1123                                 }
1124                                         
1125                             }
1126                             if ( attrName.equals("xml-key")) {
1127                                 elementIsKey = attrValue;
1128                                 path += "/{" + elementName + "}";
1129                             }
1130                             if ( attrName.equals("required")) {
1131                                 elementIsRequired = attrValue;
1132                             }
1133                             if ( attrName.equals("container-type")) {
1134                                 elementContainerType = attrValue;
1135                             }   
1136                                 }
1137                 if ( getItemName != null ) {
1138                         if ( getItemName.equals("array") ) {
1139                                 if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) {
1140                                         //System.out.println( " returning array " + elementName );
1141                                         return elementName;
1142                                 }
1143                                 
1144                         } else { // not an array check
1145                                 if ( elementContainerType == null || !elementContainerType.equals("java.util.ArrayList")) {
1146                                         //System.out.println( " returning object " + elementName );
1147                                         return elementName;
1148                                 }
1149                                 
1150                         }
1151                         //System.out.println( " returning null" );
1152                         return null;
1153                 }
1154                                 if ( elementIsRequired != null ) {
1155                                         if ( requiredCnt == 0 )
1156                                                 sbRequired.append("    required:\n");
1157                                         ++requiredCnt;
1158                                         if ( addTypeV != null ) {
1159                                                 for ( int k = 0; k < addTypeV.size(); ++i ) {
1160                                                         sbRequired.append("    - " + getXmlRootElementName(addTypeV.elementAt(k)) + ":\n");
1161                                                 }
1162                                         } else 
1163                                                 sbRequired.append("    - " + elementName + "\n");
1164
1165                                 }
1166
1167                                 if (  elementIsKey != null )  {
1168                                                                                 sbParameters.append(("        - name: " + elementName + "\n"));
1169                                         sbParameters.append(("          in: path\n"));
1170                                         if ( attrDescription != null && attrDescription.length() > 0 )
1171                                                 sbParameters.append(("          description: " + attrDescription + "\n"));
1172                                         sbParameters.append(("          required: true\n"));
1173                                         if ( elementType.equals("java.lang.String"))
1174                                                 sbParameters.append("          type: string\n");
1175                                         if ( elementType.equals("java.lang.Long")) {
1176                                                 sbParameters.append("          type: integer\n");
1177                                                 sbParameters.append("          format: int64\n");
1178                                         }
1179                                         if ( elementType.equals("java.lang.Integer")) {
1180                                                 sbParameters.append("          type: integer\n");
1181                                                 sbParameters.append("          format: int32\n");
1182                                         }
1183                                         if ( elementType.equals("java.lang.Boolean"))
1184                                                 sbParameters.append("          type: boolean\n");
1185
1186
1187                                 } else if (  indexedProps != null
1188                                                 && indexedProps.contains(elementName ) ) {
1189                                         sbIndexedParams.append(("        - name: " + elementName + "\n"));
1190                                         sbIndexedParams.append(("          in: query\n"));
1191                                         if ( attrDescription != null && attrDescription.length() > 0 )
1192                                                 sbIndexedParams.append(("          description: " + attrDescription + "\n"));
1193                                         sbIndexedParams.append(("          required: false\n"));
1194                                         if ( elementType.equals("java.lang.String"))
1195                                                 sbIndexedParams.append("          type: string\n");
1196                                         if ( elementType.equals("java.lang.Long")) {
1197                                                 sbIndexedParams.append("          type: integer\n");
1198                                                 sbIndexedParams.append("          format: int64\n");
1199                                         }
1200                                         if ( elementType.equals("java.lang.Integer")) {
1201                                                 sbIndexedParams.append("          type: integer\n");
1202                                                 sbIndexedParams.append("          format: int32\n");
1203                                         }
1204                                         if ( elementType.equals("java.lang.Boolean"))
1205                                                 sbIndexedParams.append("          type: boolean\n");
1206                                 }
1207
1208                         /*
1209                         if ( elementName != null && elementName.equals("inventory-item"))
1210                                 System.out.println( "processing inventory-item elementName");
1211                         */
1212                 
1213                         if ( isStandardType(elementType)) {
1214                                 sbProperties.append("      " + elementName + ":\n");
1215                                 ++propertyCnt;
1216                                 sbProperties.append("        type: ");
1217
1218                                 if ( elementType.equals("java.lang.String"))
1219                                         sbProperties.append("string\n");
1220                                 else if ( elementType.equals("java.lang.Long")) {
1221                                         sbProperties.append("integer\n");
1222                                         sbProperties.append("        format: int64\n");
1223                                 }
1224                                 else if ( elementType.equals("java.lang.Integer")){
1225                                         sbProperties.append("integer\n");
1226                                         sbProperties.append("        format: int32\n");
1227                                 }
1228                                 else if ( elementType.equals("java.lang.Boolean"))
1229                                         sbProperties.append("boolean\n");
1230                                 if ( attrDescription != null && attrDescription.length() > 0 )
1231                                         sbProperties.append("        description: " + attrDescription + "\n");
1232                         }
1233
1234                         //if ( addType != null && elementContainerType != null && elementContainerType.equals("java.util.ArrayList") ) {
1235
1236                 if ( addTypeV !=  null ) {
1237                         StringBuffer newPathParams = null;
1238                         if ( pathParams != null  ) {
1239                                 newPathParams = new StringBuffer();
1240                                 newPathParams.append(pathParams);
1241                         }
1242                     if ( sbParameters.toString().length() > 0 ) {
1243                                         if ( newPathParams == null )
1244                                                 newPathParams = new StringBuffer();
1245                                         newPathParams.append(sbParameters);
1246                     }
1247                     String newQueryParams = null;
1248                     if ( sbIndexedParams.toString().length() > 0 ) {
1249                         if ( queryParams == null )
1250                                 newQueryParams = sbIndexedParams.toString();
1251                         else
1252                                 newQueryParams = queryParams + sbIndexedParams.toString();
1253                     } else {
1254                         newQueryParams = queryParams;
1255                     }
1256                         for ( int k = 0; k < addTypeV.size(); ++k ) {
1257                                 addType = addTypeV.elementAt(k);
1258                 
1259                                 if ( opId == null || !opId.contains(addType)) {
1260                                         processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType), 
1261                                                 pathSb, definitionsSb, path,  tag == null ? useTag : tag, useOpId, null,
1262                                                 newPathParams, newQueryParams, validEdges);
1263                                 }
1264                                 // need item name of array
1265                                         String itemName = processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType), 
1266                                                 pathSb, definitionsSb, path,  tag == null ? useTag : tag, useOpId, 
1267                                                                 "array", null, null, null );
1268                                         
1269                                         if ( itemName != null ) {
1270                                                 if ( addType.equals("AaiInternal") ) {
1271                                                         //System.out.println( "addType AaiInternal, skip properties");
1272                                                         
1273                                                 } else if ( getItemName == null) {
1274                                                         ++propertyCnt;
1275                                                         sbProperties.append("      " + getXmlRootElementName(addType) + ":\n");
1276                                                         sbProperties.append("        type: array\n        items:\n");
1277                                                         sbProperties.append("          $ref: \"#/definitions/" + itemName + "\"\n");
1278                                                         if ( attrDescription != null && attrDescription.length() > 0 )
1279                                                                 sbProperties.append("        description: " + attrDescription + "\n");
1280                                                 }
1281                                         } else {
1282                                                 /*itemName = processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType), 
1283                                                         pathSb, definitionsSb, path,  tag == null ? useTag : tag, useOpId, "other" );
1284                                                 if ( itemName != null ) {
1285                                                 */
1286                                                 if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) {
1287                                                         // need properties for getXmlRootElementName(addType)
1288                                                 newPathParams = null;
1289                                                 if ( pathParams != null  ) {
1290                                                         newPathParams = new StringBuffer();
1291                                                         newPathParams.append(pathParams);
1292                                                 }
1293                                             if ( sbParameters.toString().length() > 0 ) {
1294                                                                 if ( newPathParams == null )
1295                                                                         newPathParams = new StringBuffer();
1296                                                                 newPathParams.append(sbParameters);
1297                                             }
1298                                             newQueryParams = null;
1299                                             if ( sbIndexedParams.toString().length() > 0 ) {
1300                                                 if ( queryParams == null )
1301                                                         newQueryParams = sbIndexedParams.toString();
1302                                                 else
1303                                                         newQueryParams = queryParams + sbIndexedParams.toString();
1304                                             } else {
1305                                                 newQueryParams = queryParams;
1306                                             }
1307                                                         processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType), 
1308                                                                 pathSb, definitionsSb, path,  tag == null ? useTag : tag, useOpId, 
1309                                                                                 null, newPathParams, newQueryParams, validEdges );
1310                                                         sbProperties.append("      " + getXmlRootElementName(addType) + ":\n");
1311                                                         sbProperties.append("        type: array\n        items:          \n");
1312                                                         sbProperties.append("          $ref: \"#/definitions/" + getXmlRootElementName(addType) + "\"\n");
1313                                                 } else {
1314                                                         sbProperties.append("      " + getXmlRootElementName(addType) + ":\n");
1315                                                         sbProperties.append("        type: object\n");
1316                                                         sbProperties.append("        $ref: \"#/definitions/" + getXmlRootElementName(addType) + "\"\n");
1317                                                 }
1318                                                 if ( attrDescription != null && attrDescription.length() > 0 )
1319                                                         sbProperties.append("        description: " + attrDescription + "\n");
1320                                                 ++propertyCnt;
1321                                                 /*}
1322                                                 else {
1323                                                         System.out.println(" unable to define swagger object for " + addType);
1324                                                 }
1325                                                 */
1326                                         }
1327                                         //if ( getItemName == null) looking for missing properties
1328                                                 //generatedJavaType.put(addType, null);
1329                         }
1330                 }
1331                 }
1332         }       
1333                 if ( genPath ) {
1334                         /*
1335                         if ( useOpId.equals("CloudInfrastructureComplexesComplexCtagPools"))
1336                                 System.out.println( "adding path CloudInfrastructureComplexesComplexCtagPools");
1337                         */
1338
1339                         if ( !path.endsWith("/relationship") ) {
1340                                 pathSb.append("  " + path + ":\n" );
1341                                 pathSb.append("    get:\n");
1342                                 pathSb.append("      tags:\n");
1343                                 pathSb.append("        - " + tag + "\n");
1344                                 pathSb.append("      summary: returns " + xmlRootElementName + "\n");
1345         
1346                                 pathSb.append("      description: returns " + xmlRootElementName + "\n");
1347                                 pathSb.append("      operationId: get" + useOpId + "\n");
1348                                 pathSb.append("      produces:\n");
1349                                 pathSb.append("        - application/json\n");
1350                                 pathSb.append("        - application/xml\n");
1351                                 
1352                                 pathSb.append("      responses:\n");
1353                                 pathSb.append("        \"200\":\n");
1354                                 pathSb.append("          description: successful operation\n");
1355                                 pathSb.append("          schema:\n");
1356                                 pathSb.append("              $ref: \"#/definitions/" + xmlRootElementName + "\"\n");
1357                                 pathSb.append("        \"default\":\n");
1358                                 pathSb.append("          " + responsesUrl);
1359                                 /*
1360                                 pathSb.append("        \"200\":\n");
1361                                 pathSb.append("          description: successful operation\n");
1362                                 pathSb.append("          schema:\n");
1363                                 pathSb.append("              $ref: \"#/definitions/" + xmlRootElementName + "\"\n");
1364                                 pathSb.append("        \"404\":\n");
1365                                 pathSb.append("          description: resource was not found\n");
1366                                 pathSb.append("        \"400\":\n");
1367                                 pathSb.append("          description: bad request\n");
1368                                 */
1369                                 if ( path.indexOf('{') > 0 ) {
1370                                 
1371                             if ( sbParameters.toString().length() > 0 ) {
1372                                                 if ( pathParams == null )
1373                                                         pathParams = new StringBuffer();
1374                                                 pathParams.append(sbParameters);
1375                             }
1376                                         if ( pathParams != null) {
1377                                                 pathSb.append("      parameters:\n");
1378                                                 pathSb.append(pathParams);
1379                                         } else
1380                                                 System.out.println( "null pathParams for " + useOpId);
1381                                         if ( sbIndexedParams.toString().length() > 0 ) {
1382                                                 if ( queryParams == null )
1383                                                         queryParams = sbIndexedParams.toString();
1384                                                 else
1385                                                         queryParams = queryParams + sbIndexedParams.toString();
1386                                         }
1387                                         if ( queryParams != null ) {
1388                                                 if ( pathParams == null ) {
1389                                                         pathSb.append("      parameters:\n");
1390                                                 }
1391                                                 pathSb.append(queryParams);
1392                                         }
1393                                 }
1394                         }
1395                         boolean skipPutDelete = false; // no put or delete for "all" 
1396                         if ( !path.endsWith("/relationship") ) {                                
1397                                 if ( !path.endsWith("}") ){
1398                                                 skipPutDelete = true;
1399                                 }
1400                                         
1401                         }
1402                         if ( path.indexOf('{') > 0 && !opId.startsWith("Search") &&!skipPutDelete) {
1403                                 // add PUT
1404                                 if ( path.endsWith("/relationship") ) {
1405                                         pathSb.append("  " + path + ":\n" );
1406                                 } 
1407                                 pathSb.append("    put:\n");
1408                                 pathSb.append("      tags:\n");
1409                                 pathSb.append("        - " + tag + "\n");
1410
1411                                 if ( path.endsWith("/relationship") ) {
1412                                         pathSb.append("      summary: see node definition for valid relationships\n");
1413                                 } else {
1414                                         pathSb.append("      summary: create or update an existing " + xmlRootElementName + "\n");
1415                                         pathSb.append("      description: create or update an existing " + xmlRootElementName + "\n");
1416                                 }
1417                                 pathSb.append("      operationId: createOrUpdate" + useOpId + "\n");
1418                                 pathSb.append("      consumes:\n");
1419                                 pathSb.append("        - application/json\n");
1420                                 pathSb.append("        - application/xml\n");                                   
1421                                 pathSb.append("      produces:\n");
1422                                 pathSb.append("        - application/json\n");
1423                                 pathSb.append("        - application/xml\n");
1424                                 pathSb.append("      responses:\n");
1425                                 pathSb.append("        \"default\":\n");
1426                                 pathSb.append("          " + responsesUrl);
1427                                 /*
1428                                 pathSb.append("      responses:\n");
1429                                 pathSb.append("        \"200\":\n");
1430                                 pathSb.append("          description: existing resource has been modified and there is a response buffer\n");                                   
1431                                 pathSb.append("        \"201\":\n");
1432                                 pathSb.append("          description: new resource is created\n");      
1433                                 pathSb.append("        \"202\":\n");
1434                                 pathSb.append("          description: action requested but may have taken other actions as well, which are returned in the response payload\n");                                
1435                                 pathSb.append("        \"204\":\n");
1436                                 pathSb.append("          description: existing resource has been modified and there is no response buffer\n");                          
1437                                 pathSb.append("        \"400\":\n");
1438                                 pathSb.append("          description: Bad Request will be returned if headers are missing\n");
1439                                 pathSb.append("        \"404\":\n");
1440                                 pathSb.append("          description: Not Found will be returned if an unknown URL is used\n");
1441                                 */                                              
1442                                 pathSb.append("      parameters:\n");
1443                                 //pathSb.append("        - in: path\n");
1444                                 pathSb.append(pathParams); // for nesting
1445                                 pathSb.append("        - name: body\n");
1446                                 pathSb.append("          in: body\n");
1447                                 pathSb.append("          description: " + xmlRootElementName + " object that needs to be created or updated\n");
1448                                 pathSb.append("          required: true\n");
1449                                 pathSb.append("          schema:\n");
1450                                 pathSb.append("            $ref: \"#/definitions/" + xmlRootElementName + "\"\n");
1451                                 /*
1452                                 if ( queryParams != null ) {
1453                                         pathSb.append(queryParams);
1454                                 }
1455                                 */
1456                                 // add DELETE
1457                                 pathSb.append("    delete:\n");
1458                                 pathSb.append("      tags:\n");
1459                                 pathSb.append("        - " + tag + "\n");
1460                                 pathSb.append("      summary: delete an existing " + xmlRootElementName + "\n");
1461                                 
1462                                 pathSb.append("      description: delete an existing " + xmlRootElementName + "\n");
1463                                 
1464                                 pathSb.append("      operationId: delete" + useOpId + "\n");
1465                                 pathSb.append("      consumes:\n");
1466                                 pathSb.append("        - application/json\n");
1467                                 pathSb.append("        - application/xml\n");                                   
1468                                 pathSb.append("      produces:\n");
1469                                 pathSb.append("        - application/json\n");
1470                                 pathSb.append("        - application/xml\n");
1471                                 pathSb.append("      responses:\n");
1472                                 pathSb.append("        \"default\":\n");
1473                                 pathSb.append("          " + responsesUrl);
1474                                 /*
1475                                 pathSb.append("      responses:\n");
1476                                 pathSb.append("        \"200\":\n");
1477                                 pathSb.append("          description: successful, the response includes an entity describing the status\n");
1478                                 pathSb.append("        \"204\":\n");
1479                                 pathSb.append("          description: successful, action has been enacted but the response does not include an entity\n");
1480                                 pathSb.append("        \"400\":\n");
1481                                 pathSb.append("          description: Bad Request will be returned if headers are missing\n");
1482                                 pathSb.append("        \"404\":\n");
1483                                 pathSb.append("          description: Not Found will be returned if an unknown URL is used\n");
1484                                 */                              
1485                                 pathSb.append("      parameters:\n");
1486                                 //pathSb.append("        - in: path\n");
1487                                 pathSb.append(pathParams); // for nesting
1488                                 if ( !path.endsWith("/relationship") ) {
1489                                         pathSb.append("        - name: resource-version\n");
1490         
1491                                         pathSb.append("          in: query\n");
1492                                         pathSb.append("          description: resource-version for concurrency\n");
1493                                         pathSb.append("          required: true\n");
1494                                         pathSb.append("          type: string\n");
1495                                 }
1496                                 /*
1497                                 if ( queryParams != null ) {
1498                                         pathSb.append(queryParams);
1499                                 }
1500                                 */
1501                         }
1502                         
1503                 }
1504                 if ( generatedJavaType.containsKey(xmlRootElementName) ) {
1505                         return null;
1506                 }
1507         
1508                 definitionsSb.append("  " + xmlRootElementName + ":\n");
1509                 Collection<EdgeDescription> edges = getEdgeRules(xmlRootElementName );
1510                 if ( edges.size() > 0 ) {
1511                         StringBuffer sbEdge = new StringBuffer();
1512                         sbEdge.append("      ###### Related Nodes\n");
1513                         for (EdgeDescription ed : edges) { 
1514                                 if ( ed.getRuleKey().startsWith(xmlRootElementName)) {
1515                                     sbEdge.append("      - TO ").append(ed.getRuleKey().substring(ed.getRuleKey().indexOf("|")+1));
1516                                     sbEdge.append(ed.getRelationshipDescription("TO", xmlRootElementName));
1517                                     sbEdge.append("\n");
1518                                 }
1519                         }
1520                         for (EdgeDescription ed : edges) { 
1521                                 if ( ed.getRuleKey().endsWith(xmlRootElementName)) {
1522                                     sbEdge.append("      - FROM ").append(ed.getRuleKey().substring(0, ed.getRuleKey().indexOf("|")));
1523                                     sbEdge.append(ed.getRelationshipDescription("FROM", xmlRootElementName));
1524                                     sbEdge.append("\n");
1525                                 }
1526                         }
1527                         validEdges = sbEdge.toString();
1528                 }
1529
1530                 String deleteRule = getDeleteRules(xmlRootElementName);
1531                 // Handle description property.  Might have a description OR valid edges OR both OR neither.
1532                 // Only put a description: tag if there is at least one.
1533                 if (pathDescriptionProperty != null || deleteRule != null || validEdges != null) {
1534                         definitionsSb.append("    description: |\n");      
1535
1536                         if ( pathDescriptionProperty != null ) 
1537                                 definitionsSb.append("      " + pathDescriptionProperty + "\n" );
1538                         if (deleteRule != null) 
1539                                 definitionsSb.append("      ###### Default Delete Scope\n      ").append(deleteRule).append("\n");
1540                         if (validEdges != null) 
1541                                 definitionsSb.append(validEdges);
1542                 }
1543                 
1544                 if ( requiredCnt > 0 )
1545                         definitionsSb.append(sbRequired);
1546                 if ( propertyCnt > 0 ) {
1547                         definitionsSb.append("    properties:\n");
1548                         definitionsSb.append(sbProperties);
1549                 }
1550                 generatedJavaType.put(xmlRootElementName, null);
1551                 return null;
1552         }
1553         
1554         public static String generateSwaggerFromOxmFile( File oxmFile )
1555         {
1556
1557                 StringBuffer sb = new StringBuffer();
1558                 sb.append("swagger: \"2.0\"\ninfo:\n  description:\n    A&AI REST API\n  version: \"" + apiVersion +"\"\n");
1559                 sb.append("  title: Active and Available Inventory REST API\n");
1560                 sb.append("  license:\n    name: Apache 2.0\n    url: http://www.apache.org/licenses/LICENSE-2.0.html\n");
1561                 sb.append("schemes:\n  - https\npaths:\n");
1562                 /*
1563                 sb.append("responses:\n");
1564                 sb.append("  \"200\":\n");
1565                 sb.append("    description: successful operation\n");
1566                 sb.append("  \"404\":\n");
1567                 sb.append("    description: resource was not found\n");
1568                 sb.append("  \"400\":\n");
1569                 sb.append("    description: bad request\n");
1570                 */
1571                 try {
1572                         
1573                         versionedClass = getEdgeRulesClass();
1574                     
1575                     DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
1576                     dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
1577                     DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
1578                     Document doc = dBuilder.parse(oxmFile);
1579
1580                     NodeList bindingsNodes = doc.getElementsByTagName("xml-bindings");
1581                         Element bindingElement;
1582                         NodeList javaTypesNodes;
1583                         Element javaTypesElement;
1584                         
1585                         Element javaTypeElement;
1586
1587                         
1588                         if ( bindingsNodes == null || bindingsNodes.getLength() == 0 ) {
1589                                 System.out.println( "missing <binding-nodes> in " + oxmFile );
1590                                 return null;
1591                         }           
1592                         
1593                         bindingElement = (Element) bindingsNodes.item(0);
1594                         javaTypesNodes = bindingElement.getElementsByTagName("java-types");
1595                         if ( javaTypesNodes.getLength() < 1 ) {
1596                                 System.out.println( "missing <binding-nodes><java-types> in " + oxmFile );
1597                                 return null;
1598                         }
1599                         javaTypesElement = (Element) javaTypesNodes.item(0);
1600
1601                         javaTypeNodes = javaTypesElement.getElementsByTagName("java-type");
1602                         if ( javaTypeNodes.getLength() < 1 ) {
1603                                 System.out.println( "missing <binding-nodes><java-types><java-type> in " + oxmFile );
1604                                 return null;
1605                         }
1606
1607                         String javaTypeName;
1608                         String attrName, attrValue;
1609                         Attr attr;
1610                         StringBuffer pathSb = new StringBuffer();
1611                         
1612                         StringBuffer definitionsSb = new StringBuffer("definitions:\n");
1613                         
1614                         for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
1615                                 javaTypeElement = (Element) javaTypeNodes.item(i);
1616                                 NamedNodeMap attributes = javaTypeElement.getAttributes();
1617                                 javaTypeName = null;
1618                                 for ( int j = 0; j < attributes.getLength(); ++j ) {
1619                             attr = (Attr) attributes.item(j);
1620                             attrName = attr.getNodeName();
1621                             attrValue = attr.getNodeValue();
1622                             if ( attrName.equals("name"))
1623                                 javaTypeName = attrValue;
1624                                 }
1625                                 if ( javaTypeName == null ) {
1626                                         System.out.println( "<java-type> has no name attribute in " + oxmFile );
1627                                         return null;
1628                                 }
1629                                 if ( !generatedJavaType.containsKey(getXmlRootElementName(javaTypeName)) ) {
1630                                         
1631                                         //generatedJavaType.put(javaTypeName, null);
1632                                         //if ( javaTypeName.equals("search")||javaTypeName.equals("actions"))
1633
1634                                         processJavaTypeElementSwagger( javaTypeName, javaTypeElement, pathSb,
1635                                                         definitionsSb, null, null, null, null, null, null, null);
1636                                 }
1637                         }
1638                         sb.append(pathSb);
1639                         //System.out.println( "definitions block\n" + definitionsSb.toString());
1640                         sb.append(definitionsSb.toString());
1641                         //sb.append(definitionsSb);
1642                                 
1643                 } catch (Exception e) {
1644                         e.printStackTrace();
1645                         return null;
1646                 }
1647                 //System.out.println("generated " + sb.toString());
1648                 return sb.toString();
1649         }
1650         
1651         private static NodeList locateXmlProperties(Element element) {
1652                 XPathExpression expr;
1653                 NodeList result = null;
1654                 try {
1655                         expr = xpath.compile("xml-properties");
1656                         if (expr != null) {
1657                                 Object nodeset = expr.evaluate(element, XPathConstants.NODESET);
1658                                 if (nodeset != null) {
1659                                         NodeList nodes = (NodeList) nodeset;
1660                                         if (nodes != null && nodes.getLength() > 0) {
1661                                                 Element xmlProperty = (Element)nodes.item(0);
1662                                                 result = xmlProperty.getElementsByTagName("xml-property");
1663                                         }
1664                                 }
1665                         }
1666                 } catch (XPathExpressionException e) {
1667                         e.printStackTrace();
1668                 }
1669                 return result;
1670                 
1671         }
1672 }