2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 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
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 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
23 package org.onap.aai.util;
25 import com.google.common.base.Joiner;
26 import com.jayway.jsonpath.JsonPath;
27 import org.apache.commons.lang3.StringUtils;
28 import org.apache.commons.text.similarity.LevenshteinDistance;
30 import org.onap.aai.introspection.Version;
31 import org.onap.aai.serialization.db.EdgeProperty;
33 import org.xml.sax.InputSource;
35 import javax.xml.XMLConstants;
36 import javax.xml.parsers.DocumentBuilder;
37 import javax.xml.parsers.DocumentBuilderFactory;
38 import javax.xml.xpath.*;
40 import java.nio.charset.Charset;
41 import java.nio.file.Files;
42 import java.nio.file.Path;
43 import java.nio.file.Paths;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
49 public class GenerateXsd {
51 private static final Logger logger = LoggerFactory.getLogger("GenerateXsd.class");
53 static String apiVersion = null;
54 static String apiVersionFmt = null;
55 static boolean useAnnotationsInXsd = false;
56 static String responsesUrl = null;
57 static String responsesLabel = null;
58 static String jsonEdges = null;
60 static Map<String, String> generatedJavaType;
61 static Map<String, String> appliedPaths;
62 static Map<String, String> deletePaths;
63 static Map<String, String> putRelationPaths;
64 static NodeList javaTypeNodes;
65 static Map<String,String> javaTypeDefinitions = createJavaTypeDefinitions();
66 private static Map<String, String> createJavaTypeDefinitions()
68 StringBuffer aaiInternal = new StringBuffer();
69 Map<String,String> javaTypeDefinitions = new HashMap<String, String>();
70 aaiInternal.append(" aai-internal:\n");
71 aaiInternal.append(" properties:\n");
72 aaiInternal.append(" property-name:\n");
73 aaiInternal.append(" type: string\n");
74 aaiInternal.append(" property-value:\n");
75 aaiInternal.append(" type: string\n");
76 javaTypeDefinitions.put("aai-internal", aaiInternal.toString());
77 return javaTypeDefinitions;
80 public static final int VALUE_NONE = 0;
81 public static final int VALUE_DESCRIPTION = 1;
82 public static final int VALUE_INDEXED_PROPS = 2;
84 private static final String generateTypeXSD = "xsd";
85 private static final String generateTypeYAML = "yaml";
87 private static final String root = "../aai-schema/src/main/resources";
88 private static final String xsd_dir = root + "/aai_schema";
89 private static final String yaml_dir = root + "/aai_swagger_yaml";
91 /* These three strings are for yaml auto-generation from aai-common class*/
92 private static final String normalStartDir = "aai-core";
93 private static final String autoGenRoot = "aai-schema/src/main/resources";
94 private static final String alt_yaml_dir = autoGenRoot + "/aai_swagger_yaml";
96 private static int annotationsStartVersion = 9; // minimum version to support annotations in xsd
97 private static int swaggerSupportStartsVersion = 7; // minimum version to support swagger documentation
99 private static XPath xpath = XPathFactory.newInstance().newXPath();
102 private enum LineageType {
103 PARENT, CHILD, UNRELATED;
105 private class EdgeDescription {
107 private String ruleKey;
110 private LineageType type = LineageType.UNRELATED;
111 private String direction;
112 private String multiplicity;
113 private String preventDelete;
114 private String deleteOtherV;
115 private boolean hasDelTarget = false;
116 private String label;
117 private String description;
119 * @return the deleteOtherV
121 public String getDeleteOtherV() {
125 * @param deleteOtherV the deleteOtherV to set
127 public void setDeleteOtherV(String deleteOtherV) {
128 logger.debug("Edge: "+this.getRuleKey());
129 logger.debug("Truth: "+(("${direction}".equals(deleteOtherV)) ? "true" : "false"));
130 logger.debug("Truth: "+(("!${direction}".equals(deleteOtherV)) ? "true" : "false"));
132 if("${direction}".equals(deleteOtherV) ) {
133 this.deleteOtherV = this.direction;
134 } else if("!${direction}".equals(deleteOtherV) ) {
135 this.deleteOtherV = this.direction.equals("IN") ? "OUT" : ((this.direction.equals("OUT")) ? "IN" : deleteOtherV);
137 this.deleteOtherV = deleteOtherV;
139 logger.debug("DeleteOtherV="+deleteOtherV+"/"+this.direction+"="+this.deleteOtherV);
142 * @return the preventDelete
144 public String getPreventDelete() {
145 return preventDelete;
148 * @param preventDelete the preventDelete to set
150 public void setPreventDelete(String preventDelete) {
151 if(this.getTo().equals("flavor") || this.getFrom().equals("flavor") ){
152 logger.debug("Edge: "+this.getRuleKey());
153 logger.debug("Truth: "+(("${direction}".equals(preventDelete)) ? "true" : "false"));
154 logger.debug("Truth: "+(("!${direction}".equals(preventDelete)) ? "true" : "false"));
157 if("${direction}".equals(preventDelete) ) {
158 this.preventDelete = this.direction;
159 } else if("!${direction}".equals(preventDelete) ) {
160 this.preventDelete = this.direction.equals("IN") ? "OUT" : ((this.direction.equals("OUT")) ? "IN" : preventDelete);
162 this.preventDelete = preventDelete;
164 if(this.getTo().equals("flavor") || this.getFrom().equals("flavor")) {
165 logger.debug("PreventDelete="+preventDelete+"/"+this.direction+"="+this.preventDelete);
171 public String getTo() {
175 * @param to the to to set
177 public void setTo(String to) {
183 public String getFrom() {
187 * @param from the from to set
189 public void setFrom(String from) {
194 public String getRuleKey() {
197 public String getMultiplicity() {
200 public String getDirection() {
203 public String getDescription() {
204 return this.description;
206 public void setRuleKey(String val) {
209 public void setType(LineageType val) {
212 public void setDirection(String val) {
213 this.direction = val;
215 public void setMultiplicity(String val) {
216 this.multiplicity=val;
218 public void setHasDelTarget(String val) {
219 hasDelTarget = Boolean.parseBoolean(val);
221 public void setDescription(String val) {
222 this.description = val;
225 public String getRelationshipDescription(String fromTo, String otherNodeName) {
229 if ("FROM".equals(fromTo)) {
230 if ("OUT".equals(direction)) {
231 if (LineageType.PARENT == type) {
232 result = " (PARENT of "+otherNodeName;
233 result = String.join(" ", result+",", this.from, this.getLabel(), this.to);
237 if (LineageType.CHILD == type) {
238 result = " (CHILD of "+otherNodeName;
239 result = String.join(" ", result+",", this.from, this.getLabel(), this.to);
241 else if (LineageType.PARENT == type) {
242 result = " (PARENT of "+otherNodeName;
243 result = String.join(" ", result+",", this.from, this.getLabel(), this.to);
246 if (result.length() == 0) result = String.join(" ", "(", this.from, this.getLabel(), this.to+",", this.getMultiplicity());
248 //if ("TO".equals(fromTo)
249 if ("OUT".equals(direction)) {
250 if (LineageType.PARENT == type) {
251 result = " (CHILD of "+otherNodeName;
252 result = String.join(" ", result+",", this.from, this.getLabel(), this.to+",", this.getMultiplicity());
255 if (LineageType.PARENT == type) {
256 result = " (PARENT of "+otherNodeName;
257 result = String.join(" ", result+",", this.from, this.getLabel(), this.to+",", this.getMultiplicity());
260 if (result.length() == 0) result = String.join(" ", "(", this.from, this.getLabel(), this.to+",", this.getMultiplicity());
264 if (hasDelTarget) result = result + ", will delete target node";
266 if (result.length() > 0) result = result + ")";
268 if (description != null && description.length() > 0) result = result + "\n "+ description; // 6 spaces is important for yaml
274 * @return the hasDelTarget
276 @SuppressWarnings("unused")
277 public boolean isHasDelTarget() {
281 * @param hasDelTarget the hasDelTarget to set
283 @SuppressWarnings("unused")
284 public void setHasDelTarget(boolean hasDelTarget) {
285 this.hasDelTarget = hasDelTarget;
290 @SuppressWarnings("unused")
291 public LineageType getType() {
297 public String getLabel() {
300 public void setLabel(String string) {
305 private static class PutRelationPathSet {
308 ArrayList<String> relations = new ArrayList<String>();
309 String objectName = "";
310 String currentAPIVersion = "";
311 public PutRelationPathSet(String opId, String path) {
313 this.apiPath = path.replace("/relationship-list/relationship", "");
315 objectName = GenerateXsd.deletePaths.get(apiPath);
316 currentAPIVersion = GenerateXsd.apiVersion;
318 public void process() {
320 this.fromRelations();
321 this.writeRelationsFile();
324 public void toRelations() {
325 logger.debug("{“comment”: “Valid TO Relations that can be added”},");
326 logger.debug("apiPath: "+apiPath+"\nopId="+opId+"\nobjectName="+objectName);
327 Collection<EdgeDescription> toEdges = GenerateXsd.getEdgeRulesTO(objectName);
329 if(toEdges.size() > 0) {
330 relations.add("{\"comment\": \"Valid TO Relations that can be added\"}\n");
332 for (EdgeDescription ed : toEdges) {
333 logger.debug(ed.getRuleKey()+"Type="+ed.type);
334 String obj = ed.getRuleKey().replace(objectName,"").replace("|","");
335 String selectedRelation = "";
336 if(ed.type == LineageType.UNRELATED) {
337 String selectObj = getUnrelatedObjectPaths(obj, apiPath);
338 logger.debug("SelectedObj:"+selectObj);
339 selectedRelation = formatObjectRelationSet(obj,selectObj);
340 logger.trace("ObjectRelationSet"+selectedRelation);
342 String selectObj = getKinObjectPath(obj, apiPath);
343 logger.debug("SelectedObj:"+selectObj);
344 selectedRelation = formatObjectRelation(obj,selectObj);
345 logger.trace("ObjectRelationSet"+selectedRelation);
347 relations.add(selectedRelation);
348 logger.trace(selectedRelation);
352 public void fromRelations() {
353 logger.debug("“comment”: “Valid FROM Relations that can be added”");
354 Collection<EdgeDescription> fromEdges = getEdgeRulesFROM(objectName);
355 if(fromEdges.size() > 0) {
356 relations.add("{\"comment\": \"Valid FROM Relations that can be added\"}\n");
358 for (EdgeDescription ed : fromEdges) {
359 logger.debug(ed.getRuleKey()+"Type="+ed.type);
360 String obj = ed.getRuleKey().replace(objectName,"").replace("|","");
361 String selectedRelation = "";
362 if(ed.type == LineageType.UNRELATED) {
363 String selectObj = getUnrelatedObjectPaths(obj, apiPath);
364 logger.debug("SelectedObj"+selectObj);
365 selectedRelation = formatObjectRelationSet(obj,selectObj);
366 logger.trace("ObjectRelationSet"+selectedRelation);
368 String selectObj = getKinObjectPath(obj, apiPath);
369 logger.debug("SelectedObj"+selectObj);
370 selectedRelation = formatObjectRelation(obj,selectObj);
371 logger.trace("ObjectRelationSet"+selectedRelation);
373 relations.add(selectedRelation);
374 logger.trace(selectedRelation);
377 public void writeRelationsFile() {
378 File examplefilePath = new File(yaml_dir + "/relations/" + currentAPIVersion+"/"+opId.replace("RelationshipListRelationship", "") + ".json");
380 logger.debug(String.join("exampleFilePath: ", examplefilePath.toString()));
381 FileOutputStream fop = null;
383 if (!examplefilePath.exists()) {
384 examplefilePath.getParentFile().mkdirs();
385 examplefilePath.createNewFile();
387 fop = new FileOutputStream(examplefilePath);
388 } catch(Exception e) {
393 if(relations.size() > 0) {fop.write("[\n".getBytes());}
394 fop.write(String.join(",\n", relations).getBytes());
395 if(relations.size() > 0) {fop.write("\n]\n".getBytes());}
398 } catch (Exception e) {
402 logger.debug(String.join(",\n", relations));
406 private static String formatObjectRelationSet(String obj, String selectObj) {
407 StringBuffer pathSb = new StringBuffer();
408 String[] paths = selectObj.split("[|]");
409 for (String s: paths) {
410 logger.trace("SelectOBJ"+s);
411 pathSb.append(formatObjectRelation(obj, s)+",\n");
413 pathSb.deleteCharAt(pathSb.length()-2);
414 return pathSb.toString();
417 private static String formatObjectRelation(String obj, String selectObj) {
418 StringBuffer pathSb = new StringBuffer();
419 pathSb.append("{\n");
420 pathSb.append("\"related-to\" : \""+obj+"\",\n");
421 pathSb.append("\"related-link\" : \""+selectObj+"\"\n");
423 return pathSb.toString();
426 private static String getKinObjectPath(String obj, String apiPath) {
427 LevenshteinDistance proximity = new LevenshteinDistance();
428 String targetPath = "";
429 int targetScore = Integer.MAX_VALUE;
430 int targetMaxScore = 0;
431 for (Map.Entry<String, String> p : deletePaths.entrySet()) {
432 if(p.getValue().equals(obj)) {
433 targetScore = (targetScore >= proximity.apply(apiPath, p.getKey())) ? proximity.apply(apiPath, p.getKey()) : targetScore;
434 targetPath = (targetScore >= proximity.apply(apiPath, p.getKey())) ? p.getKey() : targetPath;
435 targetMaxScore = (targetMaxScore <= proximity.apply(apiPath, p.getKey())) ? proximity.apply(apiPath, p.getKey()) : targetScore;
436 logger.trace(proximity.apply(apiPath, p.getKey())+":"+p.getKey());
437 logger.trace(proximity.apply(apiPath, p.getKey())+":"+apiPath);
443 private static String getUnrelatedObjectPaths(String obj, String apiPath) {
444 String targetPath = "";
445 logger.trace("Obj:"+obj +"\n" + apiPath);
446 for (Map.Entry<String, String> p : deletePaths.entrySet()) {
447 if(p.getValue().equals(obj)) {
448 logger.trace("p.getvalue:"+p.getValue()+"p.getkey:"+p.getKey());
449 targetPath += ((targetPath.length() == 0 ? "" : "|") + p.getKey());
450 logger.trace("Match:"+apiPath +"\n" + targetPath);
457 private static class PatchOperation {
459 String xmlRootElementName;
464 public PatchOperation(String useOpId, String xmlRootElementName, String tag, String path, String pathParams) {
466 this.useOpId = useOpId;
467 this.xmlRootElementName = xmlRootElementName;
470 this.pathParams = pathParams;
474 public String toString() {
475 StringBuffer pathSb = new StringBuffer();
476 pathSb.append(" patch:\n");
477 pathSb.append(" tags:\n");
478 pathSb.append(" - " + tag + "\n");
480 pathSb.append(" summary: update an existing " + xmlRootElementName + "\n");
481 pathSb.append(" description: update an existing " + xmlRootElementName + "\n");
482 pathSb.append(" operationId: Update" + useOpId + "\n");
483 pathSb.append(" consumes:\n");
484 pathSb.append(" - application/json\n");
485 pathSb.append(" - application/xml\n");
486 pathSb.append(" produces:\n");
487 pathSb.append(" - application/json\n");
488 pathSb.append(" - application/xml\n");
489 pathSb.append(" responses:\n");
490 pathSb.append(" \"default\":\n");
491 pathSb.append(" " + responsesUrl);
493 pathSb.append(" parameters:\n");
494 pathSb.append(pathParams); // for nesting
495 pathSb.append(" - name: body\n");
496 pathSb.append(" in: body\n");
497 pathSb.append(" description: " + xmlRootElementName + " object that needs to be created or updated\n");
498 pathSb.append(" required: true\n");
499 pathSb.append(" schema:\n");
500 pathSb.append(" $ref: \"patchSchema.yaml#/definitions/" + xmlRootElementName + "\"\n");
502 return pathSb.toString();
504 public String toString1() {
505 StringBuffer pathSb = new StringBuffer();
506 StringBuffer relationshipExamplesSb = new StringBuffer();
507 if ( path.endsWith("/relationship") ) {
508 pathSb.append(" " + path + ":\n" );
510 pathSb.append(" patch:\n");
511 pathSb.append(" tags:\n");
512 pathSb.append(" - " + tag + "\n");
514 if ( path.endsWith("/relationship") ) {
515 pathSb.append(" summary: see node definition for valid relationships\n");
516 relationshipExamplesSb.append("[See Examples](apidocs/relations/"+GenerateXsd.apiVersion+"/"+useOpId+".json)");
518 pathSb.append(" summary: update an existing " + xmlRootElementName + "\n");
519 pathSb.append(" description: |\n");
520 pathSb.append(" Update an existing " + xmlRootElementName + "\n");
521 pathSb.append(" #\n");
522 pathSb.append(" Note: Endpoints that are not devoted to object relationships support both PUT and PATCH operations.\n");
523 pathSb.append(" The PUT operation will entirely replace an existing object.\n");
524 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");
525 pathSb.append(" #\n");
526 pathSb.append(" Other differences between PUT and PATCH are:\n");
527 pathSb.append(" #\n");
528 pathSb.append(" - For PATCH, you can send any of the values shown in sample REQUEST body. There are no required values.\n");
529 pathSb.append(" - For PATCH, resource-id which is a required REQUEST body element for PUT, must not be sent.\n");
530 pathSb.append(" - PATCH cannot be used to update relationship elements; there are dedicated PUT operations for this.\n");
532 pathSb.append(" operationId: Update" + useOpId + "\n");
533 pathSb.append(" consumes:\n");
534 pathSb.append(" - application/json\n");
535 pathSb.append(" - application/xml\n");
536 pathSb.append(" produces:\n");
537 pathSb.append(" - application/json\n");
538 pathSb.append(" - application/xml\n");
539 pathSb.append(" responses:\n");
540 pathSb.append(" \"default\":\n");
541 pathSb.append(" " + responsesUrl);
542 pathSb.append(" parameters:\n");
543 pathSb.append(pathParams); // for nesting
544 pathSb.append(" - name: body\n");
545 pathSb.append(" in: body\n");
546 pathSb.append(" description: " + xmlRootElementName + " object that needs to be created or updated. "+relationshipExamplesSb.toString()+"\n");
547 pathSb.append(" required: true\n");
548 pathSb.append(" schema:\n");
549 pathSb.append(" $ref: \"#/patchDefinitions/" + xmlRootElementName + "\"\n");
550 return pathSb.toString();
553 private static class PutOperation {
555 String xmlRootElementName;
560 public PutOperation(String useOpId, String xmlRootElementName, String tag, String path, String pathParams) {
562 this.useOpId = useOpId;
563 this.xmlRootElementName = xmlRootElementName;
566 this.pathParams = pathParams;
570 public String toString() {
571 StringBuffer pathSb = new StringBuffer();
572 StringBuffer relationshipExamplesSb = new StringBuffer();
573 if ( path.endsWith("/relationship") ) {
574 pathSb.append(" " + path + ":\n" );
576 pathSb.append(" put:\n");
577 pathSb.append(" tags:\n");
578 pathSb.append(" - " + tag + "\n");
580 if ( path.endsWith("/relationship") ) {
581 pathSb.append(" summary: see node definition for valid relationships\n");
583 pathSb.append(" summary: create or update an existing " + xmlRootElementName + "\n");
584 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");
586 relationshipExamplesSb.append("[Valid relationship examples shown here](apidocs/relations/"+GenerateXsd.apiVersion+"/"+useOpId.replace("RelationshipListRelationship", "")+".json)");
587 pathSb.append(" operationId: createOrUpdate" + useOpId + "\n");
588 pathSb.append(" consumes:\n");
589 pathSb.append(" - application/json\n");
590 pathSb.append(" - application/xml\n");
591 pathSb.append(" produces:\n");
592 pathSb.append(" - application/json\n");
593 pathSb.append(" - application/xml\n");
594 pathSb.append(" responses:\n");
595 pathSb.append(" \"default\":\n");
596 pathSb.append(" " + responsesUrl);
598 pathSb.append(" parameters:\n");
599 pathSb.append(pathParams); // for nesting
600 pathSb.append(" - name: body\n");
601 pathSb.append(" in: body\n");
602 pathSb.append(" description: " + xmlRootElementName + " object that needs to be created or updated. "+relationshipExamplesSb.toString()+"\n");
603 pathSb.append(" required: true\n");
604 pathSb.append(" schema:\n");
605 pathSb.append(" $ref: \"#/definitions/" + xmlRootElementName + "\"\n");
606 return pathSb.toString();
608 public String tagRelationshipPathMapEntry() {
609 if ( path.endsWith("/relationship") ) {
610 putRelationPaths.put(useOpId, path);
617 private static class GetOperation {
619 String xmlRootElementName;
622 @SuppressWarnings("unused")
624 public GetOperation(String useOpId, String xmlRootElementName, String tag, String path, String pathParams) {
626 this.useOpId = useOpId;
627 this.xmlRootElementName = xmlRootElementName;
630 this.pathParams = pathParams;
633 public String toString() {
634 StringBuffer pathSb = new StringBuffer();
635 pathSb.append(" " + path + ":\n" );
636 pathSb.append(" get:\n");
637 pathSb.append(" tags:\n");
638 pathSb.append(" - " + tag + "\n");
639 pathSb.append(" summary: returns " + xmlRootElementName + "\n");
641 pathSb.append(" description: returns " + xmlRootElementName + "\n");
642 pathSb.append(" operationId: get" + useOpId + "\n");
643 pathSb.append(" produces:\n");
644 pathSb.append(" - application/json\n");
645 pathSb.append(" - application/xml\n");
647 pathSb.append(" responses:\n");
648 pathSb.append(" \"200\":\n");
649 pathSb.append(" description: successful operation\n");
650 pathSb.append(" schema:\n");
651 pathSb.append(" $ref: \"#/getDefinitions/" + xmlRootElementName + "\"\n");
652 pathSb.append(" \"default\":\n");
653 pathSb.append(" " + responsesUrl);
655 return pathSb.toString();
659 private static class DeleteOperation {
661 String xmlRootElementName;
665 public DeleteOperation(String useOpId, String xmlRootElementName, String tag, String path, String pathParams) {
667 this.useOpId = useOpId;
668 this.xmlRootElementName = xmlRootElementName;
671 this.pathParams = pathParams;
674 public String toString() {
675 StringBuffer pathSb = new StringBuffer();
676 pathSb.append(" delete:\n");
677 pathSb.append(" tags:\n");
678 pathSb.append(" - " + tag + "\n");
679 pathSb.append(" summary: delete an existing " + xmlRootElementName + "\n");
681 pathSb.append(" description: delete an existing " + xmlRootElementName + "\n");
683 pathSb.append(" operationId: delete" + useOpId + "\n");
684 pathSb.append(" consumes:\n");
685 pathSb.append(" - application/json\n");
686 pathSb.append(" - application/xml\n");
687 pathSb.append(" produces:\n");
688 pathSb.append(" - application/json\n");
689 pathSb.append(" - application/xml\n");
690 pathSb.append(" responses:\n");
691 pathSb.append(" \"default\":\n");
692 pathSb.append(" " + responsesUrl);
693 pathSb.append(" parameters:\n");
695 pathSb.append(pathParams); // for nesting
696 if ( !path.endsWith("/relationship") ) {
697 pathSb.append(" - name: resource-version\n");
699 pathSb.append(" in: query\n");
700 pathSb.append(" description: resource-version for concurrency\n");
701 pathSb.append(" required: true\n");
702 pathSb.append(" type: string\n");
704 return pathSb.toString();
706 public String objectPathMapEntry() {
707 if (! path.endsWith("/relationship") ) {
708 deletePaths.put(path, xmlRootElementName);
710 return (xmlRootElementName+":"+path);
715 private static boolean validVersion(String versionToGen) {
717 if ("ALL".equalsIgnoreCase(versionToGen)) {
721 for (Version v : Version.values()) {
722 if (v.name().equals(versionToGen)) {
730 private static boolean versionUsesAnnotations( String version) {
731 if (new Integer(version.substring(1)).intValue() >= annotationsStartVersion ) {
737 private static boolean versionSupportsSwagger( String version) {
738 if (new Integer(version.substring(1)).intValue() >= swaggerSupportStartsVersion ) {
744 public static void main(String[] args) throws IOException {
745 String versionToGen = System.getProperty("gen_version").toLowerCase();
746 String fileTypeToGen = System.getProperty("gen_type").toLowerCase();
747 if ( fileTypeToGen == null ) {
748 fileTypeToGen = generateTypeXSD;
751 if ( !fileTypeToGen.equals( generateTypeXSD ) && !fileTypeToGen.equals( generateTypeYAML )) {
752 System.err.println("Invalid gen_type passed. " + fileTypeToGen);
757 String responsesLabel = System.getProperty("yamlresponses_url");
758 responsesUrl = responsesLabel;
760 List<Version> versionsToGen = new ArrayList<>();
761 if ( versionToGen == null ) {
762 System.err.println("Version is required, ie v<n> or ALL.");
765 else if (!"ALL".equalsIgnoreCase(versionToGen) && !versionToGen.matches("v\\d+") && !validVersion(versionToGen)) {
766 System.err.println("Invalid version passed. " + versionToGen);
769 else if ("ALL".equalsIgnoreCase(versionToGen)) {
770 versionsToGen = Arrays.asList(Version.values());
771 Collections.sort(versionsToGen);
772 Collections.reverse(versionsToGen);
774 versionsToGen.add(Version.valueOf(versionToGen));
777 //process file type System property
778 fileTypeToGen = (fileTypeToGen == null ? generateTypeXSD : fileTypeToGen.toLowerCase());
779 if ( !fileTypeToGen.equals( generateTypeXSD ) && !fileTypeToGen.equals( generateTypeYAML )) {
780 System.err.println("Invalid gen_type passed. " + fileTypeToGen);
782 } else if ( fileTypeToGen.equals(generateTypeYAML) ) {
783 if ( responsesUrl == null || responsesUrl.length() < 1
784 || responsesLabel == null || responsesLabel.length() < 1 ) {
785 System.err.println("generating swagger yaml file requires yamlresponses_url and yamlresponses_label properties" );
788 responsesUrl = "description: "+ "Response codes found in [response codes]("+responsesLabel+ ").\n";
792 if(System.getProperty("user.dir") != null && !System.getProperty("user.dir").contains(normalStartDir)) {
793 oxmPath = autoGenRoot + "/oxm/";
796 oxmPath = root + "/oxm/";
803 for (Version v : versionsToGen) {
804 apiVersion = v.toString();
805 logger.info("Generating " + apiVersion + " " + fileTypeToGen);
806 File oxm_file = new File(oxmPath + "aai_oxm_" + apiVersion + ".xml");
807 apiVersionFmt = "." + apiVersion + ".";
808 generatedJavaType = new HashMap<String, String>();
809 appliedPaths = new HashMap<String, String>();
810 putRelationPaths = new HashMap<String, String>();
811 deletePaths = new HashMap<String, String>();
813 if ( fileTypeToGen.equals(generateTypeXSD) ) {
814 useAnnotationsInXsd = versionUsesAnnotations(apiVersion);
815 outfileName = xsd_dir + "/aai_schema_" + apiVersion + "." + generateTypeXSD;
816 fileContent = processOxmFile(oxm_file, v, null);
817 } else if ( versionSupportsSwagger(apiVersion )) {
818 if(System.getProperty("user.dir") != null && !System.getProperty("user.dir").contains(normalStartDir)) {
819 outfileName = alt_yaml_dir;
822 outfileName = yaml_dir;
824 outfileName = outfileName + "/aai_swagger_" + apiVersion + "." + generateTypeYAML;
825 fileContent = generateSwaggerFromOxmFile( oxm_file, null);
829 outfile = new File(outfileName);
830 File parentDir = outfile.getParentFile();
831 if(! parentDir.exists())
835 outfile.createNewFile();
836 } catch (IOException e) {
837 logger.error( "Exception creating output file " + outfileName);
840 BufferedWriter bw = null;
842 Charset charset = Charset.forName("UTF-8");
843 Path path = Paths.get(outfileName);
844 bw = Files.newBufferedWriter(path, charset);
845 bw.write(fileContent);
846 } catch ( IOException e) {
847 logger.error( "Exception writing output file " + outfileName);
854 logger.info( "GeneratedXSD successful, saved in " + outfileName);
860 public static String processJavaTypeElement( String javaTypeName, Element javaTypeElement) {
862 String xmlRootElementName = null;
864 NodeList parentNodes = javaTypeElement.getElementsByTagName("java-attributes");
865 StringBuffer sb = new StringBuffer();
866 if ( parentNodes.getLength() == 0 ) {
867 logger.trace( "no java-attributes for java-type " + javaTypeName);
872 NamedNodeMap attributes;
874 NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
875 Element valElement = (Element) valNodes.item(0);
876 attributes = valElement.getAttributes();
877 for ( int i = 0; i < attributes.getLength(); ++i ) {
878 Attr attr = (Attr) attributes.item(i);
879 String attrName = attr.getNodeName();
881 String attrValue = attr.getNodeValue();
882 logger.trace("Found xml-root-element attribute: " + attrName + " with value: " + attrValue);
883 if ( attrName.equals("name"))
884 xmlRootElementName = attrValue;
887 Element parentElement = (Element)parentNodes.item(0);
888 NodeList xmlElementNodes = parentElement.getElementsByTagName("xml-element");
890 Element childElement;
891 String xmlElementWrapper;
893 Element xmlElementElement;
895 String elementName, elementType, elementIsKey, elementIsRequired, elementContainerType;
896 StringBuffer sb1 = new StringBuffer();
897 if ( xmlElementNodes.getLength() > 0 ) {
898 sb1.append(" <xs:element name=\"" + xmlRootElementName + "\">\n");
899 sb1.append(" <xs:complexType>\n");
900 NodeList properties = GenerateXsd.locateXmlProperties(javaTypeElement);
901 if (properties != null && useAnnotationsInXsd) {
902 logger.trace("properties found for: " + xmlRootElementName);
903 sb1.append(" <xs:annotation>\r\n");
904 insertAnnotation(properties, false, "class", sb1, " ");
906 sb1.append(" </xs:annotation>\r\n");
908 logger.trace("no properties found for: " + xmlRootElementName);
910 sb1.append(" <xs:sequence>\n");
911 for ( int i = 0; i < xmlElementNodes.getLength(); ++i ) {
913 xmlElementElement = (Element)xmlElementNodes.item(i);
914 childNodes = xmlElementElement.getElementsByTagName("xml-element-wrapper");
916 xmlElementWrapper = null;
917 if ( childNodes.getLength() > 0 ) {
918 childElement = (Element)childNodes.item(0);
920 attributes = childElement.getAttributes();
921 for ( int k = 0; k < attributes.getLength(); ++k ) {
922 Attr attr = (Attr) attributes.item(k);
923 String attrName = attr.getNodeName();
924 String attrValue = attr.getNodeValue();
925 if ( attrName.equals("name")) {
926 xmlElementWrapper = attrValue;
927 logger.trace("found xml-element-wrapper " + xmlElementWrapper);
932 attributes = xmlElementElement.getAttributes();
936 elementName = elementType = elementIsKey = elementIsRequired = elementContainerType = null;
937 for ( int j = 0; j < attributes.getLength(); ++j ) {
938 Attr attr = (Attr) attributes.item(j);
939 String attrName = attr.getNodeName();
941 String attrValue = attr.getNodeValue();
942 logger.trace("For " + xmlRootElementName + " Found xml-element attribute: " + attrName + " with value: " + attrValue);
943 if ( attrName.equals("name")) {
944 elementName = attrValue;
946 if ( attrName.equals("type")) {
947 elementType = attrValue;
948 if ( attrValue.contains(apiVersionFmt) ) {
949 addType = attrValue.substring(attrValue.lastIndexOf('.')+1);
950 if ( !generatedJavaType.containsKey(addType) ) {
951 generatedJavaType.put(addType, attrValue);
952 sb.append(processJavaTypeElement( addType, getJavaTypeElement(addType) ));
958 if ( attrName.equals("xml-key")) {
959 elementIsKey = attrValue;
961 if ( attrName.equals("required")) {
962 elementIsRequired = attrValue;
964 if ( attrName.equals("container-type")) {
965 elementContainerType = attrValue;
969 if ( xmlElementWrapper != null ) {
970 sb1.append(" <xs:element name=\"" + xmlElementWrapper +"\"");
971 if ( elementIsRequired == null || !elementIsRequired.equals("true")||addType != null) {
972 sb1.append(" minOccurs=\"0\"");
975 sb1.append(" <xs:complexType>\n");
976 properties = GenerateXsd.locateXmlProperties(javaTypeElement);
977 if (properties != null && useAnnotationsInXsd) {
978 sb1.append(" <xs:annotation>\r\n");
979 insertAnnotation(properties, false, "class", sb1, " ");
980 sb1.append(" </xs:annotation>\r\n");
982 logger.trace("no properties found for: " + xmlElementWrapper);
984 sb1.append(" <xs:sequence>\n");
987 if ("Nodes".equals(addType)) {
988 logger.trace("Skipping nodes, temporary testing");
991 if ( addType != null ) {
992 sb1.append(" <xs:element ref=\"tns:" + getXmlRootElementName(addType) +"\"");
994 sb1.append(" <xs:element name=\"" + elementName +"\"");
996 if ( elementType.equals("java.lang.String"))
997 sb1.append(" type=\"xs:string\"");
998 if ( elementType.equals("java.lang.Long"))
999 sb1.append(" type=\"xs:unsignedInt\"");
1000 if ( elementType.equals("java.lang.Integer"))
1001 sb1.append(" type=\"xs:int\"");
1002 if ( elementType.equals("java.lang.Boolean"))
1003 sb1.append(" type=\"xs:boolean\"");
1004 if ( elementIsRequired == null || !elementIsRequired.equals("true")||addType != null) {
1005 sb1.append(" minOccurs=\"0\"");
1007 if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) {
1008 sb1.append(" maxOccurs=\"unbounded\"");
1010 properties = GenerateXsd.locateXmlProperties(xmlElementElement);
1011 if (properties != null || elementIsKey != null) {
1013 if ( useAnnotationsInXsd ) {
1014 sb1.append(" <xs:annotation>\r\n");
1015 insertAnnotation(properties, elementIsKey != null, "field", sb1, " ");
1016 sb1.append(" </xs:annotation>\r\n");
1018 if (xmlElementWrapper== null) {
1019 sb1.append(" </xs:element>\n");
1024 if ( xmlElementWrapper != null ) {
1025 sb1.append(" </xs:sequence>\n");
1026 sb1.append(" </xs:complexType>\n");
1027 sb1.append(" </xs:element>\n");
1030 sb1.append(" </xs:sequence>\n");
1031 sb1.append(" </xs:complexType>\n");
1032 sb1.append(" </xs:element>\n");
1035 if ( xmlElementNodes.getLength() < 1 ) {
1036 sb.append(" <xs:element name=\"" + xmlRootElementName + "\">\n");
1037 sb.append(" <xs:complexType>\n");
1038 sb.append(" <xs:sequence/>\n");
1039 sb.append(" </xs:complexType>\n");
1040 sb.append(" </xs:element>\n");
1041 generatedJavaType.put(javaTypeName, null);
1042 return sb.toString();
1045 return sb.toString();
1048 private static void insertAnnotation(NodeList items, boolean isKey, String target, StringBuffer sb1, String indentation) {
1049 if (items != null || isKey) {
1050 List<String> metadata = new ArrayList<>();
1054 Element item = null;
1056 metadata.add("isKey=true");
1058 if (items != null) {
1059 for (int i = 0; i < items.getLength(); i++) {
1060 item = (Element)items.item(i);
1061 name = item.getAttribute("name");
1062 value = item.getAttribute("value");
1063 if (name.equals("abstract")) {
1064 name = "isAbstract";
1065 } else if (name.equals("extends")) {
1066 name = "extendsFrom";
1068 metadata.add(name + "=\"" + value.replaceAll("&", "&") + "\"");
1072 indentation + " <xs:appinfo>\r\n" +
1073 indentation + " <annox:annotate target=\""+target+"\">@org.onap.aai.annotations.Metadata(" + Joiner.on(",").join(metadata) + ")</annox:annotate>\r\n" +
1074 indentation + " </xs:appinfo>\r\n");
1079 private static Element getJavaTypeElement( String javaTypeName )
1082 String attrName, attrValue;
1084 Element javaTypeElement;
1085 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
1086 javaTypeElement = (Element) javaTypeNodes.item(i);
1087 NamedNodeMap attributes = javaTypeElement.getAttributes();
1088 for ( int j = 0; j < attributes.getLength(); ++j ) {
1089 attr = (Attr) attributes.item(j);
1090 attrName = attr.getNodeName();
1091 attrValue = attr.getNodeValue();
1092 if ( attrName.equals("name") && attrValue.equals(javaTypeName))
1093 return javaTypeElement;
1096 logger.error( "oxm file format error, missing java-type " + javaTypeName);
1097 return (Element) null;
1100 private static Element getJavaTypeElementSwagger( String javaTypeName )
1103 String attrName, attrValue;
1105 Element javaTypeElement;
1106 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
1107 javaTypeElement = (Element) javaTypeNodes.item(i);
1108 NamedNodeMap attributes = javaTypeElement.getAttributes();
1109 for ( int j = 0; j < attributes.getLength(); ++j ) {
1110 attr = (Attr) attributes.item(j);
1111 attrName = attr.getNodeName();
1112 attrValue = attr.getNodeValue();
1113 if ( attrName.equals("name") && attrValue.equals(javaTypeName))
1114 return javaTypeElement;
1117 logger.error( "oxm file format error, missing java-type " + javaTypeName);
1118 return (Element) null;
1120 private static String getXmlRootElementName( String javaTypeName )
1123 String attrName, attrValue;
1125 Element javaTypeElement;
1126 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
1127 javaTypeElement = (Element) javaTypeNodes.item(i);
1128 NamedNodeMap attributes = javaTypeElement.getAttributes();
1129 for ( int j = 0; j < attributes.getLength(); ++j ) {
1130 attr = (Attr) attributes.item(j);
1131 attrName = attr.getNodeName();
1132 attrValue = attr.getNodeValue();
1133 if ( attrName.equals("name") && attrValue.equals(javaTypeName)) {
1134 NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
1135 Element valElement = (Element) valNodes.item(0);
1136 attributes = valElement.getAttributes();
1137 for ( int k = 0; k < attributes.getLength(); ++k ) {
1138 attr = (Attr) attributes.item(k);
1139 attrName = attr.getNodeName();
1141 attrValue = attr.getNodeValue();
1142 if ( attrName.equals("name"))
1148 logger.error( "oxm file format error, missing java-type " + javaTypeName);
1153 public static String processOxmFile( File oxmFile, Version v, String xml )
1156 apiVersion = v.toString();
1157 useAnnotationsInXsd = true;
1158 apiVersionFmt = "." + apiVersion + ".";
1159 generatedJavaType = new HashMap<>();
1160 appliedPaths = new HashMap<>();
1162 StringBuilder sb = new StringBuilder();
1163 logger.trace("processing starts");
1164 sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");
1165 String namespace = "org.onap";
1166 if (v.compareTo(Version.v11) < 0 || v.compareTo(Version.v12) < 0) {
1167 namespace = "org.openecomp";
1169 if ( useAnnotationsInXsd ) {
1170 sb.append("<xs:schema elementFormDefault=\"qualified\" version=\"1.0\" targetNamespace=\"http://" + namespace + ".aai.inventory/"
1171 + apiVersion + "\" xmlns:tns=\"http://" + namespace + ".aai.inventory/" + apiVersion + "\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
1173 + "xmlns:jaxb=\"http://java.sun.com/xml/ns/jaxb\"\r\n" +
1174 " jaxb:version=\"2.1\" \r\n" +
1175 " xmlns:annox=\"http://annox.dev.java.net\" \r\n" +
1176 " jaxb:extensionBindingPrefixes=\"annox\">\n\n");
1179 sb.append("<xs:schema elementFormDefault=\"qualified\" version=\"1.0\" targetNamespace=\"http://" + namespace + ".aai.inventory/"
1180 + apiVersion + "\" xmlns:tns=\"http://" + namespace + ".aai.inventory/" + apiVersion + "\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n\n");
1185 DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
1186 dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
1187 DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
1191 doc = dBuilder.parse(oxmFile);
1193 InputSource is = new InputSource(new StringReader(xml));
1194 doc = dBuilder.parse(is);
1196 NodeList bindingsNodes = doc.getElementsByTagName("xml-bindings");
1197 Element bindingElement;
1198 NodeList javaTypesNodes;
1199 Element javaTypesElement;
1201 Element javaTypeElement;
1204 if ( bindingsNodes == null || bindingsNodes.getLength() == 0 ) {
1205 logger.error( "missing <binding-nodes> in " + oxmFile );
1209 bindingElement = (Element) bindingsNodes.item(0);
1210 javaTypesNodes = bindingElement.getElementsByTagName("java-types");
1211 if ( javaTypesNodes.getLength() < 1 ) {
1212 logger.error( "missing <binding-nodes><java-types> in " + oxmFile );
1215 javaTypesElement = (Element) javaTypesNodes.item(0);
1216 javaTypeNodes = javaTypesElement.getElementsByTagName("java-type");
1217 if ( javaTypeNodes.getLength() < 1 ) {
1218 logger.error( "missing <binding-nodes><java-types><java-type> in " + oxmFile );
1222 String javaTypeName;
1223 String attrName, attrValue;
1225 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
1226 javaTypeElement = (Element) javaTypeNodes.item(i);
1227 NamedNodeMap attributes = javaTypeElement.getAttributes();
1228 javaTypeName = null;
1229 for ( int j = 0; j < attributes.getLength(); ++j ) {
1230 attr = (Attr) attributes.item(j);
1231 attrName = attr.getNodeName();
1232 attrValue = attr.getNodeValue();
1233 if ( attrName.equals("name"))
1234 javaTypeName = attrValue;
1236 if ( javaTypeName == null ) {
1237 logger.error( "<java-type> has no name attribute in " + oxmFile );
1240 if ("Nodes".equals(javaTypeName)) {
1241 logger.debug("skipping Nodes entry (temporary feature)");
1244 if ( !generatedJavaType.containsKey(javaTypeName) ) {
1245 generatedJavaType.put(javaTypeName, null);
1246 sb.append(processJavaTypeElement( javaTypeName, javaTypeElement ));
1250 } catch (Exception e) {
1251 e.printStackTrace();
1254 sb.append("</xs:schema>\n");
1255 return sb.toString();
1258 public static String toDeleteRules(String objectName) {
1259 Collection<EdgeDescription> toEdges = GenerateXsd.getEdgeRulesTO(objectName);
1260 logger.debug("TO Edges count: "+toEdges.size()+" Object: "+objectName);
1261 String prevent=null;
1263 LinkedHashSet<String> preventDelete = new LinkedHashSet<String>();
1264 LinkedHashSet<String> alsoDelete = new LinkedHashSet<String>();
1265 for (EdgeDescription ed : toEdges) {
1266 logger.debug("{“comment”: From = "+ed.getFrom()+" To: "+ed.getTo()+" Object: "+objectName);
1267 logger.debug("{“comment”: Direction = "+ed.getDirection()+" PreventDelete: "+ed.getPreventDelete()+" DeleteOtherV: "+ed.getDeleteOtherV()+" Object: "+objectName);
1268 if(ed.getPreventDelete().equals("IN") && ed.getTo().equals(objectName)) {
1269 preventDelete.add(ed.getFrom().toUpperCase());
1271 if(ed.getDeleteOtherV().equals("IN") && ed.getTo().equals(objectName) ) {
1272 alsoDelete.add(ed.getFrom().toUpperCase());
1275 if(preventDelete.size() > 0) {
1276 prevent = " - "+objectName.toUpperCase()+" cannot be deleted if linked to "+String.join(",",preventDelete);
1277 logger.info(prevent);
1279 if(alsoDelete.size() > 0) {
1280 also = " - "+objectName.toUpperCase()+" is DELETED when these are DELETED "+String.join(",",alsoDelete);
1281 // This commented out line is better (gets who deletes what correct) but still not accurate.
1282 //also = " - Deletion of an instance of "+objectName.toUpperCase()+" causes instances of these directly related types to be DELETED ["+String.join(",",alsoDelete)+"]";
1285 return String.join((prevent == null || also == null) ? "" : "\n", prevent == null ? "" : prevent, also == null ? "" : also)+((prevent == null && also == null) ? "" : "\n");
1288 public static String fromDeleteRules(String objectName) {
1289 Collection<EdgeDescription> fromEdges = GenerateXsd.getEdgeRulesFROM(objectName);
1290 LinkedHashSet<String> preventDelete = new LinkedHashSet <String>();
1291 LinkedHashSet<String> alsoDelete = new LinkedHashSet <String>();
1292 String prevent=null;
1294 for (EdgeDescription ed : fromEdges) {
1295 logger.debug("{“comment”: From = "+ed.getFrom()+" To: "+ed.getTo()+" Object: "+objectName);
1296 logger.debug("{“comment”: Direction = "+ed.getDirection()+" PreventDelete: "+ed.getPreventDelete()+" DeleteOtherV: "+ed.getDeleteOtherV()+" Object: "+objectName);
1297 if(ed.getPreventDelete().equals("OUT") && ed.getFrom().equals(objectName)) {
1298 preventDelete.add(ed.getTo().toUpperCase());
1300 if(ed.getDeleteOtherV().equals("OUT") && ed.getFrom().equals(objectName) ) {
1301 alsoDelete.add(ed.getTo().toUpperCase());
1304 if(preventDelete.size() > 0) {
1305 prevent = " - "+objectName.toUpperCase()+" cannot be deleted if linked to "+String.join(",",preventDelete);
1306 logger.info(prevent);
1308 if(alsoDelete.size() > 0) {
1309 also = " - "+objectName.toUpperCase()+" deletion means associated objects of these types are also DELETED:"+String.join(",",alsoDelete);
1310 // This commented out line is better (gets who deletes what correct) but still not accurate.
1311 //also = " - Deletion of an instance of "+objectName.toUpperCase()+" causes instances of these directly related types to be DELETED ["+String.join(",",alsoDelete)+"]";
1314 return String.join((prevent == null || also == null) ? "" : "\n", prevent == null ? "" : prevent, also == null ? "" : also)+((prevent == null && also == null) ? "" : "\n");
1318 private static boolean isStandardType( String elementType )
1320 switch ( elementType ) {
1321 case "java.lang.String":
1322 case "java.lang.Long":
1323 case "java.lang.Integer":
1324 case"java.lang.Boolean":
1330 private static Vector<String> getIndexedProps( String attrValue )
1332 if ( attrValue == null )
1334 StringTokenizer st = new StringTokenizer( attrValue, ",");
1335 if ( st.countTokens() == 0 )
1337 Vector<String> result = new Vector<String>();
1338 while ( st.hasMoreTokens()) {
1339 result.add(st.nextToken());
1345 * Guaranteed to at least return non null but empty collection of edge descriptions
1346 * @param nodeName name of the vertex whose edge relationships to return
1347 * @return collection of node neighbors based on DbEdgeRules
1349 private static Collection<EdgeDescription> getEdgeRulesFromJson( String path, boolean skipMatch )
1352 ArrayList<EdgeDescription> result = new ArrayList<>();
1353 Iterator<Map<String, Object>> edgeRulesIterator;
1356 GenerateXsd x = new GenerateXsd();
1358 List<Map<String, Object>> inEdges = JsonPath.parse(jsonEdges).read(path);
1360 edgeRulesIterator = inEdges.iterator();
1361 Map<String, Object> edgeMap;
1365 String multiplicity;
1367 String hasDelTarget;
1368 String deleteOtherV;
1369 String preventDelete;
1371 EdgeDescription edgeDes;
1373 while( edgeRulesIterator.hasNext() ){
1374 edgeMap = edgeRulesIterator.next();
1375 fromNode = (String)edgeMap.get("from");
1376 toNode = (String)edgeMap.get("to");
1378 if ( fromNode.equals(toNode)) {
1382 edgeDes = x.new EdgeDescription();
1383 edgeDes.setRuleKey(fromNode + "|" + toNode);
1384 edgeDes.setLabel((String)edgeMap.get("label"));
1385 edgeDes.setTo((String)edgeMap.get("to"));
1386 edgeDes.setFrom((String)edgeMap.get("from"));
1387 direction = (String)edgeMap.get("direction");
1388 edgeDes.setDirection(direction);
1389 multiplicity = (String)edgeMap.get("multiplicity");
1390 edgeDes.setMultiplicity(multiplicity);
1391 isParent = (String)edgeMap.get(EdgeProperty.CONTAINS.toString());
1392 if ( "${direction}".equals(isParent)) {
1393 edgeDes.setType(LineageType.PARENT);
1395 edgeDes.setType(LineageType.UNRELATED);
1397 hasDelTarget = (String)edgeMap.get(EdgeProperty.DELETE_OTHER_V.toString());
1398 deleteOtherV = (String)edgeMap.get(EdgeProperty.DELETE_OTHER_V.toString());
1399 edgeDes.setDeleteOtherV(deleteOtherV);
1400 edgeDes.setHasDelTarget(hasDelTarget);
1401 preventDelete = (String)edgeMap.get(EdgeProperty.PREVENT_DELETE.toString());
1402 edgeDes.setPreventDelete(preventDelete);
1403 description = (String)edgeMap.get(EdgeProperty.DESCRIPTION.toString());
1404 edgeDes.setDescription(description);
1406 result.add(edgeDes);
1407 logger.debug("Edge: "+edgeDes.getRuleKey());
1409 } catch (Exception ex) {
1410 ex.printStackTrace();
1417 * Guaranteed to at least return non null but empty collection of edge descriptions
1418 * @param nodeName name of the vertex whose edge relationships to return
1419 * @return collection of node neighbors based on DbEdgeRules
1421 private static Collection<EdgeDescription> getEdgeRules( String nodeName )
1423 String fromRulesPath = "$['rules'][?(@['from']=='" + nodeName + "')]";
1424 String toRulesPath = "$['rules'][?(@['to']=='" + nodeName + "')]";
1425 Collection<EdgeDescription> fromEdges = getEdgeRulesFromJson( fromRulesPath, false );
1426 Collection<EdgeDescription> edges = getEdgeRulesFromJson( toRulesPath, true );
1427 edges.addAll(fromEdges);
1431 private static Collection<EdgeDescription> getEdgeRulesTO( String nodeName )
1433 String toRulesPath = "$['rules'][?(@['to']=='" + nodeName + "')]";
1434 Collection<EdgeDescription> edges = getEdgeRulesFromJson( toRulesPath, true );
1438 private static Collection<EdgeDescription> getEdgeRulesFROM( String nodeName )
1440 String fromRulesPath = "$['rules'][?(@['from']=='" + nodeName + "')]";
1441 Collection<EdgeDescription> edges = getEdgeRulesFromJson( fromRulesPath, true );
1444 public static String processJavaTypeElementSwagger( String javaTypeName, Element javaTypeElement,
1445 StringBuffer pathSb, StringBuffer definitionsSb, String path, String tag, String opId,
1446 String getItemName, StringBuffer pathParams, String queryParams, String validEdges) {
1448 String xmlRootElementName = null;
1449 StringBuilder definitionsLocalSb = new StringBuilder(256);
1451 String useTag = null;
1452 String useOpId = null;
1454 if ( tag != null ) {
1457 case "ServiceDesignAndCreation":
1459 case "LicenseManagement":
1460 case "CloudInfrastructure":
1467 if ( !javaTypeName.equals("Inventory") ) {
1468 if ( javaTypeName.equals("AaiInternal"))
1471 useOpId = javaTypeName;
1473 useOpId = opId + javaTypeName;
1475 useTag = javaTypeName;
1478 NodeList parentNodes = javaTypeElement.getElementsByTagName("java-attributes");
1480 if ( parentNodes.getLength() == 0 ) {
1481 logger.trace( "no java-attributes for java-type " + javaTypeName);
1485 NamedNodeMap attributes;
1487 NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element");
1488 Element valElement = (Element) valNodes.item(0);
1489 attributes = valElement.getAttributes();
1490 for ( int i = 0; i < attributes.getLength(); ++i ) {
1491 Attr attr = (Attr) attributes.item(i);
1492 String attrName = attr.getNodeName();
1494 String attrValue = attr.getNodeValue();
1495 logger.trace("Found xml-root-element attribute: " + attrName + " with value: " + attrValue);
1496 if ( attrName.equals("name"))
1497 xmlRootElementName = attrValue;
1500 NodeList childNodes;
1501 Element childElement;
1502 NodeList xmlPropNodes = javaTypeElement.getElementsByTagName("xml-properties");
1503 Element xmlPropElement;
1504 String pathDescriptionProperty = null;
1507 Vector<String> indexedProps = null;
1509 if ( xmlPropNodes.getLength() > 0 ) {
1511 for ( int i = 0; i < xmlPropNodes.getLength(); ++i ) {
1512 xmlPropElement = (Element)xmlPropNodes.item(i);
1513 if ( !xmlPropElement.getParentNode().isSameNode(javaTypeElement))
1515 childNodes = xmlPropElement.getElementsByTagName("xml-property");
1517 if ( childNodes.getLength() > 0 ) {
1518 for ( int j = 0; j < childNodes.getLength(); ++j ) {
1519 childElement = (Element)childNodes.item(j);
1521 int useValue = VALUE_NONE;
1522 attributes = childElement.getAttributes();
1523 for ( int k = 0; k < attributes.getLength(); ++k ) {
1524 Attr attr = (Attr) attributes.item(k);
1525 String attrName = attr.getNodeName();
1526 String attrValue = attr.getNodeValue();
1527 if ( attrName == null || attrValue == null )
1529 if ( attrName.equals("name") && attrValue.equals("description")) {
1530 useValue = VALUE_DESCRIPTION;
1532 if ( useValue == VALUE_DESCRIPTION && attrName.equals("value")) {
1533 pathDescriptionProperty = attrValue;
1535 if ( attrValue.equals("indexedProps")) {
1536 useValue = VALUE_INDEXED_PROPS;
1538 if ( useValue == VALUE_INDEXED_PROPS && attrName.equals("value")) {
1539 indexedProps = getIndexedProps( attrValue );
1546 logger.trace("javaTypeName " + javaTypeName + " description " + pathDescriptionProperty);
1548 Element parentElement = (Element)parentNodes.item(0);
1549 NodeList xmlElementNodes = parentElement.getElementsByTagName("xml-element");
1552 String attrDescription = null;
1554 Element xmlElementElement;
1555 String addType = null;
1556 String elementType = null, elementIsKey = null, elementIsRequired, elementContainerType = null;
1557 String elementName = null;
1558 StringBuffer sbParameters = new StringBuffer();
1560 StringBuffer sbRequired = new StringBuffer();
1561 int requiredCnt = 0;
1562 int propertyCnt = 0;
1563 StringBuffer sbProperties = new StringBuffer();
1564 StringBuffer sbIndexedParams = new StringBuffer();
1568 if ( xmlRootElementName.equals("inventory"))
1570 else if ( path == null )
1571 path = "/" + xmlRootElementName;
1573 path += "/" + xmlRootElementName;
1574 st = new StringTokenizer(path, "/");
1575 boolean genPath = false;
1577 if ( st.countTokens() > 1 && getItemName == null ) {
1578 if ( appliedPaths.containsKey(path))
1580 appliedPaths.put(path, xmlRootElementName);
1582 if ( path.contains("/relationship/") ) { // filter paths with relationship-list
1585 if ( path.endsWith("/relationship-list")) {
1591 Vector<String> addTypeV = null;
1592 if ( xmlElementNodes.getLength() > 0 ) {
1594 for ( int i = 0; i < xmlElementNodes.getLength(); ++i ) {
1595 xmlElementElement = (Element)xmlElementNodes.item(i);
1596 if ( !xmlElementElement.getParentNode().isSameNode(parentElement))
1599 valNodes = xmlElementElement.getElementsByTagName("xml-properties");
1600 attrDescription = null;
1601 if ( valNodes.getLength() > 0 ) {
1602 for ( int j = 0; j < valNodes.getLength(); ++j ) {
1603 valElement = (Element)valNodes.item(j);
1604 if ( !valElement.getParentNode().isSameNode(xmlElementElement))
1606 childNodes = valElement.getElementsByTagName("xml-property");
1607 if ( childNodes.getLength() > 0 ) {
1608 childElement = (Element)childNodes.item(0);
1610 attributes = childElement.getAttributes();
1611 attrDescription = null;
1612 boolean useValue = false;
1613 for ( int k = 0; k < attributes.getLength(); ++k ) {
1614 Attr attr = (Attr) attributes.item(k);
1615 String attrName = attr.getNodeName();
1616 String attrValue = attr.getNodeValue();
1617 if ( attrName.equals("name") && attrValue.equals("description")) {
1620 if ( useValue && attrName.equals("value")) {
1621 attrDescription = attrValue;
1629 attributes = xmlElementElement.getAttributes();
1630 addTypeV = null; // vector of 1
1633 elementName = elementType = elementIsKey = elementIsRequired = elementContainerType = null;
1634 for ( int j = 0; j < attributes.getLength(); ++j ) {
1635 Attr attr = (Attr) attributes.item(j);
1636 String attrName = attr.getNodeName();
1638 String attrValue = attr.getNodeValue();
1639 logger.trace("For " + xmlRootElementName + " Found xml-element attribute: " + attrName + " with value: " + attrValue);
1640 if ( attrName.equals("name")) {
1641 elementName = attrValue;
1644 if ( attrName.equals("type") && getItemName == null ) {
1645 elementType = attrValue;
1646 if ( attrValue.contains(apiVersionFmt) ) {
1647 addType = attrValue.substring(attrValue.lastIndexOf('.')+1);
1648 if ( addTypeV == null )
1649 addTypeV = new Vector<String>();
1650 addTypeV.add(addType);
1654 if ( attrName.equals("xml-key")) {
1655 elementIsKey = attrValue;
1656 path += "/{" + elementName + "}";
1658 if ( attrName.equals("required")) {
1659 elementIsRequired = attrValue;
1661 if ( attrName.equals("container-type")) {
1662 elementContainerType = attrValue;
1665 if ( getItemName != null ) {
1666 if ( getItemName.equals("array") ) {
1667 if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) {
1668 logger.trace( " returning array " + elementName );
1672 } else { // not an array check
1673 if ( elementContainerType == null || !elementContainerType.equals("java.util.ArrayList")) {
1674 logger.trace( " returning object " + elementName );
1679 logger.trace( " returning null" );
1682 if ( elementIsRequired != null ) {
1683 if ( requiredCnt == 0 )
1684 sbRequired.append(" required:\n");
1686 if ( addTypeV != null ) {
1687 for ( int k = 0; k < addTypeV.size(); ++i ) {
1688 sbRequired.append(" - " + getXmlRootElementName(addTypeV.elementAt(k)) + ":\n");
1691 sbRequired.append(" - " + elementName + "\n");
1695 if ( elementIsKey != null ) {
1696 sbParameters.append((" - name: " + elementName + "\n"));
1697 sbParameters.append((" in: path\n"));
1698 if ( attrDescription != null && attrDescription.length() > 0 )
1699 sbParameters.append((" description: " + attrDescription + "\n"));
1700 sbParameters.append((" required: true\n"));
1701 if ( elementType.equals("java.lang.String"))
1702 sbParameters.append(" type: string\n");
1703 if ( elementType.equals("java.lang.Long")) {
1704 sbParameters.append(" type: integer\n");
1705 sbParameters.append(" format: int64\n");
1707 if ( elementType.equals("java.lang.Integer")) {
1708 sbParameters.append(" type: integer\n");
1709 sbParameters.append(" format: int32\n");
1711 if ( elementType.equals("java.lang.Boolean")) {
1712 sbParameters.append(" type: boolean\n");
1714 if(StringUtils.isNotBlank(elementName)) {
1715 sbParameters.append(" example: "+"__"+elementName.toUpperCase()+"__"+"\n");
1717 } else if ( indexedProps != null
1718 && indexedProps.contains(elementName ) ) {
1719 sbIndexedParams.append((" - name: " + elementName + "\n"));
1720 sbIndexedParams.append((" in: query\n"));
1721 if ( attrDescription != null && attrDescription.length() > 0 )
1722 sbIndexedParams.append((" description: " + attrDescription + "\n"));
1723 sbIndexedParams.append((" required: false\n"));
1724 if ( elementType.equals("java.lang.String"))
1725 sbIndexedParams.append(" type: string\n");
1726 if ( elementType.equals("java.lang.Long")) {
1727 sbIndexedParams.append(" type: integer\n");
1728 sbIndexedParams.append(" format: int64\n");
1730 if ( elementType.equals("java.lang.Integer")) {
1731 sbIndexedParams.append(" type: integer\n");
1732 sbIndexedParams.append(" format: int32\n");
1734 if ( elementType.equals("java.lang.Boolean"))
1735 sbIndexedParams.append(" type: boolean\n");
1737 if ( isStandardType(elementType)) {
1738 sbProperties.append(" " + elementName + ":\n");
1740 sbProperties.append(" type: ");
1742 if ( elementType.equals("java.lang.String"))
1743 sbProperties.append("string\n");
1744 else if ( elementType.equals("java.lang.Long")) {
1745 sbProperties.append("integer\n");
1746 sbProperties.append(" format: int64\n");
1748 else if ( elementType.equals("java.lang.Integer")){
1749 sbProperties.append("integer\n");
1750 sbProperties.append(" format: int32\n");
1752 else if ( elementType.equals("java.lang.Boolean"))
1753 sbProperties.append("boolean\n");
1754 if ( attrDescription != null && attrDescription.length() > 0 )
1755 sbProperties.append(" description: " + attrDescription + "\n");
1758 if ( addTypeV != null ) {
1759 StringBuffer newPathParams = null;
1760 if ( pathParams != null ) {
1761 newPathParams = new StringBuffer();
1762 newPathParams.append(pathParams);
1764 if ( sbParameters.toString().length() > 0 ) {
1765 if ( newPathParams == null )
1766 newPathParams = new StringBuffer();
1767 newPathParams.append(sbParameters);
1769 String newQueryParams = null;
1770 if ( sbIndexedParams.toString().length() > 0 ) {
1771 if ( queryParams == null )
1772 newQueryParams = sbIndexedParams.toString();
1774 newQueryParams = queryParams + sbIndexedParams.toString();
1776 newQueryParams = queryParams;
1778 for ( int k = 0; k < addTypeV.size(); ++k ) {
1779 addType = addTypeV.elementAt(k);
1781 if ( opId == null || !opId.contains(addType)) {
1782 processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
1783 pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId, null,
1784 newPathParams, newQueryParams, validEdges);
1786 // need item name of array
1787 String itemName = processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
1788 pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId,
1789 "array", null, null, null );
1791 if ( itemName != null ) {
1792 if ( addType.equals("AaiInternal") ) {
1793 logger.debug( "addType AaiInternal, skip properties");
1795 } else if ( getItemName == null) {
1797 sbProperties.append(" " + getXmlRootElementName(addType) + ":\n");
1798 sbProperties.append(" type: array\n items:\n");
1799 sbProperties.append(" $ref: \"#/definitions/" + (itemName == "" ? "aai-internal" : itemName) + "\"\n");
1800 if ( attrDescription != null && attrDescription.length() > 0 )
1801 sbProperties.append(" description: " + attrDescription + "\n");
1804 if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) {
1805 // need properties for getXmlRootElementName(addType)
1806 newPathParams = null;
1807 if ( pathParams != null ) {
1808 newPathParams = new StringBuffer();
1809 newPathParams.append(pathParams);
1811 if ( sbParameters.toString().length() > 0 ) {
1812 if ( newPathParams == null )
1813 newPathParams = new StringBuffer();
1814 newPathParams.append(sbParameters);
1816 newQueryParams = null;
1817 if ( sbIndexedParams.toString().length() > 0 ) {
1818 if ( queryParams == null )
1819 newQueryParams = sbIndexedParams.toString();
1821 newQueryParams = queryParams + sbIndexedParams.toString();
1823 newQueryParams = queryParams;
1825 processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType),
1826 pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId,
1827 null, newPathParams, newQueryParams, validEdges );
1828 sbProperties.append(" " + getXmlRootElementName(addType) + ":\n");
1829 sbProperties.append(" type: array\n items: \n");
1830 sbProperties.append(" $ref: \"#/definitions/" + getXmlRootElementName(addType) + "\"\n");
1832 sbProperties.append(" " + getXmlRootElementName(addType) + ":\n");
1833 sbProperties.append(" type: object\n");
1834 sbProperties.append(" $ref: \"#/definitions/" + getXmlRootElementName(addType) + "\"\n");
1836 if ( attrDescription != null && attrDescription.length() > 0 )
1837 sbProperties.append(" description: " + attrDescription + "\n");
1845 if ( !path.endsWith("/relationship") ) {
1846 GetOperation get = new GetOperation(useOpId, xmlRootElementName, tag, path, pathParams == null ? "" : pathParams.toString());
1847 pathSb.append(get.toString());
1848 // if ( path.indexOf('{') > 0 ) {
1850 if ( sbParameters.toString().length() > 0 ) {
1851 if ( pathParams == null )
1852 pathParams = new StringBuffer();
1853 pathParams.append(sbParameters);
1855 if ( pathParams != null) {
1856 pathSb.append(" parameters:\n");
1857 pathSb.append(pathParams);
1859 logger.trace( "null pathParams for " + useOpId);
1860 if ( sbIndexedParams.toString().length() > 0 ) {
1861 if ( queryParams == null )
1862 queryParams = sbIndexedParams.toString();
1864 queryParams = queryParams + sbIndexedParams.toString();
1866 if ( queryParams != null ) {
1867 if ( pathParams == null ) {
1868 pathSb.append(" parameters:\n");
1870 pathSb.append(queryParams);
1874 boolean skipPutDelete = false; // no put or delete for "all"
1875 if ( !path.endsWith("/relationship") ) {
1876 if ( !path.endsWith("}") ){
1877 skipPutDelete = true;
1881 if ( path.indexOf('{') > 0 && !opId.startsWith("Search") &&!skipPutDelete) {
1883 PutOperation put = new PutOperation(useOpId, xmlRootElementName, tag, path, pathParams == null ? "" : pathParams.toString());
1884 pathSb.append(put.toString());
1885 if ( !path.endsWith("/relationship") ) {
1886 PatchOperation patch = new PatchOperation(useOpId, xmlRootElementName, tag, path, pathParams == null ? "" : pathParams.toString());
1887 pathSb.append(patch.toString1());
1889 logger.debug(put.tagRelationshipPathMapEntry());
1892 DeleteOperation del = new DeleteOperation(useOpId, xmlRootElementName, tag, path, pathParams == null ? "" : pathParams.toString());
1893 pathSb.append(del.toString());
1894 logger.debug(del.objectPathMapEntry());
1898 if ( generatedJavaType.containsKey(xmlRootElementName) ) {
1902 definitionsSb.append(" " + xmlRootElementName + ":\n");
1903 definitionsLocalSb.append(" " + xmlRootElementName + ":\n");
1904 Collection<EdgeDescription> edges = getEdgeRules(xmlRootElementName );
1906 if ( edges.size() > 0 ) {
1907 StringBuffer sbEdge = new StringBuffer();
1908 sbEdge.append(" ###### Related Nodes\n");
1909 for (EdgeDescription ed : edges) {
1910 if ( ed.getRuleKey().startsWith(xmlRootElementName)) {
1911 sbEdge.append(" - TO ").append(ed.getRuleKey().substring(ed.getRuleKey().indexOf("|")+1));
1912 sbEdge.append(ed.getRelationshipDescription("TO", xmlRootElementName));
1913 sbEdge.append("\n");
1916 for (EdgeDescription ed : edges) {
1917 if ( ed.getRuleKey().endsWith(xmlRootElementName)) {
1918 sbEdge.append(" - FROM ").append(ed.getRuleKey().substring(0, ed.getRuleKey().indexOf("|")));
1919 sbEdge.append(ed.getRelationshipDescription("FROM", xmlRootElementName));
1920 sbEdge.append("\n");
1923 // Delete rule processing is incorrect. One cannot express the delete rules in isolation from the
1924 // specific edge. Take the case of allotted-resource and service-instance. When the service-instance owns the
1925 // allotted-resource, yes, it deletes it. But when the service-instance only uses the allotted-resource, the deletion
1926 // of the service instance does not cause the deletion of the allotted-resource.
1927 // I put some lines into the toDeleteRules and fromDeleteRules to correct things to an extent, but it's still
1929 sbEdge.append(toDeleteRules(xmlRootElementName));
1930 sbEdge.append(fromDeleteRules(xmlRootElementName));
1931 validEdges = sbEdge.toString();
1934 // Handle description property. Might have a description OR valid edges OR both OR neither.
1935 // Only put a description: tag if there is at least one.
1936 if (pathDescriptionProperty != null || validEdges != null) {
1937 definitionsSb.append(" description: |\n");
1938 definitionsLocalSb.append(" description: |\n");
1940 if ( pathDescriptionProperty != null ) {
1941 definitionsSb.append(" " + pathDescriptionProperty + "\n" );
1942 definitionsLocalSb.append(" " + pathDescriptionProperty + "\n" );
1944 if (validEdges != null) {
1945 definitionsSb.append(validEdges);
1946 definitionsLocalSb.append(validEdges);
1950 if ( requiredCnt > 0 ) {
1951 definitionsSb.append(sbRequired);
1952 definitionsLocalSb.append(sbRequired);
1955 if ( propertyCnt > 0 ) {
1956 definitionsSb.append(" properties:\n");
1957 definitionsSb.append(sbProperties);
1958 definitionsLocalSb.append(" properties:\n");
1959 definitionsLocalSb.append(sbProperties);
1962 javaTypeDefinitions.put(xmlRootElementName, definitionsLocalSb.toString());
1963 } catch (Exception e) {
1964 e.printStackTrace();
1966 generatedJavaType.put(xmlRootElementName, null);
1970 public static void generateRelations() {
1971 if(putRelationPaths == null)
1973 putRelationPaths.forEach((k,v)->{
1974 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"));
1975 logger.debug("apiPath(Operation): "+v);
1976 logger.debug("Target object: "+v.replace("/relationship-list/relationship", ""));
1977 logger.debug("Relations: ");
1978 PutRelationPathSet prp = new PutRelationPathSet(k, v);
1983 public static String generateSwaggerFromOxmFile( File oxmFile, String xml )
1986 apiVersion = Version.getLatest().toString();
1987 apiVersionFmt = "." + apiVersion + ".";
1988 generatedJavaType = new HashMap<>();
1989 appliedPaths = new HashMap<>();
1990 responsesUrl = "Description: response-label\n";
1992 StringBuffer sb = new StringBuffer();
1993 sb.append("swagger: \"2.0\"\ninfo:\n ");
1994 sb.append("description: |");
1995 sb.append("\n\n [Differences versus the previous schema version]("+"apidocs/aai_swagger_" + apiVersion + ".diff)");
1996 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");
1997 sb.append(" title: Active and Available Inventory REST API\n");
1998 sb.append(" license:\n name: Apache 2.0\n url: http://www.apache.org/licenses/LICENSE-2.0.html\n");
1999 sb.append(" contact:\n name:\n url:\n email:\n");
2000 sb.append("host:\nbasePath: /aai/" + apiVersion + "\n");
2001 sb.append("schemes:\n - https\npaths:\n");
2005 if(System.getProperty("user.dir") != null && !System.getProperty("user.dir").contains(normalStartDir)) {
2006 initialFile = new File(normalStartDir + "/src/main/resources/dbedgerules/DbEdgeRules_" + apiVersion + ".json");
2009 initialFile = new File("src/main/resources/dbedgerules/DbEdgeRules_" + apiVersion + ".json");
2011 InputStream is = new FileInputStream(initialFile);
2013 Scanner scanner = new Scanner(is);
2014 jsonEdges = scanner.useDelimiter("\\Z").next();
2018 DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
2019 dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
2020 DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
2023 if ( xml == null ) {
2024 doc = dBuilder.parse(oxmFile);
2026 InputSource isInput = new InputSource(new StringReader(xml));
2027 doc = dBuilder.parse(isInput);
2030 NodeList bindingsNodes = doc.getElementsByTagName("xml-bindings");
2031 Element bindingElement;
2032 NodeList javaTypesNodes;
2033 Element javaTypesElement;
2035 Element javaTypeElement;
2038 if ( bindingsNodes == null || bindingsNodes.getLength() == 0 ) {
2039 logger.error( "missing <binding-nodes> in " + oxmFile );
2043 bindingElement = (Element) bindingsNodes.item(0);
2044 javaTypesNodes = bindingElement.getElementsByTagName("java-types");
2045 if ( javaTypesNodes.getLength() < 1 ) {
2046 logger.error( "missing <binding-nodes><java-types> in " + oxmFile );
2049 javaTypesElement = (Element) javaTypesNodes.item(0);
2051 javaTypeNodes = javaTypesElement.getElementsByTagName("java-type");
2052 if ( javaTypeNodes.getLength() < 1 ) {
2053 logger.error( "missing <binding-nodes><java-types><java-type> in " + oxmFile );
2057 String javaTypeName;
2058 String attrName, attrValue;
2060 StringBuffer pathSb = new StringBuffer();
2062 StringBuffer definitionsSb = new StringBuffer();
2063 for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) {
2064 javaTypeElement = (Element) javaTypeNodes.item(i);
2065 NamedNodeMap attributes = javaTypeElement.getAttributes();
2066 javaTypeName = null;
2067 for ( int j = 0; j < attributes.getLength(); ++j ) {
2068 attr = (Attr) attributes.item(j);
2069 attrName = attr.getNodeName();
2070 attrValue = attr.getNodeValue();
2071 if ( attrName.equals("name"))
2072 javaTypeName = attrValue;
2074 if ( javaTypeName == null ) {
2075 logger.error( "<java-type> has no name attribute in " + oxmFile );
2078 if ( !generatedJavaType.containsKey(getXmlRootElementName(javaTypeName)) ) {
2080 processJavaTypeElementSwagger( javaTypeName, javaTypeElement, pathSb,
2081 definitionsSb, null, null, null, null, null, null, null);
2085 } catch (Exception e) {
2086 e.printStackTrace();
2089 //append definitions
2090 sb.append("definitions:\n");
2091 Map<String, String> sortedJavaTypeDefinitions = new TreeMap<String, String>(javaTypeDefinitions);
2092 for (Map.Entry<String, String> entry : sortedJavaTypeDefinitions.entrySet()) {
2093 logger.debug("Key: "+entry.getKey()+"Test: "+ (entry.getKey() == "relationship"));
2094 if(entry.getKey().matches("relationship")) {
2095 String jb=entry.getValue();
2096 logger.debug("Value: "+jb);
2097 int ndx=jb.indexOf("related-to-property:");
2099 jb=jb.substring(0, ndx);
2100 jb=jb.replaceAll(" +$", "");
2102 logger.debug("Value-after: "+jb);
2106 sb.append(entry.getValue());
2109 sb.append("patchDefinitions:\n");
2110 for (Map.Entry<String, String> entry : sortedJavaTypeDefinitions.entrySet()) {
2111 String jb=entry.getValue().replaceAll("/definitions/", "/patchDefinitions/");
2112 int ndx=jb.indexOf("relationship-list:");
2114 jb=jb.substring(0, ndx);
2115 jb=jb.replaceAll(" +$", "");
2117 int ndx1=jb.indexOf("resource-version:");
2118 logger.debug("Key: "+entry.getKey()+" index: " + ndx1);
2119 logger.debug("Value: "+jb);
2121 jb=jb.substring(0, ndx1);
2122 jb=jb.replaceAll(" +$", "");
2124 logger.debug("Value-after: "+jb);
2128 sb.append("getDefinitions:\n");
2129 for (Map.Entry<String, String> entry : sortedJavaTypeDefinitions.entrySet()) {
2130 String jb=entry.getValue().replaceAll("/definitions/", "/getDefinitions/");
2134 logger.debug("generated " + sb.toString());
2135 generateRelations();
2136 return sb.toString();
2139 private static NodeList locateXmlProperties(Element element) {
2140 XPathExpression expr;
2141 NodeList result = null;
2143 expr = xpath.compile("xml-properties");
2145 Object nodeset = expr.evaluate(element, XPathConstants.NODESET);
2146 if (nodeset != null) {
2147 NodeList nodes = (NodeList) nodeset;
2148 if (nodes != null && nodes.getLength() > 0) {
2149 Element xmlProperty = (Element)nodes.item(0);
2150 result = xmlProperty.getElementsByTagName("xml-property");
2154 } catch (XPathExpressionException e) {
2155 e.printStackTrace();