222ed0536156a9a1e83ca05fe28d0a6f1b86f9e2
[aai/schema-service.git] / aai-schema / src / test / java / org / onap / aai / schema / ValidateOXMTest.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *    http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20 package org.onap.aai.schema;
21
22 import org.json.simple.JSONArray;
23 import org.json.simple.JSONObject;
24 import org.json.simple.parser.JSONParser;
25 import org.json.simple.parser.ParseException;
26 import org.apache.commons.io.FileUtils;
27 import org.apache.commons.io.filefilter.DirectoryFileFilter;
28 import org.apache.commons.io.filefilter.FileFileFilter;
29 import org.apache.commons.io.filefilter.FileFilterUtils;
30 import org.apache.commons.io.filefilter.RegexFileFilter;
31 import org.junit.Test;
32 import org.junit.Ignore;
33 import org.w3c.dom.*;
34 import org.xml.sax.SAXException;
35
36 import javax.xml.parsers.DocumentBuilder;
37 import javax.xml.parsers.DocumentBuilderFactory;
38 import javax.xml.parsers.ParserConfigurationException;
39 import javax.xml.xpath.XPath;
40 import javax.xml.xpath.XPathConstants;
41 import javax.xml.xpath.XPathExpressionException;
42 import javax.xml.xpath.XPathFactory;
43 import java.io.*;
44 import java.nio.file.Files;
45 import java.nio.file.Path;
46 import java.nio.file.Paths;
47 import java.util.*;
48 import java.util.stream.Collectors;
49
50 import static org.junit.Assert.assertTrue;
51 import static org.junit.Assert.fail;
52
53 public class ValidateOXMTest {
54
55     private String DBEDGERULES_RULES = "rules";
56     private String DBEDGERULES_FROM = "from";
57     private String DBEDGERULES_TO = "to";
58     private String DBEDGERULES_DIRECTION = "direction";
59     private String DBEDGERULES_CONTAINS_OTHER_V = "contains-other-v";
60     private String DBEDGERULES_OUT = "OUT";
61     private String DBEDGERULES_IN = "IN";
62     private String XMLROOTELEMENT = "xml-root-element";
63     private String XMLPROPERTIES = "xml-properties";
64     private String ECOMP = "ecomp";
65     private String NARAD = "narad";
66     private String ONAP = "onap";
67
68     @Test
69     public void testFindXmlPropContainingSpace() throws XPathExpressionException, IOException, SAXException, ParserConfigurationException {
70         boolean foundIssue = false;
71         List<File> fileList = getLatestFiles();
72
73         StringBuilder msg = new StringBuilder();
74         for (File file : fileList) {
75             msg.append(file.getAbsolutePath().replaceAll(".*aai-schema", ""));
76             msg.append("\n");
77             Document xmlDocument = getDocument(file);
78             XPath xPath = XPathFactory.newInstance().newXPath();
79             String expression = "/xml-bindings/java-types/java-type/xml-properties/xml-property[@name!='description' and contains(@value,' ')]";
80             NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
81
82             for (int i = 0; i < nodeList.getLength(); i++) {
83                 foundIssue = true;
84                 msg.append("\t");
85                 msg.append(nodeList.item(i).getParentNode().getParentNode().getAttributes().getNamedItem("name").getNodeValue());
86                 msg.append("\n");
87                 msg.append("\t");
88                 msg.append("\n");
89             }
90
91         }
92
93         if (foundIssue) {
94             System.out.println(msg.toString());
95             fail("Node type xml-property should have space.");
96         }
97
98     }
99
100     /**
101      * Verifies that all of the node types in the oxm's have their uri templates.
102      * @throws XPathExpressionException
103      * @throws IOException
104      * @throws SAXException
105      * @throws ParserConfigurationException
106      */
107     @Test
108     public void allNodeTypesHaveAAIUriTemplate() throws XPathExpressionException, IOException, SAXException, ParserConfigurationException {
109         boolean foundIssue = false;
110         List<File> fileList = getFiles();
111
112         StringBuilder msg = new StringBuilder();
113         for (File file : fileList) {
114             msg.append(file.getAbsolutePath().replaceAll(".*aai-schema", ""));
115             msg.append("\n");
116             Document xmlDocument = getDocument(file);
117             XPath xPath = XPathFactory.newInstance().newXPath();
118             String expression = "/xml-bindings/java-types/java-type[" +
119                 "(" +
120                 "count(xml-properties/xml-property[@name='container']) > 0 " +
121                 "or count(xml-properties/xml-property[@name='dependentOn']) > 0" +
122                 ") " +
123                 "and count(xml-properties/xml-property[@name='uriTemplate']) = 0 " +
124                 "]";
125             NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
126
127             for (int i = 0; i < nodeList.getLength(); i++) {
128                 String name = nodeList.item(i).getAttributes().getNamedItem("name").getNodeValue();
129                 if (name.equals("InstanceFilter") || name.equals("InventoryResponseItems") || name.equals("InventoryResponseItem")) {
130                     continue;
131                 }
132                 foundIssue = true;
133                 msg.append("\t");
134                 msg.append(name);
135                 msg.append("\n");
136             }
137         }
138         if (foundIssue) {
139             System.out.println(msg.toString());
140             fail("Missing uriTemplate in oxm.");
141         }
142
143     }
144
145     @Test
146     public void verifyAllIndexedPropertiesExistInObject()
147         throws XPathExpressionException, IOException, SAXException, ParserConfigurationException {
148
149         boolean foundIssue = false;
150         List<File> fileList = getOxmSchemaFiles();
151         fileList.addAll(getOnapOxmSchemaFiles());
152         StringBuilder msg = new StringBuilder();
153         for (File file : fileList) {
154             Document xmlDocument = getDocument(file);
155             XPath xPath = XPathFactory.newInstance().newXPath();
156             String expression = "/xml-bindings/java-types/java-type[count(xml-properties/xml-property[@name='indexedProps']) > 0]";
157             NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
158
159             Map<String, List<String>> nodeTypeBadIndexProps = new HashMap<>();
160             for(int i = 0; i < nodeList.getLength(); i++){
161                 String name = nodeList.item(i).getAttributes().getNamedItem("name").getNodeValue();
162
163                 NodeList javaAttributesList = ((Element)nodeList.item(i)).getElementsByTagName("java-attributes");
164
165                 Set<String> properties = new HashSet<>();
166
167                 for(int j = 0; j < javaAttributesList.getLength(); j++){
168                     NodeList elementList = ((Element)javaAttributesList.item(j)).getElementsByTagName("xml-element");
169                     for(int k = 0; k < elementList.getLength(); k++){
170                         properties.add(elementList.item(k).getAttributes().getNamedItem("name").getNodeValue());
171                     }
172                 }
173
174                 NodeList xmlPropertiesList = ((Element)nodeList.item(i)).getElementsByTagName("xml-properties");
175                 List<String> badIndexedProps = new ArrayList<>();
176                 boolean foundIssueInNodeType = false;
177
178                 for(int j = 0; j < xmlPropertiesList.getLength(); j++){
179                     NodeList xmlProperties = ((Element)xmlPropertiesList.item(j)).getElementsByTagName("xml-property");
180                     for(int k = 0; k < xmlProperties.getLength(); k++){
181                         String xmlProp = xmlProperties.item(k).getAttributes().getNamedItem("name").getNodeValue();
182                         if("indexedProps".equals(xmlProp)){
183                             String xmlPropValue = xmlProperties.item(k).getAttributes().getNamedItem("value").getNodeValue();
184
185                             List<String> indexProps = Arrays
186                                 .stream(xmlPropValue.split(","))
187                                 .collect(Collectors.toList());
188
189                             for(String indexProp : indexProps){
190                                 if(!properties.contains(indexProp)){
191                                     foundIssueInNodeType = true;
192                                     badIndexedProps.add(indexProp);
193                                 }
194                             }
195
196                         }
197                     }
198                 }
199
200                 if(foundIssueInNodeType){
201                     foundIssue =true;
202                     nodeTypeBadIndexProps.put(name, badIndexedProps);
203                 }
204             }
205
206             if(!nodeTypeBadIndexProps.isEmpty()){
207                 msg.append("\n");
208                 msg.append("File: " + file.getAbsolutePath().replaceAll(".*aai-schema", ""));
209                 msg.append("\n");
210                 for (Map.Entry<String, List<String>> nodeTypeBadIndex : nodeTypeBadIndexProps.entrySet()) {
211                     msg.append("NodeType: " + nodeTypeBadIndex.getKey());
212                     msg.append(" contains following indexed props that are not properties in object: ");
213                     msg.append(String.join(",", nodeTypeBadIndex.getValue()));
214                     msg.append("\n");
215                 }
216             }
217
218         }
219
220         if (foundIssue) {
221             fail(msg.toString());
222         }
223     }
224
225     @Test
226     public void verifyAllUniquePropertiesExistInObject()
227         throws XPathExpressionException, IOException, SAXException, ParserConfigurationException {
228
229         boolean foundIssue = false;
230         List<File> fileList = getOxmSchemaFiles();
231         fileList.addAll(getOnapOxmSchemaFiles());
232         StringBuilder msg = new StringBuilder();
233         for (File file : fileList) {
234             Document xmlDocument = getDocument(file);
235             XPath xPath = XPathFactory.newInstance().newXPath();
236             String expression = "/xml-bindings/java-types/java-type[count(xml-properties/xml-property[@name='uniqueProps']) > 0]";
237             NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
238
239             Map<String, List<String>> nodeTypeBadUniqueProps = new HashMap<>();
240             for (int i = 0; i < nodeList.getLength(); i++) {
241                 String name = nodeList.item(i).getAttributes().getNamedItem("name").getNodeValue();
242
243                 NodeList javaAttributesList = ((Element) nodeList.item(i)).getElementsByTagName("java-attributes");
244
245                 Set<String> properties = new HashSet<>();
246
247                 for (int j = 0; j < javaAttributesList.getLength(); j++) {
248                     NodeList elementList = ((Element) javaAttributesList.item(j)).getElementsByTagName("xml-element");
249                     for (int k = 0; k < elementList.getLength(); k++) {
250                         properties.add(elementList.item(k).getAttributes().getNamedItem("name").getNodeValue());
251                     }
252                 }
253
254                 NodeList xmlPropertiesList = ((Element) nodeList.item(i)).getElementsByTagName("xml-properties");
255                 List<String> badUniqueProps = new ArrayList<>();
256                 boolean foundIssueInNodeType = false;
257
258                 for (int j = 0; j < xmlPropertiesList.getLength(); j++) {
259                     NodeList xmlProperties = ((Element) xmlPropertiesList.item(j)).getElementsByTagName("xml-property");
260                     for (int k = 0; k < xmlProperties.getLength(); k++) {
261                         String xmlProp = xmlProperties.item(k).getAttributes().getNamedItem("name").getNodeValue();
262                         if ("uniqueProps".equals(xmlProp)) {
263                             String xmlPropValue = xmlProperties.item(k).getAttributes().getNamedItem("value").getNodeValue();
264
265                             List<String> uniqueProps = Arrays
266                                 .stream(xmlPropValue.split(","))
267                                 .collect(Collectors.toList());
268
269                             for (String uniqueProp : uniqueProps) {
270                                 if (!properties.contains(uniqueProp)) {
271                                     foundIssueInNodeType = true;
272                                     badUniqueProps.add(uniqueProp);
273                                 }
274                             }
275
276                         }
277                     }
278                 }
279
280                 if (foundIssueInNodeType) {
281                     foundIssue = true;
282                     nodeTypeBadUniqueProps.put(name, badUniqueProps);
283                 }
284             }
285
286             if (!nodeTypeBadUniqueProps.isEmpty()) {
287                 msg.append("\n");
288                 msg.append("File: " + file.getAbsolutePath().replaceAll(".*aai-schema", ""));
289                 msg.append("\n");
290                 for (Map.Entry<String, List<String>> nodeTypeBadUnique : nodeTypeBadUniqueProps.entrySet()) {
291                     msg.append("NodeType: " + nodeTypeBadUnique.getKey());
292                     msg.append(" contains following unique props that are not properties in object: ");
293                     msg.append(String.join(",", nodeTypeBadUnique.getValue()));
294                     msg.append("\n");
295                 }
296             }
297
298         }
299
300         if (foundIssue) {
301             fail(msg.toString());
302         }
303     }
304
305
306     /**
307      * Verifies that all of the top level node types in the oxm's have their namespace in uri templates.
308      * @throws XPathExpressionException
309      * @throws IOException
310      * @throws SAXException
311      * @throws ParserConfigurationException
312      */
313     @Test
314   public void verifyAllUriTemplateHaveNamespace()
315       throws XPathExpressionException, IOException, SAXException, ParserConfigurationException {
316     boolean foundIssue = false;
317     List<File> fileList = getOxmSchemaFiles();
318     fileList.addAll(getOnapOxmSchemaFiles());
319     StringBuilder msg = new StringBuilder();
320     for (File file : fileList) {
321       msg.append(file.getAbsolutePath().replaceAll(".*aai-schema", ""));
322       msg.append("\n");
323       Document xmlDocument = getDocument(file);
324       XPath xPath = XPathFactory.newInstance().newXPath();
325       String expression = "/xml-bindings/java-types/java-type["
326           + "count(xml-properties/xml-property[@name='namespace']) > 0 " + "]";
327       NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
328
329       for (int i = 0; i < nodeList.getLength(); i++) {
330         String name = nodeList.item(i).getAttributes().getNamedItem("name").getNodeValue();
331
332         NodeList childNodeList = (NodeList) nodeList.item(i).getChildNodes();
333         for (int j = 0; j < childNodeList.getLength(); j++) {
334
335           String nodeName = childNodeList.item(j).getNodeName();
336           NodeList xmlPropertyNodeList = childNodeList.item(j).getChildNodes();
337           if (XMLPROPERTIES.equals(nodeName)) {
338
339             String namespaceVal = "";
340             String uriTemplateVal = "";
341             for (int k = 0; k < xmlPropertyNodeList.getLength(); k++) {
342
343               if ("xml-property".equals(xmlPropertyNodeList.item(k).getNodeName())) {
344
345                 NamedNodeMap attributes = xmlPropertyNodeList.item(k).getAttributes();
346
347                 if ("namespace".equals(attributes.getNamedItem("name").getNodeValue())) {
348                   namespaceVal = attributes.getNamedItem("value").getNodeValue();
349                 }
350                 if ("uriTemplate".equals(attributes.getNamedItem("name").getNodeValue())) {
351                   uriTemplateVal = attributes.getNamedItem("value").getNodeValue();
352                 }
353
354               }
355
356             }
357
358             if (!uriTemplateVal.startsWith("/" + namespaceVal + "/")) {
359               foundIssue = true;
360               msg.append("\t");
361               msg.append(uriTemplateVal);
362               msg.append("\n");
363             }
364
365           }
366         }
367
368       }
369     }
370     if (foundIssue) {
371       System.out.println(msg.toString());
372       fail("uriTemplate doesnt start with /namespace/.");
373     }
374
375   }
376
377
378     /**
379      * Verifies that all specified properties are indexed
380      * Currently set to check that "model-invariant-id","model-version-id" which are aliased are indexed
381      * @throws XPathExpressionException
382      * @throws IOException
383      * @throws SAXException
384      * @throws ParserConfigurationException
385      */
386     @Test
387     public void aliasedIndexedPropsAreInIndexedListWithPropName() throws XPathExpressionException, IOException, SAXException, ParserConfigurationException {
388
389         final List<String> props = Arrays.asList("model-invariant-id","model-version-id");
390
391         boolean foundIssue = false;
392         List<File> fileList = getLatestFiles();
393         StringBuilder msg = new StringBuilder();
394
395         for (File file : fileList) {
396             msg.append(file.getAbsolutePath().replaceAll(".*aai-schema", ""));
397             msg.append("\n");
398             for (String prop : props) {
399                 Document xmlDocument = getDocument(file);
400                 XPath xPath = XPathFactory.newInstance().newXPath();
401                 String expression = "/xml-bindings/java-types/java-type[" +
402                     "(" +
403                     "count(xml-properties/xml-property[@name='container']) > 0 " +
404                     "or count(xml-properties/xml-property[@name='dependentOn']) > 0" +
405                     ") " +
406                     "and count(xml-properties/xml-property[@name='indexedProps' and not(contains(@value,'" + prop + "'))]) > 0 " + //prop is not in indexed props list
407                     "and count(java-attributes/xml-element[@name='" + prop + "']) > 0 " + // prop is a property on obj
408                     "]";
409
410                 NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
411
412                 if (nodeList.getLength() > 0) {
413                     msg.append("\t")
414                         .append(prop)
415                         .append("\n");
416                 }
417                 for (int i = 0; i < nodeList.getLength(); i++) {
418                     String name = nodeList.item(i).getAttributes().getNamedItem("name").getNodeValue();
419                     if (name.equals("InstanceFilter") || name.equals("InventoryResponseItems") || name.equals("InventoryResponseItem")) {
420                         continue;
421                     }
422                     foundIssue = true;
423                     msg.append("\t\t")
424                         .append(name)
425                         .append("\n");
426                 }
427             }
428         }
429
430         if (foundIssue) {
431             System.out.println(msg.toString());
432             fail("Missing index entry in oxm.");
433         }
434
435     }
436
437     /**
438      * Check schema versions against their respective dbEdgeRules file and check if the
439      * dependentOn relationship matches what is listed in the edge rules.
440      *
441      */
442     @Ignore
443     @Test
444     public void testSchemaValidationAgainstEdgeRules() throws  XPathExpressionException, IOException, SAXException, ParserConfigurationException, ParseException {
445         Path currentRelativePath = Paths.get("../aai-schema/src/main/resources/").toAbsolutePath();
446         List<File> subDirs = Arrays.asList(currentRelativePath.toFile().listFiles(File::isDirectory));
447         boolean success = true;
448         for (File subDir : subDirs) {
449             List<String> oxmSchemaList = new ArrayList<>();
450             List<String> dbEdgeRulesList = new ArrayList<>();
451             String oxm = subDir.getAbsolutePath() + "/oxm";
452             File[] oxms = new File(oxm).listFiles(File::isDirectory);
453             Arrays.stream(oxms).map(File::getAbsolutePath).max(new Comparator<String>() {
454                 public int compare(String o1, String o2) {
455                     return extractInt(o1) - extractInt(o2);
456                 }
457
458                 int extractInt(String s) {
459                     String num = s.replaceAll("\\D", "");
460                     return num.isEmpty() ? 0 : Integer.parseInt(num);
461                 }
462             }).ifPresent(oxmSchemaList::add);
463
464             String edgeRule = subDir.getAbsolutePath() + "/dbedgerules";
465             File[] edgeRules = new File(edgeRule).listFiles(File::isDirectory);
466             Arrays.stream(edgeRules).map(File::getAbsolutePath).max(new Comparator<String>() {
467                 public int compare(String o1, String o2) {
468                     return extractInt(o1) - extractInt(o2);
469                 }
470
471                 int extractInt(String s) {
472                     String num = s.replaceAll("\\D", "");
473                     return num.isEmpty() ? 0 : Integer.parseInt(num);
474                 }
475             }).ifPresent(dbEdgeRulesList::add);
476
477
478             List<File> oxmSchemaFileList = new ArrayList<>();
479             List<File> dbEdgeRulesFileList = new ArrayList<>();
480             oxmSchemaList.forEach(s ->
481                 FileUtils.listFiles(
482                     new File(s),
483                     new RegexFileFilter(".*\\.xml"),
484                     DirectoryFileFilter.DIRECTORY)
485                     .stream()
486                     .filter(file -> file.getAbsolutePath().contains("oxm"))
487                     .forEach(oxmSchemaFileList::add));
488
489             dbEdgeRulesList.forEach(s ->
490                 FileUtils.listFiles(
491                     new File(s),
492                     new RegexFileFilter(".*\\.json"),
493                     DirectoryFileFilter.DIRECTORY)
494                     .stream()
495                     .filter(file -> file.getAbsolutePath().contains("DbEdgeRules"))
496                     .forEach(dbEdgeRulesFileList::add));
497
498             // Map the dbEdgeRules json file into a HashMap for reference
499             Map<String, Set<String>> dbEdgeRules = new HashMap<>();
500             JSONParser jsonParser = new JSONParser();
501             for (File file : dbEdgeRulesFileList) {
502                 FileReader reader = new FileReader(file);
503                 // Read JSON file. Expecting JSON file to read an object with a JSONArray names "rules"
504                 JSONObject jsonObj = (JSONObject) jsonParser.parse(reader);
505                 JSONArray rules = (JSONArray) jsonObj.get(DBEDGERULES_RULES);
506                 for (int i = 0; i < rules.size(); i++) {
507                     JSONObject rule = (JSONObject) rules.get(i);
508                     String fromNode = rule.get(DBEDGERULES_FROM).toString();
509                     String toNode = rule.get(DBEDGERULES_TO).toString();
510                     String direction = rule.get(DBEDGERULES_DIRECTION).toString();
511                     String containsOtherV = rule.get(DBEDGERULES_CONTAINS_OTHER_V).toString();
512
513                     // special case - cvlan-tag should be replaced with cvlan-tag-entry
514                     if (fromNode.equals("cvlan-tag"))
515                         fromNode = "cvlan-tag-entry";
516                     if (toNode.equals("cvlan-tag"))
517                         toNode = "cvlan-tag-entry";
518                     if (containsOtherV.equals("!${direction}")) {
519                         if (direction.equals(DBEDGERULES_IN)) {
520                             direction = DBEDGERULES_OUT;
521                         } else if (direction.equals(DBEDGERULES_OUT)) {
522                             direction = DBEDGERULES_IN;
523                         }
524                     }
525                     // If this value is none, the edge rule is for cousin nodes. Ignore.
526                     else if (containsOtherV.equals("NONE"))
527                         continue;
528                     dbEdgeRulesMapPut(dbEdgeRules, fromNode, toNode, direction);
529                 }
530             }
531
532             // Iterate through the most recent oxm schema files. Map the parent child relationships
533             Map<String, Set<String>> oxmSchemaFile = new HashMap<>();
534             for (File file : oxmSchemaFileList) {
535                 Document xmlDocument = getDocument(file);
536                 XPath xPath = XPathFactory.newInstance().newXPath();
537                 String parentNodeExpression = "/xml-bindings/java-types/java-type/xml-properties/xml-property[@name='dependentOn']";
538                 NodeList parentNodeList = (NodeList) xPath.compile(parentNodeExpression).evaluate(xmlDocument, XPathConstants.NODESET);
539                 String childNodeExpression = "/xml-bindings/java-types/java-type[" +
540                     "(" +
541                     "count(xml-properties/xml-property[@name='dependentOn']) > 0" +
542                     ")]";
543                 NodeList childNodeList = (NodeList) xPath.compile(childNodeExpression).evaluate(xmlDocument, XPathConstants.NODESET);
544
545                 for (int i = 0; i < parentNodeList.getLength(); i++) {
546
547                     // Obtain the xml-root-element field by tracing the childNodes from the java-type parent node
548                     for (int j = 0; j < childNodeList.item(i).getChildNodes().getLength(); j++) {
549                         if (childNodeList.item(i).getChildNodes().item(j).getNodeName().equals(XMLROOTELEMENT)) {
550
551                             // The parent node
552                             String dependentOn = parentNodeList.item(i).getAttributes().getNamedItem("value").getNodeValue();
553
554                             // The child node
555                             String xmlRootElement = childNodeList.item(i).getChildNodes().item(j).getAttributes().getNamedItem("name").getNodeValue();
556
557                             Set<String> childSet;
558                             String[] parents = dependentOn.split(",");
559                             for (int k = 0; k < parents.length; k++) {
560                                 String parent = parents[k];
561                                 if (oxmSchemaFile.containsKey(parent)) {
562                                     childSet = oxmSchemaFile.get(parent);
563                                 } else {
564                                     childSet = new HashSet<>();
565                                 }
566                                 childSet.add(xmlRootElement);
567                                 oxmSchemaFile.put(parent, childSet);
568                             }
569
570                         }
571                     }
572                 }
573             }
574
575             // Compare the OXM file against the dbEdgeRules file. check what is missing in dbEdgeRules from the oxm files.
576             Set<String> oxmKeySet = oxmSchemaFile.keySet();
577             for (String key : oxmKeySet) {
578                 Set<String> oxmChildren = oxmSchemaFile.get(key);
579                 Set<String> dbEdgeRulesChildren = dbEdgeRules.get(key);
580
581                 // Check if the parent vertex exists at all in the dbEdgeRules file
582                 if (dbEdgeRulesChildren == null || dbEdgeRulesChildren.isEmpty()) {
583                     for (String oxmChild : oxmChildren) {
584                         System.out.println("ERROR: dbEdgeRules under directory '" + subDir.toString() + "' does not contain parent '" + key + "' and child '" + oxmChild + "' relationship");
585                     }
586                     success = false;
587                     continue;
588                 }
589
590                 // Compare both parent-child relationships between both files
591                 if (!oxmChildren.equals(dbEdgeRulesChildren)) {
592                     for (String oxmChild : oxmChildren) {
593                         if (!dbEdgeRulesChildren.contains(oxmChild)) {
594                             System.out.println("ERROR: dbEdgeRules under directory '" + subDir.toString() + "' does not contain parent '" + key + "' and child '" + oxmChild + "' relationship");
595                             success = false;
596                         }
597                     }
598                 }
599             }
600
601             // Compare the dbEdgeRules against the OXM File
602             Set<String> dbEdgeRuleKeySet = dbEdgeRules.keySet();
603             for (String key : dbEdgeRuleKeySet) {
604                 Set<String> dbEdgeRulesChildren = dbEdgeRules.get(key);
605                 Set<String> oxmChildren = oxmSchemaFile.get(key);
606
607                 // Check if the parent vertex exists at all in the dbEdgeRules file
608                 if (oxmChildren == null || oxmChildren.isEmpty()) {
609                     for (String dbEdgeRuleChild : dbEdgeRulesChildren) {
610                         System.out.println("ERROR: oxms under directory '" + subDir.toString() + "' do not contain parent '" + key + "' and child '" + dbEdgeRuleChild + "' relationship");
611                     }
612                     success = false;
613                     continue;
614                 }
615
616                 // Compare both parent-child relationships between both files
617                 if (!dbEdgeRulesChildren.equals(oxmChildren)) {
618                     for (String dbEdgeRuleChild : dbEdgeRulesChildren) {
619                         if (!oxmChildren.contains(dbEdgeRuleChild)) {
620                             System.out.println("ERROR: oxms under directory '" + subDir.toString() + "' do not contain parent '" + key + "' and child '" + dbEdgeRuleChild + "' relationship");
621                             success = false;
622                         }
623                     }
624                 }
625             }
626         }
627         assertTrue(success);
628     }
629
630     /**
631      * Check dataOwner elements to ensure that they have ownerCheck side effect added to it.
632      *
633      */
634     @Test
635     public void testDataOwnerWithOwnerCheck() throws XPathExpressionException, IOException, SAXException, ParserConfigurationException, ParseException {
636         List<File> fileList = getLatestFiles();
637
638         for (File file : fileList) {
639             Document xmlDocument = getDocument(file);
640             XPath xPath = XPathFactory.newInstance().newXPath();
641             String expression = "/xml-bindings/java-types/java-type/java-attributes/xml-element[@name='data-owner']";
642             NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
643
644             List<String> typeMissingOwnerCheck = new ArrayList<>();
645
646             for (int i = 0; i < nodeList.getLength(); i++) {
647                 String type = nodeList.item(i).getParentNode().getParentNode().getAttributes().getNamedItem("name").getNodeValue();
648                 NodeList xmlPropertiesList = ((Element) nodeList.item(i)).getElementsByTagName("xml-properties");
649
650                 boolean missingOwnerCheck = true;
651                 for (int j = 0; j < xmlPropertiesList.getLength(); j++) {
652                     NodeList xmlProperties = ((Element) xmlPropertiesList.item(j)).getElementsByTagName("xml-property");
653
654                     for (int k = 0; k < xmlProperties.getLength(); k++) {
655                         String xmlProp = xmlProperties.item(k).getAttributes().getNamedItem("name").getNodeValue();
656
657                         if ("ownerCheck".equals(xmlProp)) {
658                             missingOwnerCheck = false;
659                             break;
660                         }
661                     }
662
663                     if (!missingOwnerCheck) {
664                         break;
665                     }
666                 }
667
668                 if (missingOwnerCheck) {
669                     typeMissingOwnerCheck.add(type);
670                 }
671             }
672
673             if (!typeMissingOwnerCheck.isEmpty()) {
674                 fail(file.getAbsolutePath().replaceAll(".*aai-schema", "") + ": " + String.join(", ", typeMissingOwnerCheck));
675             }
676         }
677     }
678
679     /**
680      * Null check for strings
681      * @param s
682      * @return
683      */
684     private boolean isStringEmpty(String s) {
685         return (s == null || s.isEmpty()) ? true : false;
686     }
687
688     /**
689      * Creating a hashmap to map what child nodes are associated to which parent nodes
690      * according to the dbEdgeRules json files. A HashMap was chosen for the value of the map for O(1) lookup time.
691      * @param from this variable will act as the key or value depending on the direction
692      * @param to this variable will act as the key or value depending on the direction
693      * @param direction dictates the direction of which vertex is dependent on which
694      * @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
695      */
696     private Map<String, Set<String>> dbEdgeRulesMapPut(Map<String, Set<String>> dbEdgeRules, String from, String to, String direction) {
697         if (isStringEmpty(from) || isStringEmpty(to) || isStringEmpty(direction))
698             return dbEdgeRules;
699
700         // Assigning the strings to parent and child for readability
701         String parent = "", child = "";
702         if (direction.equals(DBEDGERULES_OUT)) {
703             parent = from;
704             child = to;
705         } else if (direction.equals(DBEDGERULES_IN)) {
706             parent = to;
707             child = from;
708         }
709         // Add to the dbEdgeRules mapping
710         Set<String> children;
711         if (!dbEdgeRules.containsKey(parent)) {
712             children = new HashSet<>();
713             children.add(child);
714             dbEdgeRules.put(parent, children);
715         } else {
716             children = dbEdgeRules.get(parent);
717             children.add(child);
718             dbEdgeRules.put(parent, children);
719         }
720         return dbEdgeRules;
721     }
722
723     private List<File> getFiles() {
724         Path currentRelativePath = Paths.get("../aai-schema/src/main/resources/").toAbsolutePath();
725         return FileUtils.listFiles(
726             currentRelativePath.toFile(),
727             new RegexFileFilter(".*\\.xml"),
728             DirectoryFileFilter.DIRECTORY)
729             .stream()
730             .filter(file -> file.getAbsolutePath().contains("oxm"))
731             .filter(file -> !file.getAbsolutePath().contains("onap")) // skips onap for checks
732             .collect(Collectors.toList());
733     }
734
735     private List<File> getOxmSchemaFiles() {
736
737         Path currentRelativePath = Paths.get("../aai-schema/src/main/resources/").toAbsolutePath();
738         return FileUtils.listFiles(
739                 currentRelativePath.toFile(),
740                 new RegexFileFilter(".*\\.xml"),
741                 DirectoryFileFilter.DIRECTORY)
742                 .stream()
743                 .filter(file -> file.getAbsolutePath().contains("oxm"))
744                 .filter(file -> file.getAbsolutePath().contains("aai_schema_oxm"))
745                 .filter(file -> !file.getAbsolutePath().contains("onap")) // skips onap for checks
746                 .collect(Collectors.toList());
747
748     }
749
750     private List<File> getOnapOxmSchemaFiles() {
751
752         Path currentRelativePath = Paths.get("../aai-schema/src/main/resources/").toAbsolutePath();
753         return FileUtils.listFiles(
754                 currentRelativePath.toFile(),
755                 new RegexFileFilter(".*\\.xml"),
756                 DirectoryFileFilter.DIRECTORY)
757                 .stream()
758                 .filter(file -> file.getAbsolutePath().contains("oxm"))
759                 .filter(file -> file.getAbsolutePath().contains("aai_oxm"))
760                 .collect(Collectors.toList());
761
762     }
763
764     private List<File> getAaiSchemaOxmFiles() {
765         Path currentRelativePath = Paths.get("../aai-schema/src/main/resources/").toAbsolutePath();
766         return FileUtils.listFiles(
767             currentRelativePath.toFile(),
768             new RegexFileFilter(".*\\.xml"),
769             DirectoryFileFilter.DIRECTORY)
770             .stream()
771             .filter(file -> file.getAbsolutePath().contains("oxm"))
772             .filter(file -> !file.getAbsolutePath().contains("onap")) // skips onap for checks
773             .collect(Collectors.toList());
774     }
775
776     private List<File> getDbEdgeRulesFiles() {
777         Path currentRelativePath = Paths.get("../aai-schema/src/main/resources/").toAbsolutePath();
778         return FileUtils.listFiles(
779             currentRelativePath.toFile(),
780             new RegexFileFilter(".*\\.json"),
781             DirectoryFileFilter.DIRECTORY)
782             .stream()
783             .filter(file -> file.getAbsolutePath().contains("DbEdgeRules"))
784             .filter(file -> !file.getAbsolutePath().contains("onap")) // skips onap for checks
785             .collect(Collectors.toList());
786     }
787
788     /**
789      * Finds all of the oxm files for the latest version.
790      * @return list of the latest version of the oxm files.
791      */
792     private List<File> getLatestDbEdgeRulesFiles(String fileDirectory) {
793         List<String> latest = new ArrayList<>();
794         String currentRelativePath = Paths.get("../aai-schema/src/main/resources/" + fileDirectory + "/dbedgerules").toAbsolutePath().toString();
795         File[] oxms = new File(currentRelativePath).listFiles(File::isDirectory);
796         Arrays.stream(oxms).map(File::getAbsolutePath).max(new Comparator<String>() {
797             public int compare(String o1, String o2) {
798                 return extractInt(o1) - extractInt(o2);
799             }
800             int extractInt(String s) {
801                 String num = s.replaceAll("\\D", "");
802                 return num.isEmpty() ? 0 : Integer.parseInt(num);
803             }
804         }).ifPresent(latest::add);
805
806         List<File> latestFiles = new ArrayList<>();
807         latest.forEach(s ->
808             FileUtils.listFiles(
809                 new File(s),
810                 new RegexFileFilter(".*\\.json"),
811                 DirectoryFileFilter.DIRECTORY)
812                 .stream()
813                 .filter(file -> file.getAbsolutePath().contains("DbEdgeRules"))
814                 .forEach(latestFiles::add));
815
816         return latestFiles;
817     }
818
819     /**
820      * Finds all of the oxm files for the latest version.
821      * @return list of the latest version of the oxm files.
822      */
823     private List<File> getLatestFiles() {
824         List<String> latest = new ArrayList<>();
825         Path currentRelativePath = Paths.get("../aai-schema/src/main/resources/").toAbsolutePath();
826         List<File> subDirs = Arrays.asList(currentRelativePath.toFile().listFiles(File::isDirectory));
827         for (File subDir : subDirs) {
828             String oxm = subDir.getAbsolutePath() + "/oxm";
829             File[] oxms = new File(oxm).listFiles(File::isDirectory);
830             Arrays.stream(oxms).map(File::getAbsolutePath).max(new Comparator<String>() {
831                 public int compare(String o1, String o2) {
832                     return extractInt(o1) - extractInt(o2);
833                 }
834                 int extractInt(String s) {
835                     String num = s.replaceAll("\\D", "");
836                     return num.isEmpty() ? 0 : Integer.parseInt(num);
837                 }
838             }).ifPresent(latest::add);
839         }
840
841         List<File> latestFiles = new ArrayList<>();
842         latest.forEach(s ->
843             FileUtils.listFiles(
844                 new File(s),
845                 new RegexFileFilter(".*\\.xml"),
846                 DirectoryFileFilter.DIRECTORY)
847                 .stream()
848                 .filter(file -> file.getAbsolutePath().contains("oxm"))
849                 .forEach(latestFiles::add));
850
851         return latestFiles;
852     }
853
854     /**
855      * Finds all of the oxm files for the latest version.
856      * @return list of the latest version of the oxm files.
857      */
858     private List<File> getLatestFiles(String fileDirectory) {
859         List<String> latest = new ArrayList<>();
860         String currentRelativePath = Paths.get("../aai-schema/src/main/resources/" + fileDirectory + "/oxm").toAbsolutePath().toString();
861         File[] oxms = new File(currentRelativePath).listFiles(File::isDirectory);
862         Arrays.stream(oxms).map(File::getAbsolutePath).max(new Comparator<String>() {
863             public int compare(String o1, String o2) {
864                 return extractInt(o1) - extractInt(o2);
865             }
866             int extractInt(String s) {
867                 String num = s.replaceAll("\\D", "");
868                 return num.isEmpty() ? 0 : Integer.parseInt(num);
869             }
870         }).ifPresent(latest::add);
871
872         List<File> latestFiles = new ArrayList<>();
873         latest.forEach(s ->
874             FileUtils.listFiles(
875                 new File(s),
876                 new RegexFileFilter(".*\\.xml"),
877                 DirectoryFileFilter.DIRECTORY)
878                 .stream()
879                 .filter(file -> file.getAbsolutePath().contains("oxm"))
880                 .forEach(latestFiles::add));
881
882         return latestFiles;
883     }
884
885     //TODO test that all oxm xml are valid xml
886
887
888
889     public String printNodeList(NodeList nodeList, Document doc) throws IOException {
890         StringBuilder stringBuilder = new StringBuilder();
891         for (int i = 0; i < nodeList.getLength(); i++) {
892             stringBuilder.append(printNode(nodeList.item(i), doc)).append("\n");
893         }
894         return stringBuilder.toString();
895     }
896
897     public String printNode(Node node, Document document) throws IOException {
898         StringWriter stringWriter = new StringWriter();
899         return stringWriter.toString();
900
901     }
902
903     private Document getDocument(File file) throws ParserConfigurationException, SAXException, IOException {
904         InputStream fileIS = new FileInputStream(file);
905         DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
906         DocumentBuilder builder = builderFactory.newDocumentBuilder();
907         return builder.parse(fileIS);
908     }
909
910 }