aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Paroulek <pavel.paroulek@orange.com>2019-08-30 18:48:24 +0200
committerPavel Paroulek <pavel.paroulek@orange.com>2019-08-30 18:48:24 +0200
commite9f43d63da7f1f5bf2f96e7d1d0b6c1b877e60b6 (patch)
tree0d03e814d41cae56adda54cea3396c67a8b9de04
parent235c881daa50e9ec5d4f488a7feafbd1247a3168 (diff)
Adding schema validation base
Change-Id: I2047a47d2b7b233fda59bdee4c77142d4a14d540 Signed-off-by: Pavel Paroulek <pavel.paroulek@orange.com> Issue-ID: AAI-2583
-rw-r--r--graphgraph-fe/src/GraphSettings.css7
-rw-r--r--graphgraph-fe/src/GraphSettings.js15
-rw-r--r--graphgraph-fe/src/ValidationModal.css31
-rw-r--r--graphgraph-fe/src/ValidationModal.js49
-rw-r--r--graphgraph-fe/src/requests.js6
-rw-r--r--pom.xml5
-rw-r--r--src/main/java/org/onap/aai/graphgraph/SchemaResource.java12
-rw-r--r--src/main/java/org/onap/aai/graphgraph/SchemaValidator.java82
-rw-r--r--src/main/java/org/onap/aai/graphgraph/dto/ValidationProblems.java20
9 files changed, 220 insertions, 7 deletions
diff --git a/graphgraph-fe/src/GraphSettings.css b/graphgraph-fe/src/GraphSettings.css
index 4790e9b..6fb4550 100644
--- a/graphgraph-fe/src/GraphSettings.css
+++ b/graphgraph-fe/src/GraphSettings.css
@@ -27,3 +27,10 @@
display: flex;
width: 80px !important;
}
+
+
+.modal-button
+{
+ padding-top: 20px;
+ margin: 0;
+}
diff --git a/graphgraph-fe/src/GraphSettings.js b/graphgraph-fe/src/GraphSettings.js
index 1e80da9..4d44aef 100644
--- a/graphgraph-fe/src/GraphSettings.js
+++ b/graphgraph-fe/src/GraphSettings.js
@@ -3,9 +3,11 @@ import _ from 'underscore'
import { DropdownButton, MenuItem, Label } from 'react-bootstrap'
import './GraphSettings.css'
import Popup from './PopupSettings'
-import { pathGraph, basicGraph, schemas, nodeNames } from './requests'
+import ValidationModal from './ValidationModal'
+import { validateSchema, pathGraph, basicGraph, schemas, nodeNames } from './requests'
var emptyState = {
+ schemaProblems: [],
nodeNames: [],
fromNode: '',
graph: {
@@ -94,6 +96,12 @@ class GraphSettings extends React.Component {
s['nodeNames'] = nodeNames
this.setState(s)
})
+ fetch(validateSchema(schema))
+ .then(response => response.json())
+ .then(p => {
+ s['schemaProblems'] = p.problems
+ this.setState(s)
+ })
}
changeEdgeFilter (edgeFilter) {
@@ -211,8 +219,11 @@ class GraphSettings extends React.Component {
</div>
<Popup isDisabled={!this.state.showHops} edgeFilter={this.state.edgeFilter} parentHops={this.state.hops.parents} childHops={this.state.hops.child} cousinHops={this.state.hops.cousin} updateHops={this.updateHops}/>
+ <div className="modal-button">
+ <ValidationModal schemaProblems={this.state.schemaProblems}/>
+ </div>
</div>
-
+
</div>
</div>
)
diff --git a/graphgraph-fe/src/ValidationModal.css b/graphgraph-fe/src/ValidationModal.css
new file mode 100644
index 0000000..56b4567
--- /dev/null
+++ b/graphgraph-fe/src/ValidationModal.css
@@ -0,0 +1,31 @@
+.modal-content
+{
+height: 100%;
+width: 100%;
+}
+
+.modal-validator
+{
+ position: 'fixed';
+ width: 1024;
+ height: 768;
+ zIndex: 1040;
+ top: '5%';
+ left: '5%';
+ border: '1px solid #e5e5e5';
+ backgroundColor: 'white';
+ boxShadow: '0 5px 15px rgba(0,0,0,.5)';
+ padding: 0;
+}
+
+.modal-backdrop
+{
+ position: 'fixed';
+ zIndex: 1040;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ backgroundColor: '#000';
+ opacity: 0.5;
+}
diff --git a/graphgraph-fe/src/ValidationModal.js b/graphgraph-fe/src/ValidationModal.js
new file mode 100644
index 0000000..8bf1989
--- /dev/null
+++ b/graphgraph-fe/src/ValidationModal.js
@@ -0,0 +1,49 @@
+import _ from 'underscore'
+import React from 'react'
+import './ValidationModal.css'
+import { Button, Modal, ListGroup, ListGroupItem } from 'react-bootstrap'
+
+
+class ValidationModal extends React.Component {
+ constructor(...args) {
+ super(...args);
+ this.state = { showModal: false };
+
+ this.close = () => {
+ this.setState({ showModal: false });
+ };
+
+ this.open = () => {
+ this.setState({ showModal: true });
+ };
+ }
+
+ renderBackdrop(props) {
+ return <div {...props} className="modal-backdrop" />;
+ }
+
+ render() {
+ var problems = this.props.schemaProblems
+ var items = _.map(problems, (problem, i) => <ListGroupItem key={i}> {problem} </ListGroupItem>)
+ return (
+ <div>
+ <Button onClick={this.open}>Validate schema</Button>
+ <Modal
+ onHide={this.close}
+ className="modal-validator"
+ aria-labelledby="modal-label"
+ show={this.state.showModal}
+ renderBackdrop={this.renderBackdrop}
+ >
+ <div className="modal-list">
+ <ListGroup>
+ {items}
+ </ListGroup>
+ </div>
+ </Modal>
+ </div>
+ );
+ }
+}
+
+export default ValidationModal
diff --git a/graphgraph-fe/src/requests.js b/graphgraph-fe/src/requests.js
index 39c4b03..2494ba1 100644
--- a/graphgraph-fe/src/requests.js
+++ b/graphgraph-fe/src/requests.js
@@ -5,6 +5,10 @@ export function schemas () {
return `http://${host}:${port}/schemas`
}
+export function validateSchema (schema) {
+ return `http://${host}:${port}/schemas/${schema}/validation`
+}
+
export function nodeNames (schema, edgeFilter) {
return `http://${host}:${port}/schemas/${schema}/nodes?edgeFilter=${edgeFilter}`
}
@@ -23,4 +27,4 @@ export function nodeProperty (schema, node) {
export function edgeProperty (schema, fromNode, toNode) {
return `http://${host}:${port}/schemas/${schema}/edges?fromNode=${fromNode}&toNode=${toNode}`
-} \ No newline at end of file
+}
diff --git a/pom.xml b/pom.xml
index 5c4be70..a08d3ee 100644
--- a/pom.xml
+++ b/pom.xml
@@ -74,6 +74,11 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>io.vavr</groupId>
+ <artifactId>vavr</artifactId>
+ <version>0.10.2</version>
+ </dependency>
+ <dependency>
<groupId>org.jgrapht</groupId>
<artifactId>jgrapht-core</artifactId>
<version>1.3.0</version>
diff --git a/src/main/java/org/onap/aai/graphgraph/SchemaResource.java b/src/main/java/org/onap/aai/graphgraph/SchemaResource.java
index 52c7510..3182681 100644
--- a/src/main/java/org/onap/aai/graphgraph/SchemaResource.java
+++ b/src/main/java/org/onap/aai/graphgraph/SchemaResource.java
@@ -23,6 +23,7 @@ import org.onap.aai.graphgraph.dto.Graph;
import org.onap.aai.graphgraph.dto.NodeName;
import org.onap.aai.graphgraph.dto.NodeProperty;
import org.onap.aai.graphgraph.dto.Property;
+import org.onap.aai.graphgraph.dto.ValidationProblems;
import org.onap.aai.graphgraph.reader.SchemaRepository;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -58,7 +59,7 @@ public class SchemaResource {
@RequestMapping("/schemas/{schema}/edges")
- public List<Property> loadedgeProperties(
+ public List<Property> loadedgeProperties (
@PathVariable("schema") String schemaName,
@RequestParam("fromNode") String fromNodeName,
@RequestParam("toNode") String toNodeName) {
@@ -67,7 +68,7 @@ public class SchemaResource {
@RequestMapping("/schemas/{schema}/graph/basic")
- public Graph loadGraph(
+ public Graph loadGraph (
@PathVariable("schema") String schemaName,
@RequestParam("node") String initialNodeName,
@RequestParam("parentHops") Integer parentHops,
@@ -82,7 +83,7 @@ public class SchemaResource {
@RequestMapping("/schemas/{schema}/graph/paths")
- public Graph loadGraphWithPaths(
+ public Graph loadGraphWithPaths (
@PathVariable("schema") String schemaName,
@RequestParam("fromNode") String fromNode,
@RequestParam("toNode") String toNode,
@@ -91,7 +92,10 @@ public class SchemaResource {
return repository.getSchemaReader(schemaName).getGraph(fromNode, toNode, edgeFilter);
}
-
+ @RequestMapping("/schemas/{schema}/validation")
+ public ValidationProblems validateSchema ( @PathVariable("schema") String schemaName) {
+ return new SchemaValidator().validate(schemaName);
+ }
}
diff --git a/src/main/java/org/onap/aai/graphgraph/SchemaValidator.java b/src/main/java/org/onap/aai/graphgraph/SchemaValidator.java
new file mode 100644
index 0000000..b67f1ad
--- /dev/null
+++ b/src/main/java/org/onap/aai/graphgraph/SchemaValidator.java
@@ -0,0 +1,82 @@
+package org.onap.aai.graphgraph;
+
+import io.vavr.Tuple;
+import io.vavr.Tuple2;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.onap.aai.graphgraph.dto.Edge;
+import org.onap.aai.graphgraph.dto.Graph;
+import org.onap.aai.graphgraph.dto.ValidationProblems;
+import org.onap.aai.graphgraph.reader.BasicSchemaReader;
+
+public class SchemaValidator {
+ private Graph edgerules;
+ private Graph oxm;
+ public ValidationProblems validate(String schemaVersion) {
+ ValidationProblems validationProblems = new ValidationProblems();
+ BasicSchemaReader schema = new BasicSchemaReader(schemaVersion);
+ oxm = schema.getGraph("all", 0, 0, 0, "Parents");
+ edgerules = schema.getGraph("all", 0, 0, 0, "Edgerules");
+
+ checkIfDanglingEdgerules(validationProblems);
+ checkIfObsoleteOxm(validationProblems);
+ return validationProblems;
+ }
+
+ /**
+ * computes nodes connected to relationship-list but not used in edgerules
+ * @param validationProblems
+ */
+ private void checkIfObsoleteOxm(ValidationProblems validationProblems) {
+ Set<String> relationshipListConnected = getAllNodesConnectedToRelationshipList();
+ Set<String> nodesInEdgerules = getEdgerulePairs().stream().flatMap(p -> Stream.of(p._1, p._2))
+ .collect(Collectors.toSet());
+ relationshipListConnected.removeAll(nodesInEdgerules);
+ relationshipListConnected.forEach(n ->
+ validationProblems.addProblem(String.format("%s is associated with relationship-list in OXM but not present in edgerules", n)));
+ }
+
+ private Set<Tuple2<String, String>> getEdgerulePairs() {
+ return edgerules.getEdges().stream()
+ .map(e -> Tuple.of(e.getSource(), e.getTarget())).collect(
+ Collectors.toSet());
+ }
+
+ /**
+ * computes edgerules which don't have the necessary connection to relationship-list in OXM
+ * @param validationProblems
+ */
+ private void checkIfDanglingEdgerules(
+ ValidationProblems validationProblems) {
+ Set<Tuple2<String, String>> edgerulePairs = getEdgerulePairs();
+ edgerulePairs.removeAll(getOxmPairs());
+ edgerulePairs.forEach( erp ->
+ validationProblems.addProblem(String.format("%s and %s are associated in edgerules but not in OXM (via relationship-list)", erp._1, erp._2)));
+ }
+
+ private Set<Tuple2<String, String>> getOxmPairs() {
+ Set<Tuple2<String, String>> pairs = new HashSet<>();
+ Set<String> inRelationshipList = getAllNodesConnectedToRelationshipList();
+
+ inRelationshipList.forEach(edge1 ->
+ inRelationshipList.forEach(edge2 -> {
+ pairs.add(Tuple.of(edge1, edge2));
+ }));
+ return pairs;
+ }
+
+ private Set<String> getAllNodesConnectedToRelationshipList() {
+ List<Edge> edges = oxm.getEdges();
+ Set<String> inRelationshipList = edges.stream().filter(e -> e.getSource().equals("relationship-list")).map(
+ Edge::getTarget).collect(
+ Collectors.toSet());
+ inRelationshipList.addAll(edges.stream().filter(e -> e.getTarget().equals("relationship-list"))
+ .map(Edge::getSource).collect(
+ Collectors.toSet()));
+ return inRelationshipList;
+ }
+}
diff --git a/src/main/java/org/onap/aai/graphgraph/dto/ValidationProblems.java b/src/main/java/org/onap/aai/graphgraph/dto/ValidationProblems.java
new file mode 100644
index 0000000..f8c3b86
--- /dev/null
+++ b/src/main/java/org/onap/aai/graphgraph/dto/ValidationProblems.java
@@ -0,0 +1,20 @@
+package org.onap.aai.graphgraph.dto;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class ValidationProblems {
+ private List<String> problems = new LinkedList<>();
+
+ public List<String> getProblems() {
+ return problems;
+ }
+
+ public void setProblems(List<String> problems) {
+ this.problems = problems;
+ }
+
+ public void addProblem(String problem) {
+ problems.add(problem);
+ }
+}