From a1def49a6c4e5d661a08d21253c47e431eb12ddf Mon Sep 17 00:00:00 2001 From: Marko Luukkainen Date: Thu, 24 Oct 2019 14:29:46 +0300 Subject: [PATCH] Validate plant structure on DB write to prevent corruption gitlab #35 Change-Id: Ibea2a0fa90fcc4c3a39ac2ced7b85e69f5bceaeb --- .../simantics/plant3d/editor/P3DNodeMap.java | 74 +++++++++++++++++-- 1 file changed, 68 insertions(+), 6 deletions(-) diff --git a/org.simantics.plant3d/src/org/simantics/plant3d/editor/P3DNodeMap.java b/org.simantics.plant3d/src/org/simantics/plant3d/editor/P3DNodeMap.java index 10e914de..f7bb4230 100644 --- a/org.simantics.plant3d/src/org/simantics/plant3d/editor/P3DNodeMap.java +++ b/org.simantics.plant3d/src/org/simantics/plant3d/editor/P3DNodeMap.java @@ -7,7 +7,9 @@ import java.util.List; import java.util.Set; import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; import org.simantics.db.Session; +import org.simantics.db.WriteGraph; import org.simantics.db.exception.DatabaseException; import org.simantics.g3d.ontology.G3D; import org.simantics.g3d.scenegraph.base.INode; @@ -38,7 +40,7 @@ public class P3DNodeMap extends AbstractVTKNodeMap { } @Override protected void updateActor(INode n, Set ids) { - if (DEBUG) System.out.println("P3DNodeMap update " + n); + if (DEBUG) System.out.println("P3DNodeMap update " + debugString(n)); if (!(n instanceof IP3DVisualNode)) { if (n instanceof PipeControlPoint) { n = ((PipeControlPoint)n).getPipelineComponent(); @@ -52,7 +54,7 @@ public class P3DNodeMap extends AbstractVTKNodeMap { IP3DVisualNode node = (IP3DVisualNode)n; if (DEBUG) { - System.out.print("P3DNodeMap update " + node); + System.out.print("P3DNodeMap update " + debugString(node)); for (String s : ids) System.out.print(" " + s); System.out.println(); @@ -92,7 +94,7 @@ public class P3DNodeMap extends AbstractVTKNodeMap { } private void updateTransform(IP3DNode node) { - if (DEBUG) System.out.println("P3DNodeMap update Transform " + node); + if (DEBUG) System.out.println("P3DNodeMap update Transform " + debugString(node)); node.update(view.getRenderer()); @@ -117,7 +119,7 @@ public class P3DNodeMap extends AbstractVTKNodeMap { @Override protected void removeActor(INode n) { - if (DEBUG) System.out.println("P3DNodeMap.removeActor " + n); + if (DEBUG) System.out.println("P3DNodeMap.removeActor " + debugString(n)); if (!(n instanceof IP3DVisualNode)) return; IP3DVisualNode node = (IP3DVisualNode)n; @@ -132,13 +134,15 @@ public class P3DNodeMap extends AbstractVTKNodeMap { @Override protected void addActor(INode n) { - if (DEBUG) System.out.println("P3DNodeMap.addActor " + n); + if (DEBUG) System.out.println("P3DNodeMap.addActor " + debugString(n)); if (!(n instanceof IP3DVisualNode)) return; IP3DVisualNode node = (IP3DVisualNode)n; - if (hasActor(node)) + if (hasActor(node)) { + if (DEBUG) System.out.println("Node already has an actor"); return; + } if (Thread.currentThread() != view.getThreadQueue().getThread()) throw new RuntimeException("Illegal thread."); @@ -150,6 +154,7 @@ public class P3DNodeMap extends AbstractVTKNodeMap { nodeToActor.add(node, act); actorToNode.put(act, node); } + if (DEBUG) System.out.println("Added " + node.getActors().size() + " actors"); if (node instanceof P3DParentNode) { for (IP3DNode n2 : ((P3DParentNode)node).getNodes()) @@ -205,6 +210,12 @@ public class P3DNodeMap extends AbstractVTKNodeMap { super.commit(commitMessage); } + + @Override + protected void commit(WriteGraph graph) throws DatabaseException { + super.commit(graph); + validateGraph(graph); + } @Override protected void doCommit() { // System.out.println("Do commit"); @@ -240,5 +251,56 @@ public class P3DNodeMap extends AbstractVTKNodeMap { } } + + protected void validateGraph(ReadGraph graph) throws DatabaseException { + Plant3D P3D = Plant3D.getInstance(graph); + Resource root = (Resource)mapping.inverseGet(rootNode); + if (!graph.isInstanceOf(root, P3D.Plant)) + throw new DatabaseException("Root is not a Plant"); + Set equipment = new HashSet<>(); + Set pipeRuns = new HashSet<>(); + for (Resource r : graph.getObjects(root, P3D.children)) { + if (graph.isInstanceOf(r, P3D.Equipment)) { + equipment.add(r); + } else if (graph.isInstanceOf(r, P3D.PipeRun)) { + pipeRuns.add(r); + } else { + throw new DatabaseException("Unknown resource " + r); + } + } + Set nozzles = new HashSet<>(); + for (Resource e : equipment) { + for (Resource n : graph.getObjects(e, P3D.HasNozzle)) { + if (graph.isInstanceOf(n, P3D.Nozzle)) { + nozzles.add(n); + } else { + throw new DatabaseException("Unknown nozzle resource " + n); + } + } + } + + Set components = new HashSet<>(); + for (Resource run : pipeRuns) { + for (Resource c : graph.getObjects(run, P3D.children)) { + if (graph.isInstanceOf(c, P3D.PipelineComponent)) { + components.add(c); + } else { + throw new DatabaseException("Unknown component resource " + c); + } + } + } + + for (Resource c : components) { + for (Resource connected : graph.getObjects(c, P3D.Connects)) { + if (!components.contains(connected) && !nozzles.contains(connected)) { + throw new DatabaseException("Unbrowsable component resource " + connected + " connected to " + c); + } + Collection connectedConnected = graph.getObjects(connected, P3D.Connects); + if (!connectedConnected.contains(c)) { + throw new DatabaseException("Component resource " + c + " is connected to " + connected +", but its has no connection back."); + } + } + } + } } -- 2.45.2