Update license files, sonar plugin and fix tests
[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 }