diff options
author | Pavel Paroulek <pavel.paroulek@orange.com> | 2019-08-30 18:48:24 +0200 |
---|---|---|
committer | Pavel Paroulek <pavel.paroulek@orange.com> | 2019-08-30 18:48:24 +0200 |
commit | e9f43d63da7f1f5bf2f96e7d1d0b6c1b877e60b6 (patch) | |
tree | 0d03e814d41cae56adda54cea3396c67a8b9de04 | |
parent | 235c881daa50e9ec5d4f488a7feafbd1247a3168 (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.css | 7 | ||||
-rw-r--r-- | graphgraph-fe/src/GraphSettings.js | 15 | ||||
-rw-r--r-- | graphgraph-fe/src/ValidationModal.css | 31 | ||||
-rw-r--r-- | graphgraph-fe/src/ValidationModal.js | 49 | ||||
-rw-r--r-- | graphgraph-fe/src/requests.js | 6 | ||||
-rw-r--r-- | pom.xml | 5 | ||||
-rw-r--r-- | src/main/java/org/onap/aai/graphgraph/SchemaResource.java | 12 | ||||
-rw-r--r-- | src/main/java/org/onap/aai/graphgraph/SchemaValidator.java | 82 | ||||
-rw-r--r-- | src/main/java/org/onap/aai/graphgraph/dto/ValidationProblems.java | 20 |
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 +} @@ -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); + } +} |