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