From 86e7411b128bd7db440eceff7265533844e577bb Mon Sep 17 00:00:00 2001 From: "LaMont, William(wl2432)" Date: Tue, 14 Apr 2020 14:00:00 -0400 Subject: schema-service processing for v19 Issue-ID: AAI-2864 Change-Id: I41a430ec9c9fd69be75bd9d01693249895e0928b Signed-off-by: LaMont, William(wl2432) --- aai-schema/pom.xml | 4 + .../java/org/onap/aai/schema/ValidateOXMTest.java | 556 +++++++++++++++++---- 2 files changed, 451 insertions(+), 109 deletions(-) (limited to 'aai-schema') diff --git a/aai-schema/pom.xml b/aai-schema/pom.xml index 518ea41..1e49f7d 100644 --- a/aai-schema/pom.xml +++ b/aai-schema/pom.xml @@ -66,6 +66,10 @@ + + com.googlecode.json-simple + json-simple + diff --git a/aai-schema/src/test/java/org/onap/aai/schema/ValidateOXMTest.java b/aai-schema/src/test/java/org/onap/aai/schema/ValidateOXMTest.java index 0dcf1b3..527e6b7 100644 --- a/aai-schema/src/test/java/org/onap/aai/schema/ValidateOXMTest.java +++ b/aai-schema/src/test/java/org/onap/aai/schema/ValidateOXMTest.java @@ -19,16 +19,18 @@ */ package org.onap.aai.schema; - +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.DirectoryFileFilter; import org.apache.commons.io.filefilter.FileFileFilter; import org.apache.commons.io.filefilter.FileFilterUtils; import org.apache.commons.io.filefilter.RegexFileFilter; import org.junit.Test; -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; +import org.junit.Ignore; +import org.w3c.dom.*; import org.xml.sax.SAXException; import javax.xml.parsers.DocumentBuilder; @@ -45,86 +47,99 @@ import java.nio.file.Paths; import java.util.*; import java.util.stream.Collectors; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; public class ValidateOXMTest { - @Test - public void testFindXmlPropContainingSpace() throws XPathExpressionException, IOException, SAXException, ParserConfigurationException { - boolean foundIssue = false; - List fileList = getLatestFiles(); - - StringBuilder msg = new StringBuilder(); - for (File file : fileList) { - msg.append(file.getAbsolutePath().replaceAll(".*aai-schema", "")); - msg.append("\n"); - Document xmlDocument = getDocument(file); - XPath xPath = XPathFactory.newInstance().newXPath(); - String expression = "/xml-bindings/java-types/java-type/xml-properties/xml-property[@name!='description' and contains(@value,' ')]"; - NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET); - - for (int i = 0; i < nodeList.getLength(); i++) { - foundIssue = true; - msg.append("\t"); - msg.append(nodeList.item(i).getParentNode().getParentNode().getAttributes().getNamedItem("name").getNodeValue()); - msg.append("\n"); - msg.append("\t"); - msg.append("\n"); - } - - } - - if (foundIssue) { - System.out.println(msg.toString()); - fail("Node type xml-property should have space."); - } - - } - - /** - * Verifies that all of the node types in the oxm's have their uri templates. - * @throws XPathExpressionException - * @throws IOException - * @throws SAXException - * @throws ParserConfigurationException - */ - @Test - public void allNodeTypesHaveAAIUriTemplate() throws XPathExpressionException, IOException, SAXException, ParserConfigurationException { - boolean foundIssue = false; - List fileList = getFiles(); - - StringBuilder msg = new StringBuilder(); - for (File file : fileList) { - msg.append(file.getAbsolutePath().replaceAll(".*aai-schema", "")); - msg.append("\n"); - Document xmlDocument = getDocument(file); - XPath xPath = XPathFactory.newInstance().newXPath(); - String expression = "/xml-bindings/java-types/java-type[" + - "(" + - "count(xml-properties/xml-property[@name='container']) > 0 " + - "or count(xml-properties/xml-property[@name='dependentOn']) > 0" + - ") " + - "and count(xml-properties/xml-property[@name='uriTemplate']) = 0 " + - "]"; - NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET); - - for (int i = 0; i < nodeList.getLength(); i++) { - String name = nodeList.item(i).getAttributes().getNamedItem("name").getNodeValue(); - if (name.equals("InstanceFilter") || name.equals("InventoryResponseItems") || name.equals("InventoryResponseItem")) { - continue; - } - foundIssue = true; - msg.append("\t"); - msg.append(name); - msg.append("\n"); - } - } - if (foundIssue) { - System.out.println(msg.toString()); - fail("Missing uriTemplate in oxm."); - } - - } + private String DBEDGERULES_RULES = "rules"; + private String DBEDGERULES_FROM = "from"; + private String DBEDGERULES_TO = "to"; + private String DBEDGERULES_DIRECTION = "direction"; + private String DBEDGERULES_CONTAINS_OTHER_V = "contains-other-v"; + private String DBEDGERULES_OUT = "OUT"; + private String DBEDGERULES_IN = "IN"; + private String XMLROOTELEMENT = "xml-root-element"; + private String ECOMP = "ecomp"; + private String NARAD = "narad"; + private String ONAP = "onap"; + + @Test + public void testFindXmlPropContainingSpace() throws XPathExpressionException, IOException, SAXException, ParserConfigurationException { + boolean foundIssue = false; + List fileList = getLatestFiles(); + + StringBuilder msg = new StringBuilder(); + for (File file : fileList) { + msg.append(file.getAbsolutePath().replaceAll(".*aai-schema", "")); + msg.append("\n"); + Document xmlDocument = getDocument(file); + XPath xPath = XPathFactory.newInstance().newXPath(); + String expression = "/xml-bindings/java-types/java-type/xml-properties/xml-property[@name!='description' and contains(@value,' ')]"; + NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET); + + for (int i = 0; i < nodeList.getLength(); i++) { + foundIssue = true; + msg.append("\t"); + msg.append(nodeList.item(i).getParentNode().getParentNode().getAttributes().getNamedItem("name").getNodeValue()); + msg.append("\n"); + msg.append("\t"); + msg.append("\n"); + } + + } + + if (foundIssue) { + System.out.println(msg.toString()); + fail("Node type xml-property should have space."); + } + + } + + /** + * Verifies that all of the node types in the oxm's have their uri templates. + * @throws XPathExpressionException + * @throws IOException + * @throws SAXException + * @throws ParserConfigurationException + */ + @Test + public void allNodeTypesHaveAAIUriTemplate() throws XPathExpressionException, IOException, SAXException, ParserConfigurationException { + boolean foundIssue = false; + List fileList = getFiles(); + + StringBuilder msg = new StringBuilder(); + for (File file : fileList) { + msg.append(file.getAbsolutePath().replaceAll(".*aai-schema", "")); + msg.append("\n"); + Document xmlDocument = getDocument(file); + XPath xPath = XPathFactory.newInstance().newXPath(); + String expression = "/xml-bindings/java-types/java-type[" + + "(" + + "count(xml-properties/xml-property[@name='container']) > 0 " + + "or count(xml-properties/xml-property[@name='dependentOn']) > 0" + + ") " + + "and count(xml-properties/xml-property[@name='uriTemplate']) = 0 " + + "]"; + NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET); + + for (int i = 0; i < nodeList.getLength(); i++) { + String name = nodeList.item(i).getAttributes().getNamedItem("name").getNodeValue(); + if (name.equals("InstanceFilter") || name.equals("InventoryResponseItems") || name.equals("InventoryResponseItem")) { + continue; + } + foundIssue = true; + msg.append("\t"); + msg.append(name); + msg.append("\n"); + } + } + if (foundIssue) { + System.out.println(msg.toString()); + fail("Missing uriTemplate in oxm."); + } + + } /** @@ -186,17 +201,309 @@ public class ValidateOXMTest { } - private List getFiles() { - Path currentRelativePath = Paths.get("../aai-schema/src/main/resources/").toAbsolutePath(); - return FileUtils.listFiles( - currentRelativePath.toFile(), - new RegexFileFilter(".*\\.xml"), - DirectoryFileFilter.DIRECTORY) - .stream() - .filter(file -> file.getAbsolutePath().contains("oxm")) - .filter(file -> !file.getAbsolutePath().contains("onap")) // skips onap for checks - .collect(Collectors.toList()); - } + /** + * Check schema versions against their respective dbEdgeRules file and check if the + * dependentOn relationship matches what is listed in the edge rules. + * + */ + @Test + @Ignore + public void testSchemaValidationAgainstEdgeRules() throws XPathExpressionException, IOException, SAXException, ParserConfigurationException, ParseException { + Path currentRelativePath = Paths.get("../aai-schema/src/main/resources/").toAbsolutePath(); + List subDirs = Arrays.asList(currentRelativePath.toFile().listFiles(File::isDirectory)); + boolean success = true; + for (File subDir : subDirs) { + List oxmSchemaList = new ArrayList<>(); + List dbEdgeRulesList = new ArrayList<>(); + String oxm = subDir.getAbsolutePath() + "/oxm"; + File[] oxms = new File(oxm).listFiles(File::isDirectory); + Arrays.stream(oxms).map(File::getAbsolutePath).max(new Comparator() { + public int compare(String o1, String o2) { + return extractInt(o1) - extractInt(o2); + } + + int extractInt(String s) { + String num = s.replaceAll("\\D", ""); + return num.isEmpty() ? 0 : Integer.parseInt(num); + } + }).ifPresent(oxmSchemaList::add); + + String edgeRule = subDir.getAbsolutePath() + "/dbedgerules"; + File[] edgeRules = new File(edgeRule).listFiles(File::isDirectory); + Arrays.stream(edgeRules).map(File::getAbsolutePath).max(new Comparator() { + public int compare(String o1, String o2) { + return extractInt(o1) - extractInt(o2); + } + + int extractInt(String s) { + String num = s.replaceAll("\\D", ""); + return num.isEmpty() ? 0 : Integer.parseInt(num); + } + }).ifPresent(dbEdgeRulesList::add); + + + List oxmSchemaFileList = new ArrayList<>(); + List dbEdgeRulesFileList = new ArrayList<>(); + oxmSchemaList.forEach(s -> + FileUtils.listFiles( + new File(s), + new RegexFileFilter(".*\\.xml"), + DirectoryFileFilter.DIRECTORY) + .stream() + .filter(file -> file.getAbsolutePath().contains("oxm")) + .forEach(oxmSchemaFileList::add)); + + dbEdgeRulesList.forEach(s -> + FileUtils.listFiles( + new File(s), + new RegexFileFilter(".*\\.json"), + DirectoryFileFilter.DIRECTORY) + .stream() + .filter(file -> file.getAbsolutePath().contains("DbEdgeRules")) + .forEach(dbEdgeRulesFileList::add)); + + // Map the dbEdgeRules json file into a HashMap for reference + Map> dbEdgeRules = new HashMap<>(); + JSONParser jsonParser = new JSONParser(); + for (File file : dbEdgeRulesFileList) { + FileReader reader = new FileReader(file); + // Read JSON file. Expecting JSON file to read an object with a JSONArray names "rules" + JSONObject jsonObj = (JSONObject) jsonParser.parse(reader); + JSONArray rules = (JSONArray) jsonObj.get(DBEDGERULES_RULES); + for (int i = 0; i < rules.size(); i++) { + JSONObject rule = (JSONObject) rules.get(i); + String fromNode = rule.get(DBEDGERULES_FROM).toString(); + String toNode = rule.get(DBEDGERULES_TO).toString(); + String direction = rule.get(DBEDGERULES_DIRECTION).toString(); + String containsOtherV = rule.get(DBEDGERULES_CONTAINS_OTHER_V).toString(); + + // special case - cvlan-tag should be replaced with cvlan-tag-entry + if (fromNode.equals("cvlan-tag")) + fromNode = "cvlan-tag-entry"; + if (toNode.equals("cvlan-tag")) + toNode = "cvlan-tag-entry"; + if (containsOtherV.equals("!${direction}")) { + if (direction.equals(DBEDGERULES_IN)) { + direction = DBEDGERULES_OUT; + } else if (direction.equals(DBEDGERULES_OUT)) { + direction = DBEDGERULES_IN; + } + } + // If this value is none, the edge rule is for cousin nodes. Ignore. + else if (containsOtherV.equals("NONE")) + continue; + dbEdgeRulesMapPut(dbEdgeRules, fromNode, toNode, direction); + } + } + + // Iterate through the most recent oxm schema files. Map the parent child relationships + Map> oxmSchemaFile = new HashMap<>(); + for (File file : oxmSchemaFileList) { + Document xmlDocument = getDocument(file); + XPath xPath = XPathFactory.newInstance().newXPath(); + String parentNodeExpression = "/xml-bindings/java-types/java-type/xml-properties/xml-property[@name='dependentOn']"; + NodeList parentNodeList = (NodeList) xPath.compile(parentNodeExpression).evaluate(xmlDocument, XPathConstants.NODESET); + String childNodeExpression = "/xml-bindings/java-types/java-type[" + + "(" + + "count(xml-properties/xml-property[@name='dependentOn']) > 0" + + ")]"; + NodeList childNodeList = (NodeList) xPath.compile(childNodeExpression).evaluate(xmlDocument, XPathConstants.NODESET); + + for (int i = 0; i < parentNodeList.getLength(); i++) { + + // Obtain the xml-root-element field by tracing the childNodes from the java-type parent node + for (int j = 0; j < childNodeList.item(i).getChildNodes().getLength(); j++) { + if (childNodeList.item(i).getChildNodes().item(j).getNodeName().equals(XMLROOTELEMENT)) { + + // The parent node + String dependentOn = parentNodeList.item(i).getAttributes().getNamedItem("value").getNodeValue(); + + // The child node + String xmlRootElement = childNodeList.item(i).getChildNodes().item(j).getAttributes().getNamedItem("name").getNodeValue(); + + Set childSet; + String[] parents = dependentOn.split(","); + for (int k = 0; k < parents.length; k++) { + String parent = parents[k]; + if (oxmSchemaFile.containsKey(parent)) { + childSet = oxmSchemaFile.get(parent); + } else { + childSet = new HashSet<>(); + } + childSet.add(xmlRootElement); + oxmSchemaFile.put(parent, childSet); + } + + } + } + } + } + + // Compare the OXM file against the dbEdgeRules file. check what is missing in dbEdgeRules from the oxm files. + Set oxmKeySet = oxmSchemaFile.keySet(); + for (String key : oxmKeySet) { + Set oxmChildren = oxmSchemaFile.get(key); + Set dbEdgeRulesChildren = dbEdgeRules.get(key); + + // Check if the parent vertex exists at all in the dbEdgeRules file + if (dbEdgeRulesChildren == null || dbEdgeRulesChildren.isEmpty()) { + for (String oxmChild : oxmChildren) { + System.out.println("ERROR: dbEdgeRules under directory '" + subDir.toString() + "' does not contain parent '" + key + "' and child '" + oxmChild + "' relationship"); + } + success = false; + continue; + } + + // Compare both parent-child relationships between both files + if (!oxmChildren.equals(dbEdgeRulesChildren)) { + for (String oxmChild : oxmChildren) { + if (!dbEdgeRulesChildren.contains(oxmChild)) { + System.out.println("ERROR: dbEdgeRules under directory '" + subDir.toString() + "' does not contain parent '" + key + "' and child '" + oxmChild + "' relationship"); + success = false; + } + } + } + } + + // Compare the dbEdgeRules against the OXM File + Set dbEdgeRuleKeySet = dbEdgeRules.keySet(); + for (String key : dbEdgeRuleKeySet) { + Set dbEdgeRulesChildren = dbEdgeRules.get(key); + Set oxmChildren = oxmSchemaFile.get(key); + + // Check if the parent vertex exists at all in the dbEdgeRules file + if (oxmChildren == null || oxmChildren.isEmpty()) { + for (String dbEdgeRuleChild : dbEdgeRulesChildren) { + System.out.println("ERROR: oxms under directory '" + subDir.toString() + "' do not contain parent '" + key + "' and child '" + dbEdgeRuleChild + "' relationship"); + } + success = false; + continue; + } + + // Compare both parent-child relationships between both files + if (!dbEdgeRulesChildren.equals(oxmChildren)) { + for (String dbEdgeRuleChild : dbEdgeRulesChildren) { + if (!oxmChildren.contains(dbEdgeRuleChild)) { + System.out.println("ERROR: oxms under directory '" + subDir.toString() + "' do not contain parent '" + key + "' and child '" + dbEdgeRuleChild + "' relationship"); + success = false; + } + } + } + } + } + assertTrue(success); + } + + /** + * Null check for strings + * @param s + * @return + */ + private boolean isStringEmpty(String s) { + return (s == null || s.isEmpty()) ? true : false; + } + + /** + * Creating a hashmap to map what child nodes are associated to which parent nodes + * according to the dbEdgeRules json files. A HashMap was chosen for the value of the map for O(1) lookup time. + * @param from this variable will act as the key or value depending on the direction + * @param to this variable will act as the key or value depending on the direction + * @param direction dictates the direction of which vertex is dependent on which + * @return The map returned will act as a dictionary to keep track of the parent nodes. Value of the map is a hashmap to help handle collision of multiple children to one parent + */ + private Map> dbEdgeRulesMapPut(Map> dbEdgeRules, String from, String to, String direction) { + if (isStringEmpty(from) || isStringEmpty(to) || isStringEmpty(direction)) + return dbEdgeRules; + + // Assigning the strings to parent and child for readability + String parent = "", child = ""; + if (direction.equals(DBEDGERULES_OUT)) { + parent = from; + child = to; + } else if (direction.equals(DBEDGERULES_IN)) { + parent = to; + child = from; + } + // Add to the dbEdgeRules mapping + Set children; + if (!dbEdgeRules.containsKey(parent)) { + children = new HashSet<>(); + children.add(child); + dbEdgeRules.put(parent, children); + } else { + children = dbEdgeRules.get(parent); + children.add(child); + dbEdgeRules.put(parent, children); + } + return dbEdgeRules; + } + + private List getFiles() { + Path currentRelativePath = Paths.get("../aai-schema/src/main/resources/").toAbsolutePath(); + return FileUtils.listFiles( + currentRelativePath.toFile(), + new RegexFileFilter(".*\\.xml"), + DirectoryFileFilter.DIRECTORY) + .stream() + .filter(file -> file.getAbsolutePath().contains("oxm")) + .filter(file -> !file.getAbsolutePath().contains("onap")) // skips onap for checks + .collect(Collectors.toList()); + } + + private List getAaiSchemaOxmFiles() { + Path currentRelativePath = Paths.get("../aai-schema/src/main/resources/").toAbsolutePath(); + return FileUtils.listFiles( + currentRelativePath.toFile(), + new RegexFileFilter(".*\\.xml"), + DirectoryFileFilter.DIRECTORY) + .stream() + .filter(file -> file.getAbsolutePath().contains("oxm")) + .filter(file -> !file.getAbsolutePath().contains("onap")) // skips onap for checks + .collect(Collectors.toList()); + } + + private List getDbEdgeRulesFiles() { + Path currentRelativePath = Paths.get("../aai-schema/src/main/resources/").toAbsolutePath(); + return FileUtils.listFiles( + currentRelativePath.toFile(), + new RegexFileFilter(".*\\.json"), + DirectoryFileFilter.DIRECTORY) + .stream() + .filter(file -> file.getAbsolutePath().contains("DbEdgeRules")) + .filter(file -> !file.getAbsolutePath().contains("onap")) // skips onap for checks + .collect(Collectors.toList()); + } + + /** + * Finds all of the oxm files for the latest version. + * @return list of the latest version of the oxm files. + */ + private List getLatestDbEdgeRulesFiles(String fileDirectory) { + List latest = new ArrayList<>(); + String currentRelativePath = Paths.get("../aai-schema/src/main/resources/" + fileDirectory + "/dbedgerules").toAbsolutePath().toString(); + File[] oxms = new File(currentRelativePath).listFiles(File::isDirectory); + Arrays.stream(oxms).map(File::getAbsolutePath).max(new Comparator() { + public int compare(String o1, String o2) { + return extractInt(o1) - extractInt(o2); + } + int extractInt(String s) { + String num = s.replaceAll("\\D", ""); + return num.isEmpty() ? 0 : Integer.parseInt(num); + } + }).ifPresent(latest::add); + + List latestFiles = new ArrayList<>(); + latest.forEach(s -> + FileUtils.listFiles( + new File(s), + new RegexFileFilter(".*\\.json"), + DirectoryFileFilter.DIRECTORY) + .stream() + .filter(file -> file.getAbsolutePath().contains("DbEdgeRules")) + .forEach(latestFiles::add)); + + return latestFiles; + } /** * Finds all of the oxm files for the latest version. @@ -233,29 +540,60 @@ public class ValidateOXMTest { return latestFiles; } - //TODO test that all oxm xml are valid xml + /** + * Finds all of the oxm files for the latest version. + * @return list of the latest version of the oxm files. + */ + private List getLatestFiles(String fileDirectory) { + List latest = new ArrayList<>(); + String currentRelativePath = Paths.get("../aai-schema/src/main/resources/" + fileDirectory + "/oxm").toAbsolutePath().toString(); + File[] oxms = new File(currentRelativePath).listFiles(File::isDirectory); + Arrays.stream(oxms).map(File::getAbsolutePath).max(new Comparator() { + public int compare(String o1, String o2) { + return extractInt(o1) - extractInt(o2); + } + int extractInt(String s) { + String num = s.replaceAll("\\D", ""); + return num.isEmpty() ? 0 : Integer.parseInt(num); + } + }).ifPresent(latest::add); + List latestFiles = new ArrayList<>(); + latest.forEach(s -> + FileUtils.listFiles( + new File(s), + new RegexFileFilter(".*\\.xml"), + DirectoryFileFilter.DIRECTORY) + .stream() + .filter(file -> file.getAbsolutePath().contains("oxm")) + .forEach(latestFiles::add)); + return latestFiles; + } + + //TODO test that all oxm xml are valid xml - public String printNodeList(NodeList nodeList, Document doc) throws IOException { - StringBuilder stringBuilder = new StringBuilder(); - for (int i = 0; i < nodeList.getLength(); i++) { - stringBuilder.append(printNode(nodeList.item(i), doc)).append("\n"); - } - return stringBuilder.toString(); - } - public String printNode(Node node, Document document) throws IOException { - StringWriter stringWriter = new StringWriter(); - return stringWriter.toString(); - } + public String printNodeList(NodeList nodeList, Document doc) throws IOException { + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < nodeList.getLength(); i++) { + stringBuilder.append(printNode(nodeList.item(i), doc)).append("\n"); + } + return stringBuilder.toString(); + } - private Document getDocument(File file) throws ParserConfigurationException, SAXException, IOException { - InputStream fileIS = new FileInputStream(file); - DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = builderFactory.newDocumentBuilder(); - return builder.parse(fileIS); - } + public String printNode(Node node, Document document) throws IOException { + StringWriter stringWriter = new StringWriter(); + return stringWriter.toString(); + + } + + private Document getDocument(File file) throws ParserConfigurationException, SAXException, IOException { + InputStream fileIS = new FileInputStream(file); + DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = builderFactory.newDocumentBuilder(); + return builder.parse(fileIS); + } } -- cgit 1.2.3-korg