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