2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
20 package org.onap.aai.util;
22 import com.google.common.base.Joiner;
23 import com.jayway.jsonpath.JsonPath;
24 import org.apache.commons.lang3.StringUtils;
25 import org.apache.commons.text.similarity.LevenshteinDistance;
27 import org.onap.aai.introspection.Version;
28 import org.onap.aai.serialization.db.EdgeProperty;
30 import org.xml.sax.InputSource;
32 import javax.xml.XMLConstants;
33 import javax.xml.parsers.DocumentBuilder;
34 import javax.xml.parsers.DocumentBuilderFactory;
35 import javax.xml.xpath.*;
37 import java.nio.charset.Charset;
38 import java.nio.file.Files;
39 import java.nio.file.Path;
40 import java.nio.file.Paths;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
46 public class GenerateXsd {
48 private static final Logger logger = LoggerFactory.getLogger("GenerateXsd.class");
50 static String apiVersion = null;
51 static String apiVersionFmt = null;
52 static boolean useAnnotationsInXsd = false;
53 static String responsesUrl = null;
54 static String responsesLabel = null;
55 static String jsonEdges = null;
57 static Map<String, String> generatedJavaType;
58 static Map<String, String> appliedPaths;
59 static Map<String, String> deletePaths;
60 static Map<String, String> putRelationPaths;
61 static NodeList javaTypeNodes;
62 static Map<String,String> javaTypeDefinitions = createJavaTypeDefinitions();
63 private static Map<String, String> createJavaTypeDefinitions()
65 StringBuffer aaiInternal = new StringBuffer();
66 Map<String,String> javaTypeDefinitions = new HashMap<String, String>();
67 aaiInternal.append(" aai-internal:\n");
68 aaiInternal.append(" properties:\n");
69 aaiInternal.append(" property-name:\n");
70 aaiInternal.append(" type: string\n");
71 aaiInternal.append(" property-value:\n");
72 aaiInternal.append(" type: string\n");
73 javaTypeDefinitions.put("aai-internal", aaiInternal.toString());
74 return javaTypeDefinitions;
77 public static final int VALUE_NONE = 0;
78 public static final int VALUE_DESCRIPTION = 1;
79 public static final int VALUE_INDEXED_PROPS = 2;
81 private static final String generateTypeXSD = "xsd";
82 private static final String generateTypeYAML = "yaml";
84 private static final String root = "../aai-schema/src/main/resources";
85 private static final String xsd_dir = root + "/aai_schema";
86 private static final String yaml_dir = root + "/aai_swagger_yaml";
88 /* These three strings are for yaml auto-generation from aai-common class*/
89 private static final String normalStartDir = "aai-core";
90 private static final String autoGenRoot = "aai-schema/src/main/resources";
91 private static final String alt_yaml_dir = autoGenRoot + "/aai_swagger_yaml";
93 private static int annotationsStartVersion = 9; // minimum version to support annotations in xsd
94 private static int swaggerSupportStartsVersion = 7; // minimum version to support swagger documentation
96 private static XPath xpath = XPathFactory.newInstance().newXPath();
99 private enum LineageType {
100 PARENT, CHILD, UNRELATED;
102 private class EdgeDescription {
104 private String ruleKey;
107 private LineageType type = LineageType.UNRELATED;
108 private String direction;
109 private String multiplicity;
110 private String preventDelete;
111 private String deleteOtherV;
112 private boolean hasDelTarget = false;
113 private String label;
114 private String description;
116 * @return the deleteOtherV
118 public String getDeleteOtherV() {
122 * @param deleteOtherV the deleteOtherV to set
124 public void setDeleteOtherV(String deleteOtherV) {
125 logger.debug("Edge: "+this.getRuleKey());
126 logger.debug("Truth: "+(("${direction}".equals(deleteOtherV)) ? "true" : "false"));
127 logger.debug("Truth: "+(("!${direction}".equals(deleteOtherV)) ? "true" : "false"));
129 if("${direction}".equals(deleteOtherV) ) {
130 this.deleteOtherV = this.direction;
131 } else if("!${direction}".equals(deleteOtherV) ) {
132 this.deleteOtherV = this.direction.equals("IN") ? "OUT" : ((this.direction.equals("OUT")) ? "IN" : deleteOtherV);
134 this.deleteOtherV = deleteOtherV;
136 logger.debug("DeleteOtherV="+deleteOtherV+"/"+this.direction+"="+this.deleteOtherV);
139 * @return the preventDelete
141 public String getPreventDelete() {
142 return preventDelete;
145 * @param preventDelete the preventDelete to set
147 public void setPreventDelete(String preventDelete) {
148 if(this.getTo().equals("flavor") || this.getFrom().equals("flavor") ){
149 logger.debug("Edge: "+this.getRuleKey());
150 logger.debug("Truth: "+(("${direction}".equals(preventDelete)) ? "true" : "false"));
151 logger.debug("Truth: "+(("!${direction}".equals(preventDelete)) ? "true" : "false"));
154 if("${direction}".equals(preventDelete) ) {
155 this.preventDelete = this.direction;
156 } else if("!${direction}".equals(preventDelete) ) {
157 this.preventDelete = this.direction.equals("IN") ? "OUT" : ((this.direction.equals("OUT")) ? "IN" : preventDelete);
159 this.preventDelete = preventDelete;
161 if(this.getTo().equals("flavor") || this.getFrom().equals("flavor")) {
162 logger.debug("PreventDelete="+preventDelete+"/"+this.direction+"="+this.preventDelete);
168 public String getTo() {
172 * @param to the to to set
174 public void setTo(String to) {
180 public String getFrom() {
184 * @param from the from to set
186 public void setFrom(String from) {
191 public String getRuleKey() {
194 public String getMultiplicity() {
197 public String getDirection() {
200 public String getDescription() {
201 return this.description;
203 public void setRuleKey(String val) {
206 public void setType(LineageType val) {
209 public void setDirection(String val) {
210 this.direction = val;
212 public void setMultiplicity(String val) {
213 this.multiplicity=val;
215 public void setHasDelTarget(String val) {
216 hasDelTarget = Boolean.parseBoolean(val);
218 public void setDescription(String val) {
219 this.description = val;
222 public String getRelationshipDescription(String fromTo, String otherNodeName) {
226 if ("FROM".equals(fromTo)) {
227 if ("OUT".equals(direction)) {
228 if (LineageType.PARENT == type) {
229 result = " (PARENT of "+otherNodeName;
230 result = String.join(" ", result+",", this.from, this.getLabel(), this.to);
234 if (LineageType.CHILD == type) {
235 result = " (CHILD of "+otherNodeName;
236 result = String.join(" ", result+",", this.from, this.getLabel(), this.to);
238 else if (LineageType.PARENT == type) {
239 result = " (PARENT of "+otherNodeName;
240 result = String.join(" ", result+",", this.from, this.getLabel(), this.to);
243 if (result.length() == 0) result = String.join(" ", "(", this.from, this.getLabel(), this.to+",", this.getMultiplicity());
245 //if ("TO".equals(fromTo)
246 if ("OUT".equals(direction)) {
247 if (LineageType.PARENT == type) {
248 result = " (CHILD of "+otherNodeName;
249 result = String.join(" ", result+",", this.from, this.getLabel(), this.to+",", this.getMultiplicity());
252 if (LineageType.PARENT == type) {
253 result = " (PARENT of "+otherNodeName;
254 result = String.join(" ", result+",", this.from, this.getLabel(), this.to+",", this.getMultiplicity());
257 if (result.length() == 0) result = String.join(" ", "(", this.from, this.getLabel(), this.to+",", this.getMultiplicity());
261 if (hasDelTarget) result = result + ", will delete target node";
263 if (result.length() > 0) result = result + ")";
265 if (description != null && description.length() > 0) result = result + "\n "+ description; // 6 spaces is important for yaml
271 * @return the hasDelTarget
273 @SuppressWarnings("unused")
274 public boolean isHasDelTarget() {
278 * @param hasDelTarget the hasDelTarget to set
280 @SuppressWarnings("unused")
281 public void setHasDelTarget(boolean hasDelTarget) {
282 this.hasDelTarget = hasDelTarget;
287 @SuppressWarnings("unused")
288 public LineageType getType() {
294 public String getLabel() {
297 public void setLabel(String string) {
302 private static class PutRelationPathSet {
305 ArrayList<String> relations = new ArrayList<String>();
306 String objectName = "";
307 String currentAPIVersion = "";
308 public PutRelationPathSet(String opId, String path) {
310 this.apiPath = path.replace("/relationship-list/relationship", "");
312 objectName = GenerateXsd.deletePaths.get(apiPath);
313 currentAPIVersion = GenerateXsd.apiVersion;
315 public void process() {
317 this.fromRelations();
318 this.writeRelationsFile();
321 public void toRelations() {
322 logger.debug("{“comment”: “Valid TO Relations that can be added”},");
323 logger.debug("apiPath: "+apiPath+"\nopId="+opId+"\nobjectName="+objectName);
324 Collection<EdgeDescription> toEdges = GenerateXsd.getEdgeRulesTO(objectName);
326 if(toEdges.size() > 0) {
327 relations.add("{\"comment\": \"Valid TO Relations that can be added\"}\n");
329 for (EdgeDescription ed : toEdges) {
330 logger.debug(ed.getRuleKey()+"Type="+ed.type);
331 String obj = ed.getRuleKey().replace(objectName,"").replace("|","");
332 String selectedRelation = "";
333 if(ed.type == LineageType.UNRELATED) {
334 String selectObj = getUnrelatedObjectPaths(obj, apiPath);
335 logger.debug("SelectedObj:"+selectObj);
336 selectedRelation = formatObjectRelationSet(obj,selectObj);
337 logger.trace("ObjectRelationSet"+selectedRelation);
339 String selectObj = getKinObjectPath(obj, apiPath);
340 logger.debug("SelectedObj:"+selectObj);
341 selectedRelation = formatObjectRelation(obj,selectObj);
342 logger.trace("ObjectRelationSet"+selectedRelation);
344 relations.add(selectedRelation);
345 logger.trace(selectedRelation);
349 public void fromRelations() {
350 logger.debug("“comment”: “Valid FROM Relations that can be added”");
351 Collection<EdgeDescription> fromEdges = getEdgeRulesFROM(objectName);
352 if(fromEdges.size() > 0) {
353 relations.add("{\"comment\": \"Valid FROM Relations that can be added\"}\n");
355 for (EdgeDescription ed : fromEdges) {
356 logger.debug(ed.getRuleKey()+"Type="+ed.type);
357 String obj = ed.getRuleKey().replace(objectName,"").replace("|","");
358 String selectedRelation = "";
359 if(ed.type == LineageType.UNRELATED) {
360 String selectObj = getUnrelatedObjectPaths(obj, apiPath);
361 logger.debug("SelectedObj"+selectObj);
362 selectedRelation = formatObjectRelationSet(obj,selectObj);
363 logger.trace("ObjectRelationSet"+selectedRelation);
365 String selectObj = getKinObjectPath(obj, apiPath);
366 logger.debug("SelectedObj"+selectObj);
367 selectedRelation = formatObjectRelation(obj,selectObj);
368 logger.trace("ObjectRelationSet"+selectedRelation);
370 relations.add(selectedRelation);
371 logger.trace(selectedRelation);
374 public void writeRelationsFile() {
375 File examplefilePath = new File(yaml_dir + "/relations/" + currentAPIVersion+"/"+opId.replace("RelationshipListRelationship", "") + ".json");
377 logger.debug(String.join("exampleFilePath: ", examplefilePath.toString()));
378 FileOutputStream fop = null;
380 if (!examplefilePath.exists()) {
381 examplefilePath.getParentFile().mkdirs();
382 examplefilePath.createNewFile();
384 fop = new FileOutputStream(examplefilePath);
385 } catch(Exception e) {
390 if(relations.size() > 0) {fop.write("[\n".getBytes());}
391 fop.write(String.join(",\n", relations).getBytes());
392 if(relations.size() > 0) {fop.write("\n]\n".getBytes());}
395 } catch (Exception e) {
399 logger.debug(String.join(",\n", relations));
403 private static String formatObjectRelationSet(String obj, String selectObj) {
404 StringBuffer pathSb = new StringBuffer();
405 String[] paths = selectObj.split("[|]");
406 for (String s: paths) {
407 logger.trace("SelectOBJ"+s);
408 pathSb.append(formatObjectRelation(obj, s)+",\n");
410 pathSb.deleteCharAt(pathSb.length()-2);
411 return pathSb.toString();
414 private static String formatObjectRelation(String obj, String selectObj) {
415 StringBuffer pathSb = new StringBuffer();
416 pathSb.append("{\n");
417 pathSb.append("\"related-to\" : \""+obj+"\",\n");
418 pathSb.append("\"related-link\" : \""+selectObj+"\"\n");
420 return pathSb.toString();
423 private static String getKinObjectPath(String obj, String apiPath) {
424 LevenshteinDistance proximity = new LevenshteinDistance();
425 String targetPath = "";
426 int targetScore = Integer.MAX_VALUE;
427 int targetMaxScore = 0;
428 for (Map.Entry<String, String> p : deletePaths.entrySet()) {
429 if(p.getValue().equals(obj)) {
430 targetScore = (targetScore >= proximity.apply(apiPath, p.getKey())) ? proximity.apply(apiPath, p.getKey()) : targetScore;
431 targetPath = (targetScore >= proximity.apply(apiPath, p.getKey())) ? p.getKey() : targetPath;
432 targetMaxScore = (targetMaxScore <= proximity.apply(apiPath, p.getKey())) ? proximity.apply(apiPath, p.getKey()) : targetScore;
433 logger.trace(proximity.apply(apiPath, p.getKey())+":"+p.getKey());
434 logger.trace(proximity.apply(apiPath, p.getKey())+":"+apiPath);
440 private static String getUnrelatedObjectPaths(String obj, String apiPath) {
441 String targetPath = "";
442 logger.trace("Obj:"+obj +"\n" + apiPath);
443 for (Map.Entry<String, String> p : deletePaths.entrySet()) {
444 if(p.getValue().equals(obj)) {
445 logger.trace("p.getvalue:"+p.getValue()+"p.getkey:"+p.getKey());
446 targetPath += ((targetPath.length() == 0 ? "" : "|") + p.getKey());
447 logger.trace("Match:"+apiPath +"\n" + targetPath);
454 private static class PatchOperation {
456 String xmlRootElementName;
461 public PatchOperation(String useOpId, String xmlRootElementName, String tag, String path, String pathParams) {
463 this.useOpId = useOpId;
464 this.xmlRootElementName = xmlRootElementName;
467 this.pathParams = pathParams;
471 public String toString() {
472 StringBuffer pathSb = new StringBuffer();
473 pathSb.append(" patch:\n");
474 pathSb.append(" tags:\n");
475 pathSb.append(" - " + tag + "\n");
477 pathSb.append(" summary: update an existing " + xmlRootElementName + "\n");
478 pathSb.append(" description: update an existing " + xmlRootElementName + "\n");
479 pathSb.append(" operationId: Update" + useOpId + "\n");
480 pathSb.append(" consumes:\n");
481 pathSb.append(" - application/json\n");
482 pathSb.append(" - application/xml\n");
483 pathSb.append(" produces:\n");
484 pathSb.append(" - application/json\n");
485 pathSb.append(" - application/xml\n");
486 pathSb.append(" responses:\n");
487 pathSb.append(" \"default\":\n");
488 pathSb.append(" " + responsesUrl);
490 pathSb.append(" parameters:\n");
491 pathSb.append(pathParams); // for nesting
492 pathSb.append(" - name: body\n");
493 pathSb.append(" in: body\n");
494 pathSb.append(" description: " + xmlRootElementName + " object that needs to be created or updated\n");
495 pathSb.append(" required: true\n");
496 pathSb.append(" schema:\n");
497 pathSb.append(" $ref: \"patchSchema.yaml#/definitions/" + xmlRootElementName + "\"\n");
499 return pathSb.toString();
501 public String toString1() {
502 StringBuffer pathSb = new StringBuffer();
503 StringBuffer relationshipExamplesSb = new StringBuffer();
504 if ( path.endsWith("/relationship") ) {
505 pathSb.append(" " + path + ":\n" );
507 pathSb.append(" patch:\n");
508 pathSb.append(" tags:\n");
509 pathSb.append(" - " + tag + "\n");
511 if ( path.endsWith("/relationship") ) {
512 pathSb.append(" summary: see node definition for valid relationships\n");
513 relationshipExamplesSb.append("[See Examples](apidocs/relations/"+GenerateXsd.apiVersion+"/"+useOpId+".json)");
515 pathSb.append(" summary: update an existing " + xmlRootElementName + "\n");
516 pathSb.append(" description: |\n");
517 pathSb.append(" Update an existing " + xmlRootElementName + "\n");
518 pathSb.append(" #\n");
519 pathSb.append(" Note: Endpoints that are not devoted to object relationships support both PUT and PATCH operations.\n");
520 pathSb.append(" The PUT operation will entirely replace an existing object.\n");
521 pathSb.append(" The PATCH operation sends a \"description of changes\" for an existing object. The entire set of changes must be applied. An error result means no change occurs.\n");
522 pathSb.append(" #\n");
523 pathSb.append(" Other differences between PUT and PATCH are:\n");
524 pathSb.append(" #\n");
525 pathSb.append(" - For PATCH, you can send any of the values shown in sample REQUEST body. There are no required values.\n");
526 pathSb.append(" - For PATCH, resource-id which is a required REQUEST body element for PUT, must not be sent.\n");
527 pathSb.append(" - PATCH cannot be used to update relationship elements; there are dedicated PUT operations for this.\n");
529 pathSb.append(" operationId: Update" + useOpId + "\n");
530 pathSb.append(" consumes:\n");
531 pathSb.append(" - application/json\n");
532 pathSb.append(" - application/xml\n");
533 pathSb.append(" produces:\n");
534 pathSb.append(" - application/json\n");
535 pathSb.append(" - application/xml\n");
536 pathSb.append(" responses:\n");
537 pathSb.append(" \"default\":\n");
538 pathSb.append(" " + responsesUrl);
539 pathSb.append(" parameters:\n");
540 pathSb.append(pathParams); // for nesting
541 pathSb.append(" - name: body\n");
542 pathSb.append(" in: body\n");
543 pathSb.append(" description: " + xmlRootElementName + " object that needs to be created or updated. "+relationshipExamplesSb.toString()+"\n");
544 pathSb.append(" required: true\n");
545 pathSb.append(" schema:\n");
546 pathSb.append(" $ref: \"#/patchDefinitions/" + xmlRootElementName + "\"\n");
547 return pathSb.toString();
550 private static class PutOperation {
552 String xmlRootElementName;
557 public PutOperation(String useOpId, String xmlRootElementName, String tag, String path, String pathParams) {
559 this.useOpId = useOpId;
560 this.xmlRootElementName = xmlRootElementName;
563 this.pathParams = pathParams;
567 public String toString() {
568 StringBuffer pathSb = new StringBuffer();
569 StringBuffer relationshipExamplesSb = new StringBuffer();
570 if ( path.endsWith("/relationship") ) {
571 pathSb.append(" " + path + ":\n" );
573 pathSb.append(" put:\n");
574 pathSb.append(" tags:\n");
575 pathSb.append(" - " + tag + "\n");
577 if ( path.endsWith("/relationship") ) {
578 pathSb.append(" summary: see node definition for valid relationships\n");
580 pathSb.append(" summary: create or update an existing " + xmlRootElementName + "\n");
581 pathSb.append(" description: |\n Create or update an existing " + xmlRootElementName + ".\n #\n Note! This PUT method has a corresponding PATCH method that can be used to update just a few of the fields of an existing object, rather than a full object replacement. An example can be found in the [PATCH section] below\n");
583 relationshipExamplesSb.append("[Valid relationship examples shown here](apidocs/relations/"+GenerateXsd.apiVersion+"/"+useOpId.replace("RelationshipListRelationship", "")+".json)");
584 pathSb.append(" operationId: createOrUpdate" + useOpId + "\n");
585 pathSb.append(" consumes:\n");
586 pathSb.append(" - application/json\n");
587 pathSb.append(" - application/xml\n");
588 pathSb.append(" produces:\n");
589 pathSb.append(" - application/json\n");
590 pathSb.append(" - application/xml\n");
591 pathSb.append(" responses:\n");
592 pathSb.append(" \"default\":\n");
593 pathSb.append(" " + responsesUrl);
595 pathSb.append(" parameters:\n");
596 pathSb.append(pathParams); // for nesting
597 pathSb.append(" - name: body\n");
598 pathSb.append(" in: body\n");
599 pathSb.append(" description: " + xmlRootElementName + " object that needs to be created or updated. "+relationshipExamplesSb.toString()+"\n");
600 pathSb.append(" required: true\n");
601 pathSb.append(" schema:\n");
602 pathSb.append(" $ref: \"#/definitions/" + xmlRootElementName + "\"\n");
603 return pathSb.toString();
605 public String tagRelationshipPathMapEntry() {
606 if ( path.endsWith("/relationship") ) {
607 putRelationPaths.put(useOpId, path);
614 private static class GetOperation {
616 String xmlRootElementName;
619 @SuppressWarnings("unused")
621 public GetOperation(String useOpId, String xmlRootElementName, String tag, String path, String pathParams) {
623 this.useOpId = useOpId;
624 this.xmlRootElementName = xmlRootElementName;
627 this.pathParams = pathParams;
630 public String toString() {
631 StringBuffer pathSb = new StringBuffer();
632 pathSb.append(" " + path + ":\n" );
633 pathSb.append(" get:\n");
634 pathSb.append(" tags:\n");
635 pathSb.append(" - " + tag + "\n");
636 pathSb.append(" summary: returns " + xmlRootElementName + "\n");
638 pathSb.append(" description: returns " + xmlRootElementName + "\n");
639 pathSb.append(" operationId: get" + useOpId + "\n");
640 pathSb.append(" produces:\n");
641 pathSb.append(" - application/json\n");
642 pathSb.append(" - application/xml\n");
644 pathSb.append(" responses:\n");
645 pathSb.append(" \"200\":\n");
646 pathSb.append(" description: successful operation\n");
647 pathSb.append(" schema:\n");
648 pathSb.append(" $ref: \"#/getDefinitions/" + xmlRootElementName + "\"\n");
649 pathSb.append(" \"default\":\n");
650 pathSb.append(" " + responsesUrl);
652 return pathSb.toString();
656 private static class DeleteOperation {
658 String xmlRootElementName;
662 public DeleteOperation(String useOpId, String xmlRootElementName, String tag, String path, String pathParams) {
664 this.useOpId = useOpId;
665 this.xmlRootElementName = xmlRootElementName;
668 this.pathParams = pathParams;
671 public String toString() {
672 StringBuffer pathSb = new StringBuffer();
673 pathSb.append(" delete:\n");
674 pathSb.append(" tags:\n");
675 pathSb.append(" - " + tag + "\n");
676 pathSb.append(" summary: delete an existing " + xmlRootElementName + "\n");
678 pathSb.append(" description: delete an existing " + xmlRootElementName + "\n");
680 pathSb.append(" operationId: delete" + useOpId + "\n");
681 pathSb.append(" consumes:\n");
682 pathSb.append(" - application/json\n");
683 pathSb.append(" - application/xml\n");
684 pathSb.append(" produces:\n");
685 pathSb.append(" - application/json\n");
686 pathSb.append(" - application/xml\n");
687 pathSb.append(" responses:\n");
688 pathSb.append(" \"default\":\n");
689 pathSb.append(" " + responsesUrl);
690 pathSb.append(" parameters:\n");
692 pathSb.append(pathParams); // for nesting
693 if ( !path.endsWith("/relationship") ) {
694 pathSb.append(" - name: resource-version\n");
696 pathSb.append(" in: query\n");
697 pathSb.append(" description: resource-version for concurrency\n");
698 pathSb.append(" required: true\n");
699 pathSb.append(" type: string\n");
701 return pathSb.toString();
703 public String objectPathMapEntry() {
704 if (! path.endsWith("/relationship") ) {
705 deletePaths.put(path, xmlRootElementName);
707 return (xmlRootElementName+":"+path);
712 private static boolean validVersion(String versionToGen) {
714 if ("ALL".equalsIgnoreCase(versionToGen)) {
718 for (Version v : Version.values()) {
719 if (v.name().equals(versionToGen)) {
727 private static boolean versionUsesAnnotations( String version) {
728 if (new Integer(version.substring(1)).intValue() >= annotationsStartVersion ) {
734 private static boolean versionSupportsSwagger( String version) {
735 if (new Integer(version.substring(1)).intValue() >= swaggerSupportStartsVersion ) {
741 public static void main(String[] args) throws IOException {
742 String versionToGen = System.getProperty("gen_version").toLowerCase();
743 String fileTypeToGen = System.getProperty("gen_type").toLowerCase();
744 if ( fileTypeToGen == null ) {
745 fileTypeToGen = generateTypeXSD;
748 if ( !fileTypeToGen.equals( generateTypeXSD ) && !fileTypeToGen.equals( generateTypeYAML )) {
749 System.err.println("Invalid gen_type passed. " + fileTypeToGen);
754 String responsesLabel = System.getProperty("yamlresponses_url");
755 responsesUrl = responsesLabel;
757 List<Version> versionsToGen = new ArrayList<>();
758 if ( versionToGen == null ) {
759 System.err.println("Version is required, ie v<n> or ALL.");
762 else if (!"ALL".equalsIgnoreCase(versionToGen) && !versionToGen.matches("v\\d+") && !validVersion(versionToGen)) {
763 System.err.println("Invalid version passed. " + versionToGen);
766 else if ("ALL".equalsIgnoreCase(versionToGen)) {
767 versionsToGen = Arrays.asList(Version.values());
768 Collections.sort(versionsToGen);
769 Collections.reverse(versionsToGen);
771 versionsToGen.add(Version.valueOf(versionToGen));
774 //process file type System property
775 fileTypeToGen = (fileTypeToGen == null ? generateTypeXSD : fileTypeToGen.toLowerCase());
776 if ( !fileTypeToGen.equals( generateTypeXSD ) && !fileTypeToGen.equals( generateTypeYAML )) {
777 System.err.println("Invalid gen_type passed. " + fileTypeToGen);
779 } else if ( fileTypeToGen.equals(generateTypeYAML) ) {
780 if ( responsesUrl == null || responsesUrl.length() < 1
781 || responsesLabel == null || responsesLabel.length() < 1 ) {
782 System.err.println("generating swagger yaml file requires yamlresponses_url and yamlresponses_label properties" );
785 responsesUrl = "description: "+ "Response codes found in [response codes]("+responsesLabel+ ").\n";
789 if(System.getProperty("user.dir") != null && !System.getProperty("user.dir").contains(normalStartDir)) {
790 oxmPath = autoGenRoot + "/oxm/";
793 oxmPath = root + "/oxm/";
800 for (Version v : versionsToGen) {
801 apiVersion = v.toString();
802 logger.info("Generating " + apiVersion + " " + fileTypeToGen);
803 File oxm_file = new File(oxmPath + "aai_oxm_" + apiVersion + ".xml");
804 apiVersionFmt = "." + apiVersion + ".";
805 generatedJavaType = new HashMap<String, String>();
806 appliedPaths = new HashMap<String, String>();
807 putRelationPaths = new HashMap<String, String>();
808 deletePaths = new HashMap<String, String>();
810 if ( fileTypeToGen.equals(generateTypeXSD) ) {
811 useAnnotationsInXsd = versionUsesAnnotations(apiVersion);
812 outfileName = xsd_dir + "/aai_schema_" + apiVersion + "." + generateTypeXSD;
813 fileContent = processOxmFile(oxm_file, v, null);
814 } else if ( versionSupportsSwagger(apiVersion )) {
815 if(System.getProperty("user.dir") != null && !System.getProperty("user.dir").contains(normalStartDir)) {
816 outfileName = alt_yaml_dir;
819 outfileName = yaml_dir;
821 outfileName = outfileName + "/aai_swagger_" + apiVersion + "." + generateTypeYAML;
822 fileContent = generateSwaggerFromOxmFile( oxm_file, null);
826 outfile = new File(outfileName);
827 File parentDir = outfile.getParentFile();
828 if(! parentDir.exists())
832 outfile.createNewFile();
833 } catch (IOException e) {
834 logger.error( "Exception creating output file " + outfileName);
837 BufferedWriter bw = null;
839 Charset charset = Charset.forName("UTF-8");
840 Path path = Paths.get(outfileName);
841 bw = Files.newBufferedWriter(path, charset);
842 bw.write(fileContent);
843 } catch ( IOException e) {
844 logger.error( "Exception writing output file " + outfileName);
851 logger.info( "GeneratedXSD successful, saved in " + outfileName);
857 public static String processJavaTypeElement( String javaTypeName, Element javaTypeElement) {
859 String xmlRootElementName = null;
861 NodeList parentNodes = javaTypeElement.getElementsByTagName("java-attributes");
862 StringBuffer sb = new StringBuffer();
863 if ( parentNodes.getLength() == 0 ) {
864 logger.trace( "no java-attributes for java-type " + javaTypeName);
869 NamedNodeMap attributes;
871 NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
872 Element valElement = (Element) valNodes.item(0);
873 attributes = valElement.getAttributes();
874 for ( int i = 0; i < attributes.getLength(); ++i ) {
875 Attr attr = (Attr) attributes.item(i);
876 String attrName = attr.getNodeName();
878 String attrValue = attr.getNodeValue();
879 logger.trace("Found xml-root-element attribute: " + attrName + " with value: " + attrValue);
880 if ( attrName.equals("name"))
881 xmlRootElementName = attrValue;
884 Element parentElement = (Element)parentNodes.item(0);
885 NodeList xmlElementNodes = parentElement.getElementsByTagName("xml-element");
887 Element childElement;
888 String xmlElementWrapper;
890 Element xmlElementElement;
892 String elementName, elementType, elementIsKey, elementIsRequired, elementContainerType;
893 StringBuffer sb1 = new StringBuffer();
894 if ( xmlElementNodes.getLength() > 0 ) {
895 sb1.append(" <xs:element name=\"" + xmlRootElementName + "\">\n");
896 sb1.append(" <xs:complexType>\n");
897 NodeList properties = GenerateXsd.locateXmlProperties(javaTypeElement);
898 if (properties != null && useAnnotationsInXsd) {
899 logger.trace("properties found for: " + xmlRootElementName);
900 sb1.append(" <xs:annotation>\r\n");
901 insertAnnotation(properties, false, "class", sb1, " ");
903 sb1.append(" </xs:annotation>\r\n");
905 logger.trace("no properties found for: " + xmlRootElementName);
907 sb1.append(" <xs:sequence>\n");
908 for ( int i = 0; i < xmlElementNodes.getLength(); ++i ) {
910 xmlElementElement = (Element)xmlElementNodes.item(i);
911 childNodes = xmlElementElement.getElementsByTagName("xml-element-wrapper");
913 xmlElementWrapper = null;
914 if ( childNodes.getLength() > 0 ) {
915 childElement = (Element)childNodes.item(0);
917 attributes = childElement.getAttributes();
918 for ( int k = 0; k < attributes.getLength(); ++k ) {
919 Attr attr = (Attr) attributes.item(k);
920 String attrName = attr.getNodeName();
921 String attrValue = attr.getNodeValue();
922 if ( attrName.equals("name")) {
923 xmlElementWrapper = attrValue;
924 logger.trace("found xml-element-wrapper " + xmlElementWrapper);
929 attributes = xmlElementElement.getAttributes();
933 elementName = elementType = elementIsKey = elementIsRequired = elementContainerType = null;
934 for ( int j = 0; j < attributes.getLength(); ++j ) {
935 Attr attr = (Attr) attributes.item(j);
936 String attrName = attr.getNodeName();
938 String attrValue = attr.getNodeValue();
939 logger.trace("For " + xmlRootElementName + " Found xml-element attribute: " + attrName + " with value: " + attrValue);
940 if ( attrName.equals("name")) {
941 elementName = attrValue;
943 if ( attrName.equals("type")) {
944 elementType = attrValue;
945 if ( attrValue.contains(apiVersionFmt) ) {
946 addType = attrValue.substring(attrValue.lastIndexOf('.')+1);
947 if ( !generatedJavaType.containsKey(addType) ) {
948 generatedJavaType.put(addType, attrValue);
949 sb.append(processJavaTypeElement( addType, getJavaTypeElement(addType) ));
955 if ( attrName.equals("xml-key")) {
956 elementIsKey = attrValue;
958 if ( attrName.equals("required")) {
959 elementIsRequired = attrValue;
961 if ( attrName.equals("container-type")) {
962 elementContainerType = attrValue;
966 if ( xmlElementWrapper != null ) {
967 sb1.append(" <xs:element name=\"" + xmlElementWrapper +"\"");
968 if ( elementIsRequired == null || !elementIsRequired.equals("true")||addType != null) {
969 sb1.append(" minOccurs=\"0\"");
972 sb1.append(" <xs:complexType>\n");
973 properties = GenerateXsd.locateXmlProperties(javaTypeElement);
974 if (properties != null && useAnnotationsInXsd) {
975 sb1.append(" <xs:annotation>\r\n");
976 insertAnnotation(properties, false, "class", sb1, " ");
977 sb1.append(" </xs:annotation>\r\n");
979 logger.trace("no properties found for: " + xmlElementWrapper);
981 sb1.append(" <xs:sequence>\n");
984 if ("Nodes".equals(addType)) {
985 logger.trace("Skipping nodes, temporary testing");
988 if ( addType != null ) {
989 sb1.append(" <xs:element ref=\"tns:" + getXmlRootElementName(addType) +"\"");
991 sb1.append(" <xs:element name=\"" + elementName +"\"");
993 if ( elementType.equals("java.lang.String"))
994 sb1.append(" type=\"xs:string\"");
995 if ( elementType.equals("java.lang.Long"))
996 sb1.append(" type=\"xs:unsignedInt\"");
997 if ( elementType.equals("java.lang.Integer"))
998 sb1.append(" type=\"xs:int\"");
999 if ( elementType.equals("java.lang.Boolean"))
1000 sb1.append(" type=\"xs:boolean\"");
1001 if ( elementIsRequired == null || !elementIsRequired.equals("true")||addType != null) {
1002 sb1.append(" minOccurs=\"0\"");
1004 if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) {
1005 sb1.append(" maxOccurs=\"unbounded\"");
1007 properties = GenerateXsd.locateXmlProperties(xmlElementElement);
1008 if (properties != null || elementIsKey != null) {
1010 if ( useAnnotationsInXsd ) {
1011 sb1.append(" <xs:annotation>\r\n");
1012 insertAnnotation(properties, elementIsKey != null, "field", sb1, " ");
1013 sb1.append(" </xs:annotation>\r\n");
1015 if (xmlElementWrapper== null) {
1016 sb1.append(" </xs:element>\n");
1021 if ( xmlElementWrapper != null ) {
1022 sb1.append(" </xs:sequence>\n");
1023 sb1.append(" </xs:complexType>\n");
1024 sb1.append(" </xs:element>\n");
1027 sb1.append(" </xs:sequence>\n");
1028 sb1.append(" </xs:complexType>\n");
1029 sb1.append(" </xs:element>\n");
1032 if ( xmlElementNodes.getLength() < 1 ) {
1033 sb.append(" <xs:element name=\"" + xmlRootElementName + "\">\n");
1034 sb.append(" <xs:complexType>\n");
1035 sb.append(" <xs:sequence/>\n");
1036 sb.append(" </xs:complexType>\n");
1037 sb.append(" </xs:element>\n");
1038 generatedJavaType.put(javaTypeName, null);
1039 return sb.toString();
1042 return sb.toString();
1045 private static void insertAnnotation(NodeList items, boolean isKey, String target, StringBuffer sb1, String indentation) {
1046 if (items != null || isKey) {
1047 List<String> metadata = new ArrayList<>();
1051 Element item = null;
1053 metadata.add("isKey=true");
1055 if (items != null) {
1056 for (int i = 0; i < items.getLength(); i++) {
1057 item = (Element)items.item(i);
1058 name = item.getAttribute("name");
1059 value = item.getAttribute("value");
1060 if (name.equals("abstract")) {
1061 name = "isAbstract";
1062 } else if (name.equals("extends")) {
1063 name = "extendsFrom";
1065 metadata.add(name + "=\"" + value.replaceAll("&", "&") + "\"");
1069 indentation + " <xs:appinfo>\r\n" +
1070 indentation + " <annox:annotate target=\""+target+"\">@org.onap.aai.annotations.Metadata(" + Joiner.on(",").join(metadata) + ")</annox:annotate>\r\n" +
1071 indentation + " </xs:appinfo>\r\n");
1076 private static Element getJavaTypeElement( String javaTypeName )
1079 String attrName, attrValue;
1081 Element javaTypeElement;
1082 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
1083 javaTypeElement = (Element) javaTypeNodes.item(i);
1084 NamedNodeMap attributes = javaTypeElement.getAttributes();
1085 for ( int j = 0; j < attributes.getLength(); ++j ) {
1086 attr = (Attr) attributes.item(j);
1087 attrName = attr.getNodeName();
1088 attrValue = attr.getNodeValue();
1089 if ( attrName.equals("name") && attrValue.equals(javaTypeName))
1090 return javaTypeElement;
1093 logger.error( "oxm file format error, missing java-type " + javaTypeName);
1094 return (Element) null;
1097 private static Element getJavaTypeElementSwagger( String javaTypeName )
1100 String attrName, attrValue;
1102 Element javaTypeElement;
1103 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
1104 javaTypeElement = (Element) javaTypeNodes.item(i);
1105 NamedNodeMap attributes = javaTypeElement.getAttributes();
1106 for ( int j = 0; j < attributes.getLength(); ++j ) {
1107 attr = (Attr) attributes.item(j);
1108 attrName = attr.getNodeName();
1109 attrValue = attr.getNodeValue();
1110 if ( attrName.equals("name") && attrValue.equals(javaTypeName))
1111 return javaTypeElement;
1114 logger.error( "oxm file format error, missing java-type " + javaTypeName);
1115 return (Element) null;
1117 private static String getXmlRootElementName( String javaTypeName )
1120 String attrName, attrValue;
1122 Element javaTypeElement;
1123 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
1124 javaTypeElement = (Element) javaTypeNodes.item(i);
1125 NamedNodeMap attributes = javaTypeElement.getAttributes();
1126 for ( int j = 0; j < attributes.getLength(); ++j ) {
1127 attr = (Attr) attributes.item(j);
1128 attrName = attr.getNodeName();
1129 attrValue = attr.getNodeValue();
1130 if ( attrName.equals("name") && attrValue.equals(javaTypeName)) {
1131 NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
1132 Element valElement = (Element) valNodes.item(0);
1133 attributes = valElement.getAttributes();
1134 for ( int k = 0; k < attributes.getLength(); ++k ) {
1135 attr = (Attr) attributes.item(k);
1136 attrName = attr.getNodeName();
1138 attrValue = attr.getNodeValue();
1139 if ( attrName.equals("name"))
1145 logger.error( "oxm file format error, missing java-type " + javaTypeName);
1150 public static String processOxmFile( File oxmFile, Version v, String xml )
1153 apiVersion = v.toString();
1154 useAnnotationsInXsd = true;
1155 apiVersionFmt = "." + apiVersion + ".";
1156 generatedJavaType = new HashMap<>();
1157 appliedPaths = new HashMap<>();
1159 StringBuilder sb = new StringBuilder();
1160 logger.trace("processing starts");
1161 sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");
1162 String namespace = "org.onap";
1163 if (v.compareTo(Version.v11) < 0) {
1164 namespace = "org.openecomp";
1166 if ( useAnnotationsInXsd ) {
1167 sb.append("<xs:schema elementFormDefault=\"qualified\" version=\"1.0\" targetNamespace=\"http://" + namespace + ".aai.inventory/"
1168 + apiVersion + "\" xmlns:tns=\"http://" + namespace + ".aai.inventory/" + apiVersion + "\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
1170 + "xmlns:jaxb=\"http://java.sun.com/xml/ns/jaxb\"\r\n" +
1171 " jaxb:version=\"2.1\" \r\n" +
1172 " xmlns:annox=\"http://annox.dev.java.net\" \r\n" +
1173 " jaxb:extensionBindingPrefixes=\"annox\">\n\n");
1176 sb.append("<xs:schema elementFormDefault=\"qualified\" version=\"1.0\" targetNamespace=\"http://" + namespace + ".aai.inventory/"
1177 + apiVersion + "\" xmlns:tns=\"http://" + namespace + ".aai.inventory/" + apiVersion + "\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n\n");
1182 DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
1183 dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
1184 DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
1188 doc = dBuilder.parse(oxmFile);
1190 InputSource is = new InputSource(new StringReader(xml));
1191 doc = dBuilder.parse(is);
1193 NodeList bindingsNodes = doc.getElementsByTagName("xml-bindings");
1194 Element bindingElement;
1195 NodeList javaTypesNodes;
1196 Element javaTypesElement;
1198 Element javaTypeElement;
1201 if ( bindingsNodes == null || bindingsNodes.getLength() == 0 ) {
1202 logger.error( "missing <binding-nodes> in " + oxmFile );
1206 bindingElement = (Element) bindingsNodes.item(0);
1207 javaTypesNodes = bindingElement.getElementsByTagName("java-types");
1208 if ( javaTypesNodes.getLength() < 1 ) {
1209 logger.error( "missing <binding-nodes><java-types> in " + oxmFile );
1212 javaTypesElement = (Element) javaTypesNodes.item(0);
1213 javaTypeNodes = javaTypesElement.getElementsByTagName("java-type");
1214 if ( javaTypeNodes.getLength() < 1 ) {
1215 logger.error( "missing <binding-nodes><java-types><java-type> in " + oxmFile );
1219 String javaTypeName;
1220 String attrName, attrValue;
1222 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
1223 javaTypeElement = (Element) javaTypeNodes.item(i);
1224 NamedNodeMap attributes = javaTypeElement.getAttributes();
1225 javaTypeName = null;
1226 for ( int j = 0; j < attributes.getLength(); ++j ) {
1227 attr = (Attr) attributes.item(j);
1228 attrName = attr.getNodeName();
1229 attrValue = attr.getNodeValue();
1230 if ( attrName.equals("name"))
1231 javaTypeName = attrValue;
1233 if ( javaTypeName == null ) {
1234 logger.error( "<java-type> has no name attribute in " + oxmFile );
1237 if ("Nodes".equals(javaTypeName)) {
1238 logger.debug("skipping Nodes entry (temporary feature)");
1241 if ( !generatedJavaType.containsKey(javaTypeName) ) {
1242 generatedJavaType.put(javaTypeName, null);
1243 sb.append(processJavaTypeElement( javaTypeName, javaTypeElement ));
1247 } catch (Exception e) {
1248 e.printStackTrace();
1251 sb.append("</xs:schema>\n");
1252 return sb.toString();
1255 public static String toDeleteRules(String objectName) {
1256 Collection<EdgeDescription> toEdges = GenerateXsd.getEdgeRulesTO(objectName);
1257 logger.debug("TO Edges count: "+toEdges.size()+" Object: "+objectName);
1258 String prevent=null;
1260 LinkedHashSet<String> preventDelete = new LinkedHashSet<String>();
1261 LinkedHashSet<String> alsoDelete = new LinkedHashSet<String>();
1262 for (EdgeDescription ed : toEdges) {
1263 logger.debug("{“comment”: From = "+ed.getFrom()+" To: "+ed.getTo()+" Object: "+objectName);
1264 logger.debug("{“comment”: Direction = "+ed.getDirection()+" PreventDelete: "+ed.getPreventDelete()+" DeleteOtherV: "+ed.getDeleteOtherV()+" Object: "+objectName);
1265 if(ed.getPreventDelete().equals("IN") && ed.getTo().equals(objectName)) {
1266 preventDelete.add(ed.getFrom().toUpperCase());
1268 if(ed.getDeleteOtherV().equals("IN") && ed.getTo().equals(objectName) ) {
1269 alsoDelete.add(ed.getFrom().toUpperCase());
1272 if(preventDelete.size() > 0) {
1273 prevent = " - "+objectName.toUpperCase()+" cannot be deleted if linked to "+String.join(",",preventDelete);
1274 logger.info(prevent);
1276 if(alsoDelete.size() > 0) {
1277 also = " - "+objectName.toUpperCase()+" is DELETED when these are DELETED "+String.join(",",alsoDelete);
1278 // This commented out line is better (gets who deletes what correct) but still not accurate.
1279 //also = " - Deletion of an instance of "+objectName.toUpperCase()+" causes instances of these directly related types to be DELETED ["+String.join(",",alsoDelete)+"]";
1282 return String.join((prevent == null || also == null) ? "" : "\n", prevent == null ? "" : prevent, also == null ? "" : also)+((prevent == null && also == null) ? "" : "\n");
1285 public static String fromDeleteRules(String objectName) {
1286 Collection<EdgeDescription> fromEdges = GenerateXsd.getEdgeRulesFROM(objectName);
1287 LinkedHashSet<String> preventDelete = new LinkedHashSet <String>();
1288 LinkedHashSet<String> alsoDelete = new LinkedHashSet <String>();
1289 String prevent=null;
1291 for (EdgeDescription ed : fromEdges) {
1292 logger.debug("{“comment”: From = "+ed.getFrom()+" To: "+ed.getTo()+" Object: "+objectName);
1293 logger.debug("{“comment”: Direction = "+ed.getDirection()+" PreventDelete: "+ed.getPreventDelete()+" DeleteOtherV: "+ed.getDeleteOtherV()+" Object: "+objectName);
1294 if(ed.getPreventDelete().equals("OUT") && ed.getFrom().equals(objectName)) {
1295 preventDelete.add(ed.getTo().toUpperCase());
1297 if(ed.getDeleteOtherV().equals("OUT") && ed.getFrom().equals(objectName) ) {
1298 alsoDelete.add(ed.getTo().toUpperCase());
1301 if(preventDelete.size() > 0) {
1302 prevent = " - "+objectName.toUpperCase()+" cannot be deleted if linked to "+String.join(",",preventDelete);
1303 logger.info(prevent);
1305 if(alsoDelete.size() > 0) {
1306 also = " - "+objectName.toUpperCase()+" deletion means associated objects of these types are also DELETED:"+String.join(",",alsoDelete);
1307 // This commented out line is better (gets who deletes what correct) but still not accurate.
1308 //also = " - Deletion of an instance of "+objectName.toUpperCase()+" causes instances of these directly related types to be DELETED ["+String.join(",",alsoDelete)+"]";
1311 return String.join((prevent == null || also == null) ? "" : "\n", prevent == null ? "" : prevent, also == null ? "" : also)+((prevent == null && also == null) ? "" : "\n");
1315 private static boolean isStandardType( String elementType )
1317 switch ( elementType ) {
1318 case "java.lang.String":
1319 case "java.lang.Long":
1320 case "java.lang.Integer":
1321 case"java.lang.Boolean":
1327 private static Vector<String> getIndexedProps( String attrValue )
1329 if ( attrValue == null )
1331 StringTokenizer st = new StringTokenizer( attrValue, ",");
1332 if ( st.countTokens() == 0 )
1334 Vector<String> result = new Vector<String>();
1335 while ( st.hasMoreTokens()) {
1336 result.add(st.nextToken());
1342 * Guaranteed to at least return non null but empty collection of edge descriptions
1343 * @param nodeName name of the vertex whose edge relationships to return
1344 * @return collection of node neighbors based on DbEdgeRules
1346 private static Collection<EdgeDescription> getEdgeRulesFromJson( String path, boolean skipMatch )
1349 ArrayList<EdgeDescription> result = new ArrayList<>();
1350 Iterator<Map<String, Object>> edgeRulesIterator;
1353 GenerateXsd x = new GenerateXsd();
1355 List<Map<String, Object>> inEdges = JsonPath.parse(jsonEdges).read(path);
1357 edgeRulesIterator = inEdges.iterator();
1358 Map<String, Object> edgeMap;
1362 String multiplicity;
1364 String hasDelTarget;
1365 String deleteOtherV;
1366 String preventDelete;
1368 EdgeDescription edgeDes;
1370 while( edgeRulesIterator.hasNext() ){
1371 edgeMap = edgeRulesIterator.next();
1372 fromNode = (String)edgeMap.get("from");
1373 toNode = (String)edgeMap.get("to");
1375 if ( fromNode.equals(toNode)) {
1379 edgeDes = x.new EdgeDescription();
1380 edgeDes.setRuleKey(fromNode + "|" + toNode);
1381 edgeDes.setLabel((String)edgeMap.get("label"));
1382 edgeDes.setTo((String)edgeMap.get("to"));
1383 edgeDes.setFrom((String)edgeMap.get("from"));
1384 direction = (String)edgeMap.get("direction");
1385 edgeDes.setDirection(direction);
1386 multiplicity = (String)edgeMap.get("multiplicity");
1387 edgeDes.setMultiplicity(multiplicity);
1388 isParent = (String)edgeMap.get(EdgeProperty.CONTAINS.toString());
1389 if ( "${direction}".equals(isParent)) {
1390 edgeDes.setType(LineageType.PARENT);
1392 edgeDes.setType(LineageType.UNRELATED);
1394 hasDelTarget = (String)edgeMap.get(EdgeProperty.DELETE_OTHER_V.toString());
1395 deleteOtherV = (String)edgeMap.get(EdgeProperty.DELETE_OTHER_V.toString());
1396 edgeDes.setDeleteOtherV(deleteOtherV);
1397 edgeDes.setHasDelTarget(hasDelTarget);
1398 preventDelete = (String)edgeMap.get(EdgeProperty.PREVENT_DELETE.toString());
1399 edgeDes.setPreventDelete(preventDelete);
1400 description = (String)edgeMap.get(EdgeProperty.DESCRIPTION.toString());
1401 edgeDes.setDescription(description);
1403 result.add(edgeDes);
1404 logger.debug("Edge: "+edgeDes.getRuleKey());
1406 } catch (Exception ex) {
1407 ex.printStackTrace();
1414 * Guaranteed to at least return non null but empty collection of edge descriptions
1415 * @param nodeName name of the vertex whose edge relationships to return
1416 * @return collection of node neighbors based on DbEdgeRules
1418 private static Collection<EdgeDescription> getEdgeRules( String nodeName )
1420 String fromRulesPath = "$['rules'][?(@['from']=='" + nodeName + "')]";
1421 String toRulesPath = "$['rules'][?(@['to']=='" + nodeName + "')]";
1422 Collection<EdgeDescription> fromEdges = getEdgeRulesFromJson( fromRulesPath, false );
1423 Collection<EdgeDescription> edges = getEdgeRulesFromJson( toRulesPath, true );
1424 edges.addAll(fromEdges);
1428 private static Collection<EdgeDescription> getEdgeRulesTO( String nodeName )
1430 String toRulesPath = "$['rules'][?(@['to']=='" + nodeName + "')]";
1431 Collection<EdgeDescription> edges = getEdgeRulesFromJson( toRulesPath, true );
1435 private static Collection<EdgeDescription> getEdgeRulesFROM( String nodeName )
1437 String fromRulesPath = "$['rules'][?(@['from']=='" + nodeName + "')]";
1438 Collection<EdgeDescription> edges = getEdgeRulesFromJson( fromRulesPath, true );
1441 public static String processJavaTypeElementSwagger( String javaTypeName, Element javaTypeElement,
1442 StringBuffer pathSb, StringBuffer definitionsSb, String path, String tag, String opId,
1443 String getItemName, StringBuffer pathParams, String queryParams, String validEdges) {
1445 String xmlRootElementName = null;
1446 StringBuilder definitionsLocalSb = new StringBuilder(256);
1448 String useTag = null;
1449 String useOpId = null;
1451 if ( tag != null ) {
1454 case "ServiceDesignAndCreation":
1456 case "LicenseManagement":
1457 case "CloudInfrastructure":
1464 if ( !javaTypeName.equals("Inventory") ) {
1465 if ( javaTypeName.equals("AaiInternal"))
1468 useOpId = javaTypeName;
1470 useOpId = opId + javaTypeName;
1472 useTag = javaTypeName;
1475 NodeList parentNodes = javaTypeElement.getElementsByTagName("java-attributes");
1477 if ( parentNodes.getLength() == 0 ) {
1478 logger.trace( "no java-attributes for java-type " + javaTypeName);
1482 NamedNodeMap attributes;
1484 NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
1485 Element valElement = (Element) valNodes.item(0);
1486 attributes = valElement.getAttributes();
1487 for ( int i = 0; i < attributes.getLength(); ++i ) {
1488 Attr attr = (Attr) attributes.item(i);
1489 String attrName = attr.getNodeName();
1491 String attrValue = attr.getNodeValue();
1492 logger.trace("Found xml-root-element attribute: " + attrName + " with value: " + attrValue);
1493 if ( attrName.equals("name"))
1494 xmlRootElementName = attrValue;
1497 NodeList childNodes;
1498 Element childElement;
1499 NodeList xmlPropNodes = javaTypeElement.getElementsByTagName("xml-properties");
1500 Element xmlPropElement;
1501 String pathDescriptionProperty = null;
1504 Vector<String> indexedProps = null;
1506 if ( xmlPropNodes.getLength() > 0 ) {
1508 for ( int i = 0; i < xmlPropNodes.getLength(); ++i ) {
1509 xmlPropElement = (Element)xmlPropNodes.item(i);
1510 if ( !xmlPropElement.getParentNode().isSameNode(javaTypeElement))
1512 childNodes = xmlPropElement.getElementsByTagName("xml-property");
1514 if ( childNodes.getLength() > 0 ) {
1515 for ( int j = 0; j < childNodes.getLength(); ++j ) {
1516 childElement = (Element)childNodes.item(j);
1518 int useValue = VALUE_NONE;
1519 attributes = childElement.getAttributes();
1520 for ( int k = 0; k < attributes.getLength(); ++k ) {
1521 Attr attr = (Attr) attributes.item(k);
1522 String attrName = attr.getNodeName();
1523 String attrValue = attr.getNodeValue();
1524 if ( attrName == null || attrValue == null )
1526 if ( attrName.equals("name") && attrValue.equals("description")) {
1527 useValue = VALUE_DESCRIPTION;
1529 if ( useValue == VALUE_DESCRIPTION && attrName.equals("value")) {
1530 pathDescriptionProperty = attrValue;
1532 if ( attrValue.equals("indexedProps")) {
1533 useValue = VALUE_INDEXED_PROPS;
1535 if ( useValue == VALUE_INDEXED_PROPS && attrName.equals("value")) {
1536 indexedProps = getIndexedProps( attrValue );
1543 logger.trace("javaTypeName " + javaTypeName + " description " + pathDescriptionProperty);
1545 Element parentElement = (Element)parentNodes.item(0);
1546 NodeList xmlElementNodes = parentElement.getElementsByTagName("xml-element");
1549 String attrDescription = null;
1551 Element xmlElementElement;
1552 String addType = null;
1553 String elementType = null, elementIsKey = null, elementIsRequired, elementContainerType = null;
1554 String elementName = null;
1555 StringBuffer sbParameters = new StringBuffer();
1557 StringBuffer sbRequired = new StringBuffer();
1558 int requiredCnt = 0;
1559 int propertyCnt = 0;
1560 StringBuffer sbProperties = new StringBuffer();
1561 StringBuffer sbIndexedParams = new StringBuffer();
1565 if ( xmlRootElementName.equals("inventory"))
1567 else if ( path == null )
1568 path = "/" + xmlRootElementName;
1570 path += "/" + xmlRootElementName;
1571 st = new StringTokenizer(path, "/");
1572 boolean genPath = false;
1574 if ( st.countTokens() > 1 && getItemName == null ) {
1575 if ( appliedPaths.containsKey(path))
1577 appliedPaths.put(path, xmlRootElementName);
1579 if ( path.contains("/relationship/") ) { // filter paths with relationship-list
1582 if ( path.endsWith("/relationship-list")) {
1588 Vector<String> addTypeV = null;
1589 if ( xmlElementNodes.getLength() > 0 ) {
1591 for ( int i = 0; i < xmlElementNodes.getLength(); ++i ) {
1592 xmlElementElement = (Element)xmlElementNodes.item(i);
1593 if ( !xmlElementElement.getParentNode().isSameNode(parentElement))
1596 valNodes = xmlElementElement.getElementsByTagName("xml-properties");
1597 attrDescription = null;
1598 if ( valNodes.getLength() > 0 ) {
1599 for ( int j = 0; j < valNodes.getLength(); ++j ) {
1600 valElement = (Element)valNodes.item(j);
1601 if ( !valElement.getParentNode().isSameNode(xmlElementElement))
1603 childNodes = valElement.getElementsByTagName("xml-property");
1604 if ( childNodes.getLength() > 0 ) {
1605 childElement = (Element)childNodes.item(0);
1607 attributes = childElement.getAttributes();
1608 attrDescription = null;
1609 boolean useValue = false;
1610 for ( int k = 0; k < attributes.getLength(); ++k ) {
1611 Attr attr = (Attr) attributes.item(k);
1612 String attrName = attr.getNodeName();
1613 String attrValue = attr.getNodeValue();
1614 if ( attrName.equals("name") && attrValue.equals("description")) {
1617 if ( useValue && attrName.equals("value")) {
1618 attrDescription = attrValue;
1626 attributes = xmlElementElement.getAttributes();
1627 addTypeV = null; // vector of 1
1630 elementName = elementType = elementIsKey = elementIsRequired = elementContainerType = null;
1631 for ( int j = 0; j < attributes.getLength(); ++j ) {
1632 Attr attr = (Attr) attributes.item(j);
1633 String attrName = attr.getNodeName();
1635 String attrValue = attr.getNodeValue();
1636 logger.trace("For " + xmlRootElementName + " Found xml-element attribute: " + attrName + " with value: " + attrValue);
1637 if ( attrName.equals("name")) {
1638 elementName = attrValue;
1641 if ( attrName.equals("type") && getItemName == null ) {
1642 elementType = attrValue;
1643 if ( attrValue.contains(apiVersionFmt) ) {
1644 addType = attrValue.substring(attrValue.lastIndexOf('.')+1);
1645 if ( addTypeV == null )
1646 addTypeV = new Vector<String>();
1647 addTypeV.add(addType);
1651 if ( attrName.equals("xml-key")) {
1652 elementIsKey = attrValue;
1653 path += "/{" + elementName + "}";
1655 if ( attrName.equals("required")) {
1656 elementIsRequired = attrValue;
1658 if ( attrName.equals("container-type")) {
1659 elementContainerType = attrValue;
1662 if ( getItemName != null ) {
1663 if ( getItemName.equals("array") ) {
1664 if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) {
1665 logger.trace( " returning array " + elementName );
1669 } else { // not an array check
1670 if ( elementContainerType == null || !elementContainerType.equals("java.util.ArrayList")) {
1671 logger.trace( " returning object " + elementName );
1676 logger.trace( " returning null" );
1679 if ( elementIsRequired != null ) {
1680 if ( requiredCnt == 0 )
1681 sbRequired.append(" required:\n");
1683 if ( addTypeV != null ) {
1684 for ( int k = 0; k < addTypeV.size(); ++i ) {
1685 sbRequired.append(" - " + getXmlRootElementName(addTypeV.elementAt(k)) + ":\n");
1688 sbRequired.append(" - " + elementName + "\n");
1692 if ( elementIsKey != null ) {
1693 sbParameters.append((" - name: " + elementName + "\n"));
1694 sbParameters.append((" in: path\n"));
1695 if ( attrDescription != null && attrDescription.length() > 0 )
1696 sbParameters.append((" description: " + attrDescription + "\n"));
1697 sbParameters.append((" required: true\n"));
1698 if ( elementType.equals("java.lang.String"))
1699 sbParameters.append(" type: string\n");
1700 if ( elementType.equals("java.lang.Long")) {
1701 sbParameters.append(" type: integer\n");
1702 sbParameters.append(" format: int64\n");
1704 if ( elementType.equals("java.lang.Integer")) {
1705 sbParameters.append(" type: integer\n");
1706 sbParameters.append(" format: int32\n");
1708 if ( elementType.equals("java.lang.Boolean")) {
1709 sbParameters.append(" type: boolean\n");
1711 if(StringUtils.isNotBlank(elementName)) {
1712 sbParameters.append(" example: "+"__"+elementName.toUpperCase()+"__"+"\n");
1714 } else if ( indexedProps != null
1715 && indexedProps.contains(elementName ) ) {
1716 sbIndexedParams.append((" - name: " + elementName + "\n"));
1717 sbIndexedParams.append((" in: query\n"));
1718 if ( attrDescription != null && attrDescription.length() > 0 )
1719 sbIndexedParams.append((" description: " + attrDescription + "\n"));
1720 sbIndexedParams.append((" required: false\n"));
1721 if ( elementType.equals("java.lang.String"))
1722 sbIndexedParams.append(" type: string\n");
1723 if ( elementType.equals("java.lang.Long")) {
1724 sbIndexedParams.append(" type: integer\n");
1725 sbIndexedParams.append(" format: int64\n");
1727 if ( elementType.equals("java.lang.Integer")) {
1728 sbIndexedParams.append(" type: integer\n");
1729 sbIndexedParams.append(" format: int32\n");
1731 if ( elementType.equals("java.lang.Boolean"))
1732 sbIndexedParams.append(" type: boolean\n");
1734 if ( isStandardType(elementType)) {
1735 sbProperties.append(" " + elementName + ":\n");
1737 sbProperties.append(" type: ");
1739 if ( elementType.equals("java.lang.String"))
1740 sbProperties.append("string\n");
1741 else if ( elementType.equals("java.lang.Long")) {
1742 sbProperties.append("integer\n");
1743 sbProperties.append(" format: int64\n");
1745 else if ( elementType.equals("java.lang.Integer")){
1746 sbProperties.append("integer\n");
1747 sbProperties.append(" format: int32\n");
1749 else if ( elementType.equals("java.lang.Boolean"))
1750 sbProperties.append("boolean\n");
1751 if ( attrDescription != null && attrDescription.length() > 0 )
1752 sbProperties.append(" description: " + attrDescription + "\n");
1755 if ( addTypeV != null ) {
1756 StringBuffer newPathParams = null;
1757 if ( pathParams != null ) {
1758 newPathParams = new StringBuffer();
1759 newPathParams.append(pathParams);
1761 if ( sbParameters.toString().length() > 0 ) {
1762 if ( newPathParams == null )
1763 newPathParams = new StringBuffer();
1764 newPathParams.append(sbParameters);
1766 String newQueryParams = null;
1767 if ( sbIndexedParams.toString().length() > 0 ) {
1768 if ( queryParams == null )
1769 newQueryParams = sbIndexedParams.toString();
1771 newQueryParams = queryParams + sbIndexedParams.toString();
1773 newQueryParams = queryParams;
1775 for ( int k = 0; k < addTypeV.size(); ++k ) {
1776 addType = addTypeV.elementAt(k);
1778 if ( opId == null || !opId.contains(addType)) {
1779 processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
1780 pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId, null,
1781 newPathParams, newQueryParams, validEdges);
1783 // need item name of array
1784 String itemName = processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
1785 pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId,
1786 "array", null, null, null );
1788 if ( itemName != null ) {
1789 if ( addType.equals("AaiInternal") ) {
1790 logger.debug( "addType AaiInternal, skip properties");
1792 } else if ( getItemName == null) {
1794 sbProperties.append(" " + getXmlRootElementName(addType) + ":\n");
1795 sbProperties.append(" type: array\n items:\n");
1796 sbProperties.append(" $ref: \"#/definitions/" + (itemName == "" ? "aai-internal" : itemName) + "\"\n");
1797 if ( attrDescription != null && attrDescription.length() > 0 )
1798 sbProperties.append(" description: " + attrDescription + "\n");
1801 if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) {
1802 // need properties for getXmlRootElementName(addType)
1803 newPathParams = null;
1804 if ( pathParams != null ) {
1805 newPathParams = new StringBuffer();
1806 newPathParams.append(pathParams);
1808 if ( sbParameters.toString().length() > 0 ) {
1809 if ( newPathParams == null )
1810 newPathParams = new StringBuffer();
1811 newPathParams.append(sbParameters);
1813 newQueryParams = null;
1814 if ( sbIndexedParams.toString().length() > 0 ) {
1815 if ( queryParams == null )
1816 newQueryParams = sbIndexedParams.toString();
1818 newQueryParams = queryParams + sbIndexedParams.toString();
1820 newQueryParams = queryParams;
1822 processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
1823 pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId,
1824 null, newPathParams, newQueryParams, validEdges );
1825 sbProperties.append(" " + getXmlRootElementName(addType) + ":\n");
1826 sbProperties.append(" type: array\n items: \n");
1827 sbProperties.append(" $ref: \"#/definitions/" + getXmlRootElementName(addType) + "\"\n");
1829 sbProperties.append(" " + getXmlRootElementName(addType) + ":\n");
1830 sbProperties.append(" type: object\n");
1831 sbProperties.append(" $ref: \"#/definitions/" + getXmlRootElementName(addType) + "\"\n");
1833 if ( attrDescription != null && attrDescription.length() > 0 )
1834 sbProperties.append(" description: " + attrDescription + "\n");
1842 if ( !path.endsWith("/relationship") ) {
1843 GetOperation get = new GetOperation(useOpId, xmlRootElementName, tag, path, pathParams == null ? "" : pathParams.toString());
1844 pathSb.append(get.toString());
1845 // if ( path.indexOf('{') > 0 ) {
1847 if ( sbParameters.toString().length() > 0 ) {
1848 if ( pathParams == null )
1849 pathParams = new StringBuffer();
1850 pathParams.append(sbParameters);
1852 if ( pathParams != null) {
1853 pathSb.append(" parameters:\n");
1854 pathSb.append(pathParams);
1856 logger.trace( "null pathParams for " + useOpId);
1857 if ( sbIndexedParams.toString().length() > 0 ) {
1858 if ( queryParams == null )
1859 queryParams = sbIndexedParams.toString();
1861 queryParams = queryParams + sbIndexedParams.toString();
1863 if ( queryParams != null ) {
1864 if ( pathParams == null ) {
1865 pathSb.append(" parameters:\n");
1867 pathSb.append(queryParams);
1871 boolean skipPutDelete = false; // no put or delete for "all"
1872 if ( !path.endsWith("/relationship") ) {
1873 if ( !path.endsWith("}") ){
1874 skipPutDelete = true;
1878 if ( path.indexOf('{') > 0 && !opId.startsWith("Search") &&!skipPutDelete) {
1880 PutOperation put = new PutOperation(useOpId, xmlRootElementName, tag, path, pathParams == null ? "" : pathParams.toString());
1881 pathSb.append(put.toString());
1882 if ( !path.endsWith("/relationship") ) {
1883 PatchOperation patch = new PatchOperation(useOpId, xmlRootElementName, tag, path, pathParams == null ? "" : pathParams.toString());
1884 pathSb.append(patch.toString1());
1886 logger.debug(put.tagRelationshipPathMapEntry());
1889 DeleteOperation del = new DeleteOperation(useOpId, xmlRootElementName, tag, path, pathParams == null ? "" : pathParams.toString());
1890 pathSb.append(del.toString());
1891 logger.debug(del.objectPathMapEntry());
1895 if ( generatedJavaType.containsKey(xmlRootElementName) ) {
1899 definitionsSb.append(" " + xmlRootElementName + ":\n");
1900 definitionsLocalSb.append(" " + xmlRootElementName + ":\n");
1901 Collection<EdgeDescription> edges = getEdgeRules(xmlRootElementName );
1903 if ( edges.size() > 0 ) {
1904 StringBuffer sbEdge = new StringBuffer();
1905 sbEdge.append(" ###### Related Nodes\n");
1906 for (EdgeDescription ed : edges) {
1907 if ( ed.getRuleKey().startsWith(xmlRootElementName)) {
1908 sbEdge.append(" - TO ").append(ed.getRuleKey().substring(ed.getRuleKey().indexOf("|")+1));
1909 sbEdge.append(ed.getRelationshipDescription("TO", xmlRootElementName));
1910 sbEdge.append("\n");
1913 for (EdgeDescription ed : edges) {
1914 if ( ed.getRuleKey().endsWith(xmlRootElementName)) {
1915 sbEdge.append(" - FROM ").append(ed.getRuleKey().substring(0, ed.getRuleKey().indexOf("|")));
1916 sbEdge.append(ed.getRelationshipDescription("FROM", xmlRootElementName));
1917 sbEdge.append("\n");
1920 // Delete rule processing is incorrect. One cannot express the delete rules in isolation from the
1921 // specific edge. Take the case of allotted-resource and service-instance. When the service-instance owns the
1922 // allotted-resource, yes, it deletes it. But when the service-instance only uses the allotted-resource, the deletion
1923 // of the service instance does not cause the deletion of the allotted-resource.
1924 // I put some lines into the toDeleteRules and fromDeleteRules to correct things to an extent, but it's still
1926 sbEdge.append(toDeleteRules(xmlRootElementName));
1927 sbEdge.append(fromDeleteRules(xmlRootElementName));
1928 validEdges = sbEdge.toString();
1931 // Handle description property. Might have a description OR valid edges OR both OR neither.
1932 // Only put a description: tag if there is at least one.
1933 if (pathDescriptionProperty != null || validEdges != null) {
1934 definitionsSb.append(" description: |\n");
1935 definitionsLocalSb.append(" description: |\n");
1937 if ( pathDescriptionProperty != null ) {
1938 definitionsSb.append(" " + pathDescriptionProperty + "\n" );
1939 definitionsLocalSb.append(" " + pathDescriptionProperty + "\n" );
1941 if (validEdges != null) {
1942 definitionsSb.append(validEdges);
1943 definitionsLocalSb.append(validEdges);
1947 if ( requiredCnt > 0 ) {
1948 definitionsSb.append(sbRequired);
1949 definitionsLocalSb.append(sbRequired);
1952 if ( propertyCnt > 0 ) {
1953 definitionsSb.append(" properties:\n");
1954 definitionsSb.append(sbProperties);
1955 definitionsLocalSb.append(" properties:\n");
1956 definitionsLocalSb.append(sbProperties);
1959 javaTypeDefinitions.put(xmlRootElementName, definitionsLocalSb.toString());
1960 } catch (Exception e) {
1961 e.printStackTrace();
1963 generatedJavaType.put(xmlRootElementName, null);
1967 public static void generateRelations() {
1968 if(putRelationPaths == null)
1970 putRelationPaths.forEach((k,v)->{
1971 logger.trace("k="+k+"\n"+"v="+v+v.equals("/business/customers/customer/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances/service-instance/{service-instance-id}/allotted-resources/allotted-resource/{id}/relationship-list/relationship"));
1972 logger.debug("apiPath(Operation): "+v);
1973 logger.debug("Target object: "+v.replace("/relationship-list/relationship", ""));
1974 logger.debug("Relations: ");
1975 PutRelationPathSet prp = new PutRelationPathSet(k, v);
1980 public static String generateSwaggerFromOxmFile( File oxmFile, String xml )
1983 apiVersion = Version.getLatest().toString();
1984 apiVersionFmt = "." + apiVersion + ".";
1985 generatedJavaType = new HashMap<>();
1986 appliedPaths = new HashMap<>();
1987 responsesUrl = "Description: response-label\n";
1989 StringBuffer sb = new StringBuffer();
1990 sb.append("swagger: \"2.0\"\ninfo:\n ");
1991 sb.append("description: |");
1992 sb.append("\n\n [Differences versus the previous schema version]("+"apidocs/aai_swagger_" + apiVersion + ".diff)");
1993 sb.append("\n\n Copyright © 2017 AT&T Intellectual Property. All rights reserved.\n\n Licensed under the Creative Commons License, Attribution 4.0 Intl. (the "License"); you may not use this documentation except in compliance with the License.\n\n You may obtain a copy of the License at\n\n (https://creativecommons.org/licenses/by/4.0/)\n\n Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.\n\n ECOMP and OpenECOMP are trademarks and service marks of AT&T Intellectual Property.\n\n This document is best viewed with Firefox or Chrome. Nodes can be found by appending /#/definitions/node-type-to-find to the path to this document. Edge definitions can be found with the node definitions.\n version: \"" + apiVersion +"\"\n");
1994 sb.append(" title: Active and Available Inventory REST API\n");
1995 sb.append(" license:\n name: Apache 2.0\n url: http://www.apache.org/licenses/LICENSE-2.0.html\n");
1996 sb.append(" contact:\n name:\n url:\n email:\n");
1997 sb.append("host:\nbasePath: /aai/" + apiVersion + "\n");
1998 sb.append("schemes:\n - https\npaths:\n");
2002 if(System.getProperty("user.dir") != null && !System.getProperty("user.dir").contains(normalStartDir)) {
2003 initialFile = new File(normalStartDir + "/src/main/resources/dbedgerules/DbEdgeRules_" + apiVersion + ".json");
2006 initialFile = new File("src/main/resources/dbedgerules/DbEdgeRules_" + apiVersion + ".json");
2008 InputStream is = new FileInputStream(initialFile);
2010 Scanner scanner = new Scanner(is);
2011 jsonEdges = scanner.useDelimiter("\\Z").next();
2015 DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
2016 dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
2017 DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
2020 if ( xml == null ) {
2021 doc = dBuilder.parse(oxmFile);
2023 InputSource isInput = new InputSource(new StringReader(xml));
2024 doc = dBuilder.parse(isInput);
2027 NodeList bindingsNodes = doc.getElementsByTagName("xml-bindings");
2028 Element bindingElement;
2029 NodeList javaTypesNodes;
2030 Element javaTypesElement;
2032 Element javaTypeElement;
2035 if ( bindingsNodes == null || bindingsNodes.getLength() == 0 ) {
2036 logger.error( "missing <binding-nodes> in " + oxmFile );
2040 bindingElement = (Element) bindingsNodes.item(0);
2041 javaTypesNodes = bindingElement.getElementsByTagName("java-types");
2042 if ( javaTypesNodes.getLength() < 1 ) {
2043 logger.error( "missing <binding-nodes><java-types> in " + oxmFile );
2046 javaTypesElement = (Element) javaTypesNodes.item(0);
2048 javaTypeNodes = javaTypesElement.getElementsByTagName("java-type");
2049 if ( javaTypeNodes.getLength() < 1 ) {
2050 logger.error( "missing <binding-nodes><java-types><java-type> in " + oxmFile );
2054 String javaTypeName;
2055 String attrName, attrValue;
2057 StringBuffer pathSb = new StringBuffer();
2059 StringBuffer definitionsSb = new StringBuffer();
2060 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
2061 javaTypeElement = (Element) javaTypeNodes.item(i);
2062 NamedNodeMap attributes = javaTypeElement.getAttributes();
2063 javaTypeName = null;
2064 for ( int j = 0; j < attributes.getLength(); ++j ) {
2065 attr = (Attr) attributes.item(j);
2066 attrName = attr.getNodeName();
2067 attrValue = attr.getNodeValue();
2068 if ( attrName.equals("name"))
2069 javaTypeName = attrValue;
2071 if ( javaTypeName == null ) {
2072 logger.error( "<java-type> has no name attribute in " + oxmFile );
2075 if ( !generatedJavaType.containsKey(getXmlRootElementName(javaTypeName)) ) {
2077 processJavaTypeElementSwagger( javaTypeName, javaTypeElement, pathSb,
2078 definitionsSb, null, null, null, null, null, null, null);
2082 } catch (Exception e) {
2083 e.printStackTrace();
2086 //append definitions
2087 sb.append("definitions:\n");
2088 Map<String, String> sortedJavaTypeDefinitions = new TreeMap<String, String>(javaTypeDefinitions);
2089 for (Map.Entry<String, String> entry : sortedJavaTypeDefinitions.entrySet()) {
2090 logger.debug("Key: "+entry.getKey()+"Test: "+ (entry.getKey() == "relationship"));
2091 if(entry.getKey().matches("relationship")) {
2092 String jb=entry.getValue();
2093 logger.debug("Value: "+jb);
2094 int ndx=jb.indexOf("related-to-property:");
2096 jb=jb.substring(0, ndx);
2097 jb=jb.replaceAll(" +$", "");
2099 logger.debug("Value-after: "+jb);
2103 sb.append(entry.getValue());
2106 sb.append("patchDefinitions:\n");
2107 for (Map.Entry<String, String> entry : sortedJavaTypeDefinitions.entrySet()) {
2108 String jb=entry.getValue().replaceAll("/definitions/", "/patchDefinitions/");
2109 int ndx=jb.indexOf("relationship-list:");
2111 jb=jb.substring(0, ndx);
2112 jb=jb.replaceAll(" +$", "");
2114 int ndx1=jb.indexOf("resource-version:");
2115 logger.debug("Key: "+entry.getKey()+" index: " + ndx1);
2116 logger.debug("Value: "+jb);
2118 jb=jb.substring(0, ndx1);
2119 jb=jb.replaceAll(" +$", "");
2121 logger.debug("Value-after: "+jb);
2125 sb.append("getDefinitions:\n");
2126 for (Map.Entry<String, String> entry : sortedJavaTypeDefinitions.entrySet()) {
2127 String jb=entry.getValue().replaceAll("/definitions/", "/getDefinitions/");
2131 logger.debug("generated " + sb.toString());
2132 generateRelations();
2133 return sb.toString();
2136 private static NodeList locateXmlProperties(Element element) {
2137 XPathExpression expr;
2138 NodeList result = null;
2140 expr = xpath.compile("xml-properties");
2142 Object nodeset = expr.evaluate(element, XPathConstants.NODESET);
2143 if (nodeset != null) {
2144 NodeList nodes = (NodeList) nodeset;
2145 if (nodes != null && nodes.getLength() > 0) {
2146 Element xmlProperty = (Element)nodes.item(0);
2147 result = xmlProperty.getElementsByTagName("xml-property");
2151 } catch (XPathExpressionException e) {
2152 e.printStackTrace();