From f1a8fb1bc04f5d685f2b31d35db605f6fa054f60 Mon Sep 17 00:00:00 2001 From: "Kajur, Harish (vk250x)" Date: Sat, 24 Mar 2018 21:59:03 -0400 Subject: Add plugin to check coverage Get line coverage to 50% and ensure it doesn't go down Issue-ID: AAI-498 Change-Id: Ib466b7e2b7cb6d2f888e3b58c2073bb02ab6f809 Signed-off-by: Kajur, Harish (vk250x) --- .../java/org/onap/aai/introspection/Version.java | 37 +- .../main/java/org/onap/aai/util/GenerateXsd.java | 2038 +------------------- .../onap/aai/util/genxsd/DeleteFootnoteSet.java | 57 + .../org/onap/aai/util/genxsd/DeleteOperation.java | 106 + .../org/onap/aai/util/genxsd/EdgeDescription.java | 242 +++ .../java/org/onap/aai/util/genxsd/EdgeRuleSet.java | 196 ++ .../org/onap/aai/util/genxsd/GetOperation.java | 121 ++ .../java/org/onap/aai/util/genxsd/HTMLfromOXM.java | 190 ++ .../org/onap/aai/util/genxsd/OxmFileProcessor.java | 199 ++ .../org/onap/aai/util/genxsd/PatchOperation.java | 116 ++ .../org/onap/aai/util/genxsd/PutOperation.java | 114 ++ .../onap/aai/util/genxsd/PutRelationPathSet.java | 216 +++ .../java/org/onap/aai/util/genxsd/XSDElement.java | 678 +++++++ .../java/org/onap/aai/util/genxsd/XSDJavaType.java | 64 + .../java/org/onap/aai/util/genxsd/YAMLfromOXM.java | 470 +++++ 15 files changed, 2865 insertions(+), 1979 deletions(-) create mode 100644 aai-core/src/main/java/org/onap/aai/util/genxsd/DeleteFootnoteSet.java create mode 100644 aai-core/src/main/java/org/onap/aai/util/genxsd/DeleteOperation.java create mode 100644 aai-core/src/main/java/org/onap/aai/util/genxsd/EdgeDescription.java create mode 100644 aai-core/src/main/java/org/onap/aai/util/genxsd/EdgeRuleSet.java create mode 100644 aai-core/src/main/java/org/onap/aai/util/genxsd/GetOperation.java create mode 100644 aai-core/src/main/java/org/onap/aai/util/genxsd/HTMLfromOXM.java create mode 100644 aai-core/src/main/java/org/onap/aai/util/genxsd/OxmFileProcessor.java create mode 100644 aai-core/src/main/java/org/onap/aai/util/genxsd/PatchOperation.java create mode 100644 aai-core/src/main/java/org/onap/aai/util/genxsd/PutOperation.java create mode 100644 aai-core/src/main/java/org/onap/aai/util/genxsd/PutRelationPathSet.java create mode 100644 aai-core/src/main/java/org/onap/aai/util/genxsd/XSDElement.java create mode 100644 aai-core/src/main/java/org/onap/aai/util/genxsd/XSDJavaType.java create mode 100644 aai-core/src/main/java/org/onap/aai/util/genxsd/YAMLfromOXM.java (limited to 'aai-core/src/main/java/org') diff --git a/aai-core/src/main/java/org/onap/aai/introspection/Version.java b/aai-core/src/main/java/org/onap/aai/introspection/Version.java index 76ff939f..d32212b8 100644 --- a/aai-core/src/main/java/org/onap/aai/introspection/Version.java +++ b/aai-core/src/main/java/org/onap/aai/introspection/Version.java @@ -19,6 +19,9 @@ */ package org.onap.aai.introspection; +/** + * Requires the order to be in ascending order + */ public enum Version { v8, v9, @@ -26,12 +29,38 @@ public enum Version { v11, v12, v13; - + + public static final String VERSION_EXPRESSION = "v8|v9|v10|v11|v12|v13|latest"; + public static final String VERSION_EXPRESSION_V8_PLUS = "v8|v9|v10|v11|v12|v13|latest"; + public static final String VERSION_EXPRESSION_V9_PLUS = "v9|v10|v11|v12|v13|latest"; + + /** + * Checks if v is the latest version + * @param v + * @return + */ public static boolean isLatest(Version v) { - return (Version.v13.equals(v)); //TODO update when we increment the version, or find a better way of doing this + return Version.getLatest().equals(v); } - + + /** + * Gets the latest version + * @return + */ public static Version getLatest(){ - return Version.v13; //TODO update when we increment the version, or find a better way of doing this + return Version.values()[Version.values().length-1]; + } + + /** + * To be used inplace of Version.getVersion(String) to correctly get version of "latest" + * @param v + * @return + */ + public static Version getVersion(String v) { + if ("latest".equals(v)) { + return Version.getLatest(); + } + return Version.valueOf(v); } + } diff --git a/aai-core/src/main/java/org/onap/aai/util/GenerateXsd.java b/aai-core/src/main/java/org/onap/aai/util/GenerateXsd.java index 4ee65dd0..63318da3 100644 --- a/aai-core/src/main/java/org/onap/aai/util/GenerateXsd.java +++ b/aai-core/src/main/java/org/onap/aai/util/GenerateXsd.java @@ -7,708 +7,71 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * 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. * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.util; -import com.google.common.base.Joiner; -import com.jayway.jsonpath.JsonPath; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.text.similarity.LevenshteinDistance; +package org.onap.aai.util; import org.onap.aai.introspection.Version; -import org.onap.aai.serialization.db.EdgeProperty; -import org.w3c.dom.*; -import org.xml.sax.InputSource; +import org.onap.aai.util.genxsd.EdgeRuleSet; +import org.onap.aai.util.genxsd.HTMLfromOXM; +import org.onap.aai.util.genxsd.YAMLfromOXM; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import javax.xml.XMLConstants; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.xpath.*; -import java.io.*; +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class GenerateXsd { private static final Logger logger = LoggerFactory.getLogger("GenerateXsd.class"); - - static String apiVersion = null; + protected static String apiVersion = null; static String apiVersionFmt = null; static boolean useAnnotationsInXsd = false; static String responsesUrl = null; static String responsesLabel = null; static String jsonEdges = null; + static EdgeRuleSet edgeRuleSet = null; static Map generatedJavaType; static Map appliedPaths; - static Map deletePaths; - static Map putRelationPaths; - static NodeList javaTypeNodes; - static Map javaTypeDefinitions = createJavaTypeDefinitions(); - private static Map createJavaTypeDefinitions() - { - StringBuffer aaiInternal = new StringBuffer(); - Map javaTypeDefinitions = new HashMap(); - aaiInternal.append(" aai-internal:\n"); - aaiInternal.append(" properties:\n"); - aaiInternal.append(" property-name:\n"); - aaiInternal.append(" type: string\n"); - aaiInternal.append(" property-value:\n"); - aaiInternal.append(" type: string\n"); - javaTypeDefinitions.put("aai-internal", aaiInternal.toString()); - return javaTypeDefinitions; - } public static final int VALUE_NONE = 0; public static final int VALUE_DESCRIPTION = 1; public static final int VALUE_INDEXED_PROPS = 2; + public static final int VALUE_CONTAINER = 3; private static final String generateTypeXSD = "xsd"; private static final String generateTypeYAML = "yaml"; private static final String root = "../aai-schema/src/main/resources"; + private static final String autoGenRoot = "aai-schema/src/main/resources"; + private static final String normalStartDir = "aai-core"; private static final String xsd_dir = root + "/aai_schema"; - private static final String yaml_dir = root + "/aai_swagger_yaml"; + private static final String yaml_dir = (((System.getProperty("user.dir") != null) && (!System.getProperty("user.dir").contains(normalStartDir))) ? autoGenRoot : root) + "/aai_swagger_yaml"; /* These three strings are for yaml auto-generation from aai-common class*/ - private static final String normalStartDir = "aai-core"; - private static final String autoGenRoot = "aai-schema/src/main/resources"; - private static final String alt_yaml_dir = autoGenRoot + "/aai_swagger_yaml"; +// private static final String alt_yaml_dir = autoGenRoot + "/aai_swagger_yaml"; private static int annotationsStartVersion = 9; // minimum version to support annotations in xsd private static int swaggerSupportStartsVersion = 7; // minimum version to support swagger documentation - private static XPath xpath = XPathFactory.newInstance().newXPath(); - - - private enum LineageType { - PARENT, CHILD, UNRELATED; - } - private class EdgeDescription { - - private String ruleKey; - private String to; - private String from; - private LineageType type = LineageType.UNRELATED; - private String direction; - private String multiplicity; - private String preventDelete; - private String deleteOtherV; - private boolean hasDelTarget = false; - private String label; - private String description; - /** - * @return the deleteOtherV - */ - public String getDeleteOtherV() { - return deleteOtherV; - } - /** - * @param deleteOtherV the deleteOtherV to set - */ - public void setDeleteOtherV(String deleteOtherV) { - logger.debug("Edge: "+this.getRuleKey()); - logger.debug("Truth: "+(("${direction}".equals(deleteOtherV)) ? "true" : "false")); - logger.debug("Truth: "+(("!${direction}".equals(deleteOtherV)) ? "true" : "false")); - - if("${direction}".equals(deleteOtherV) ) { - this.deleteOtherV = this.direction; - } else if("!${direction}".equals(deleteOtherV) ) { - this.deleteOtherV = this.direction.equals("IN") ? "OUT" : ((this.direction.equals("OUT")) ? "IN" : deleteOtherV); - } else { - this.deleteOtherV = deleteOtherV; - } - logger.debug("DeleteOtherV="+deleteOtherV+"/"+this.direction+"="+this.deleteOtherV); - } - /** - * @return the preventDelete - */ - public String getPreventDelete() { - return preventDelete; - } - /** - * @param preventDelete the preventDelete to set - */ - public void setPreventDelete(String preventDelete) { - if(this.getTo().equals("flavor") || this.getFrom().equals("flavor") ){ - logger.debug("Edge: "+this.getRuleKey()); - logger.debug("Truth: "+(("${direction}".equals(preventDelete)) ? "true" : "false")); - logger.debug("Truth: "+(("!${direction}".equals(preventDelete)) ? "true" : "false")); - } - - if("${direction}".equals(preventDelete) ) { - this.preventDelete = this.direction; - } else if("!${direction}".equals(preventDelete) ) { - this.preventDelete = this.direction.equals("IN") ? "OUT" : ((this.direction.equals("OUT")) ? "IN" : preventDelete); - } else { - this.preventDelete = preventDelete; - } - if(this.getTo().equals("flavor") || this.getFrom().equals("flavor")) { - logger.debug("PreventDelete="+preventDelete+"/"+this.direction+"="+this.preventDelete); - } - } - /** - * @return the to - */ - public String getTo() { - return to; - } - /** - * @param to the to to set - */ - public void setTo(String to) { - this.to = to; - } - /** - * @return the from - */ - public String getFrom() { - return from; - } - /** - * @param from the from to set - */ - public void setFrom(String from) { - this.from = from; - } - - - public String getRuleKey() { - return ruleKey; - } - public String getMultiplicity() { - return multiplicity; - } - public String getDirection() { - return direction; - } - public String getDescription() { - return this.description; - } - public void setRuleKey(String val) { - this.ruleKey=val; - } - public void setType(LineageType val) { - this.type=val; - } - public void setDirection(String val) { - this.direction = val; - } - public void setMultiplicity(String val) { - this.multiplicity=val; - } - public void setHasDelTarget(String val) { - hasDelTarget = Boolean.parseBoolean(val); - } - public void setDescription(String val) { - this.description = val; - } - - public String getRelationshipDescription(String fromTo, String otherNodeName) { - - String result = ""; - - if ("FROM".equals(fromTo)) { - if ("OUT".equals(direction)) { - if (LineageType.PARENT == type) { - result = " (PARENT of "+otherNodeName; - result = String.join(" ", result+",", this.from, this.getLabel(), this.to); - } - } - else { - if (LineageType.CHILD == type) { - result = " (CHILD of "+otherNodeName; - result = String.join(" ", result+",", this.from, this.getLabel(), this.to); - } - else if (LineageType.PARENT == type) { - result = " (PARENT of "+otherNodeName; - result = String.join(" ", result+",", this.from, this.getLabel(), this.to); - } - } - if (result.length() == 0) result = String.join(" ", "(", this.from, this.getLabel(), this.to+",", this.getMultiplicity()); - } else { - //if ("TO".equals(fromTo) - if ("OUT".equals(direction)) { - if (LineageType.PARENT == type) { - result = " (CHILD of "+otherNodeName; - result = String.join(" ", result+",", this.from, this.getLabel(), this.to+",", this.getMultiplicity()); - } - } else { - if (LineageType.PARENT == type) { - result = " (PARENT of "+otherNodeName; - result = String.join(" ", result+",", this.from, this.getLabel(), this.to+",", this.getMultiplicity()); - } - } - if (result.length() == 0) result = String.join(" ", "(", this.from, this.getLabel(), this.to+",", this.getMultiplicity()); - - } - - if (hasDelTarget) result = result + ", will delete target node"; - - if (result.length() > 0) result = result + ")"; - - if (description != null && description.length() > 0) result = result + "\n "+ description; // 6 spaces is important for yaml - - return result; - } - - /** - * @return the hasDelTarget - */ - @SuppressWarnings("unused") - public boolean isHasDelTarget() { - return hasDelTarget; - } - /** - * @param hasDelTarget the hasDelTarget to set - */ - @SuppressWarnings("unused") - public void setHasDelTarget(boolean hasDelTarget) { - this.hasDelTarget = hasDelTarget; - } - /** - * @return the type - */ - @SuppressWarnings("unused") - public LineageType getType() { - return type; - } - /** - * @return the label - */ - public String getLabel() { - return label; - } - public void setLabel(String string) { - this.label=string; - } - } - - private static class PutRelationPathSet { - String apiPath; - String opId; - ArrayList relations = new ArrayList(); - String objectName = ""; - String currentAPIVersion = ""; - public PutRelationPathSet(String opId, String path) { - super(); - this.apiPath = path.replace("/relationship-list/relationship", ""); - this.opId = opId; - objectName = GenerateXsd.deletePaths.get(apiPath); - currentAPIVersion = GenerateXsd.apiVersion; - } - public void process() { - this.toRelations(); - this.fromRelations(); - this.writeRelationsFile(); - - } - public void toRelations() { - logger.debug("{“comment”: “Valid TO Relations that can be added”},"); - logger.debug("apiPath: "+apiPath+"\nopId="+opId+"\nobjectName="+objectName); - Collection toEdges = GenerateXsd.getEdgeRulesTO(objectName); - - if(toEdges.size() > 0) { - relations.add("{\"comment\": \"Valid TO Relations that can be added\"}\n"); - } - for (EdgeDescription ed : toEdges) { - logger.debug(ed.getRuleKey()+"Type="+ed.type); - String obj = ed.getRuleKey().replace(objectName,"").replace("|",""); - String selectedRelation = ""; - if(ed.type == LineageType.UNRELATED) { - String selectObj = getUnrelatedObjectPaths(obj, apiPath); - logger.debug("SelectedObj:"+selectObj); - selectedRelation = formatObjectRelationSet(obj,selectObj); - logger.trace("ObjectRelationSet"+selectedRelation); - } else { - String selectObj = getKinObjectPath(obj, apiPath); - logger.debug("SelectedObj:"+selectObj); - selectedRelation = formatObjectRelation(obj,selectObj); - logger.trace("ObjectRelationSet"+selectedRelation); - } - relations.add(selectedRelation); - logger.trace(selectedRelation); - } - } - - public void fromRelations() { - logger.debug("“comment”: “Valid FROM Relations that can be added”"); - Collection fromEdges = getEdgeRulesFROM(objectName); - if(fromEdges.size() > 0) { - relations.add("{\"comment\": \"Valid FROM Relations that can be added\"}\n"); - } - for (EdgeDescription ed : fromEdges) { - logger.debug(ed.getRuleKey()+"Type="+ed.type); - String obj = ed.getRuleKey().replace(objectName,"").replace("|",""); - String selectedRelation = ""; - if(ed.type == LineageType.UNRELATED) { - String selectObj = getUnrelatedObjectPaths(obj, apiPath); - logger.debug("SelectedObj"+selectObj); - selectedRelation = formatObjectRelationSet(obj,selectObj); - logger.trace("ObjectRelationSet"+selectedRelation); - } else { - String selectObj = getKinObjectPath(obj, apiPath); - logger.debug("SelectedObj"+selectObj); - selectedRelation = formatObjectRelation(obj,selectObj); - logger.trace("ObjectRelationSet"+selectedRelation); - } - relations.add(selectedRelation); - logger.trace(selectedRelation); - } - } - public void writeRelationsFile() { - File examplefilePath = new File(yaml_dir + "/relations/" + currentAPIVersion+"/"+opId.replace("RelationshipListRelationship", "") + ".json"); - - logger.debug(String.join("exampleFilePath: ", examplefilePath.toString())); - FileOutputStream fop = null; - try { - if (!examplefilePath.exists()) { - examplefilePath.getParentFile().mkdirs(); - examplefilePath.createNewFile(); - } - fop = new FileOutputStream(examplefilePath); - } catch(Exception e) { - e.printStackTrace(); - return; - } - try { - if(relations.size() > 0) {fop.write("[\n".getBytes());} - fop.write(String.join(",\n", relations).getBytes()); - if(relations.size() > 0) {fop.write("\n]\n".getBytes());} - fop.flush(); - fop.close(); - } catch (Exception e) { - e.printStackTrace(); - return; - } - logger.debug(String.join(",\n", relations)); - return; - } - - private static String formatObjectRelationSet(String obj, String selectObj) { - StringBuffer pathSb = new StringBuffer(); - String[] paths = selectObj.split("[|]"); - for (String s: paths) { - logger.trace("SelectOBJ"+s); - pathSb.append(formatObjectRelation(obj, s)+",\n"); - } - pathSb.deleteCharAt(pathSb.length()-2); - return pathSb.toString(); - } - - private static String formatObjectRelation(String obj, String selectObj) { - StringBuffer pathSb = new StringBuffer(); - pathSb.append("{\n"); - pathSb.append("\"related-to\" : \""+obj+"\",\n"); - pathSb.append("\"related-link\" : \""+selectObj+"\"\n"); - pathSb.append("}"); - return pathSb.toString(); - } - - private static String getKinObjectPath(String obj, String apiPath) { - LevenshteinDistance proximity = new LevenshteinDistance(); - String targetPath = ""; - int targetScore = Integer.MAX_VALUE; - int targetMaxScore = 0; - for (Map.Entry p : deletePaths.entrySet()) { - if(p.getValue().equals(obj)) { - targetScore = (targetScore >= proximity.apply(apiPath, p.getKey())) ? proximity.apply(apiPath, p.getKey()) : targetScore; - targetPath = (targetScore >= proximity.apply(apiPath, p.getKey())) ? p.getKey() : targetPath; - targetMaxScore = (targetMaxScore <= proximity.apply(apiPath, p.getKey())) ? proximity.apply(apiPath, p.getKey()) : targetScore; - logger.trace(proximity.apply(apiPath, p.getKey())+":"+p.getKey()); - logger.trace(proximity.apply(apiPath, p.getKey())+":"+apiPath); - } - } - return targetPath; - } - - private static String getUnrelatedObjectPaths(String obj, String apiPath) { - String targetPath = ""; - logger.trace("Obj:"+obj +"\n" + apiPath); - for (Map.Entry p : deletePaths.entrySet()) { - if(p.getValue().equals(obj)) { - logger.trace("p.getvalue:"+p.getValue()+"p.getkey:"+p.getKey()); - targetPath += ((targetPath.length() == 0 ? "" : "|") + p.getKey()); - logger.trace("Match:"+apiPath +"\n" + targetPath); - } - } - return targetPath; - } - } - - private static class PatchOperation { - String useOpId; - String xmlRootElementName; - String tag; - String path; - String pathParams; - - public PatchOperation(String useOpId, String xmlRootElementName, String tag, String path, String pathParams) { - super(); - this.useOpId = useOpId; - this.xmlRootElementName = xmlRootElementName; - this.tag = tag; - this.path = path; - this.pathParams = pathParams; - } - - @Override - public String toString() { - StringBuffer pathSb = new StringBuffer(); - pathSb.append(" patch:\n"); - pathSb.append(" tags:\n"); - pathSb.append(" - " + tag + "\n"); - - pathSb.append(" summary: update an existing " + xmlRootElementName + "\n"); - pathSb.append(" description: update an existing " + xmlRootElementName + "\n"); - pathSb.append(" operationId: Update" + useOpId + "\n"); - pathSb.append(" consumes:\n"); - pathSb.append(" - application/json\n"); - pathSb.append(" - application/xml\n"); - pathSb.append(" produces:\n"); - pathSb.append(" - application/json\n"); - pathSb.append(" - application/xml\n"); - pathSb.append(" responses:\n"); - pathSb.append(" \"default\":\n"); - pathSb.append(" " + responsesUrl); - - pathSb.append(" parameters:\n"); - pathSb.append(pathParams); // for nesting - pathSb.append(" - name: body\n"); - pathSb.append(" in: body\n"); - pathSb.append(" description: " + xmlRootElementName + " object that needs to be created or updated\n"); - pathSb.append(" required: true\n"); - pathSb.append(" schema:\n"); - pathSb.append(" $ref: \"patchSchema.yaml#/definitions/" + xmlRootElementName + "\"\n"); - - return pathSb.toString(); - } - public String toString1() { - StringBuffer pathSb = new StringBuffer(); - StringBuffer relationshipExamplesSb = new StringBuffer(); - if ( path.endsWith("/relationship") ) { - pathSb.append(" " + path + ":\n" ); - } - pathSb.append(" patch:\n"); - pathSb.append(" tags:\n"); - pathSb.append(" - " + tag + "\n"); - - if ( path.endsWith("/relationship") ) { - pathSb.append(" summary: see node definition for valid relationships\n"); - relationshipExamplesSb.append("[See Examples](apidocs/relations/"+GenerateXsd.apiVersion+"/"+useOpId+".json)"); - } else { - pathSb.append(" summary: update an existing " + xmlRootElementName + "\n"); - pathSb.append(" description: |\n"); - pathSb.append(" Update an existing " + xmlRootElementName + "\n"); - pathSb.append(" #\n"); - pathSb.append(" Note: Endpoints that are not devoted to object relationships support both PUT and PATCH operations.\n"); - pathSb.append(" The PUT operation will entirely replace an existing object.\n"); - 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"); - pathSb.append(" #\n"); - pathSb.append(" Other differences between PUT and PATCH are:\n"); - pathSb.append(" #\n"); - pathSb.append(" - For PATCH, you can send any of the values shown in sample REQUEST body. There are no required values.\n"); - pathSb.append(" - For PATCH, resource-id which is a required REQUEST body element for PUT, must not be sent.\n"); - pathSb.append(" - PATCH cannot be used to update relationship elements; there are dedicated PUT operations for this.\n"); - } - pathSb.append(" operationId: Update" + useOpId + "\n"); - pathSb.append(" consumes:\n"); - pathSb.append(" - application/json\n"); - pathSb.append(" - application/xml\n"); - pathSb.append(" produces:\n"); - pathSb.append(" - application/json\n"); - pathSb.append(" - application/xml\n"); - pathSb.append(" responses:\n"); - pathSb.append(" \"default\":\n"); - pathSb.append(" " + responsesUrl); - pathSb.append(" parameters:\n"); - pathSb.append(pathParams); // for nesting - pathSb.append(" - name: body\n"); - pathSb.append(" in: body\n"); - pathSb.append(" description: " + xmlRootElementName + " object that needs to be created or updated. "+relationshipExamplesSb.toString()+"\n"); - pathSb.append(" required: true\n"); - pathSb.append(" schema:\n"); - pathSb.append(" $ref: \"#/patchDefinitions/" + xmlRootElementName + "\"\n"); - return pathSb.toString(); - } - } - private static class PutOperation { - String useOpId; - String xmlRootElementName; - String tag; - String path; - String pathParams; - - public PutOperation(String useOpId, String xmlRootElementName, String tag, String path, String pathParams) { - super(); - this.useOpId = useOpId; - this.xmlRootElementName = xmlRootElementName; - this.tag = tag; - this.path = path; - this.pathParams = pathParams; - } - - @Override - public String toString() { - StringBuffer pathSb = new StringBuffer(); - StringBuffer relationshipExamplesSb = new StringBuffer(); - if ( path.endsWith("/relationship") ) { - pathSb.append(" " + path + ":\n" ); - } - pathSb.append(" put:\n"); - pathSb.append(" tags:\n"); - pathSb.append(" - " + tag + "\n"); - - if ( path.endsWith("/relationship") ) { - pathSb.append(" summary: see node definition for valid relationships\n"); - } else { - pathSb.append(" summary: create or update an existing " + xmlRootElementName + "\n"); - 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"); - } - relationshipExamplesSb.append("[Valid relationship examples shown here](apidocs/relations/"+GenerateXsd.apiVersion+"/"+useOpId.replace("RelationshipListRelationship", "")+".json)"); - pathSb.append(" operationId: createOrUpdate" + useOpId + "\n"); - pathSb.append(" consumes:\n"); - pathSb.append(" - application/json\n"); - pathSb.append(" - application/xml\n"); - pathSb.append(" produces:\n"); - pathSb.append(" - application/json\n"); - pathSb.append(" - application/xml\n"); - pathSb.append(" responses:\n"); - pathSb.append(" \"default\":\n"); - pathSb.append(" " + responsesUrl); - - pathSb.append(" parameters:\n"); - pathSb.append(pathParams); // for nesting - pathSb.append(" - name: body\n"); - pathSb.append(" in: body\n"); - pathSb.append(" description: " + xmlRootElementName + " object that needs to be created or updated. "+relationshipExamplesSb.toString()+"\n"); - pathSb.append(" required: true\n"); - pathSb.append(" schema:\n"); - pathSb.append(" $ref: \"#/definitions/" + xmlRootElementName + "\"\n"); - return pathSb.toString(); - } - public String tagRelationshipPathMapEntry() { - if ( path.endsWith("/relationship") ) { - putRelationPaths.put(useOpId, path); - } - return ""; - } - - } - - private static class GetOperation { - String useOpId; - String xmlRootElementName; - String tag; - String path; - @SuppressWarnings("unused") - String pathParams; - public GetOperation(String useOpId, String xmlRootElementName, String tag, String path, String pathParams) { - super(); - this.useOpId = useOpId; - this.xmlRootElementName = xmlRootElementName; - this.tag = tag; - this.path = path; - this.pathParams = pathParams; - } - @Override - public String toString() { - StringBuffer pathSb = new StringBuffer(); - pathSb.append(" " + path + ":\n" ); - pathSb.append(" get:\n"); - pathSb.append(" tags:\n"); - pathSb.append(" - " + tag + "\n"); - pathSb.append(" summary: returns " + xmlRootElementName + "\n"); - - pathSb.append(" description: returns " + xmlRootElementName + "\n"); - pathSb.append(" operationId: get" + useOpId + "\n"); - pathSb.append(" produces:\n"); - pathSb.append(" - application/json\n"); - pathSb.append(" - application/xml\n"); - - pathSb.append(" responses:\n"); - pathSb.append(" \"200\":\n"); - pathSb.append(" description: successful operation\n"); - pathSb.append(" schema:\n"); - pathSb.append(" $ref: \"#/getDefinitions/" + xmlRootElementName + "\"\n"); - pathSb.append(" \"default\":\n"); - pathSb.append(" " + responsesUrl); - - return pathSb.toString(); - } - - } - private static class DeleteOperation { - String useOpId; - String xmlRootElementName; - String tag; - String path; - String pathParams; - public DeleteOperation(String useOpId, String xmlRootElementName, String tag, String path, String pathParams) { - super(); - this.useOpId = useOpId; - this.xmlRootElementName = xmlRootElementName; - this.tag = tag; - this.path = path; - this.pathParams = pathParams; - } - @Override - public String toString() { - StringBuffer pathSb = new StringBuffer(); - pathSb.append(" delete:\n"); - pathSb.append(" tags:\n"); - pathSb.append(" - " + tag + "\n"); - pathSb.append(" summary: delete an existing " + xmlRootElementName + "\n"); - - pathSb.append(" description: delete an existing " + xmlRootElementName + "\n"); - - pathSb.append(" operationId: delete" + useOpId + "\n"); - pathSb.append(" consumes:\n"); - pathSb.append(" - application/json\n"); - pathSb.append(" - application/xml\n"); - pathSb.append(" produces:\n"); - pathSb.append(" - application/json\n"); - pathSb.append(" - application/xml\n"); - pathSb.append(" responses:\n"); - pathSb.append(" \"default\":\n"); - pathSb.append(" " + responsesUrl); - pathSb.append(" parameters:\n"); - - pathSb.append(pathParams); // for nesting - if ( !path.endsWith("/relationship") ) { - pathSb.append(" - name: resource-version\n"); - - pathSb.append(" in: query\n"); - pathSb.append(" description: resource-version for concurrency\n"); - pathSb.append(" required: true\n"); - pathSb.append(" type: string\n"); - } - return pathSb.toString(); - } - public String objectPathMapEntry() { - if (! path.endsWith("/relationship") ) { - deletePaths.put(path, xmlRootElementName); - } - return (xmlRootElementName+":"+path); - } - - } - private static boolean validVersion(String versionToGen) { if ("ALL".equalsIgnoreCase(versionToGen)) { @@ -738,6 +101,18 @@ public class GenerateXsd { return false; } + public static String getAPIVersion() { + return apiVersion; + } + + public static String getYamlDir() { + return yaml_dir; + } + + public static String getResponsesUrl() { + return responsesUrl; + } + public static void main(String[] args) throws IOException { String versionToGen = System.getProperty("gen_version").toLowerCase(); String fileTypeToGen = System.getProperty("gen_type").toLowerCase(); @@ -768,7 +143,7 @@ public class GenerateXsd { Collections.sort(versionsToGen); Collections.reverse(versionsToGen); } else { - versionsToGen.add(Version.valueOf(versionToGen)); + versionsToGen.add(Version.getVersion(versionToGen)); } //process file type System property @@ -795,31 +170,46 @@ public class GenerateXsd { String outfileName; File outfile; - String fileContent; + String fileContent = null; for (Version v : versionsToGen) { apiVersion = v.toString(); - logger.info("Generating " + apiVersion + " " + fileTypeToGen); + logger.debug("YAMLdir = "+yaml_dir); + logger.debug("Generating " + apiVersion + " " + fileTypeToGen); File oxm_file = new File(oxmPath + "aai_oxm_" + apiVersion + ".xml"); apiVersionFmt = "." + apiVersion + "."; generatedJavaType = new HashMap(); appliedPaths = new HashMap(); - putRelationPaths = new HashMap(); - deletePaths = new HashMap(); - + File edgeRuleFile = null; + logger.debug("user.dir = "+System.getProperty("user.dir")); + if(System.getProperty("user.dir") != null && !System.getProperty("user.dir").contains(normalStartDir)) { + edgeRuleFile = new File(normalStartDir + "/src/main/resources/dbedgerules/DbEdgeRules_" + apiVersion + ".json"); + } + else { + edgeRuleFile = new File("src/main/resources/dbedgerules/DbEdgeRules_" + apiVersion + ".json"); + } + if ( fileTypeToGen.equals(generateTypeXSD) ) { useAnnotationsInXsd = versionUsesAnnotations(apiVersion); outfileName = xsd_dir + "/aai_schema_" + apiVersion + "." + generateTypeXSD; - fileContent = processOxmFile(oxm_file, v, null); - } else if ( versionSupportsSwagger(apiVersion )) { - if(System.getProperty("user.dir") != null && !System.getProperty("user.dir").contains(normalStartDir)) { - outfileName = alt_yaml_dir; + try { + HTMLfromOXM swagger = new HTMLfromOXM(oxm_file, v); + fileContent = swagger.process(); + } catch(Exception e) { + logger.error( "Exception creating output file " + outfileName); + logger.error( e.getMessage()); + e.printStackTrace(); } - else { - outfileName = yaml_dir; + } else if ( versionSupportsSwagger(apiVersion )) { + outfileName = yaml_dir + "/aai_swagger_" + apiVersion + "." + generateTypeYAML; + try { + YAMLfromOXM swagger = new YAMLfromOXM(oxm_file, v, edgeRuleFile); + fileContent = swagger.process(); + } catch(Exception e) { + logger.error( "Exception creating output file " + outfileName); + logger.error( e.getMessage()); + e.printStackTrace(); } - outfileName = outfileName + "/aai_swagger_" + apiVersion + "." + generateTypeYAML; - fileContent = generateSwaggerFromOxmFile( oxm_file, null); } else { continue; } @@ -848,1310 +238,8 @@ public class GenerateXsd { bw.close(); } } - logger.info( "GeneratedXSD successful, saved in " + outfileName); - } - - } - - - public static String processJavaTypeElement( String javaTypeName, Element javaTypeElement) { - - String xmlRootElementName = null; - - NodeList parentNodes = javaTypeElement.getElementsByTagName("java-attributes"); - StringBuffer sb = new StringBuffer(); - if ( parentNodes.getLength() == 0 ) { - logger.trace( "no java-attributes for java-type " + javaTypeName); - return ""; - - } - - NamedNodeMap attributes; - - NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element"); - Element valElement = (Element) valNodes.item(0); - attributes = valElement.getAttributes(); - for ( int i = 0; i < attributes.getLength(); ++i ) { - Attr attr = (Attr) attributes.item(i); - String attrName = attr.getNodeName(); - - String attrValue = attr.getNodeValue(); - logger.trace("Found xml-root-element attribute: " + attrName + " with value: " + attrValue); - if ( attrName.equals("name")) - xmlRootElementName = attrValue; - } - - Element parentElement = (Element)parentNodes.item(0); - NodeList xmlElementNodes = parentElement.getElementsByTagName("xml-element"); - NodeList childNodes; - Element childElement; - String xmlElementWrapper; - - Element xmlElementElement; - String addType; - String elementName, elementType, elementIsKey, elementIsRequired, elementContainerType; - StringBuffer sb1 = new StringBuffer(); - if ( xmlElementNodes.getLength() > 0 ) { - sb1.append(" \n"); - sb1.append(" \n"); - NodeList properties = GenerateXsd.locateXmlProperties(javaTypeElement); - if (properties != null && useAnnotationsInXsd) { - logger.trace("properties found for: " + xmlRootElementName); - sb1.append(" \r\n"); - insertAnnotation(properties, false, "class", sb1, " "); - - sb1.append(" \r\n"); - } else { - logger.trace("no properties found for: " + xmlRootElementName); - } - sb1.append(" \n"); - for ( int i = 0; i < xmlElementNodes.getLength(); ++i ) { - - xmlElementElement = (Element)xmlElementNodes.item(i); - childNodes = xmlElementElement.getElementsByTagName("xml-element-wrapper"); - - xmlElementWrapper = null; - if ( childNodes.getLength() > 0 ) { - childElement = (Element)childNodes.item(0); - // get name - attributes = childElement.getAttributes(); - for ( int k = 0; k < attributes.getLength(); ++k ) { - Attr attr = (Attr) attributes.item(k); - String attrName = attr.getNodeName(); - String attrValue = attr.getNodeValue(); - if ( attrName.equals("name")) { - xmlElementWrapper = attrValue; - logger.trace("found xml-element-wrapper " + xmlElementWrapper); - } - } - - } - attributes = xmlElementElement.getAttributes(); - addType = null; - - - elementName = elementType = elementIsKey = elementIsRequired = elementContainerType = null; - for ( int j = 0; j < attributes.getLength(); ++j ) { - Attr attr = (Attr) attributes.item(j); - String attrName = attr.getNodeName(); - - String attrValue = attr.getNodeValue(); - logger.trace("For " + xmlRootElementName + " Found xml-element attribute: " + attrName + " with value: " + attrValue); - if ( attrName.equals("name")) { - elementName = attrValue; - } - if ( attrName.equals("type")) { - elementType = attrValue; - if ( attrValue.contains(apiVersionFmt) ) { - addType = attrValue.substring(attrValue.lastIndexOf('.')+1); - if ( !generatedJavaType.containsKey(addType) ) { - generatedJavaType.put(addType, attrValue); - sb.append(processJavaTypeElement( addType, getJavaTypeElement(addType) )); - } - } - - } - - if ( attrName.equals("xml-key")) { - elementIsKey = attrValue; - } - if ( attrName.equals("required")) { - elementIsRequired = attrValue; - } - if ( attrName.equals("container-type")) { - elementContainerType = attrValue; - } - } - - if ( xmlElementWrapper != null ) { - sb1.append(" \n"); - sb1.append(" \n"); - properties = GenerateXsd.locateXmlProperties(javaTypeElement); - if (properties != null && useAnnotationsInXsd) { - sb1.append(" \r\n"); - insertAnnotation(properties, false, "class", sb1, " "); - sb1.append(" \r\n"); - } else { - logger.trace("no properties found for: " + xmlElementWrapper); - } - sb1.append(" \n"); - sb1.append(" "); - } - if ("Nodes".equals(addType)) { - logger.trace("Skipping nodes, temporary testing"); - continue; - } - if ( addType != null ) { - sb1.append(" \n"); - if ( useAnnotationsInXsd ) { - sb1.append(" \r\n"); - insertAnnotation(properties, elementIsKey != null, "field", sb1, " "); - sb1.append(" \r\n"); - } - if (xmlElementWrapper== null) { - sb1.append(" \n"); - } - } else { - sb1.append("/>\n"); - } - if ( xmlElementWrapper != null ) { - sb1.append(" \n"); - sb1.append(" \n"); - sb1.append(" \n"); - } - } - sb1.append(" \n"); - sb1.append(" \n"); - sb1.append(" \n"); - } - - if ( xmlElementNodes.getLength() < 1 ) { - sb.append(" \n"); - sb.append(" \n"); - sb.append(" \n"); - sb.append(" \n"); - sb.append(" \n"); - generatedJavaType.put(javaTypeName, null); - return sb.toString(); - } - sb.append( sb1 ); - return sb.toString(); - } - - private static void insertAnnotation(NodeList items, boolean isKey, String target, StringBuffer sb1, String indentation) { - if (items != null || isKey) { - List metadata = new ArrayList<>(); - - String name = ""; - String value = ""; - Element item = null; - if (isKey) { - metadata.add("isKey=true"); - } - if (items != null) { - for (int i = 0; i < items.getLength(); i++) { - item = (Element)items.item(i); - name = item.getAttribute("name"); - value = item.getAttribute("value"); - if (name.equals("abstract")) { - name = "isAbstract"; - } else if (name.equals("extends")) { - name = "extendsFrom"; - } - metadata.add(name + "=\"" + value.replaceAll("&", "&") + "\""); - } - } - sb1.append( - indentation + " \r\n" + - indentation + " @org.onap.aai.annotations.Metadata(" + Joiner.on(",").join(metadata) + ")\r\n" + - indentation + " \r\n"); - } - - } - - private static Element getJavaTypeElement( String javaTypeName ) - { - - String attrName, attrValue; - Attr attr; - Element javaTypeElement; - for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) { - javaTypeElement = (Element) javaTypeNodes.item(i); - NamedNodeMap attributes = javaTypeElement.getAttributes(); - for ( int j = 0; j < attributes.getLength(); ++j ) { - attr = (Attr) attributes.item(j); - attrName = attr.getNodeName(); - attrValue = attr.getNodeValue(); - if ( attrName.equals("name") && attrValue.equals(javaTypeName)) - return javaTypeElement; - } - } - logger.error( "oxm file format error, missing java-type " + javaTypeName); - return (Element) null; - } - - private static Element getJavaTypeElementSwagger( String javaTypeName ) - { - - String attrName, attrValue; - Attr attr; - Element javaTypeElement; - for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) { - javaTypeElement = (Element) javaTypeNodes.item(i); - NamedNodeMap attributes = javaTypeElement.getAttributes(); - for ( int j = 0; j < attributes.getLength(); ++j ) { - attr = (Attr) attributes.item(j); - attrName = attr.getNodeName(); - attrValue = attr.getNodeValue(); - if ( attrName.equals("name") && attrValue.equals(javaTypeName)) - return javaTypeElement; - } - } - logger.error( "oxm file format error, missing java-type " + javaTypeName); - return (Element) null; - } - private static String getXmlRootElementName( String javaTypeName ) - { - - String attrName, attrValue; - Attr attr; - Element javaTypeElement; - for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) { - javaTypeElement = (Element) javaTypeNodes.item(i); - NamedNodeMap attributes = javaTypeElement.getAttributes(); - for ( int j = 0; j < attributes.getLength(); ++j ) { - attr = (Attr) attributes.item(j); - attrName = attr.getNodeName(); - attrValue = attr.getNodeValue(); - if ( attrName.equals("name") && attrValue.equals(javaTypeName)) { - NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element"); - Element valElement = (Element) valNodes.item(0); - attributes = valElement.getAttributes(); - for ( int k = 0; k < attributes.getLength(); ++k ) { - attr = (Attr) attributes.item(k); - attrName = attr.getNodeName(); - - attrValue = attr.getNodeValue(); - if ( attrName.equals("name")) - return (attrValue); - } - } - } - } - logger.error( "oxm file format error, missing java-type " + javaTypeName); - return null; - } - - - public static String processOxmFile( File oxmFile, Version v, String xml ) - { - if ( xml != null ){ - apiVersion = v.toString(); - useAnnotationsInXsd = true; - apiVersionFmt = "." + apiVersion + "."; - generatedJavaType = new HashMap<>(); - appliedPaths = new HashMap<>(); - } - StringBuilder sb = new StringBuilder(); - logger.trace("processing starts"); - sb.append("\n"); - String namespace = "org.onap"; - if (v.compareTo(Version.v11) < 0) { - namespace = "org.openecomp"; - } - if ( useAnnotationsInXsd ) { - sb.append("\n\n"); - } else { - - sb.append("\n\n"); - } - - try { - - DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); - dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); - Document doc; - - if ( xml == null ){ - doc = dBuilder.parse(oxmFile); - } else { - InputSource is = new InputSource(new StringReader(xml)); - doc = dBuilder.parse(is); - } - NodeList bindingsNodes = doc.getElementsByTagName("xml-bindings"); - Element bindingElement; - NodeList javaTypesNodes; - Element javaTypesElement; - - Element javaTypeElement; - - - if ( bindingsNodes == null || bindingsNodes.getLength() == 0 ) { - logger.error( "missing in " + oxmFile ); - return null; - } - - bindingElement = (Element) bindingsNodes.item(0); - javaTypesNodes = bindingElement.getElementsByTagName("java-types"); - if ( javaTypesNodes.getLength() < 1 ) { - logger.error( "missing in " + oxmFile ); - return null; - } - javaTypesElement = (Element) javaTypesNodes.item(0); - javaTypeNodes = javaTypesElement.getElementsByTagName("java-type"); - if ( javaTypeNodes.getLength() < 1 ) { - logger.error( "missing in " + oxmFile ); - return null; - } - - String javaTypeName; - String attrName, attrValue; - Attr attr; - for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) { - javaTypeElement = (Element) javaTypeNodes.item(i); - NamedNodeMap attributes = javaTypeElement.getAttributes(); - javaTypeName = null; - for ( int j = 0; j < attributes.getLength(); ++j ) { - attr = (Attr) attributes.item(j); - attrName = attr.getNodeName(); - attrValue = attr.getNodeValue(); - if ( attrName.equals("name")) - javaTypeName = attrValue; - } - if ( javaTypeName == null ) { - logger.error( " has no name attribute in " + oxmFile ); - return null; - } - if ("Nodes".equals(javaTypeName)) { - logger.debug("skipping Nodes entry (temporary feature)"); - continue; - } - if ( !generatedJavaType.containsKey(javaTypeName) ) { - generatedJavaType.put(javaTypeName, null); - sb.append(processJavaTypeElement( javaTypeName, javaTypeElement )); - } - } - - } catch (Exception e) { - e.printStackTrace(); - return null; - } - sb.append("\n"); - return sb.toString(); - } - - public static String toDeleteRules(String objectName) { - Collection toEdges = GenerateXsd.getEdgeRulesTO(objectName); - logger.debug("TO Edges count: "+toEdges.size()+" Object: "+objectName); - String prevent=null; - String also=null; - LinkedHashSet preventDelete = new LinkedHashSet(); - LinkedHashSet alsoDelete = new LinkedHashSet(); - for (EdgeDescription ed : toEdges) { - logger.debug("{“comment”: From = "+ed.getFrom()+" To: "+ed.getTo()+" Object: "+objectName); - logger.debug("{“comment”: Direction = "+ed.getDirection()+" PreventDelete: "+ed.getPreventDelete()+" DeleteOtherV: "+ed.getDeleteOtherV()+" Object: "+objectName); - if(ed.getPreventDelete().equals("IN") && ed.getTo().equals(objectName)) { - preventDelete.add(ed.getFrom().toUpperCase()); - } - if(ed.getDeleteOtherV().equals("IN") && ed.getTo().equals(objectName) ) { - alsoDelete.add(ed.getFrom().toUpperCase()); - } - } - if(preventDelete.size() > 0) { - prevent = " - "+objectName.toUpperCase()+" cannot be deleted if linked to "+String.join(",",preventDelete); - logger.info(prevent); - } - if(alsoDelete.size() > 0) { - also = " - "+objectName.toUpperCase()+" is DELETED when these are DELETED "+String.join(",",alsoDelete); - // This commented out line is better (gets who deletes what correct) but still not accurate. - //also = " - Deletion of an instance of "+objectName.toUpperCase()+" causes instances of these directly related types to be DELETED ["+String.join(",",alsoDelete)+"]"; - logger.info(also); - } - return String.join((prevent == null || also == null) ? "" : "\n", prevent == null ? "" : prevent, also == null ? "" : also)+((prevent == null && also == null) ? "" : "\n"); - } - - public static String fromDeleteRules(String objectName) { - Collection fromEdges = GenerateXsd.getEdgeRulesFROM(objectName); - LinkedHashSet preventDelete = new LinkedHashSet (); - LinkedHashSet alsoDelete = new LinkedHashSet (); - String prevent=null; - String also=null; - for (EdgeDescription ed : fromEdges) { - logger.debug("{“comment”: From = "+ed.getFrom()+" To: "+ed.getTo()+" Object: "+objectName); - logger.debug("{“comment”: Direction = "+ed.getDirection()+" PreventDelete: "+ed.getPreventDelete()+" DeleteOtherV: "+ed.getDeleteOtherV()+" Object: "+objectName); - if(ed.getPreventDelete().equals("OUT") && ed.getFrom().equals(objectName)) { - preventDelete.add(ed.getTo().toUpperCase()); - } - if(ed.getDeleteOtherV().equals("OUT") && ed.getFrom().equals(objectName) ) { - alsoDelete.add(ed.getTo().toUpperCase()); - } - } - if(preventDelete.size() > 0) { - prevent = " - "+objectName.toUpperCase()+" cannot be deleted if linked to "+String.join(",",preventDelete); - logger.info(prevent); - } - if(alsoDelete.size() > 0) { - also = " - "+objectName.toUpperCase()+" deletion means associated objects of these types are also DELETED:"+String.join(",",alsoDelete); - // This commented out line is better (gets who deletes what correct) but still not accurate. - //also = " - Deletion of an instance of "+objectName.toUpperCase()+" causes instances of these directly related types to be DELETED ["+String.join(",",alsoDelete)+"]"; - logger.info(also); - } - return String.join((prevent == null || also == null) ? "" : "\n", prevent == null ? "" : prevent, also == null ? "" : also)+((prevent == null && also == null) ? "" : "\n"); - } - - - private static boolean isStandardType( String elementType ) - { - switch ( elementType ) { - case "java.lang.String": - case "java.lang.Long": - case "java.lang.Integer": - case"java.lang.Boolean": - return true; - } - return false; - } - - private static Vector getIndexedProps( String attrValue ) - { - if ( attrValue == null ) - return null; - StringTokenizer st = new StringTokenizer( attrValue, ","); - if ( st.countTokens() == 0 ) - return null; - Vector result = new Vector(); - while ( st.hasMoreTokens()) { - result.add(st.nextToken()); - } - return result; - } - - /** - * Guaranteed to at least return non null but empty collection of edge descriptions - * @param nodeName name of the vertex whose edge relationships to return - * @return collection of node neighbors based on DbEdgeRules - **/ - private static Collection getEdgeRulesFromJson( String path, boolean skipMatch ) - { - - ArrayList result = new ArrayList<>(); - Iterator> edgeRulesIterator; - try { - - GenerateXsd x = new GenerateXsd(); - - List> inEdges = JsonPath.parse(jsonEdges).read(path); - - edgeRulesIterator = inEdges.iterator(); - Map edgeMap; - String fromNode; - String toNode; - String direction; - String multiplicity; - String isParent; - String hasDelTarget; - String deleteOtherV; - String preventDelete; - String description; - EdgeDescription edgeDes; - - while( edgeRulesIterator.hasNext() ){ - edgeMap = edgeRulesIterator.next(); - fromNode = (String)edgeMap.get("from"); - toNode = (String)edgeMap.get("to"); - if ( skipMatch ) { - if ( fromNode.equals(toNode)) { - continue; - } - } - edgeDes = x.new EdgeDescription(); - edgeDes.setRuleKey(fromNode + "|" + toNode); - edgeDes.setLabel((String)edgeMap.get("label")); - edgeDes.setTo((String)edgeMap.get("to")); - edgeDes.setFrom((String)edgeMap.get("from")); - direction = (String)edgeMap.get("direction"); - edgeDes.setDirection(direction); - multiplicity = (String)edgeMap.get("multiplicity"); - edgeDes.setMultiplicity(multiplicity); - isParent = (String)edgeMap.get(EdgeProperty.CONTAINS.toString()); - if ( "${direction}".equals(isParent)) { - edgeDes.setType(LineageType.PARENT); - } else { - edgeDes.setType(LineageType.UNRELATED); - } - hasDelTarget = (String)edgeMap.get(EdgeProperty.DELETE_OTHER_V.toString()); - deleteOtherV = (String)edgeMap.get(EdgeProperty.DELETE_OTHER_V.toString()); - edgeDes.setDeleteOtherV(deleteOtherV); - edgeDes.setHasDelTarget(hasDelTarget); - preventDelete = (String)edgeMap.get(EdgeProperty.PREVENT_DELETE.toString()); - edgeDes.setPreventDelete(preventDelete); - description = (String)edgeMap.get(EdgeProperty.DESCRIPTION.toString()); - edgeDes.setDescription(description); - - result.add(edgeDes); - logger.debug("Edge: "+edgeDes.getRuleKey()); - } - } catch (Exception ex) { - ex.printStackTrace(); - } - return result; - - } - - /** - * Guaranteed to at least return non null but empty collection of edge descriptions - * @param nodeName name of the vertex whose edge relationships to return - * @return collection of node neighbors based on DbEdgeRules - **/ - private static Collection getEdgeRules( String nodeName ) - { - String fromRulesPath = "$['rules'][?(@['from']=='" + nodeName + "')]"; - String toRulesPath = "$['rules'][?(@['to']=='" + nodeName + "')]"; - Collection fromEdges = getEdgeRulesFromJson( fromRulesPath, false ); - Collection edges = getEdgeRulesFromJson( toRulesPath, true ); - edges.addAll(fromEdges); - return edges; - } - - private static Collection getEdgeRulesTO( String nodeName ) - { - String toRulesPath = "$['rules'][?(@['to']=='" + nodeName + "')]"; - Collection edges = getEdgeRulesFromJson( toRulesPath, true ); - return edges; - } - - private static Collection getEdgeRulesFROM( String nodeName ) - { - String fromRulesPath = "$['rules'][?(@['from']=='" + nodeName + "')]"; - Collection edges = getEdgeRulesFromJson( fromRulesPath, true ); - return edges; - } - public static String processJavaTypeElementSwagger( String javaTypeName, Element javaTypeElement, - StringBuffer pathSb, StringBuffer definitionsSb, String path, String tag, String opId, - String getItemName, StringBuffer pathParams, String queryParams, String validEdges) { - - String xmlRootElementName = null; - StringBuilder definitionsLocalSb = new StringBuilder(256); - - String useTag = null; - String useOpId = null; - - if ( tag != null ) { - switch ( tag ) { - case "Network": - case "ServiceDesignAndCreation": - case "Business": - case "LicenseManagement": - case "CloudInfrastructure": - break; - default: - return null; - } - } - - if ( !javaTypeName.equals("Inventory") ) { - if ( javaTypeName.equals("AaiInternal")) - return null; - if ( opId == null ) - useOpId = javaTypeName; - else - useOpId = opId + javaTypeName; - if ( tag == null ) - useTag = javaTypeName; - } - - NodeList parentNodes = javaTypeElement.getElementsByTagName("java-attributes"); - - if ( parentNodes.getLength() == 0 ) { - logger.trace( "no java-attributes for java-type " + javaTypeName); - return ""; - } - - NamedNodeMap attributes; - - NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element"); - Element valElement = (Element) valNodes.item(0); - attributes = valElement.getAttributes(); - for ( int i = 0; i < attributes.getLength(); ++i ) { - Attr attr = (Attr) attributes.item(i); - String attrName = attr.getNodeName(); - - String attrValue = attr.getNodeValue(); - logger.trace("Found xml-root-element attribute: " + attrName + " with value: " + attrValue); - if ( attrName.equals("name")) - xmlRootElementName = attrValue; - } - - NodeList childNodes; - Element childElement; - NodeList xmlPropNodes = javaTypeElement.getElementsByTagName("xml-properties"); - Element xmlPropElement; - String pathDescriptionProperty = null; - - - Vector indexedProps = null; - - if ( xmlPropNodes.getLength() > 0 ) { - - for ( int i = 0; i < xmlPropNodes.getLength(); ++i ) { - xmlPropElement = (Element)xmlPropNodes.item(i); - if ( !xmlPropElement.getParentNode().isSameNode(javaTypeElement)) - continue; - childNodes = xmlPropElement.getElementsByTagName("xml-property"); - - if ( childNodes.getLength() > 0 ) { - for ( int j = 0; j < childNodes.getLength(); ++j ) { - childElement = (Element)childNodes.item(j); - // get name - int useValue = VALUE_NONE; - attributes = childElement.getAttributes(); - for ( int k = 0; k < attributes.getLength(); ++k ) { - Attr attr = (Attr) attributes.item(k); - String attrName = attr.getNodeName(); - String attrValue = attr.getNodeValue(); - if ( attrName == null || attrValue == null ) - continue; - if ( attrName.equals("name") && attrValue.equals("description")) { - useValue = VALUE_DESCRIPTION; - } - if ( useValue == VALUE_DESCRIPTION && attrName.equals("value")) { - pathDescriptionProperty = attrValue; - } - if ( attrValue.equals("indexedProps")) { - useValue = VALUE_INDEXED_PROPS; - } - if ( useValue == VALUE_INDEXED_PROPS && attrName.equals("value")) { - indexedProps = getIndexedProps( attrValue ); - } - } - } - } - } - } - logger.trace("javaTypeName " + javaTypeName + " description " + pathDescriptionProperty); - - Element parentElement = (Element)parentNodes.item(0); - NodeList xmlElementNodes = parentElement.getElementsByTagName("xml-element"); - - - String attrDescription = null; - - Element xmlElementElement; - String addType = null; - String elementType = null, elementIsKey = null, elementIsRequired, elementContainerType = null; - String elementName = null; - StringBuffer sbParameters = new StringBuffer(); - - StringBuffer sbRequired = new StringBuffer(); - int requiredCnt = 0; - int propertyCnt = 0; - StringBuffer sbProperties = new StringBuffer(); - StringBuffer sbIndexedParams = new StringBuffer(); - - - StringTokenizer st; - if ( xmlRootElementName.equals("inventory")) - path = ""; - else if ( path == null ) - path = "/" + xmlRootElementName; - else - path += "/" + xmlRootElementName; - st = new StringTokenizer(path, "/"); - boolean genPath = false; - - if ( st.countTokens() > 1 && getItemName == null ) { - if ( appliedPaths.containsKey(path)) - return null; - appliedPaths.put(path, xmlRootElementName); - genPath = true; - if ( path.contains("/relationship/") ) { // filter paths with relationship-list - genPath = false; - } - if ( path.endsWith("/relationship-list")) { - genPath = false; - } - - } - - Vector addTypeV = null; - if ( xmlElementNodes.getLength() > 0 ) { - - for ( int i = 0; i < xmlElementNodes.getLength(); ++i ) { - xmlElementElement = (Element)xmlElementNodes.item(i); - if ( !xmlElementElement.getParentNode().isSameNode(parentElement)) - continue; - - valNodes = xmlElementElement.getElementsByTagName("xml-properties"); - attrDescription = null; - if ( valNodes.getLength() > 0 ) { - for ( int j = 0; j < valNodes.getLength(); ++j ) { - valElement = (Element)valNodes.item(j); - if ( !valElement.getParentNode().isSameNode(xmlElementElement)) - continue; - childNodes = valElement.getElementsByTagName("xml-property"); - if ( childNodes.getLength() > 0 ) { - childElement = (Element)childNodes.item(0); - // get name - attributes = childElement.getAttributes(); - attrDescription = null; - boolean useValue = false; - for ( int k = 0; k < attributes.getLength(); ++k ) { - Attr attr = (Attr) attributes.item(k); - String attrName = attr.getNodeName(); - String attrValue = attr.getNodeValue(); - if ( attrName.equals("name") && attrValue.equals("description")) { - useValue = true; - } - if ( useValue && attrName.equals("value")) { - attrDescription = attrValue; - } - } - - } - } - } - - attributes = xmlElementElement.getAttributes(); - addTypeV = null; // vector of 1 - addType = null; - - elementName = elementType = elementIsKey = elementIsRequired = elementContainerType = null; - for ( int j = 0; j < attributes.getLength(); ++j ) { - Attr attr = (Attr) attributes.item(j); - String attrName = attr.getNodeName(); - - String attrValue = attr.getNodeValue(); - logger.trace("For " + xmlRootElementName + " Found xml-element attribute: " + attrName + " with value: " + attrValue); - if ( attrName.equals("name")) { - elementName = attrValue; - - } - if ( attrName.equals("type") && getItemName == null ) { - elementType = attrValue; - if ( attrValue.contains(apiVersionFmt) ) { - addType = attrValue.substring(attrValue.lastIndexOf('.')+1); - if ( addTypeV == null ) - addTypeV = new Vector(); - addTypeV.add(addType); - } - - } - if ( attrName.equals("xml-key")) { - elementIsKey = attrValue; - path += "/{" + elementName + "}"; - } - if ( attrName.equals("required")) { - elementIsRequired = attrValue; - } - if ( attrName.equals("container-type")) { - elementContainerType = attrValue; - } - } - if ( getItemName != null ) { - if ( getItemName.equals("array") ) { - if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) { - logger.trace( " returning array " + elementName ); - return elementName; - } - - } else { // not an array check - if ( elementContainerType == null || !elementContainerType.equals("java.util.ArrayList")) { - logger.trace( " returning object " + elementName ); - return elementName; - } - - } - logger.trace( " returning null" ); - return null; - } - if ( elementIsRequired != null ) { - if ( requiredCnt == 0 ) - sbRequired.append(" required:\n"); - ++requiredCnt; - if ( addTypeV != null ) { - for ( int k = 0; k < addTypeV.size(); ++i ) { - sbRequired.append(" - " + getXmlRootElementName(addTypeV.elementAt(k)) + ":\n"); - } - } else - sbRequired.append(" - " + elementName + "\n"); - - } - - if ( elementIsKey != null ) { - sbParameters.append((" - name: " + elementName + "\n")); - sbParameters.append((" in: path\n")); - if ( attrDescription != null && attrDescription.length() > 0 ) - sbParameters.append((" description: " + attrDescription + "\n")); - sbParameters.append((" required: true\n")); - if ( elementType.equals("java.lang.String")) - sbParameters.append(" type: string\n"); - if ( elementType.equals("java.lang.Long")) { - sbParameters.append(" type: integer\n"); - sbParameters.append(" format: int64\n"); - } - if ( elementType.equals("java.lang.Integer")) { - sbParameters.append(" type: integer\n"); - sbParameters.append(" format: int32\n"); - } - if ( elementType.equals("java.lang.Boolean")) { - sbParameters.append(" type: boolean\n"); - } - if(StringUtils.isNotBlank(elementName)) { - sbParameters.append(" example: "+"__"+elementName.toUpperCase()+"__"+"\n"); - } - } else if ( indexedProps != null - && indexedProps.contains(elementName ) ) { - sbIndexedParams.append((" - name: " + elementName + "\n")); - sbIndexedParams.append((" in: query\n")); - if ( attrDescription != null && attrDescription.length() > 0 ) - sbIndexedParams.append((" description: " + attrDescription + "\n")); - sbIndexedParams.append((" required: false\n")); - if ( elementType.equals("java.lang.String")) - sbIndexedParams.append(" type: string\n"); - if ( elementType.equals("java.lang.Long")) { - sbIndexedParams.append(" type: integer\n"); - sbIndexedParams.append(" format: int64\n"); - } - if ( elementType.equals("java.lang.Integer")) { - sbIndexedParams.append(" type: integer\n"); - sbIndexedParams.append(" format: int32\n"); - } - if ( elementType.equals("java.lang.Boolean")) - sbIndexedParams.append(" type: boolean\n"); - } - if ( isStandardType(elementType)) { - sbProperties.append(" " + elementName + ":\n"); - ++propertyCnt; - sbProperties.append(" type: "); - - if ( elementType.equals("java.lang.String")) - sbProperties.append("string\n"); - else if ( elementType.equals("java.lang.Long")) { - sbProperties.append("integer\n"); - sbProperties.append(" format: int64\n"); - } - else if ( elementType.equals("java.lang.Integer")){ - sbProperties.append("integer\n"); - sbProperties.append(" format: int32\n"); - } - else if ( elementType.equals("java.lang.Boolean")) - sbProperties.append("boolean\n"); - if ( attrDescription != null && attrDescription.length() > 0 ) - sbProperties.append(" description: " + attrDescription + "\n"); - } - - if ( addTypeV != null ) { - StringBuffer newPathParams = null; - if ( pathParams != null ) { - newPathParams = new StringBuffer(); - newPathParams.append(pathParams); - } - if ( sbParameters.toString().length() > 0 ) { - if ( newPathParams == null ) - newPathParams = new StringBuffer(); - newPathParams.append(sbParameters); - } - String newQueryParams = null; - if ( sbIndexedParams.toString().length() > 0 ) { - if ( queryParams == null ) - newQueryParams = sbIndexedParams.toString(); - else - newQueryParams = queryParams + sbIndexedParams.toString(); - } else { - newQueryParams = queryParams; - } - for ( int k = 0; k < addTypeV.size(); ++k ) { - addType = addTypeV.elementAt(k); - - if ( opId == null || !opId.contains(addType)) { - processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType), - pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId, null, - newPathParams, newQueryParams, validEdges); - } - // need item name of array - String itemName = processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType), - pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId, - "array", null, null, null ); - - if ( itemName != null ) { - if ( addType.equals("AaiInternal") ) { - logger.debug( "addType AaiInternal, skip properties"); - - } else if ( getItemName == null) { - ++propertyCnt; - sbProperties.append(" " + getXmlRootElementName(addType) + ":\n"); - sbProperties.append(" type: array\n items:\n"); - sbProperties.append(" $ref: \"#/definitions/" + (itemName == "" ? "aai-internal" : itemName) + "\"\n"); - if ( attrDescription != null && attrDescription.length() > 0 ) - sbProperties.append(" description: " + attrDescription + "\n"); - } - } else { - if ( elementContainerType != null && elementContainerType.equals("java.util.ArrayList")) { - // need properties for getXmlRootElementName(addType) - newPathParams = null; - if ( pathParams != null ) { - newPathParams = new StringBuffer(); - newPathParams.append(pathParams); - } - if ( sbParameters.toString().length() > 0 ) { - if ( newPathParams == null ) - newPathParams = new StringBuffer(); - newPathParams.append(sbParameters); - } - newQueryParams = null; - if ( sbIndexedParams.toString().length() > 0 ) { - if ( queryParams == null ) - newQueryParams = sbIndexedParams.toString(); - else - newQueryParams = queryParams + sbIndexedParams.toString(); - } else { - newQueryParams = queryParams; - } - processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType), - pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId, - null, newPathParams, newQueryParams, validEdges ); - sbProperties.append(" " + getXmlRootElementName(addType) + ":\n"); - sbProperties.append(" type: array\n items: \n"); - sbProperties.append(" $ref: \"#/definitions/" + getXmlRootElementName(addType) + "\"\n"); - } else { - sbProperties.append(" " + getXmlRootElementName(addType) + ":\n"); - sbProperties.append(" type: object\n"); - sbProperties.append(" $ref: \"#/definitions/" + getXmlRootElementName(addType) + "\"\n"); - } - if ( attrDescription != null && attrDescription.length() > 0 ) - sbProperties.append(" description: " + attrDescription + "\n"); - ++propertyCnt; - } - } - } - } - } - if ( genPath ) { - if ( !path.endsWith("/relationship") ) { - GetOperation get = new GetOperation(useOpId, xmlRootElementName, tag, path, pathParams == null ? "" : pathParams.toString()); - pathSb.append(get.toString()); -// if ( path.indexOf('{') > 0 ) { - - if ( sbParameters.toString().length() > 0 ) { - if ( pathParams == null ) - pathParams = new StringBuffer(); - pathParams.append(sbParameters); - } - if ( pathParams != null) { - pathSb.append(" parameters:\n"); - pathSb.append(pathParams); - } else - logger.trace( "null pathParams for " + useOpId); - if ( sbIndexedParams.toString().length() > 0 ) { - if ( queryParams == null ) - queryParams = sbIndexedParams.toString(); - else - queryParams = queryParams + sbIndexedParams.toString(); - } - if ( queryParams != null ) { - if ( pathParams == null ) { - pathSb.append(" parameters:\n"); - } - pathSb.append(queryParams); - } -// } - } - boolean skipPutDelete = false; // no put or delete for "all" - if ( !path.endsWith("/relationship") ) { - if ( !path.endsWith("}") ){ - skipPutDelete = true; - } - - } - if ( path.indexOf('{') > 0 && !opId.startsWith("Search") &&!skipPutDelete) { - // add PUT - PutOperation put = new PutOperation(useOpId, xmlRootElementName, tag, path, pathParams == null ? "" : pathParams.toString()); - pathSb.append(put.toString()); - if ( !path.endsWith("/relationship") ) { - PatchOperation patch = new PatchOperation(useOpId, xmlRootElementName, tag, path, pathParams == null ? "" : pathParams.toString()); - pathSb.append(patch.toString1()); - } - logger.debug(put.tagRelationshipPathMapEntry()); - - // add DELETE - DeleteOperation del = new DeleteOperation(useOpId, xmlRootElementName, tag, path, pathParams == null ? "" : pathParams.toString()); - pathSb.append(del.toString()); - logger.debug(del.objectPathMapEntry()); - } - - } - if ( generatedJavaType.containsKey(xmlRootElementName) ) { - return null; - } - - definitionsSb.append(" " + xmlRootElementName + ":\n"); - definitionsLocalSb.append(" " + xmlRootElementName + ":\n"); - Collection edges = getEdgeRules(xmlRootElementName ); - - if ( edges.size() > 0 ) { - StringBuffer sbEdge = new StringBuffer(); - sbEdge.append(" ###### Related Nodes\n"); - for (EdgeDescription ed : edges) { - if ( ed.getRuleKey().startsWith(xmlRootElementName)) { - sbEdge.append(" - TO ").append(ed.getRuleKey().substring(ed.getRuleKey().indexOf("|")+1)); - sbEdge.append(ed.getRelationshipDescription("TO", xmlRootElementName)); - sbEdge.append("\n"); - } - } - for (EdgeDescription ed : edges) { - if ( ed.getRuleKey().endsWith(xmlRootElementName)) { - sbEdge.append(" - FROM ").append(ed.getRuleKey().substring(0, ed.getRuleKey().indexOf("|"))); - sbEdge.append(ed.getRelationshipDescription("FROM", xmlRootElementName)); - sbEdge.append("\n"); - } - } - // Delete rule processing is incorrect. One cannot express the delete rules in isolation from the - // specific edge. Take the case of allotted-resource and service-instance. When the service-instance owns the - // allotted-resource, yes, it deletes it. But when the service-instance only uses the allotted-resource, the deletion - // of the service instance does not cause the deletion of the allotted-resource. - // I put some lines into the toDeleteRules and fromDeleteRules to correct things to an extent, but it's still - // not right. - sbEdge.append(toDeleteRules(xmlRootElementName)); - sbEdge.append(fromDeleteRules(xmlRootElementName)); - validEdges = sbEdge.toString(); - } - - // Handle description property. Might have a description OR valid edges OR both OR neither. - // Only put a description: tag if there is at least one. - if (pathDescriptionProperty != null || validEdges != null) { - definitionsSb.append(" description: |\n"); - definitionsLocalSb.append(" description: |\n"); - - if ( pathDescriptionProperty != null ) { - definitionsSb.append(" " + pathDescriptionProperty + "\n" ); - definitionsLocalSb.append(" " + pathDescriptionProperty + "\n" ); - } - if (validEdges != null) { - definitionsSb.append(validEdges); - definitionsLocalSb.append(validEdges); - } - } - - if ( requiredCnt > 0 ) { - definitionsSb.append(sbRequired); - definitionsLocalSb.append(sbRequired); - } - - if ( propertyCnt > 0 ) { - definitionsSb.append(" properties:\n"); - definitionsSb.append(sbProperties); - definitionsLocalSb.append(" properties:\n"); - definitionsLocalSb.append(sbProperties); - } - try { - javaTypeDefinitions.put(xmlRootElementName, definitionsLocalSb.toString()); - } catch (Exception e) { - e.printStackTrace(); - } - generatedJavaType.put(xmlRootElementName, null); - return null; - } - - public static void generateRelations() { - if(putRelationPaths == null) - return; - putRelationPaths.forEach((k,v)->{ - 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")); - logger.debug("apiPath(Operation): "+v); - logger.debug("Target object: "+v.replace("/relationship-list/relationship", "")); - logger.debug("Relations: "); - PutRelationPathSet prp = new PutRelationPathSet(k, v); - prp.process(); - }); - } - - public static String generateSwaggerFromOxmFile( File oxmFile, String xml ) - { - if ( xml != null ){ - apiVersion = Version.getLatest().toString(); - apiVersionFmt = "." + apiVersion + "."; - generatedJavaType = new HashMap<>(); - appliedPaths = new HashMap<>(); - responsesUrl = "Description: response-label\n"; - } - StringBuffer sb = new StringBuffer(); - sb.append("swagger: \"2.0\"\ninfo:\n "); - sb.append("description: |"); - sb.append("\n\n [Differences versus the previous schema version]("+"apidocs/aai_swagger_" + apiVersion + ".diff)"); - 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"); - sb.append(" title: Active and Available Inventory REST API\n"); - sb.append(" license:\n name: Apache 2.0\n url: http://www.apache.org/licenses/LICENSE-2.0.html\n"); - sb.append(" contact:\n name:\n url:\n email:\n"); - sb.append("host:\nbasePath: /aai/" + apiVersion + "\n"); - sb.append("schemes:\n - https\npaths:\n"); - - try { - File initialFile; - if(System.getProperty("user.dir") != null && !System.getProperty("user.dir").contains(normalStartDir)) { - initialFile = new File(normalStartDir + "/src/main/resources/dbedgerules/DbEdgeRules_" + apiVersion + ".json"); - } - else { - initialFile = new File("src/main/resources/dbedgerules/DbEdgeRules_" + apiVersion + ".json"); - } - InputStream is = new FileInputStream(initialFile); - - Scanner scanner = new Scanner(is); - jsonEdges = scanner.useDelimiter("\\Z").next(); - scanner.close(); - is.close(); - - DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); - dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); - Document doc; - - if ( xml == null ) { - doc = dBuilder.parse(oxmFile); - } else { - InputSource isInput = new InputSource(new StringReader(xml)); - doc = dBuilder.parse(isInput); - } - - NodeList bindingsNodes = doc.getElementsByTagName("xml-bindings"); - Element bindingElement; - NodeList javaTypesNodes; - Element javaTypesElement; - - Element javaTypeElement; - - - if ( bindingsNodes == null || bindingsNodes.getLength() == 0 ) { - logger.error( "missing in " + oxmFile ); - return null; - } - - bindingElement = (Element) bindingsNodes.item(0); - javaTypesNodes = bindingElement.getElementsByTagName("java-types"); - if ( javaTypesNodes.getLength() < 1 ) { - logger.error( "missing in " + oxmFile ); - return null; - } - javaTypesElement = (Element) javaTypesNodes.item(0); - - javaTypeNodes = javaTypesElement.getElementsByTagName("java-type"); - if ( javaTypeNodes.getLength() < 1 ) { - logger.error( "missing in " + oxmFile ); - return null; - } - - String javaTypeName; - String attrName, attrValue; - Attr attr; - StringBuffer pathSb = new StringBuffer(); - - StringBuffer definitionsSb = new StringBuffer(); - for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) { - javaTypeElement = (Element) javaTypeNodes.item(i); - NamedNodeMap attributes = javaTypeElement.getAttributes(); - javaTypeName = null; - for ( int j = 0; j < attributes.getLength(); ++j ) { - attr = (Attr) attributes.item(j); - attrName = attr.getNodeName(); - attrValue = attr.getNodeValue(); - if ( attrName.equals("name")) - javaTypeName = attrValue; - } - if ( javaTypeName == null ) { - logger.error( " has no name attribute in " + oxmFile ); - return null; - } - if ( !generatedJavaType.containsKey(getXmlRootElementName(javaTypeName)) ) { - - processJavaTypeElementSwagger( javaTypeName, javaTypeElement, pathSb, - definitionsSb, null, null, null, null, null, null, null); - } - } - sb.append(pathSb); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - //append definitions - sb.append("definitions:\n"); - Map sortedJavaTypeDefinitions = new TreeMap(javaTypeDefinitions); - for (Map.Entry entry : sortedJavaTypeDefinitions.entrySet()) { - logger.debug("Key: "+entry.getKey()+"Test: "+ (entry.getKey() == "relationship")); - if(entry.getKey().matches("relationship")) { - String jb=entry.getValue(); - logger.debug("Value: "+jb); - int ndx=jb.indexOf("related-to-property:"); - if(ndx > 0) { - jb=jb.substring(0, ndx); - jb=jb.replaceAll(" +$", ""); - } - logger.debug("Value-after: "+jb); - sb.append(jb); - continue; - } - sb.append(entry.getValue()); - } - - sb.append("patchDefinitions:\n"); - for (Map.Entry entry : sortedJavaTypeDefinitions.entrySet()) { - String jb=entry.getValue().replaceAll("/definitions/", "/patchDefinitions/"); - int ndx=jb.indexOf("relationship-list:"); - if(ndx > 0) { - jb=jb.substring(0, ndx); - jb=jb.replaceAll(" +$", ""); - } - int ndx1=jb.indexOf("resource-version:"); - logger.debug("Key: "+entry.getKey()+" index: " + ndx1); - logger.debug("Value: "+jb); - if(ndx1 > 0) { - jb=jb.substring(0, ndx1); - jb=jb.replaceAll(" +$", ""); - } - logger.debug("Value-after: "+jb); - sb.append(jb); - } - - sb.append("getDefinitions:\n"); - for (Map.Entry entry : sortedJavaTypeDefinitions.entrySet()) { - String jb=entry.getValue().replaceAll("/definitions/", "/getDefinitions/"); - sb.append(jb); - } - - logger.debug("generated " + sb.toString()); - generateRelations(); - return sb.toString(); - } - - private static NodeList locateXmlProperties(Element element) { - XPathExpression expr; - NodeList result = null; - try { - expr = xpath.compile("xml-properties"); - if (expr != null) { - Object nodeset = expr.evaluate(element, XPathConstants.NODESET); - if (nodeset != null) { - NodeList nodes = (NodeList) nodeset; - if (nodes != null && nodes.getLength() > 0) { - Element xmlProperty = (Element)nodes.item(0); - result = xmlProperty.getElementsByTagName("xml-property"); - } - } - } - } catch (XPathExpressionException e) { - e.printStackTrace(); + logger.debug( "GeneratedXSD successful, saved in " + outfileName); } - return result; } } \ No newline at end of file diff --git a/aai-core/src/main/java/org/onap/aai/util/genxsd/DeleteFootnoteSet.java b/aai-core/src/main/java/org/onap/aai/util/genxsd/DeleteFootnoteSet.java new file mode 100644 index 00000000..dca5b7ce --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/util/genxsd/DeleteFootnoteSet.java @@ -0,0 +1,57 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.util.genxsd; + +import java.util.Set; +import java.util.TreeSet; + +public class DeleteFootnoteSet { + protected Set footnotes = new TreeSet<>(); + protected String targetNode = ""; + public DeleteFootnoteSet(String targetNode) { + super(); + this.targetNode = targetNode == null ? "" : targetNode; + } + + public void add(String s ) { + String fullnote=null; + if("(1)".equals(s)) { + fullnote = s+" IF this "+targetNode.toUpperCase()+" node is deleted, this FROM node is DELETED also"; + } else if("(2)".equals(s)) { + fullnote = s+" IF this "+targetNode.toUpperCase()+" node is deleted, this TO node is DELETED also"; + } else if("(3)".equals(s)) { + fullnote = s+" IF this FROM node is deleted, this "+targetNode.toUpperCase()+" is DELETED also"; + } else if("(4)".equals(s)) { + fullnote = s+" IF this TO node is deleted, this "+targetNode.toUpperCase()+" is DELETED also"; + } else if(s.contains(targetNode.toUpperCase())) { + fullnote = s; + } else { + return; + } + footnotes.add(fullnote); + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + if(footnotes.size() > 0) sb.append("\n -"); + sb.append(String.join("\n -", footnotes)+"\n"); + return sb.toString(); + } +} diff --git a/aai-core/src/main/java/org/onap/aai/util/genxsd/DeleteOperation.java b/aai-core/src/main/java/org/onap/aai/util/genxsd/DeleteOperation.java new file mode 100644 index 00000000..0651566e --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/util/genxsd/DeleteOperation.java @@ -0,0 +1,106 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.util.genxsd; + +import org.apache.commons.lang3.StringUtils; +import org.onap.aai.util.GenerateXsd; + +import java.util.HashMap; +import java.util.StringTokenizer; + +public class DeleteOperation { + private String useOpId; + private String xmlRootElementName; + private String tag; + private String path; + private String pathParams; + + public static HashMap deletePaths = new HashMap(); + public DeleteOperation(String useOpId, String xmlRootElementName, String tag, String path, String pathParams) { + super(); + this.useOpId = useOpId; + this.xmlRootElementName = xmlRootElementName; + this.tag = tag; + this.path = path; + this.pathParams = pathParams; + } + @Override + public String toString() { + StringTokenizer st; + st = new StringTokenizer(path, "/"); + //a valid tag is necessary + if ( StringUtils.isEmpty(tag) ) { + return ""; + } + if ( path.contains("/relationship/") ) { // filter paths with relationship-list + return ""; + } + if ( path.endsWith("/relationship-list")) { + return ""; + } + if ( path.startsWith("/search")) { + return ""; + } + //All Delete operation paths end with "relationship" + //or there is a parameter at the end of the path + //and there is a parameter in the path + + if ( !path.endsWith("/relationship") && !path.endsWith("}") ) { + return ""; + } + StringBuffer pathSb = new StringBuffer(); + pathSb.append(" delete:\n"); + pathSb.append(" tags:\n"); + pathSb.append(" - " + tag + "\n"); + pathSb.append(" summary: delete an existing " + xmlRootElementName + "\n"); + + pathSb.append(" description: delete an existing " + xmlRootElementName + "\n"); + + pathSb.append(" operationId: delete" + useOpId + "\n"); + pathSb.append(" consumes:\n"); + pathSb.append(" - application/json\n"); + pathSb.append(" - application/xml\n"); + pathSb.append(" produces:\n"); + pathSb.append(" - application/json\n"); + pathSb.append(" - application/xml\n"); + pathSb.append(" responses:\n"); + pathSb.append(" \"default\":\n"); + pathSb.append(" " + GenerateXsd.getResponsesUrl()); + pathSb.append(" parameters:\n"); + + pathSb.append(pathParams); // for nesting + if ( !path.endsWith("/relationship") ) { + pathSb.append(" - name: resource-version\n"); + + pathSb.append(" in: query\n"); + pathSb.append(" description: resource-version for concurrency\n"); + pathSb.append(" required: true\n"); + pathSb.append(" type: string\n"); + } + this.objectPathMapEntry(); + return pathSb.toString(); + } + public String objectPathMapEntry() { + if (! path.endsWith("/relationship") ) { + deletePaths.put(path, xmlRootElementName); + } + return (xmlRootElementName+":"+path); + } + } \ No newline at end of file diff --git a/aai-core/src/main/java/org/onap/aai/util/genxsd/EdgeDescription.java b/aai-core/src/main/java/org/onap/aai/util/genxsd/EdgeDescription.java new file mode 100644 index 00000000..6e1294ab --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/util/genxsd/EdgeDescription.java @@ -0,0 +1,242 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.util.genxsd; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class EdgeDescription { + private static final Logger logger = LoggerFactory.getLogger("EdgeDescription.class"); + + public static enum LineageType { + PARENT, CHILD, UNRELATED; + } + private String ruleKey; + private String to; + private String from; + private LineageType type = LineageType.UNRELATED; + private String direction; + private String multiplicity; + private String preventDelete; + private String deleteOtherV; + private String label; + private String description; + /** + * @return the deleteOtherV + */ + public String getDeleteOtherV() { + return deleteOtherV; + } + /** + * @param deleteOtherV the deleteOtherV to set + */ + public void setDeleteOtherV(String deleteOtherV) { + logger.debug("Edge: "+this.getRuleKey()); + logger.debug("Truth: "+(("${direction}".equals(deleteOtherV)) ? "true" : "false")); + logger.debug("Truth: "+(("!${direction}".equals(deleteOtherV)) ? "true" : "false")); + + if("${direction}".equals(deleteOtherV) ) { + this.deleteOtherV = this.direction; + } else if("!${direction}".equals(deleteOtherV) ) { + this.deleteOtherV = this.direction.equals("IN") ? "OUT" : ((this.direction.equals("OUT")) ? "IN" : deleteOtherV); + } else { + this.deleteOtherV = deleteOtherV; + } + logger.debug("DeleteOtherV="+deleteOtherV+"/"+this.direction+"="+this.deleteOtherV); + } + /** + * @return the preventDelete + */ + public String getPreventDelete() { + return preventDelete; + } + /** + * @param preventDelete the preventDelete to set + */ + public void setPreventDelete(String preventDelete) { + if(this.getTo().equals("flavor") || this.getFrom().equals("flavor") ){ + logger.debug("Edge: "+this.getRuleKey()); + logger.debug("Truth: "+(("${direction}".equals(preventDelete)) ? "true" : "false")); + logger.debug("Truth: "+(("!${direction}".equals(preventDelete)) ? "true" : "false")); + } + + if("${direction}".equals(preventDelete) ) { + this.preventDelete = this.direction; + } else if("!${direction}".equals(preventDelete) ) { + this.preventDelete = this.direction.equals("IN") ? "OUT" : ((this.direction.equals("OUT")) ? "IN" : preventDelete); + } else { + this.preventDelete = preventDelete; + } + } + public String getAlsoDeleteFootnote(String targetNode) { + String returnVal = ""; + if(this.deleteOtherV.equals("IN") && this.to.equals(targetNode) ) { + logger.debug("Edge: "+this.getRuleKey()); + logger.debug("IF this "+targetNode+" node is deleted, this FROM node is DELETED also"); + returnVal = "(1)"; + } + if(this.deleteOtherV.equals("OUT") && this.from.equals(targetNode) ) { + logger.debug("Edge: "+this.getRuleKey()); + logger.debug("IF this "+targetNode+" is deleted, this TO node is DELETED also"); + returnVal = "(2)"; + } + if(this.deleteOtherV.equals("OUT") && this.to.equals(targetNode) ) { + logger.debug("Edge: "+this.getRuleKey()); + logger.debug("IF this FROM node is deleted, this "+targetNode+" is DELETED also"); + returnVal = "(3)"; + } + if(this.deleteOtherV.equals("IN") && this.from.equals(targetNode) ) { + logger.debug("Edge: "+this.getRuleKey()); + logger.debug("IF this TO node is deleted, this "+targetNode+" node is DELETED also"); + returnVal = "(4)"; + } + return returnVal; + } + /** + * @return the to + */ + public String getTo() { + return to; + } + /** + * @param to the to to set + */ + public void setTo(String to) { + this.to = to; + } + /** + * @return the from + */ + public String getFrom() { + return from; + } + /** + * @param from the from to set + */ + public void setFrom(String from) { + this.from = from; + } + + + public String getRuleKey() { + return ruleKey; + } + public String getMultiplicity() { + return multiplicity; + } + public String getDirection() { + return direction; + } + public String getDescription() { + return this.description; + } + public void setRuleKey(String val) { + this.ruleKey=val; + } + public void setType(LineageType val) { + this.type=val; + } + public void setDirection(String val) { + this.direction = val; + } + public void setMultiplicity(String val) { + this.multiplicity=val; + } + + public void setDescription(String val) { + this.description = val; + } + + public String getRelationshipDescription(String fromTo, String otherNodeName) { + + String result = ""; + + if ("FROM".equals(fromTo)) { + if ("OUT".equals(direction)) { + if (LineageType.PARENT == type) { + result = " (PARENT of "+otherNodeName; + result = String.join(" ", result+",", this.from, this.getShortLabel(), this.to); + } + } + else { + if (LineageType.CHILD == type) { + result = " (CHILD of "+otherNodeName; + result = String.join(" ", result+",", this.from, this.getShortLabel(), this.to); + } + else if (LineageType.PARENT == type) { + result = " (PARENT of "+otherNodeName; + result = String.join(" ", result+",", this.from, this.getShortLabel(), this.to); + } + } + if (result.length() == 0) result = String.join(" ", "(", this.from, this.getShortLabel(), this.to+",", this.getMultiplicity()); + } else { + //if ("TO".equals(fromTo) + if ("OUT".equals(direction)) { + if (LineageType.PARENT == type) { + result = " (CHILD of "+otherNodeName; + result = String.join(" ", result+",", this.from, this.getShortLabel(), this.to+",", this.getMultiplicity()); + } + } else { + if (LineageType.PARENT == type) { + result = " (PARENT of "+otherNodeName; + result = String.join(" ", result+",", this.from, this.getShortLabel(), this.to+",", this.getMultiplicity()); + } + } + if (result.length() == 0) result = String.join(" ", "(", this.from, this.getShortLabel(), this.to+",", this.getMultiplicity()); + } +// Confusing... +// if (hasDelTarget()) result = result + ", will delete target node"; + + if (result.length() > 0) result = result + ")"; + + if (description != null && description.length() > 0) result = result + "\n "+ description; // 6 spaces is important for yaml + + return result; + } + + /** + * @return the hasDelTarget + */ + + public boolean hasDelTarget() { + return StringUtils.isNotEmpty(this.deleteOtherV) && (! "NONE".equalsIgnoreCase(this.deleteOtherV)); + } + + /** + * @return the type + */ + public LineageType getType() { + return type; + } + /** + * @return the label + */ + public String getLabel() { + return label; + } + public String getShortLabel() { + String[] pieces = this.getLabel().split("[.]"); + return pieces[pieces.length-1]; + } + public void setLabel(String string) { + this.label=string; + } +} \ No newline at end of file diff --git a/aai-core/src/main/java/org/onap/aai/util/genxsd/EdgeRuleSet.java b/aai-core/src/main/java/org/onap/aai/util/genxsd/EdgeRuleSet.java new file mode 100644 index 00000000..f3ef298a --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/util/genxsd/EdgeRuleSet.java @@ -0,0 +1,196 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.util.genxsd; + +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; +import org.onap.aai.serialization.db.EdgeProperty; + +import java.io.*; +import java.util.*; + +public class EdgeRuleSet { + private File edgeFile; + private DocumentContext jsonContext; + + public EdgeRuleSet(File edgeFile) throws IOException,FileNotFoundException { + this.edgeFile = edgeFile; + init(); + } + public EdgeRuleSet(DocumentContext jsonContext) { + this.jsonContext = jsonContext; + } + + public Collection getEdgeRules( String nodeName ) + { + String fromRulesPath = "$['rules'][?(@['from']=='" + nodeName + "')]"; + String toRulesPath = "$['rules'][?(@['to']=='" + nodeName + "')]"; + Collection fromEdges = getEdgeRulesFromJson( fromRulesPath, false ); + Collection edges = getEdgeRulesFromJson( toRulesPath, true ); + edges.addAll(fromEdges); + return edges; + } + + public Collection getEdgeRulesTO( String nodeName ) + { + String toRulesPath = "$['rules'][?(@['to']=='" + nodeName + "')]"; + Collection edges = getEdgeRulesFromJson( toRulesPath, true ); + return edges; + } + + public Collection getEdgeRulesFROM( String nodeName ) + { + String fromRulesPath = "$['rules'][?(@['from']=='" + nodeName + "')]"; + Collection edges = getEdgeRulesFromJson( fromRulesPath, true ); + return edges; + } + + /** + * Guaranteed to at least return non null but empty collection of edge descriptions + * @param nodeName name of the vertex whose edge relationships to return + * @return collection of node neighbors based on DbEdgeRules + **/ + public Collection getEdgeRulesFromJson( String path, boolean skipMatch ) + { + + ArrayList result = new ArrayList<>(); + Iterator> edgeRulesIterator; + try { + List> inEdges = jsonContext.read(path); + + edgeRulesIterator = inEdges.iterator(); + Map edgeMap; + String fromNode; + String toNode; + String direction; + String multiplicity; + String isParent; + String deleteOtherV; + String preventDelete; + String description; + EdgeDescription edgeDes; + + while( edgeRulesIterator.hasNext() ){ + edgeMap = edgeRulesIterator.next(); + fromNode = (String)edgeMap.get("from"); + toNode = (String)edgeMap.get("to"); + if ( skipMatch ) { + if ( fromNode.equals(toNode)) { + continue; + } + } + edgeDes = new EdgeDescription(); + edgeDes.setRuleKey(fromNode + "|" + toNode); + edgeDes.setLabel((String)edgeMap.get("label")); + edgeDes.setTo((String)edgeMap.get("to")); + edgeDes.setFrom((String)edgeMap.get("from")); + direction = (String)edgeMap.get("direction"); + edgeDes.setDirection(direction); + multiplicity = (String)edgeMap.get("multiplicity"); + edgeDes.setMultiplicity(multiplicity); + isParent = (String)edgeMap.get(EdgeProperty.CONTAINS.toString()); + if ( "${direction}".equals(isParent)) { + edgeDes.setType(EdgeDescription.LineageType.PARENT); + } else { + edgeDes.setType(EdgeDescription.LineageType.UNRELATED); + } + deleteOtherV = (String)edgeMap.get(EdgeProperty.DELETE_OTHER_V.toString()); + edgeDes.setDeleteOtherV(deleteOtherV); + preventDelete = (String)edgeMap.get(EdgeProperty.PREVENT_DELETE.toString()); + edgeDes.setPreventDelete(preventDelete); + description = (String)edgeMap.get(EdgeProperty.DESCRIPTION.toString()); + edgeDes.setDescription(description); + + result.add(edgeDes); +// logger.debug("Edge: "+edgeDes.getRuleKey()); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + return result; + + } + + private void init() throws FileNotFoundException, IOException { + InputStream is = null; + Scanner scanner = null; + String jsonEdges = null; + try { + is = new FileInputStream(edgeFile); + scanner = new Scanner(is); + jsonEdges = scanner.useDelimiter("\\Z").next(); + } catch (Exception e) { + throw e; + } finally { + scanner.close(); + if (is != null) { + try { + is.close(); + } catch (IOException e) { + throw e; + } + } + } + jsonContext = JsonPath.parse(jsonEdges); + } + + public String preventDeleteRules(String objectName) { + Collection toEdges = getEdgeRulesTO(objectName); + toEdges.addAll(getEdgeRulesFROM(objectName)); +// logger.debug("TO Edges count: "+toEdges.size()+" Object: "+objectName); + String prevent=null; + LinkedHashSet preventDelete = new LinkedHashSet(); + for (EdgeDescription ed : toEdges) { +// logger.debug("{“comment”: From = "+ed.getFrom()+" To: "+ed.getTo()+" Object: "+objectName); +// logger.debug("{“comment”: Direction = "+ed.getDirection()+" PreventDelete: "+ed.getPreventDelete()+" DeleteOtherV: "+ed.getDeleteOtherV()+" Object: "+objectName); + if(ed.getPreventDelete().equals("IN") && ed.getTo().equals(objectName)) { + preventDelete.add(ed.getFrom().toUpperCase()); + } + if(ed.getPreventDelete().equals("OUT") && ed.getFrom().equals(objectName)) { + preventDelete.add(ed.getTo().toUpperCase()); + } + } + if(preventDelete.size() > 0) { + prevent = objectName.toUpperCase()+" cannot be deleted if related to "+String.join(",",preventDelete); +// logger.debug(prevent); + } + return String.join((prevent == null) ? "" : "\n", prevent == null ? "" : prevent)+((prevent == null) ? "" : "\n"); +// return String.join((prevent == null) ? "" : "\n", prevent == null ? "" : prevent, also == null ? "" : also)+((prevent == null) ? "" : "\n"); + } + + public String fromDeleteRules(String objectName) { + Collection fromEdges = getEdgeRulesFROM(objectName); + LinkedHashSet preventDelete = new LinkedHashSet (); + String prevent=null; + String also=null; + for (EdgeDescription ed : fromEdges) { +// logger.debug("{“comment”: From = "+ed.getFrom()+" To: "+ed.getTo()+" Object: "+objectName); +// logger.debug("{“comment”: Direction = "+ed.getDirection()+" PreventDelete: "+ed.getPreventDelete()+" DeleteOtherV: "+ed.getDeleteOtherV()+" Object: "+objectName); + if(ed.getPreventDelete().equals("OUT") && ed.getFrom().equals(objectName)) { + preventDelete.add(ed.getTo().toUpperCase()); + } + } + if(preventDelete.size() > 0) { + prevent = objectName.toUpperCase()+" cannot be deleted if related to "+String.join(",",preventDelete); +// logger.debug(prevent); + } + return String.join((prevent == null || also == null) ? "" : "\n", prevent == null ? "" : prevent, also == null ? "" : also)+((prevent == null && also == null) ? "" : "\n"); + } +} diff --git a/aai-core/src/main/java/org/onap/aai/util/genxsd/GetOperation.java b/aai-core/src/main/java/org/onap/aai/util/genxsd/GetOperation.java new file mode 100644 index 00000000..16a2e682 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/util/genxsd/GetOperation.java @@ -0,0 +1,121 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.util.genxsd; + +import org.apache.commons.lang3.StringUtils; +import org.onap.aai.util.GenerateXsd; + +import java.util.HashMap; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.Vector; + +public class GetOperation { + static Map> containers = new HashMap>(); + public static void addContainerProps(String container, Vector containerProps) { + containers.put(container, containerProps);; + } + private String useOpId; + private String xmlRootElementName; + private String tag; + private String path; + private String pathParams; + private String queryParams; + + public GetOperation(String useOpId, String xmlRootElementName, String tag, String path, String pathParams) { + super(); + this.useOpId = useOpId; + this.xmlRootElementName = xmlRootElementName; + this.tag = tag; + this.path = path; + this.pathParams = pathParams; +// StringBuilder p = new StringBuilder(); + + if(containers.get(xmlRootElementName) == null) { + this.queryParams = ""; + } else { + this.queryParams= String.join("", containers.get(xmlRootElementName)); +// for(String param : containers.get(xmlRootElementName)) { +// p.append(param); +// } +// this.queryParams = p.toString(); + } + } + @Override + public String toString() { + StringTokenizer st; + st = new StringTokenizer(path, "/"); + //Path has to be longer than one element + /* + if ( st.countTokens() <= 1) { + return ""; + } + */ + //a valid tag is necessary + if ( StringUtils.isEmpty(tag) ) { + return ""; + } + if ( path.endsWith("/relationship") ) { + return ""; + } + if ( path.contains("/relationship/") ) { // filter paths with relationship-list + return ""; + } + if ( path.endsWith("/relationship-list")) { + return ""; + } + if ( path.startsWith("/search")) { + return ""; + } + StringBuffer pathSb = new StringBuffer(); + pathSb.append(" " + path + ":\n" ); + pathSb.append(" get:\n"); + pathSb.append(" tags:\n"); + pathSb.append(" - " + tag + "\n"); + pathSb.append(" summary: returns " + xmlRootElementName + "\n"); + + pathSb.append(" description: returns " + xmlRootElementName + "\n"); + pathSb.append(" operationId: get" + useOpId + "\n"); + pathSb.append(" produces:\n"); + pathSb.append(" - application/json\n"); + pathSb.append(" - application/xml\n"); + + pathSb.append(" responses:\n"); + pathSb.append(" \"200\":\n"); + pathSb.append(" description: successful operation\n"); + pathSb.append(" schema:\n"); + pathSb.append(" $ref: \"#/getDefinitions/" + xmlRootElementName + "\"\n"); + pathSb.append(" \"default\":\n"); + pathSb.append(" " + GenerateXsd.getResponsesUrl()); + if ( StringUtils.isNotEmpty(pathParams) || StringUtils.isNotEmpty(queryParams)) { + pathSb.append(" parameters:\n"); + } + if ( StringUtils.isNotEmpty(pathParams)) { + pathSb.append(pathParams); + } +// if ( StringUtils.isNotEmpty(pathParams) && StringUtils.isNotEmpty(queryParams)) { +// pathSb.append("\n"); +// } + if ( StringUtils.isNotEmpty(queryParams)) { + pathSb.append(queryParams); + } + return pathSb.toString(); + } + } diff --git a/aai-core/src/main/java/org/onap/aai/util/genxsd/HTMLfromOXM.java b/aai-core/src/main/java/org/onap/aai/util/genxsd/HTMLfromOXM.java new file mode 100644 index 00000000..287b3b5c --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/util/genxsd/HTMLfromOXM.java @@ -0,0 +1,190 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.util.genxsd; + +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Version; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import javax.xml.parsers.ParserConfigurationException; +import java.io.File; +import java.io.IOException; + +public class HTMLfromOXM extends OxmFileProcessor { + private static final Logger logger = LoggerFactory.getLogger("HTMLfromOXM.class"); + + Version v; + public HTMLfromOXM(File oxmFile, Version v) throws ParserConfigurationException, SAXException, IOException, AAIException { + super(oxmFile, v); + super.init(); + this.v = v; + } + public HTMLfromOXM(String xml, Version v) throws ParserConfigurationException, SAXException, IOException, AAIException { + super(xml, v); + super.init(); + this.v = v; + } + + @Override + public String getDocumentHeader() { + StringBuffer sb = new StringBuffer(); + logger.trace("processing starts"); + sb.append("\n"); + String namespace = "org.onap"; + if (v.compareTo(Version.v11) < 0 || v.compareTo(Version.v12) < 0) { + namespace = "org.openecomp"; + } + if ( versionUsesAnnotations(v.name()) ) { + sb.append("\n\n"); + } else { + sb.append("\n\n"); + } + return sb.toString(); + } + + @Override + public String process() throws AAIException { + StringBuilder sb = new StringBuilder(); + sb.append(getDocumentHeader()); + for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) { + XSDElement javaTypeElement = new XSDElement((Element)javaTypeNodes.item(i)); + String javaTypeName = javaTypeElement.name(); + if ( javaTypeName == null ) { + String msg = "Invalid OXM file: has no name attribute in " + oxmFile; + logger.error(msg); + throw new AAIException(msg); + } + if ("Nodes".equals(javaTypeName)) { + logger.debug("skipping Nodes entry (temporary feature)"); + continue; + } + //Skip any type that has already been processed(recursion could be the reason) + logger.debug(getXmlRootElementName(javaTypeName)+" vs "+ javaTypeName+":"+generatedJavaType.containsKey(getXmlRootElementName(javaTypeName))); + if ( generatedJavaType.containsKey(javaTypeName) ) { + continue; + } + generatedJavaType.put(javaTypeName, null); + sb.append(processJavaTypeElement( javaTypeName, javaTypeElement )); + } + sb.append("\n"); + return sb.toString(); + } + + public String processJavaTypeElement( String javaTypeName, Element javaType_Element) { + + String xmlRootElementName = getXMLRootElementName(javaType_Element); + + NodeList parentNodes = javaType_Element.getElementsByTagName("java-attributes"); + StringBuffer sb = new StringBuffer(); + if ( parentNodes.getLength() == 0 ) { + logger.trace( "no java-attributes for java-type " + javaTypeName); + return ""; + } + + Element parentElement = (Element)parentNodes.item(0); + NodeList xmlElementNodes = parentElement.getElementsByTagName("xml-element"); + + StringBuffer sb1 = new StringBuffer(); + if ( xmlElementNodes.getLength() > 0 ) { + sb1.append(" \n"); + sb1.append(" \n"); + XSDElement javaTypeElement = new XSDElement(javaType_Element); + logger.debug("XSDElement name: "+javaTypeElement.name()); + if(versionUsesAnnotations(v.name())) { + sb1.append(javaTypeElement.getHTMLAnnotation("class", " ")); + } + sb1.append(" \n"); + for ( int i = 0; i < xmlElementNodes.getLength(); ++i ) { + + XSDElement xmlElementElement = new XSDElement((Element)xmlElementNodes.item(i)); + + String elementName = xmlElementElement.getAttribute("name"); + String elementType = xmlElementElement.getAttribute("type"); + //No simple types; only AAI custom types + String addType = elementType.contains("." + v.name() + ".") ? elementType.substring(elementType.lastIndexOf('.')+1) : null; + if ( elementType.contains("." + v.name() + ".") && !generatedJavaType.containsKey(addType) ) { + generatedJavaType.put(addType, elementType); + sb.append(processJavaTypeElement( addType, getJavaTypeElement(addType) )); + } + if ("Nodes".equals(addType)) { + logger.trace("Skipping nodes, temporary testing"); + continue; + } + //assembles the basic + sb1.append(xmlElementElement.getHTMLElement(v, versionUsesAnnotations(v.name()), this)); + } + sb1.append(" \n"); + sb1.append(" \n"); + sb1.append(" \n"); + } + + if ( xmlElementNodes.getLength() < 1 ) { + sb.append(" \n"); + sb.append(" \n"); + sb.append(" \n"); + sb.append(" \n"); + sb.append(" \n"); + generatedJavaType.put(javaTypeName, null); + return sb.toString(); + } + sb.append( sb1 ); + return sb.toString(); + } + + private Element getJavaTypeElement( String javaTypeName ) + { + String attrName, attrValue; + Attr attr; + Element javaTypeElement; + for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) { + javaTypeElement = (Element) javaTypeNodes.item(i); + NamedNodeMap attributes = javaTypeElement.getAttributes(); + for ( int j = 0; j < attributes.getLength(); ++j ) { + attr = (Attr) attributes.item(j); + attrName = attr.getNodeName(); + attrValue = attr.getNodeValue(); + if ( attrName.equals("name") && attrValue.equals(javaTypeName)) + return javaTypeElement; + } + } + logger.error( "oxm file format error, missing java-type " + javaTypeName); + return (Element) null; + } + + private boolean versionUsesAnnotations( String version) { + if (new Integer(version.substring(1)).intValue() >= HTMLfromOXM.annotationsStartVersion ) { + return true; + } + return false; + } +} \ No newline at end of file diff --git a/aai-core/src/main/java/org/onap/aai/util/genxsd/OxmFileProcessor.java b/aai-core/src/main/java/org/onap/aai/util/genxsd/OxmFileProcessor.java new file mode 100644 index 00000000..04fdd3c0 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/util/genxsd/OxmFileProcessor.java @@ -0,0 +1,199 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.util.genxsd; + +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Version; +import org.w3c.dom.*; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.File; +import java.io.IOException; +import java.io.StringReader; +import java.util.HashMap; +import java.util.Map; + +public abstract class OxmFileProcessor { + protected File oxmFile; + protected String xml; + protected Version v; + protected Document doc = null; + protected String apiVersion = null; + protected static int annotationsStartVersion = 9; // minimum version to support annotations in xsd + protected static int swaggerSupportStartsVersion = 7; // minimum version to support swagger documentation + + protected String apiVersionFmt = null; + protected HashMap generatedJavaType = new HashMap(); + protected HashMap appliedPaths = new HashMap(); + protected NodeList javaTypeNodes = null; + protected static Map javaTypeDefinitions = createJavaTypeDefinitions(); + private static Map createJavaTypeDefinitions() + { + StringBuffer aaiInternal = new StringBuffer(); + StringBuffer nodes = new StringBuffer(); + Map javaTypeDefinitions = new HashMap(); + aaiInternal.append(" aai-internal:\n"); + aaiInternal.append(" properties:\n"); + aaiInternal.append(" property-name:\n"); + aaiInternal.append(" type: string\n"); + aaiInternal.append(" property-value:\n"); + aaiInternal.append(" type: string\n"); +// javaTypeDefinitions.put("aai-internal", aaiInternal.toString()); + nodes.append(" nodes:\n"); + nodes.append(" properties:\n"); + nodes.append(" inventory-item-data:\n"); + nodes.append(" type: array\n"); + nodes.append(" items:\n"); + nodes.append(" $ref: \"#/definitions/inventory-item-data\"\n"); + javaTypeDefinitions.put("nodes", nodes.toString()); + return javaTypeDefinitions; + } + + + public OxmFileProcessor(File oxmFile, Version v) { + super(); + this.oxmFile = oxmFile; + this.v = v; + } + + public OxmFileProcessor(String xml, Version v) { + this.xml = xml; + this.v = v; + } + protected void init() throws ParserConfigurationException, SAXException, IOException, AAIException { + DocumentBuilder dBuilder = null; + try { + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + dBuilder = dbFactory.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + throw e; + } + try { + if ( xml == null ) { + doc = dBuilder.parse(oxmFile); + } else { + InputSource isInput = new InputSource(new StringReader(xml)); + doc = dBuilder.parse(isInput); + } + } catch (SAXException e) { + throw e; + } catch (IOException e) { + throw e; + } + + NodeList bindingsNodes = doc.getElementsByTagName("xml-bindings"); + Element bindingElement; + NodeList javaTypesNodes; + Element javaTypesElement; + + if ( bindingsNodes == null || bindingsNodes.getLength() == 0 ) { + throw new AAIException("OXM file error: missing in " + oxmFile); + } + + bindingElement = (Element) bindingsNodes.item(0); + javaTypesNodes = bindingElement.getElementsByTagName("java-types"); + if ( javaTypesNodes.getLength() < 1 ) { + throw new AAIException("OXM file error: missing in " + oxmFile); + } + javaTypesElement = (Element) javaTypesNodes.item(0); + + javaTypeNodes = javaTypesElement.getElementsByTagName("java-type"); + if ( javaTypeNodes.getLength() < 1 ) { + throw new AAIException("OXM file error: missing in " + oxmFile ); + } + } + public abstract String getDocumentHeader(); + public abstract String process() throws AAIException; + + public String getXMLRootElementName(Element javaTypeElement) { + String xmlRootElementName=null; + NamedNodeMap attributes; + + NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element"); + Element valElement = (Element) valNodes.item(0); + attributes = valElement.getAttributes(); + for ( int i = 0; i < attributes.getLength(); ++i ) { + Attr attr = (Attr) attributes.item(i); + String attrName = attr.getNodeName(); + + String attrValue = attr.getNodeValue(); + if ( attrName.equals("name")) + xmlRootElementName = attrValue; + } + return xmlRootElementName; + } + + public String getXmlRootElementName( String javaTypeName ) + { + String attrName, attrValue; + Attr attr; + Element javaTypeElement; + for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) { + javaTypeElement = (Element) javaTypeNodes.item(i); + NamedNodeMap attributes = javaTypeElement.getAttributes(); + for ( int j = 0; j < attributes.getLength(); ++j ) { + attr = (Attr) attributes.item(j); + attrName = attr.getNodeName(); + attrValue = attr.getNodeValue(); + if ( attrName.equals("name") && attrValue.equals(javaTypeName)) { + NodeList valNodes = javaTypeElement.getElementsByTagName("xml-root-element"); + Element valElement = (Element) valNodes.item(0); + attributes = valElement.getAttributes(); + for ( int k = 0; k < attributes.getLength(); ++k ) { + attr = (Attr) attributes.item(k); + attrName = attr.getNodeName(); + + attrValue = attr.getNodeValue(); + if ( attrName.equals("name")) + return (attrValue); + } + } + } + } + return null; + } + + public Element getJavaTypeElementSwagger( String javaTypeName ) + { + + String attrName, attrValue; + Attr attr; + Element javaTypeElement; + for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) { + javaTypeElement = (Element) javaTypeNodes.item(i); + NamedNodeMap attributes = javaTypeElement.getAttributes(); + for ( int j = 0; j < attributes.getLength(); ++j ) { + attr = (Attr) attributes.item(j); + attrName = attr.getNodeName(); + attrValue = attr.getNodeValue(); + if ( attrName.equals("name") && attrValue.equals(javaTypeName)) + return javaTypeElement; + } + } + return (Element) null; + } + +} diff --git a/aai-core/src/main/java/org/onap/aai/util/genxsd/PatchOperation.java b/aai-core/src/main/java/org/onap/aai/util/genxsd/PatchOperation.java new file mode 100644 index 00000000..cc90114f --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/util/genxsd/PatchOperation.java @@ -0,0 +1,116 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.util.genxsd; + +import org.apache.commons.lang3.StringUtils; +import org.onap.aai.util.GenerateXsd; + +import java.util.StringTokenizer; + +public class PatchOperation { + private String useOpId; + private String xmlRootElementName; + private String tag; + private String path; + private String pathParams; + + public PatchOperation(String useOpId, String xmlRootElementName, String tag, String path, String pathParams) { + super(); + this.useOpId = useOpId; + this.xmlRootElementName = xmlRootElementName; + this.tag = tag; + this.path = path; + this.pathParams = pathParams; + } + + public String toString() { + StringTokenizer st; + st = new StringTokenizer(path, "/"); + //a valid tag is necessary + if ( StringUtils.isEmpty(tag) ) { + return ""; + } + if ( path.contains("/relationship/") ) { // filter paths with relationship-list + return ""; + } + if ( path.endsWith("/relationship-list")) { + return ""; + } + if ( path.startsWith("/search")) { + return ""; + } + //No Patch operation paths end with "relationship" + + if (path.endsWith("/relationship") ) { + return ""; + } + if (!path.endsWith("}")) { + return ""; + } + + StringBuffer pathSb = new StringBuffer(); + StringBuffer relationshipExamplesSb = new StringBuffer(); + if ( path.endsWith("/relationship") ) { + pathSb.append(" " + path + ":\n" ); + } + pathSb.append(" patch:\n"); + pathSb.append(" tags:\n"); + pathSb.append(" - " + tag + "\n"); + + if ( path.endsWith("/relationship") ) { + pathSb.append(" summary: see node definition for valid relationships\n"); + relationshipExamplesSb.append("[See Examples](apidocs/relations/"+ GenerateXsd.getAPIVersion()+"/"+useOpId+".json)"); + } else { + pathSb.append(" summary: update an existing " + xmlRootElementName + "\n"); + pathSb.append(" description: |\n"); + pathSb.append(" Update an existing " + xmlRootElementName + "\n"); + pathSb.append(" #\n"); + pathSb.append(" Note: Endpoints that are not devoted to object relationships support both PUT and PATCH operations.\n"); + pathSb.append(" The PUT operation will entirely replace an existing object.\n"); + 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"); + pathSb.append(" #\n"); + pathSb.append(" Other differences between PUT and PATCH are:\n"); + pathSb.append(" #\n"); + pathSb.append(" - For PATCH, you can send any of the values shown in sample REQUEST body. There are no required values.\n"); + pathSb.append(" - For PATCH, resource-id which is a required REQUEST body element for PUT, must not be sent.\n"); + pathSb.append(" - PATCH cannot be used to update relationship elements; there are dedicated PUT operations for this.\n"); + } + pathSb.append(" operationId: Update" + useOpId + "\n"); + pathSb.append(" consumes:\n"); + pathSb.append(" - application/json\n"); + pathSb.append(" - application/xml\n"); + pathSb.append(" produces:\n"); + pathSb.append(" - application/json\n"); + pathSb.append(" - application/xml\n"); + pathSb.append(" responses:\n"); + pathSb.append(" \"default\":\n"); + pathSb.append(" " + GenerateXsd.getResponsesUrl()); + pathSb.append(" parameters:\n"); + pathSb.append(pathParams); // for nesting + pathSb.append(" - name: body\n"); + pathSb.append(" in: body\n"); + pathSb.append(" description: " + xmlRootElementName + " object that needs to be updated."+relationshipExamplesSb.toString()+"\n"); + pathSb.append(" required: true\n"); + pathSb.append(" schema:\n"); + pathSb.append(" $ref: \"#/patchDefinitions/" + xmlRootElementName + "\"\n"); + return pathSb.toString(); + } + } + \ No newline at end of file diff --git a/aai-core/src/main/java/org/onap/aai/util/genxsd/PutOperation.java b/aai-core/src/main/java/org/onap/aai/util/genxsd/PutOperation.java new file mode 100644 index 00000000..58ccec37 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/util/genxsd/PutOperation.java @@ -0,0 +1,114 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.util.genxsd; + +import org.apache.commons.lang3.StringUtils; +import org.onap.aai.introspection.Version; +import org.onap.aai.util.GenerateXsd; + +import java.util.StringTokenizer; + +public class PutOperation { + private String useOpId; + private String xmlRootElementName; + private String tag; + private String path; + private String pathParams; + private Version version; + + public PutOperation(String useOpId, String xmlRootElementName, String tag, String path, String pathParams, Version v) { + super(); + this.useOpId = useOpId; + this.xmlRootElementName = xmlRootElementName; + this.tag = tag; + this.path = path; + this.pathParams = pathParams; + this.version = v; + } + + @Override + public String toString() { + StringTokenizer st = new StringTokenizer(path, "/"); + //a valid tag is necessary + if ( StringUtils.isEmpty(tag) ) { + return ""; + } + //All Put operation paths end with "relationship" + //or there is a parameter at the end of the path + //and there is a parameter in the path + if ( path.contains("/relationship/") ) { // filter paths with relationship-list + return ""; + } + if ( path.endsWith("/relationship-list")) { + return ""; + } + if ( !path.endsWith("/relationship") && !path.endsWith("}") ) { + return ""; + } + if ( path.startsWith("/search")) { + return ""; + } + StringBuffer pathSb = new StringBuffer(); + StringBuffer relationshipExamplesSb = new StringBuffer(); + if ( path.endsWith("/relationship") ) { + pathSb.append(" " + path + ":\n" ); + } + pathSb.append(" put:\n"); + pathSb.append(" tags:\n"); + pathSb.append(" - " + tag + "\n"); + + if ( path.endsWith("/relationship") ) { + pathSb.append(" summary: see node definition for valid relationships\n"); + } else { + pathSb.append(" summary: create or update an existing " + xmlRootElementName + "\n"); + 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"); + } + relationshipExamplesSb.append("[Valid relationship examples shown here](apidocs/relations/"+version.name()+"/"+useOpId.replace("RelationshipListRelationship", "")+".json)"); + pathSb.append(" operationId: createOrUpdate" + useOpId + "\n"); + pathSb.append(" consumes:\n"); + pathSb.append(" - application/json\n"); + pathSb.append(" - application/xml\n"); + pathSb.append(" produces:\n"); + pathSb.append(" - application/json\n"); + pathSb.append(" - application/xml\n"); + pathSb.append(" responses:\n"); + pathSb.append(" \"default\":\n"); + pathSb.append(" " + GenerateXsd.getResponsesUrl()); + + pathSb.append(" parameters:\n"); + pathSb.append(pathParams); // for nesting + pathSb.append(" - name: body\n"); + pathSb.append(" in: body\n"); + pathSb.append(" description: " + xmlRootElementName + " object that needs to be created or updated. "+relationshipExamplesSb.toString()+"\n"); + pathSb.append(" required: true\n"); + pathSb.append(" schema:\n"); + pathSb.append(" $ref: \"#/definitions/" + xmlRootElementName + "\"\n"); + this.tagRelationshipPathMapEntry(); + return pathSb.toString(); + } + + public String tagRelationshipPathMapEntry() { + if ( path.endsWith("/relationship") ) { + PutRelationPathSet.add(useOpId, path); + } + return ""; + } + + } \ No newline at end of file diff --git a/aai-core/src/main/java/org/onap/aai/util/genxsd/PutRelationPathSet.java b/aai-core/src/main/java/org/onap/aai/util/genxsd/PutRelationPathSet.java new file mode 100644 index 00000000..3e411946 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/util/genxsd/PutRelationPathSet.java @@ -0,0 +1,216 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.util.genxsd; + +import org.apache.commons.text.similarity.LevenshteinDistance; +import org.onap.aai.introspection.Version; +import org.onap.aai.util.GenerateXsd; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +public class PutRelationPathSet { + private static final Logger logger = LoggerFactory.getLogger("PutRelationPathSet.class"); + protected static HashMap putRelationPaths = new HashMap(); + private static EdgeRuleSet edgeRuleSet = null; + public static void add(String useOpId, String path) { + putRelationPaths.put(useOpId, path); + } + + String apiPath; + String opId; + Version version; + protected ArrayList relations = new ArrayList(); + String objectName = ""; + + public PutRelationPathSet(Version v) { + this.version = v; + } + + public PutRelationPathSet(String opId, String path, Version v) { + this.apiPath = path.replace("/relationship-list/relationship", ""); + this.opId = opId; + this.version = v; + objectName = DeleteOperation.deletePaths.get(apiPath); + logger.debug("II-apiPath: "+apiPath+"\nPath: "+path+"\nopId="+opId+"\nobjectName="+objectName); + } + private void process() { + this.toRelations(); + this.fromRelations(); + this.writeRelationsFile(); + + } + private void toRelations() { + logger.debug("{“comment”: “Valid TO Relations that can be added”},"); + logger.debug("apiPath: "+apiPath+"\nopId="+opId+"\nobjectName="+objectName); + Collection toEdges = edgeRuleSet.getEdgeRulesTO(objectName); + + if(toEdges.size() > 0) { + relations.add("{\"comment\": \"Valid TO Relations that can be added\"}\n"); + } + for (EdgeDescription ed : toEdges) { + logger.debug(ed.getRuleKey()+"Type="+ed.getType()); + String obj = ed.getRuleKey().replace(objectName,"").replace("|",""); + String selectedRelation = ""; + if(ed.getType() == EdgeDescription.LineageType.UNRELATED) { + String selectObj = getUnrelatedObjectPaths(obj, apiPath); + logger.debug("SelectedObj:"+selectObj); + selectedRelation = formatObjectRelationSet(obj,selectObj); + logger.debug("ObjectRelationSet"+selectedRelation); + } else { + String selectObj = getKinObjectPath(obj, apiPath); + logger.debug("SelectedObj:"+selectObj); + selectedRelation = formatObjectRelation(obj,selectObj); + logger.debug("ObjectRelationSet"+selectedRelation); + } + relations.add(selectedRelation); + logger.debug("Relation added: "+selectedRelation); + } + } + + private void fromRelations() { + logger.debug("“comment”: “Valid FROM Relations that can be added”"); + Collection fromEdges = edgeRuleSet.getEdgeRulesFROM(objectName); + if(fromEdges.size() > 0) { + relations.add("{\"comment\": \"Valid FROM Relations that can be added\"}\n"); + } + for (EdgeDescription ed : fromEdges) { + logger.debug(ed.getRuleKey()+"Type="+ed.getType()); + String obj = ed.getRuleKey().replace(objectName,"").replace("|",""); + String selectedRelation = ""; + if(ed.getType() == EdgeDescription.LineageType.UNRELATED) { + String selectObj = getUnrelatedObjectPaths(obj, apiPath); + logger.debug("SelectedObj"+selectObj); + selectedRelation = formatObjectRelationSet(obj,selectObj); + logger.trace("ObjectRelationSet"+selectedRelation); + } else { + String selectObj = getKinObjectPath(obj, apiPath); + logger.debug("SelectedObj"+selectObj); + selectedRelation = formatObjectRelation(obj,selectObj); + logger.trace("ObjectRelationSet"+selectedRelation); + } + relations.add(selectedRelation); + logger.trace(selectedRelation); + } + } + private void writeRelationsFile() { + File examplefilePath = new File(GenerateXsd.getYamlDir() + "/relations/" + version.name()+"/"+opId.replace("RelationshipListRelationship", "") + ".json"); + + logger.debug(String.join("exampleFilePath: ", examplefilePath.toString())); + FileOutputStream fop = null; + try { + if (!examplefilePath.exists()) { + examplefilePath.getParentFile().mkdirs(); + examplefilePath.createNewFile(); + } + fop = new FileOutputStream(examplefilePath); + } catch(Exception e) { + e.printStackTrace(); + return; + } + try { + if(relations.size() > 0) {fop.write("[\n".getBytes());} + fop.write(String.join(",\n", relations).getBytes()); + if(relations.size() > 0) {fop.write("\n]\n".getBytes());} + fop.flush(); + fop.close(); + } catch (Exception e) { + e.printStackTrace(); + return; + } + logger.debug(String.join(",\n", relations)); + return; + } + + private static String formatObjectRelationSet(String obj, String selectObj) { + StringBuffer pathSb = new StringBuffer(); + String[] paths = selectObj.split("[|]"); + for (String s: paths) { + logger.trace("SelectOBJ"+s); + pathSb.append(formatObjectRelation(obj, s)+",\n"); + } + pathSb.deleteCharAt(pathSb.length()-2); + return pathSb.toString(); + } + + private static String formatObjectRelation(String obj, String selectObj) { + StringBuffer pathSb = new StringBuffer(); + pathSb.append("{\n"); + pathSb.append("\"related-to\" : \""+obj+"\",\n"); + pathSb.append("\"related-link\" : \""+selectObj+"\"\n"); + pathSb.append("}"); + return pathSb.toString(); + } + + private static String getKinObjectPath(String obj, String apiPath) { + LevenshteinDistance proximity = new LevenshteinDistance(); + String targetPath = ""; + int targetScore = Integer.MAX_VALUE; + int targetMaxScore = 0; + for (Map.Entry p : DeleteOperation.deletePaths.entrySet()) { + if(p.getValue().equals(obj)) { + targetScore = (targetScore >= proximity.apply(apiPath, p.getKey())) ? proximity.apply(apiPath, p.getKey()) : targetScore; + targetPath = (targetScore >= proximity.apply(apiPath, p.getKey())) ? p.getKey() : targetPath; + targetMaxScore = (targetMaxScore <= proximity.apply(apiPath, p.getKey())) ? proximity.apply(apiPath, p.getKey()) : targetScore; + logger.trace(proximity.apply(apiPath, p.getKey())+":"+p.getKey()); + logger.trace(proximity.apply(apiPath, p.getKey())+":"+apiPath); + } + } + return targetPath; + } + + private static String getUnrelatedObjectPaths(String obj, String apiPath) { + String targetPath = ""; + logger.trace("Obj:"+obj +"\n" + apiPath); + for (Map.Entry p : DeleteOperation.deletePaths.entrySet()) { + if(p.getValue().equals(obj)) { + logger.trace("p.getvalue:"+p.getValue()+"p.getkey:"+p.getKey()); + targetPath += ((targetPath.length() == 0 ? "" : "|") + p.getKey()); + logger.trace("Match:"+apiPath +"\n" + targetPath); + } + } + return targetPath; + } + + public void generateRelations(EdgeRuleSet edgeRuleSet) { + + if(putRelationPaths == null) + return; + if(edgeRuleSet == null) + return; + else + PutRelationPathSet.edgeRuleSet = edgeRuleSet; + putRelationPaths.forEach((k,v)->{ + 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")); + logger.debug("apiPath(Operation): "+v); + logger.debug("Target object: "+v.replace("/relationship-list/relationship", "")); + logger.debug("Relations: "); + PutRelationPathSet prp = new PutRelationPathSet(k, v, this.version); + prp.process(); + }); + } + +} diff --git a/aai-core/src/main/java/org/onap/aai/util/genxsd/XSDElement.java b/aai-core/src/main/java/org/onap/aai/util/genxsd/XSDElement.java new file mode 100644 index 00000000..894e7520 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/util/genxsd/XSDElement.java @@ -0,0 +1,678 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.util.genxsd; + +import com.google.common.base.Joiner; +import org.apache.commons.lang3.StringUtils; +import org.onap.aai.introspection.Version; +import org.w3c.dom.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; +import java.util.Vector; + +public class XSDElement implements Element { + Element xmlElementElement; + private static final int VALUE_NONE = 0; + private static final int VALUE_DESCRIPTION = 1; + private static final int VALUE_INDEXED_PROPS = 2; + private static final int VALUE_CONTAINER = 3; + + public XSDElement(Element xmlElementElement) { + super(); + this.xmlElementElement = xmlElementElement; + } + public String name() { + return this.getAttribute("name"); + } + + public Vector getAddTypes(String version) { + String apiVersionFmt = "." + version + "."; + NamedNodeMap attributes = this.getAttributes(); + Vector addTypeV = new Vector(); // vector of 1 + String addType = null; + + for ( int j = 0; j < attributes.getLength(); ++j ) { + Attr attr = (Attr) attributes.item(j); + String attrName = attr.getNodeName(); + + String attrValue = attr.getNodeValue(); + if ( attrName.equals("type")) { + if ( attrValue.contains(apiVersionFmt) ) { + addType = attrValue.substring(attrValue.lastIndexOf('.')+1); + if ( addTypeV == null ) + addTypeV = new Vector(); + addTypeV.add(addType); + } + + } + } + return addTypeV; + } + + public String getPathDescriptionProperty() { + String pathDescriptionProperty = null; + NodeList xmlPropNodes = this.getElementsByTagName("xml-properties"); + + for ( int i = 0; i < xmlPropNodes.getLength(); ++i ) { + Element xmlPropElement = (Element)xmlPropNodes.item(i); + if (! xmlPropElement.getParentNode().getAttributes().getNamedItem("name").getNodeValue().equals(this.xmlElementElement.getAttribute("name"))){ + continue; + } +// This stopped working, replaced with above - should figure out why... +// if ( !xmlPropElement.getParentNode().isSameNode(this.xmlElementElement)) +// continue; + NodeList childNodes = xmlPropElement.getElementsByTagName("xml-property"); + + for ( int j = 0; j < childNodes.getLength(); ++j ) { + Element childElement = (Element)childNodes.item(j); + // get name + int useValue = VALUE_NONE; + NamedNodeMap attributes = childElement.getAttributes(); + for ( int k = 0; k < attributes.getLength(); ++k ) { + Attr attr = (Attr) attributes.item(k); + String attrName = attr.getNodeName(); + String attrValue = attr.getNodeValue(); + if ( attrName == null || attrValue == null ) + continue; + if ( attrName.equals("name") && attrValue.equals("description")) { + useValue = VALUE_DESCRIPTION; + } + if ( useValue == VALUE_DESCRIPTION && attrName.equals("value")) { + pathDescriptionProperty = attrValue; + } + } + } + } + return pathDescriptionProperty; + } + public Vector getIndexedProps() { + Vector indexedProps = new Vector(); + NodeList xmlPropNodes = this.getElementsByTagName("xml-properties"); + + for ( int i = 0; i < xmlPropNodes.getLength(); ++i ) { + Element xmlPropElement = (Element)xmlPropNodes.item(i); + if ( !xmlPropElement.getParentNode().isSameNode(this.xmlElementElement)) + continue; + NodeList childNodes = xmlPropElement.getElementsByTagName("xml-property"); + for ( int j = 0; j < childNodes.getLength(); ++j ) { + Element childElement = (Element)childNodes.item(j); + // get name + int useValue = VALUE_NONE; + NamedNodeMap attributes = childElement.getAttributes(); + for ( int k = 0; k < attributes.getLength(); ++k ) { + Attr attr = (Attr) attributes.item(k); + String attrName = attr.getNodeName(); + String attrValue = attr.getNodeValue(); + if ( attrName == null || attrValue == null ) + continue; + if ( attrValue.equals("indexedProps")) { + useValue = VALUE_INDEXED_PROPS; + } + if ( useValue == VALUE_INDEXED_PROPS && attrName.equals("value")) { + indexedProps = getIndexedProps( attrValue ); + } + } + } + } + return indexedProps; + } + + private static Vector getIndexedProps( String attrValue ) + { + if ( attrValue == null ) + return null; + StringTokenizer st = new StringTokenizer( attrValue, ","); + if ( st.countTokens() == 0 ) + return null; + Vector result = new Vector(); + while ( st.hasMoreTokens()) { + result.add(st.nextToken()); + } + return result; + } + + public String getContainerProperty() { + NodeList xmlPropNodes = this.getElementsByTagName("xml-properties"); + String container = null; + for ( int i = 0; i < xmlPropNodes.getLength(); ++i ) { + Element xmlPropElement = (Element)xmlPropNodes.item(i); + if ( !xmlPropElement.getParentNode().isSameNode(this.xmlElementElement)) + continue; + NodeList childNodes = xmlPropElement.getElementsByTagName("xml-property"); + for ( int j = 0; j < childNodes.getLength(); ++j ) { + Element childElement = (Element)childNodes.item(j); + // get name + int useValue = VALUE_NONE; + NamedNodeMap attributes = childElement.getAttributes(); + for ( int k = 0; k < attributes.getLength(); ++k ) { + Attr attr = (Attr) attributes.item(k); + String attrName = attr.getNodeName(); + String attrValue = attr.getNodeValue(); + if ( attrName == null || attrValue == null ) + continue; + if ( useValue == VALUE_CONTAINER && attrName.equals("value")) { + container = attrValue; + } + if ( attrValue.equals("container")) { + useValue = VALUE_CONTAINER; + } + } + } + } + return container; + } + + public String getQueryParamYAML() { + StringBuffer sbParameter = new StringBuffer(); + sbParameter.append((" - name: " + this.getAttribute("name") + "\n")); + sbParameter.append((" in: query\n")); + if ( this.getAttribute("description") != null && this.getAttribute("description").length() > 0 ) + sbParameter.append((" description: " + this.getAttribute("description") + "\n")); + else + sbParameter.append((" description:\n")); + sbParameter.append((" required: false\n")); + if ( ("java.lang.String").equals(this.getAttribute("type"))) + sbParameter.append(" type: string\n"); + if ( ("java.lang.Long").equals(this.getAttribute("type"))) { + sbParameter.append(" type: integer\n"); + sbParameter.append(" format: int64\n"); + } + if ( ("java.lang.Integer").equals(this.getAttribute("type"))) { + sbParameter.append(" type: integer\n"); + sbParameter.append(" format: int32\n"); + } + if ( ("java.lang.Boolean").equals(this.getAttribute("type"))) { + sbParameter.append(" type: boolean\n"); + } + return sbParameter.toString(); + } + + public String getPathParamYAML(String elementDescription) { + StringBuffer sbParameter = new StringBuffer(); + sbParameter.append((" - name: " + this.getAttribute("name") + "\n")); + sbParameter.append((" in: path\n")); + if ( elementDescription != null && elementDescription.length() > 0 ) + sbParameter.append((" description: " + elementDescription + "\n")); + sbParameter.append((" required: true\n")); + if ( ("java.lang.String").equals(this.getAttribute("type"))) + sbParameter.append(" type: string\n"); + if ( ("java.lang.Long").equals(this.getAttribute("type"))) { + sbParameter.append(" type: integer\n"); + sbParameter.append(" format: int64\n"); + } + if ( ("java.lang.Integer").equals(this.getAttribute("type"))) { + sbParameter.append(" type: integer\n"); + sbParameter.append(" format: int32\n"); + } + if ( ("java.lang.Boolean").equals(this.getAttribute("type"))) { + sbParameter.append(" type: boolean\n"); + } + if(StringUtils.isNotBlank(this.getAttribute("name"))) { + sbParameter.append(" example: "+"__"+this.getAttribute("name").toUpperCase()+"__"+"\n"); + } + return sbParameter.toString(); + } + + public String getHTMLElement(Version v, boolean useAnnotation, HTMLfromOXM driver) { + StringBuffer sbElement = new StringBuffer(); + String elementName = this.getAttribute("name"); + String elementType = this.getAttribute("type"); + String elementContainerType = this.getAttribute("container-type"); + String elementIsRequired = this.getAttribute("required"); + String addType = elementType.contains("." + v.name() + ".") ? elementType.substring(elementType.lastIndexOf('.')+1) : null; + + if ( addType != null ) { + sbElement.append(" \n" : ""); + sbElement.append(annotation); + sbElement.append(StringUtils.isNotEmpty(annotation) ? " \n" : "/>\n" ); + } else { + sbElement.append("/>\n"); + } + return this.getHTMLElementWrapper(sbElement.toString(), v, useAnnotation); +// return sbElement.toString(); + } + + public String getHTMLElementWrapper(String unwrappedElement, Version v, boolean useAnnotation) { + + NodeList childNodes = this.getElementsByTagName("xml-element-wrapper"); + + String xmlElementWrapper = null; + if ( childNodes.getLength() > 0 ) { + Element childElement = (Element)childNodes.item(0); + // get name + xmlElementWrapper = childElement == null ? null : childElement.getAttribute("name"); + } + if(xmlElementWrapper == null) + return unwrappedElement; + + StringBuffer sbElement = new StringBuffer(); + sbElement.append(" \n"); + sbElement.append(" \n"); + if(useAnnotation) { + XSDElement javaTypeElement = new XSDElement((Element)this.getParentNode()); + sbElement.append(javaTypeElement.getHTMLAnnotation("class", " ")); + } + sbElement.append(" \n"); + sbElement.append(" "); + sbElement.append(unwrappedElement); + sbElement.append(" \n"); + sbElement.append(" \n"); + sbElement.append(" \n"); + return sbElement.toString(); + } + + public String getHTMLAnnotation(String target, String indentation) { + StringBuffer sb = new StringBuffer(); + List metadata = new ArrayList<>(); + if("true".equals(this.getAttribute("xml-key")) ) { + metadata.add("isKey=true"); + } + + NodeList xmlPropTags = this.getElementsByTagName("xml-properties"); + Element xmlPropElement = null; + for ( int i = 0; i < xmlPropTags.getLength(); ++i ) { + xmlPropElement = (Element)xmlPropTags.item(i); + if (! xmlPropElement.getParentNode().getAttributes().getNamedItem("name").getNodeValue().equals(this.xmlElementElement.getAttribute("name"))) + continue; + else + break; + } + if(xmlPropElement != null) { + NodeList xmlProperties = xmlPropElement.getElementsByTagName("xml-property"); + for (int i = 0; i < xmlProperties.getLength(); i++) { + Element item = (Element)xmlProperties.item(i); + String name = item.getAttribute("name"); + String value = item.getAttribute("value"); + if (name.equals("abstract")) { + name = "isAbstract"; + } else if (name.equals("extends")) { + name = "extendsFrom"; + } + metadata.add(name + "=\"" + value.replaceAll("&", "&") + "\""); + } + } + if(metadata.size() == 0) { + return ""; + } + sb.append(indentation +"\r\n"); + sb.append( + indentation + " \r\n" + + indentation + " @org.onap.aai.annotations.Metadata(" + Joiner.on(",").join(metadata) + ")\r\n" + + indentation + " \r\n"); + sb.append(indentation +"\r\n"); + return sb.toString(); + } + + public String getTypePropertyYAML() { + StringBuffer sbProperties = new StringBuffer(); + sbProperties.append(" " + this.getAttribute("name") + ":\n"); + sbProperties.append(" type: "); + + if ( ("java.lang.String").equals(this.getAttribute("type"))) + sbProperties.append("string\n"); + else if ( ("java.lang.Long").equals(this.getAttribute("type"))) { + sbProperties.append("integer\n"); + sbProperties.append(" format: int64\n"); + } + else if ( ("java.lang.Integer").equals(this.getAttribute("type"))){ + sbProperties.append("integer\n"); + sbProperties.append(" format: int32\n"); + } + else if ( ("java.lang.Boolean").equals(this.getAttribute("type"))) + sbProperties.append("boolean\n"); + String attrDescription = this.getPathDescriptionProperty(); + if ( attrDescription != null && attrDescription.length() > 0 ) + sbProperties.append(" description: " + attrDescription + "\n"); + return sbProperties.toString(); + } + + public boolean isStandardType() + { + switch ( this.getAttribute("type") ) { + case "java.lang.String": + case "java.lang.Long": + case "java.lang.Integer": + case"java.lang.Boolean": + return true; + } + return false; + } + + @Override + public String getNodeName() { + return xmlElementElement.getNodeName(); + } + + @Override + public String getNodeValue() throws DOMException { + return xmlElementElement.getNodeValue(); + } + + @Override + public void setNodeValue(String nodeValue) throws DOMException { + xmlElementElement.setNodeValue(nodeValue); + } + + @Override + public short getNodeType() { + return xmlElementElement.getNodeType(); + } + + @Override + public Node getParentNode() { + return xmlElementElement.getParentNode(); + } + + @Override + public NodeList getChildNodes() { + return xmlElementElement.getChildNodes(); + } + + @Override + public Node getFirstChild() { + return xmlElementElement.getFirstChild(); + } + + @Override + public Node getLastChild() { + return xmlElementElement.getLastChild(); + } + + @Override + public Node getPreviousSibling() { + return xmlElementElement.getPreviousSibling(); + } + + @Override + public Node getNextSibling() { + return xmlElementElement.getNextSibling(); + } + + @Override + public NamedNodeMap getAttributes() { + return xmlElementElement.getAttributes(); + } + + @Override + public Document getOwnerDocument() { + return xmlElementElement.getOwnerDocument(); + } + + @Override + public Node insertBefore(Node newChild, Node refChild) throws DOMException { + return xmlElementElement.insertBefore(newChild, refChild); + } + + @Override + public Node replaceChild(Node newChild, Node oldChild) throws DOMException { + return xmlElementElement.replaceChild(newChild, oldChild); + } + + @Override + public Node removeChild(Node oldChild) throws DOMException { + return xmlElementElement.removeChild(oldChild); + } + + @Override + public Node appendChild(Node newChild) throws DOMException { + return xmlElementElement.appendChild(newChild); + } + + @Override + public boolean hasChildNodes() { + return xmlElementElement.hasChildNodes(); + } + + @Override + public Node cloneNode(boolean deep) { + return xmlElementElement.cloneNode(deep); + } + + @Override + public void normalize() { + xmlElementElement.normalize(); + } + + @Override + public boolean isSupported(String feature, String version) { + return xmlElementElement.isSupported(feature, version); + } + + @Override + public String getNamespaceURI() { + return xmlElementElement.getNamespaceURI(); + } + + @Override + public String getPrefix() { + return xmlElementElement.getPrefix(); + } + + @Override + public void setPrefix(String prefix) throws DOMException { + xmlElementElement.setPrefix(prefix); + } + + @Override + public String getLocalName() { + + return xmlElementElement.getLocalName(); + } + + @Override + public boolean hasAttributes() { + return xmlElementElement.hasAttributes(); + } + + @Override + public String getBaseURI() { + return xmlElementElement.getBaseURI(); + } + + @Override + public short compareDocumentPosition(Node other) throws DOMException { + return xmlElementElement.compareDocumentPosition(other); + } + + @Override + public String getTextContent() throws DOMException { + return xmlElementElement.getTextContent(); + } + + @Override + public void setTextContent(String textContent) throws DOMException { + xmlElementElement.setTextContent(textContent); + } + + @Override + public boolean isSameNode(Node other) { + return xmlElementElement.isSameNode(other); + } + + @Override + public String lookupPrefix(String namespaceURI) { + return xmlElementElement.lookupPrefix(namespaceURI); + } + + @Override + public boolean isDefaultNamespace(String namespaceURI) { + return xmlElementElement.isDefaultNamespace(namespaceURI); + } + + @Override + public String lookupNamespaceURI(String prefix) { + return xmlElementElement.lookupNamespaceURI(prefix); + } + + @Override + public boolean isEqualNode(Node arg) { + return xmlElementElement.isEqualNode(arg); + } + + @Override + public Object getFeature(String feature, String version) { + return xmlElementElement.getFeature(feature, version); + } + + @Override + public Object setUserData(String key, Object data, UserDataHandler handler) { + return xmlElementElement.setUserData(key, data, handler); + } + + @Override + public Object getUserData(String key) { + return xmlElementElement.getUserData(key); + } + + @Override + public String getTagName() { + return xmlElementElement.getTagName(); + } + + @Override + public String getAttribute(String name) { + return xmlElementElement.getAttribute(name); + } + + @Override + public void setAttribute(String name, String value) throws DOMException { + xmlElementElement.setAttribute(name, value); + } + + @Override + public void removeAttribute(String name) throws DOMException { + xmlElementElement.removeAttribute(name); + } + + @Override + public Attr getAttributeNode(String name) { + return xmlElementElement.getAttributeNode(name); + } + + @Override + public Attr setAttributeNode(Attr newAttr) throws DOMException { + return xmlElementElement.setAttributeNode(newAttr); + } + + @Override + public Attr removeAttributeNode(Attr oldAttr) throws DOMException { + return xmlElementElement.removeAttributeNode(oldAttr); + } + + @Override + public NodeList getElementsByTagName(String name) { + return xmlElementElement.getElementsByTagName(name); + } + + @Override + public String getAttributeNS(String namespaceURI, String localName) throws DOMException { + return xmlElementElement.getAttributeNS(namespaceURI, localName); + } + + @Override + public void setAttributeNS(String namespaceURI, String qualifiedName, String value) throws DOMException { + xmlElementElement.setAttributeNS(namespaceURI, qualifiedName, value); + return; + } + + @Override + public void removeAttributeNS(String namespaceURI, String localName) throws DOMException { + xmlElementElement.removeAttributeNS(namespaceURI, localName); + } + + @Override + public Attr getAttributeNodeNS(String namespaceURI, String localName) throws DOMException { + return xmlElementElement.getAttributeNodeNS(namespaceURI, localName); + } + + @Override + public Attr setAttributeNodeNS(Attr newAttr) throws DOMException { + return xmlElementElement.setAttributeNodeNS(newAttr); + } + + @Override + public NodeList getElementsByTagNameNS(String namespaceURI, String localName) throws DOMException { + return xmlElementElement.getElementsByTagNameNS(namespaceURI, localName); + } + + @Override + public boolean hasAttribute(String name) { + return xmlElementElement.hasAttribute(name); + } + + @Override + public boolean hasAttributeNS(String namespaceURI, String localName) throws DOMException { + return xmlElementElement.hasAttributeNS(namespaceURI, localName); + } + + @Override + public TypeInfo getSchemaTypeInfo() { + return xmlElementElement.getSchemaTypeInfo(); + } + + @Override + public void setIdAttribute(String name, boolean isId) throws DOMException { + xmlElementElement.setIdAttribute(name, isId); + + } + + @Override + public void setIdAttributeNS(String namespaceURI, String localName, boolean isId) throws DOMException { + xmlElementElement.setIdAttributeNS(namespaceURI, localName, isId); + } + + @Override + public void setIdAttributeNode(Attr idAttr, boolean isId) throws DOMException { + xmlElementElement.setIdAttributeNode(idAttr, isId); + return; + } + + +} diff --git a/aai-core/src/main/java/org/onap/aai/util/genxsd/XSDJavaType.java b/aai-core/src/main/java/org/onap/aai/util/genxsd/XSDJavaType.java new file mode 100644 index 00000000..6315ddff --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/util/genxsd/XSDJavaType.java @@ -0,0 +1,64 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.util.genxsd; + +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +public class XSDJavaType extends XSDElement { + StringBuffer pathSb; + StringBuffer definitionsSb; + StringBuffer pathParams; + + public XSDJavaType(Element javaTypeElement) { + super(javaTypeElement); + } +/* + public XSDJavaType(XSDElement javaTypeElement, StringBuffer pathSb, StringBuffer definitionsSb, + StringBuffer pathParams) { + super(javaTypeElement); + this.pathSb = pathSb; + this.definitionsSb = definitionsSb; + this.pathParams = pathParams; + } +*/ + public String getItemName() { + NodeList parentNodes = this.getElementsByTagName("java-attributes"); + if(parentNodes.getLength() == 0) + return null; + Element parentElement = (Element)parentNodes.item(0); + NodeList xmlElementNodes = parentElement.getElementsByTagName("xml-element"); + XSDElement xmlElementElement = new XSDElement((Element)xmlElementNodes.item(0)); + return xmlElementElement.getAttribute("name"); + } + + public String getArrayType() { + NodeList parentNodes = this.getElementsByTagName("java-attributes"); + if(parentNodes.getLength() == 0) + return null; + Element parentElement = (Element)parentNodes.item(0); + NodeList xmlElementNodes = parentElement.getElementsByTagName("xml-element"); + XSDElement xmlElementElement = new XSDElement((Element)xmlElementNodes.item(0)); + if ( xmlElementElement.hasAttribute("container-type") && xmlElementElement.getAttribute("container-type").equals("java.util.ArrayList")) { + return xmlElementElement.getAttribute("name"); + } + return null; + } +} diff --git a/aai-core/src/main/java/org/onap/aai/util/genxsd/YAMLfromOXM.java b/aai-core/src/main/java/org/onap/aai/util/genxsd/YAMLfromOXM.java new file mode 100644 index 00000000..ff7d44b6 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/util/genxsd/YAMLfromOXM.java @@ -0,0 +1,470 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.util.genxsd; + +import org.apache.commons.lang3.StringUtils; +import org.onap.aai.exceptions.AAIException; +import org.onap.aai.introspection.Version; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import javax.xml.parsers.ParserConfigurationException; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; + +public class YAMLfromOXM extends OxmFileProcessor { + private static final Logger logger = LoggerFactory.getLogger("GenerateXsd.class"); + private static final String root = "../aai-schema/src/main/resources"; + private static final String autoGenRoot = "aai-schema/src/main/resources"; + private static final String generateTypeYAML = "yaml"; + private static final String normalStartDir = "aai-core"; + private static final String yaml_dir = (((System.getProperty("user.dir") != null) && (!System.getProperty("user.dir").contains(normalStartDir))) ? autoGenRoot : root) + "/aai_swagger_yaml"; + + private File edgeFile; + private EdgeRuleSet edgeRuleSet = null; + public YAMLfromOXM(File oxmFile, Version v, File edgeFile) throws ParserConfigurationException, SAXException, IOException, AAIException, FileNotFoundException { + super(oxmFile, v); + this.edgeFile = edgeFile; + init(); + } + public YAMLfromOXM(String xml, Version v, File edgeFile) throws ParserConfigurationException, SAXException, IOException, AAIException, FileNotFoundException { + super(xml, v); + this.edgeFile = edgeFile; + init(); + } + + @Override + public String getDocumentHeader() { + StringBuffer sb = new StringBuffer(); + sb.append("swagger: \"2.0\"\ninfo:\n "); + sb.append("description: |"); + sb.append("\n\n [Differences versus the previous schema version]("+"apidocs/aai_swagger_" + v.name() + ".diff)"); + 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: \"" + v.name() +"\"\n"); + sb.append(" title: Active and Available Inventory REST API\n"); + sb.append(" license:\n name: Apache 2.0\n url: http://www.apache.org/licenses/LICENSE-2.0.html\n"); + sb.append(" contact:\n name:\n url:\n email:\n"); + sb.append("host:\nbasePath: /aai/" + v.name() + "\n"); + sb.append("schemes:\n - https\npaths:\n"); + return sb.toString(); + } + + protected void init() throws ParserConfigurationException, SAXException, IOException, AAIException, FileNotFoundException { + super.init(); + edgeRuleSet = new EdgeRuleSet(edgeFile); + } + + @Override + public String process() throws AAIException { + StringBuffer sb = new StringBuffer(); + EdgeRuleSet edgeRuleSet = null; + try { + edgeRuleSet = new EdgeRuleSet(edgeFile); + } catch (Exception e) { + logger.warn("No valid Edge Rule Set available("+edgeFile+"): "+e.getMessage()); + } + + StringBuffer pathSb = new StringBuffer(); + pathSb.append(getDocumentHeader()); + StringBuffer definitionsSb = new StringBuffer(); + for ( int i = 0; i < javaTypeNodes.getLength(); ++ i ) { + XSDElement javaTypeElement = new XSDElement((Element)javaTypeNodes.item(i)); + logger.debug("External: "+javaTypeElement.getAttribute("name")); + String javaTypeName = javaTypeElement.name(); + if ( javaTypeName == null ) { + String msg = "Invalid OXM file: has no name attribute in " + oxmFile; + logger.error(msg); + throw new AAIException(msg); + } + //Skip any type that has already been processed(recursion could be the reason) + if ( generatedJavaType.containsKey(getXmlRootElementName(javaTypeName)) ) { + continue; + } + processJavaTypeElementSwagger( javaTypeName, javaTypeElement, pathSb, + definitionsSb, null, null, null, null, null, null); + } + sb.append(pathSb); + + sb.append(appendDefinitions()); + PutRelationPathSet prp = new PutRelationPathSet(v); + prp.generateRelations(edgeRuleSet); + return sb.toString(); + } + + public String appendDefinitions() { + //append definitions + StringBuffer sb = new StringBuffer("definitions:\n"); + Map sortedJavaTypeDefinitions = new TreeMap(javaTypeDefinitions); + for (Map.Entry entry : sortedJavaTypeDefinitions.entrySet()) { + logger.debug("Key: "+entry.getKey()+"Test: "+ (entry.getKey() == "relationship")); + if(entry.getKey().matches("relationship")) { + String jb=entry.getValue(); + logger.debug("Value: "+jb); + int ndx=jb.indexOf("related-to-property:"); + if(ndx > 0) { + jb=jb.substring(0, ndx); + jb=jb.replaceAll(" +$", ""); + } + logger.debug("Value-after: "+jb); + sb.append(jb); + continue; + } + sb.append(entry.getValue()); + } + + sb.append("patchDefinitions:\n"); + for (Map.Entry entry : sortedJavaTypeDefinitions.entrySet()) { + String jb=entry.getValue().replaceAll("/definitions/", "/patchDefinitions/"); + int ndx=jb.indexOf("relationship-list:"); + if(ndx > 0) { + jb=jb.substring(0, ndx); + jb=jb.replaceAll(" +$", ""); + } + int ndx1=jb.indexOf("resource-version:"); + logger.debug("Key: "+entry.getKey()+" index: " + ndx1); + logger.debug("Value: "+jb); + if(ndx1 > 0) { + jb=jb.substring(0, ndx1); + jb=jb.replaceAll(" +$", ""); + } + logger.debug("Value-after: "+jb); + sb.append(jb); + } + + sb.append("getDefinitions:\n"); + for (Map.Entry entry : sortedJavaTypeDefinitions.entrySet()) { + String jb=entry.getValue().replaceAll("/definitions/", "/getDefinitions/"); + sb.append(jb); + } + return sb.toString(); + } + + private String processJavaTypeElementSwagger( String javaTypeName, Element javaTypeElement, + StringBuffer pathSb, StringBuffer definitionsSb, String path, String tag, String opId, + String getItemName, StringBuffer pathParams, String validEdges) { + + String xmlRootElementName = getXMLRootElementName(javaTypeElement); + StringBuilder definitionsLocalSb = new StringBuilder(256); + + String useTag = null; + String useOpId = null; + logger.debug("tag="+tag); + if ( tag != null ) { + switch ( tag ) { + case "Network": + case "ServiceDesignAndCreation": + case "Business": + case "LicenseManagement": + case "CloudInfrastructure": + break; + default: + logger.debug("javaTypeName="+javaTypeName); + return null; + } + } + + if ( !javaTypeName.equals("Inventory") ) { + if ( javaTypeName.equals("AaiInternal")) + return null; + if ( opId == null ) + useOpId = javaTypeName; + else + useOpId = opId + javaTypeName; + if ( tag == null ) + useTag = javaTypeName; + } + + path = xmlRootElementName.equals("inventory") ? "" : (path == null) ? "/" + xmlRootElementName : path + "/" + xmlRootElementName; + XSDJavaType javaType = new XSDJavaType(javaTypeElement); + if ( getItemName != null) { + if ( getItemName.equals("array") ) + return javaType.getArrayType(); + else + return javaType.getItemName(); + } + + NodeList parentNodes = javaTypeElement.getElementsByTagName("java-attributes"); + if ( parentNodes.getLength() == 0 ) { + logger.debug( "no java-attributes for java-type " + javaTypeName); + return ""; + } + + String pathDescriptionProperty = javaType.getPathDescriptionProperty(); + String container = javaType.getContainerProperty(); + Vector indexedProps = javaType.getIndexedProps(); + Vector containerProps = new Vector(); + if(container != null) { + logger.debug("javaTypeName " + javaTypeName + " container:" + container +" indexedProps:"+indexedProps); + } + + Element parentElement = (Element)parentNodes.item(0); + NodeList xmlElementNodes = parentElement.getElementsByTagName("xml-element"); + + StringBuffer sbParameters = new StringBuffer(); + StringBuffer sbRequired = new StringBuffer(); + int requiredCnt = 0; + int propertyCnt = 0; + StringBuffer sbProperties = new StringBuffer(); + + if ( appliedPaths.containsKey(path)) + return null; + + StringTokenizer st = new StringTokenizer(path, "/"); + logger.debug("path: " + path + " st? " + st.toString()); + if ( st.countTokens() > 1 && getItemName == null ) { + logger.debug("appliedPaths: " + appliedPaths + " containsKey? " + appliedPaths.containsKey(path)); + appliedPaths.put(path, xmlRootElementName); + } + + Vector addTypeV = null; + for ( int i = 0; i < xmlElementNodes.getLength(); ++i ) { + XSDElement xmlElementElement = new XSDElement((Element)xmlElementNodes.item(i)); + if ( !xmlElementElement.getParentNode().isSameNode(parentElement)) + continue; + String elementDescription=xmlElementElement.getPathDescriptionProperty(); + if(getItemName == null) { + addTypeV = xmlElementElement.getAddTypes(v.name()); + } + if ( "true".equals(xmlElementElement.getAttribute("xml-key"))) { + path += "/{" + xmlElementElement.getAttribute("name") + "}"; + } + logger.debug("path: " + path); + logger.debug( "xmlElementElement.getAttribute(required):"+xmlElementElement.getAttribute("required") ); + + if ( ("true").equals(xmlElementElement.getAttribute("required"))) { + if ( requiredCnt == 0 ) + sbRequired.append(" required:\n"); + ++requiredCnt; + if ( addTypeV == null || addTypeV.isEmpty()) { + sbRequired.append(" - " + xmlElementElement.getAttribute("name") + "\n"); + } else { + for ( int k = 0; k < addTypeV.size(); ++k ) { + sbRequired.append(" - " + getXmlRootElementName(addTypeV.elementAt(k)) + ":\n"); + } + } + } + + if ( "true".equals(xmlElementElement.getAttribute("xml-key")) ) { + sbParameters.append(xmlElementElement.getPathParamYAML(elementDescription)); + } + if ( indexedProps != null + && indexedProps.contains(xmlElementElement.getAttribute("name") ) ) { + containerProps.add(xmlElementElement.getQueryParamYAML()); + GetOperation.addContainerProps(container, containerProps); + } + if ( xmlElementElement.isStandardType()) { + sbProperties.append(xmlElementElement.getTypePropertyYAML()); + ++propertyCnt; + } + + StringBuffer newPathParams = new StringBuffer((pathParams == null ? "" : pathParams.toString())+sbParameters.toString()); + for ( int k = 0; addTypeV != null && k < addTypeV.size(); ++k ) { + String addType = addTypeV.elementAt(k); + logger.debug("addType: "+ addType); + if(addType == "overloaded-model" || addType.equals("OverloadedModel") || addType == "owning-entity") { + logger.debug("Description check: "+ addType+"opId="+opId+" itemName=none"); +// Log.info("Element name="+xmlElementElement.getAttribute("name")); + } + + + if ( opId == null || !opId.contains(addType)) { + processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType), + pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId, null, + newPathParams, validEdges); + } + // need item name of array + String itemName = processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType), + pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId, + "array", null, null ); + + if ( itemName != null ) { + if ( addType.equals("AaiInternal") ) { + logger.debug( "addType AaiInternal, skip properties"); + + } else if ( getItemName == null) { + ++propertyCnt; + sbProperties.append(" " + getXmlRootElementName(addType) + ":\n"); + sbProperties.append(" type: array\n items:\n"); + sbProperties.append(" $ref: \"#/definitions/" + (itemName == "" ? "aai-internal" : itemName) + "\"\n"); + if ( StringUtils.isNotEmpty(elementDescription) ) + sbProperties.append(" description: " + elementDescription + "\n"); + } + } else { + if ( ("java.util.ArrayList").equals(xmlElementElement.getAttribute("container-type"))) { + // need properties for getXmlRootElementName(addType) + newPathParams = new StringBuffer((pathParams == null ? "" : pathParams.toString())+sbParameters.toString()); + processJavaTypeElementSwagger( addType, getJavaTypeElementSwagger(addType), + pathSb, definitionsSb, path, tag == null ? useTag : tag, useOpId, + null, newPathParams, validEdges ); + sbProperties.append(" " + getXmlRootElementName(addType) + ":\n"); + sbProperties.append(" type: array\n items: \n"); + sbProperties.append(" $ref: \"#/definitions/" + getXmlRootElementName(addType) + "\"\n"); + if ( StringUtils.isNotEmpty(elementDescription) ) + sbProperties.append(" description: " + elementDescription + "\n"); + + } else { + if(addType.equals("AaiInternal")) //Filter out references to AaiInternal + sbProperties.append(""); + else { + sbProperties.append(" " + getXmlRootElementName(addType) + ":\n"); + sbProperties.append(" type: object\n"); + sbProperties.append(" $ref: \"#/definitions/" + getXmlRootElementName(addType) + "\"\n"); + } + } + if ( StringUtils.isNotEmpty(elementDescription) ) + sbProperties.append(" description: " + elementDescription + "\n"); + ++propertyCnt; + } + } + } + + if ( sbParameters.toString().length() > 0 ) { + if ( pathParams == null ) + pathParams = new StringBuffer(); + pathParams.append(sbParameters); + } + GetOperation get = new GetOperation(useOpId, xmlRootElementName, tag, path, pathParams == null ? "" : pathParams.toString()); + pathSb.append(get.toString()); + logger.debug("opId vs useOpId:"+opId+" vs "+useOpId+" PathParams="+pathParams); + // add PUT + PutOperation put = new PutOperation(useOpId, xmlRootElementName, tag, path, pathParams == null ? "" : pathParams.toString(), this.v); + pathSb.append(put.toString()); + // add PATCH + PatchOperation patch = new PatchOperation(useOpId, xmlRootElementName, tag, path, pathParams == null ? "" : pathParams.toString()); + pathSb.append(patch.toString()); + // add DELETE + DeleteOperation del = new DeleteOperation(useOpId, xmlRootElementName, tag, path, pathParams == null ? "" : pathParams.toString()); + pathSb.append(del.toString()); + //Write operations by Namespace(tagName) +// if(javaTypeName == useTag && tag == null) { +// pathSb.append(appendDefinitions()); +// writeYAMLfile(javaTypeName, pathSb.toString()); +// pathSb.delete(0, pathSb.length()); +// javaTypeDefinitions.clear(); +// generatedJavaType.clear(); +// } + if ( generatedJavaType.containsKey(xmlRootElementName) ) { + logger.debug("xmlRootElementName(1)="+xmlRootElementName); + return null; + } + + definitionsSb.append(" " + xmlRootElementName + ":\n"); + definitionsLocalSb.append(" " + xmlRootElementName + ":\n"); + Collection edges = edgeRuleSet.getEdgeRules(xmlRootElementName ); + DeleteFootnoteSet footnotes = new DeleteFootnoteSet(xmlRootElementName); + if ( edges.size() > 0 ) { + StringBuffer sbEdge = new StringBuffer(); + sbEdge.append(" ###### Related Nodes\n"); + + for (EdgeDescription ed : edges) { + if ( ed.getRuleKey().startsWith(xmlRootElementName)) { + sbEdge.append(" - TO ").append(ed.getRuleKey().substring(ed.getRuleKey().indexOf("|")+1)); + String footnote = ed.getAlsoDeleteFootnote(xmlRootElementName); + sbEdge.append(ed.getRelationshipDescription("TO", xmlRootElementName)+footnote+"\n"); + if(StringUtils.isNotEmpty(footnote)) footnotes.add(footnote); + } + } + for (EdgeDescription ed : edges) { + if ( ed.getRuleKey().endsWith(xmlRootElementName)) { + sbEdge.append(" - FROM ").append(ed.getRuleKey().substring(0, ed.getRuleKey().indexOf("|"))); + String footnote = ed.getAlsoDeleteFootnote(xmlRootElementName); + sbEdge.append(ed.getRelationshipDescription("FROM", xmlRootElementName)+footnote+"\n"); + if(StringUtils.isNotEmpty(footnote)) footnotes.add(footnote); + } + } + footnotes.add(edgeRuleSet.preventDeleteRules(xmlRootElementName)); + sbEdge.append(footnotes.toString()); + validEdges = sbEdge.toString(); + } + + // Handle description property. Might have a description OR valid edges OR both OR neither. + // Only put a description: tag if there is at least one. + if (pathDescriptionProperty != null || validEdges != null) { + definitionsSb.append(" description: |\n"); + definitionsLocalSb.append(" description: |\n"); + + if ( pathDescriptionProperty != null ) { + definitionsSb.append(" " + pathDescriptionProperty + "\n" ); + definitionsLocalSb.append(" " + pathDescriptionProperty + "\n" ); + } + if (validEdges != null) { + definitionsSb.append(validEdges); + definitionsLocalSb.append(validEdges); + } + } + + if ( requiredCnt > 0 ) { + definitionsSb.append(sbRequired); + definitionsLocalSb.append(sbRequired); + } + + if ( propertyCnt > 0 ) { + definitionsSb.append(" properties:\n"); + definitionsSb.append(sbProperties); + definitionsLocalSb.append(" properties:\n"); + definitionsLocalSb.append(sbProperties); + } + try { + javaTypeDefinitions.put(xmlRootElementName, definitionsLocalSb.toString()); + } catch (Exception e) { + e.printStackTrace(); + } + generatedJavaType.put(xmlRootElementName, null); + logger.trace("xmlRootElementName(2)="+xmlRootElementName); + return null; + } + + private void writeYAMLfile(String outfileName, String fileContent) { + outfileName = (StringUtils.isEmpty(outfileName)) ? "aai_swagger" : outfileName; + outfileName = (outfileName.lastIndexOf(File.separator) == -1) ? yaml_dir + File.separator +outfileName+"_" + v.name() + "." + generateTypeYAML : outfileName; + File outfile = new File(outfileName); + File parentDir = outfile.getParentFile(); + if(parentDir != null && ! parentDir.exists()) + parentDir.mkdirs(); + try { + outfile.createNewFile(); + } catch (IOException e) { + logger.error( "Exception creating output file " + outfileName); + e.printStackTrace(); + } + BufferedWriter bw = null; + try { + Charset charset = Charset.forName("UTF-8"); + Path path = Paths.get(outfileName); + bw = Files.newBufferedWriter(path, charset); + bw.write(fileContent); + if ( bw != null ) { + bw.close(); + } + } catch ( IOException e) { + logger.error( "Exception writing output file " + outfileName); + e.printStackTrace(); + } + } +} -- cgit 1.2.3-korg