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