]> gerrit.simantics Code Review - simantics/interop.git/commitdiff
Base classes for model updates
authorMarko Luukkainen <marko.luukkainen@vtt.fi>
Mon, 20 Feb 2017 13:30:40 +0000 (15:30 +0200)
committerMarko Luukkainen <marko.luukkainen@vtt.fi>
Mon, 20 Feb 2017 13:30:40 +0000 (15:30 +0200)
refs #7045

Change-Id: I9ac528fcec68f834d0229c14480b00635ad42e6b

12 files changed:
org.simantics.interop.update/.classpath [new file with mode: 0644]
org.simantics.interop.update/.gitignore [new file with mode: 0644]
org.simantics.interop.update/.project [new file with mode: 0644]
org.simantics.interop.update/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
org.simantics.interop.update/META-INF/MANIFEST.MF [new file with mode: 0644]
org.simantics.interop.update/build.properties [new file with mode: 0644]
org.simantics.interop.update/src/org/simantics/interop/update/Activator.java [new file with mode: 0644]
org.simantics.interop.update/src/org/simantics/interop/update/model/AddDeleteUpdateOp.java [new file with mode: 0644]
org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateNode.java [new file with mode: 0644]
org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateOp.java [new file with mode: 0644]
org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateOperations.java [new file with mode: 0644]
org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateTree.java [new file with mode: 0644]

diff --git a/org.simantics.interop.update/.classpath b/org.simantics.interop.update/.classpath
new file mode 100644 (file)
index 0000000..eca7bdb
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.simantics.interop.update/.gitignore b/org.simantics.interop.update/.gitignore
new file mode 100644 (file)
index 0000000..ae3c172
--- /dev/null
@@ -0,0 +1 @@
+/bin/
diff --git a/org.simantics.interop.update/.project b/org.simantics.interop.update/.project
new file mode 100644 (file)
index 0000000..a0ac7df
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>org.simantics.interop.update</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.ManifestBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.SchemaBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+       </natures>
+</projectDescription>
diff --git a/org.simantics.interop.update/.settings/org.eclipse.jdt.core.prefs b/org.simantics.interop.update/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..0c68a61
--- /dev/null
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/org.simantics.interop.update/META-INF/MANIFEST.MF b/org.simantics.interop.update/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..83657de
--- /dev/null
@@ -0,0 +1,18 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Update
+Bundle-SymbolicName: org.simantics.interop.update
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.simantics.interop.update.Activator
+Bundle-Vendor: VTT
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.simantics.interop;bundle-version="1.0.0",
+ org.simantics.db;bundle-version="1.1.0",
+ org.simantics.db.common;bundle-version="1.1.0",
+ org.simantics.layer0;bundle-version="1.1.0",
+ org.simantics.issues;bundle-version="1.1.0",
+ org.simantics.issues.common;bundle-version="1.1.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-ActivationPolicy: lazy
+Export-Package: org.simantics.interop.update.model
diff --git a/org.simantics.interop.update/build.properties b/org.simantics.interop.update/build.properties
new file mode 100644 (file)
index 0000000..34d2e4d
--- /dev/null
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .
diff --git a/org.simantics.interop.update/src/org/simantics/interop/update/Activator.java b/org.simantics.interop.update/src/org/simantics/interop/update/Activator.java
new file mode 100644 (file)
index 0000000..ee2cf6f
--- /dev/null
@@ -0,0 +1,50 @@
+package org.simantics.interop.update;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+       // The plug-in ID
+       public static final String PLUGIN_ID = "org.simantics.interop.update"; //$NON-NLS-1$
+
+       // The shared instance
+       private static Activator plugin;
+       
+       /**
+        * The constructor
+        */
+       public Activator() {
+       }
+
+       /*
+        * (non-Javadoc)
+        * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+        */
+       public void start(BundleContext context) throws Exception {
+               super.start(context);
+               plugin = this;
+       }
+
+       /*
+        * (non-Javadoc)
+        * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+        */
+       public void stop(BundleContext context) throws Exception {
+               plugin = null;
+               super.stop(context);
+       }
+
+       /**
+        * Returns the shared instance
+        *
+        * @return the shared instance
+        */
+       public static Activator getDefault() {
+               return plugin;
+       }
+
+}
diff --git a/org.simantics.interop.update/src/org/simantics/interop/update/model/AddDeleteUpdateOp.java b/org.simantics.interop.update/src/org/simantics/interop/update/model/AddDeleteUpdateOp.java
new file mode 100644 (file)
index 0000000..c01297e
--- /dev/null
@@ -0,0 +1,93 @@
+package org.simantics.interop.update.model;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.simantics.db.Resource;
+import org.simantics.db.Statement;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.utils.ListUtils;
+import org.simantics.db.common.utils.NameUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.interop.test.GraphChanges;
+import org.simantics.issues.common.IssueUtils;
+import org.simantics.issues.ontology.IssueResource;
+import org.simantics.layer0.Layer0;
+
+public abstract class AddDeleteUpdateOp extends UpdateOp {
+       
+       boolean add;
+       
+       public AddDeleteUpdateOp(GraphChanges changes) {
+               super(changes);
+       }
+       
+       @Override
+       public boolean isAdd() {
+               return add;
+       }
+       
+       @Override
+       public boolean isDelete() {
+               return !add;
+       }
+       
+       @Override
+       public boolean requiresParentOps() {
+               return add;
+       }
+
+       @Override
+       public boolean requiresSubOps() {
+               return !add;
+       }
+
+       protected static void copyProperties(WriteGraph g, Resource source, Resource destination) throws DatabaseException {
+               Layer0 l0 = Layer0.getInstance(g);
+               for (Statement s : g.getStatements(source, l0.HasProperty)) {
+                       if (s.isAsserted(source))
+                               continue;
+                       Object value = g.getPossibleValue(s.getObject());
+                       System.out.println(NameUtils.getSafeName(g, s.getSubject()) + " " + NameUtils.getSafeName(g, s.getPredicate()) + " " + NameUtils.getSafeName(g, s.getObject()) + " " + value);
+                       if (value != null) {
+                               Statement valueStm = g.getPossibleStatement(destination, s.getPredicate());
+                               Resource valueResource = null;
+                               if (valueStm != null && !valueStm.isAsserted(destination))
+                                       valueResource = valueStm.getObject();
+                               if (valueResource == null) {
+                                       valueResource = g.newResource();
+                                       g.claim(valueResource, l0.InstanceOf, g.getSingleObject(s.getObject(), l0.InstanceOf));
+                                       g.claim(destination, s.getPredicate(), valueResource);
+                               }
+                               g.claimValue(valueResource, value);
+                               //g.claimLiteral(destination, s.getPredicate(), value);
+                       }
+               }
+       }
+       
+       protected void copyIssues(WriteGraph g, Resource source, Resource destination) throws DatabaseException {
+               Layer0 l0 = Layer0.getInstance(g);
+               IssueResource ir = IssueResource.getInstance(g);
+               Collection<Resource> issues = g.getObjects(source, ir.Issue_HasContext_Inverse);
+               for (Resource issue : issues) {
+                       String label = g.getRelatedValue(issue, l0.HasLabel);
+                       Resource severity = g.getSingleObject(issue, ir.Issue_HasSeverity);
+                       List<Resource> sourceContexts = ListUtils.toList(g, g.getSingleObject(issue, ir.Issue_HasContexts));
+                       List<Resource> destinationContext = new ArrayList<Resource>(sourceContexts.size());
+                       // map context resources
+                       for (Resource r : sourceContexts) {
+                               if (r.equals(source))
+                                       destinationContext.add(destination);
+                               else {
+                                       if (getChanges().getComparable().containsLeft(r))
+                                               destinationContext.add(getChanges().getComparable().getRight(r));
+                                       else
+                                               destinationContext.add(r);
+                               }
+                       }
+                       
+                       IssueUtils.newUserIssue(g, label, severity, destinationContext);
+               }
+       }
+}
diff --git a/org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateNode.java b/org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateNode.java
new file mode 100644 (file)
index 0000000..e1312bf
--- /dev/null
@@ -0,0 +1,91 @@
+package org.simantics.interop.update.model;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.utils.NameUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.NoSingleResultException;
+import org.simantics.db.exception.ServiceException;
+import org.simantics.db.exception.ValidationException;
+import org.simantics.layer0.Layer0;
+
+public abstract class UpdateNode {
+
+       public enum Status {EXIST,DELETED,NEW,CONTAINS};
+       
+
+       private Status status;
+       private UpdateOp op;
+       private Resource r;
+       
+       
+       private Collection<UpdateNode> children = new ArrayList<UpdateNode>();
+       /**
+        * 
+        * @param resource old Resource if status is DELETED or EXISTS.
+        * @param status
+        * @param changes
+        */
+       public UpdateNode(Status status, UpdateOp op) {
+
+               this.status = status;
+               this.op = op;
+               this.r = op.getResource();
+       }
+       
+       public UpdateNode(Status status, Resource r) {
+
+               this.status = status;
+               this.op = null;
+               this.r = r;
+       }
+       
+       public Resource getResource() {
+               return r;
+       }
+       
+       public Resource getParentResource(ReadGraph g) throws DatabaseException {
+               Layer0 l0 = Layer0.getInstance(g);
+               return g.getPossibleObject(r, l0.PartOf);
+       }
+       
+       public void setStatus(Status status) {
+               this.status = status;
+       }
+       
+       public Status getStatus() {
+               return status;
+       }
+       
+       public Collection<UpdateNode> getChildren() {
+               return children;
+       }
+       
+       public void addChild(UpdateNode node) {
+               children.add(node);
+       }
+
+       public abstract ImageDescriptor getImage(ReadGraph graph) throws DatabaseException;
+
+       public String getLabel(ReadGraph graph) throws DatabaseException {
+               return getLabel(graph,r);
+       }
+       
+       protected String getLabel(ReadGraph graph, Resource r) throws ValidationException, ServiceException, NoSingleResultException {
+               String label = NameUtils.getSafeLabel(graph, r);
+               if (label.length() == 0)
+                       label = NameUtils.getSafeName(graph, r);
+               
+               return label;
+       }
+
+
+       public UpdateOp getOp() {
+               return op;
+       }
+
+}
diff --git a/org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateOp.java b/org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateOp.java
new file mode 100644 (file)
index 0000000..907741c
--- /dev/null
@@ -0,0 +1,137 @@
+package  org.simantics.interop.update.model;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.interop.test.GraphChanges;
+
+/**
+ * Base class for update operations (adding and deleting objects)  
+ * 
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
+ *
+ */
+public abstract class UpdateOp {
+       
+       private GraphChanges changes;
+       
+       private boolean selected = false;
+       private boolean manualSelection = false;
+       protected boolean applied = false;
+       
+       private Collection<UpdateOp> parentOps = new ArrayList<UpdateOp>();
+       private Collection<UpdateOp> subOps = new ArrayList<UpdateOp>();
+       
+       
+       public UpdateOp(GraphChanges changes) {
+               this.changes = changes;
+       }
+       
+       public Collection<UpdateOp> getParentOps() {
+               return parentOps;
+       }
+       
+       public Collection<UpdateOp> getSubOps() {
+               return subOps;
+       }
+       
+       public void addParentOp(UpdateOp op) {
+               assert (!op.equals(this));
+               parentOps.add(op);
+       }
+       
+       public void addSubOp(UpdateOp op) {
+               assert (!op.equals(this));
+               subOps.add(op);
+       }
+       
+       public void removeParentOp(UpdateOp op) {
+               parentOps.remove(op);
+       }
+       
+       public void removeSubOp(UpdateOp op) {
+               subOps.remove(op);
+       }
+       
+       public GraphChanges getChanges() {
+               return changes;
+       }
+       
+       public abstract boolean isAdd();
+       public abstract boolean isDelete();
+       
+       public abstract boolean requiresParentOps();
+       public abstract boolean requiresSubOps(); 
+       
+       public boolean select(boolean select) {
+               boolean b = _select(select);
+               if (b)
+                       manualSelection = true;
+               return b;
+       }
+       
+       private boolean _select(boolean select) {
+               if (select == selected)
+                       return true;
+               if (select) {
+                       if (requiresParentOps()) {
+                               for (UpdateOp op : parentOps)
+                                       op._select(true);
+                       }
+                       
+                       selected = true;
+                       manualSelection = false;
+                       if (requiresSubOps()) {
+                               for (UpdateOp op : subOps)
+                                       op._select(true);
+                       }
+                       
+               } else {
+                       selected = false;
+                       manualSelection = false;
+                       for (UpdateOp op : subOps) {
+                               if (op.requiresParentOps())
+                                       op._select(false);
+                               else if (!op.manualSelection)
+                                       op._select(false);
+                       }
+                       for (UpdateOp op : parentOps)
+                               if (op.requiresSubOps())
+                                       op._select(false);
+                       return true;
+               }
+               return false;
+       }
+       public boolean selected() {
+               return selected;
+       }
+       
+       public boolean applied() {
+               return applied;
+       }
+       public void apply(WriteGraph g) throws DatabaseException {
+               if (applied)
+                       return;
+               _apply(g);
+               applied = true;
+               
+       }
+       
+       protected abstract void _apply(WriteGraph g) throws DatabaseException;
+       
+       /**
+        * Returns resource that this operation is changing.
+        * @return
+        */
+       public abstract Resource getResource();
+       
+       /**
+        * Returns resource that this operation created during apply operation. If operation did not add anything, this returns null.
+        * @return
+        */
+       public abstract Resource getCreatedResource();
+
+}
diff --git a/org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateOperations.java b/org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateOperations.java
new file mode 100644 (file)
index 0000000..a324763
--- /dev/null
@@ -0,0 +1,112 @@
+package org.simantics.interop.update.model;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.Statement;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.interop.test.GraphChanges;
+
+/**
+ * 
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
+ *
+ */
+public abstract  class UpdateOperations {
+       
+       private List<UpdateOp> operations = new ArrayList<UpdateOp>();
+       private Map<Resource, UpdateOp> opMap = new HashMap<Resource, UpdateOp>();
+       private GraphChanges changes;
+       
+       public UpdateOperations(GraphChanges changes) {
+               this.changes = changes;
+               
+       }
+       
+       public UpdateOp getUpdateOp(Resource r) {
+               return opMap.get(r);
+       }
+       
+       public void applyAll(WriteGraph g) throws DatabaseException {
+               for (UpdateOp op : operations) {
+                       apply(g, op);
+               }
+       }
+
+       public void applySelected(WriteGraph g) throws DatabaseException {
+               for (UpdateOp op : operations) {
+                       if (op.selected())
+                               apply(g, op);
+               }
+       }
+       
+       public List<UpdateOp> getOperations() {
+               return operations;
+       }
+
+       private void apply(WriteGraph g, UpdateOp op) throws DatabaseException {
+               Stack<UpdateOp> stack = new Stack<UpdateOp>();
+               _apply(g, stack, op);
+       }
+       
+       private void _apply(WriteGraph g, Stack<UpdateOp> stack, UpdateOp op) throws DatabaseException {
+               if (op.applied())
+                       return;
+               if (stack.contains(op))
+                       return;
+               stack.push(op);
+               if (op.requiresParentOps()) {
+                       for (UpdateOp pop : op.getParentOps())
+                               if (!pop.applied())
+                                       _apply(g, stack, pop);
+               } 
+               if (op.requiresSubOps()) {
+                       for (UpdateOp sop : op.getSubOps())
+                               if (!sop.applied())
+                                       _apply(g, stack, sop);
+               }
+               stack.pop();
+               op.apply(g);
+       }
+
+       protected List<UpdateOp> getOps() {
+               List<UpdateOp> list = new ArrayList<UpdateOp>(operations.size());
+               list.addAll(operations);
+               return list;
+       }
+       
+       protected void addOp(Resource r, UpdateOp op) {
+               opMap.put(r, op);
+               operations.add(op);
+       }
+       
+       protected UpdateOp getOP(Resource r) {
+               return opMap.get(r);
+       }
+
+       public abstract void populate(ReadGraph g) throws DatabaseException;
+       
+       protected static Statement getInverse(ReadGraph g, Statement otherComponentInv) throws DatabaseException{
+               Statement otherComponent = null;
+               for (Statement s : g.getStatements(otherComponentInv.getObject(), g.getInverse(otherComponentInv.getPredicate()))) {
+                       if (s.getObject().equals(otherComponentInv.getSubject()))
+                               otherComponent = s;
+               }
+               return otherComponent;
+       }
+       
+       protected boolean compares(Resource r1, Resource r2) {
+               if (r1.equals(r2))
+                       return true;
+               if (changes.getComparable().contains(r1, r2))
+                       return true;
+               return false;
+       }
+
+}
diff --git a/org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateTree.java b/org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateTree.java
new file mode 100644 (file)
index 0000000..516ccd3
--- /dev/null
@@ -0,0 +1,115 @@
+package  org.simantics.interop.update.model;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.interop.test.GraphChanges;
+import org.simantics.interop.update.model.UpdateNode.Status;
+
+
+public abstract class UpdateTree {
+       
+       private UpdateNode rootNode;
+       private Map<Resource,UpdateNode> nodes;
+       private GraphChanges changes;
+       private UpdateOperations updateOps;
+       
+       
+       public UpdateTree(ReadGraph g, GraphChanges changes, UpdateOperations updateOps) throws DatabaseException {
+               this.changes = changes;
+               this.nodes = new HashMap<Resource, UpdateNode>();
+               this.rootNode = createNode(Status.EXIST, changes.getResource1());
+               nodes.put(changes.getResource1(), rootNode);
+               nodes.put(changes.getResource2(), rootNode);
+               this.updateOps = updateOps;
+               this.updateOps.populate(g);
+               populate(g);
+       }
+       
+       public UpdateOperations getUpdateOps() {
+               return updateOps;
+       }
+       
+       public UpdateNode getRootNode() {
+               return rootNode;
+       }
+       
+       protected abstract UpdateNode createNode(Status staus, Resource r);
+       protected abstract UpdateNode createNode(Status staus, UpdateOp op);
+       
+       private UpdateNode createNode(Resource r1, Resource r2) {
+               UpdateNode node = null;
+               if (r1 != null && r2 != null) {
+                       node =  createNode(Status.EXIST, r1);
+                       nodes.put(r1, node);
+                       nodes.put(r2, node);
+               } else if (r1 != null) {
+                       node = createNode(Status.DELETED ,updateOps.getUpdateOp(r1));
+                       nodes.put(r1, node);
+               } else if (r2 != null) {
+                       node = createNode(Status.NEW, updateOps.getUpdateOp(r2));
+                       nodes.put(r2, node);
+               }
+               return node;
+       }
+       
+       public UpdateNode addNode(ReadGraph g, Resource r1, Resource r2) throws DatabaseException {
+               if (r1 != null && r2 != null) {
+                       return null;
+               }
+               if (nodes.containsKey(r1))
+                       return nodes.get(r1);
+               if (nodes.containsKey(r2))
+                       return nodes.get(r2);
+               
+               UpdateNode node = createNode(r1, r2);
+               connectParent(g,node);
+               return node;
+               
+       }
+       
+       private boolean connectParent(ReadGraph g, UpdateNode node) throws DatabaseException {
+               UpdateNode parent = null;
+               while (true) {
+                       Resource parentResource = node.getParentResource(g);
+                       parent = nodes.get(parentResource);
+                       if (parent == null) {
+                               if (changes.getComparable().containsLeft(parentResource)) {
+                                       parent = createNode(parentResource, changes.getComparable().getRight(parentResource));
+                               } else if (changes.getComparable().containsRight(parentResource)) {
+                                       parent = createNode(changes.getComparable().getLeft(parentResource) ,parentResource);
+                               } else {
+                                       return false;
+                               }
+                               //parent.setStatus(Status.CONTAINS);
+                               parent.addChild(node);
+                               node = parent;
+                               parent = null;
+                       } else {
+                               parent.addChild(node);
+                               return true;
+                       }
+                       
+               }
+       }
+       
+       protected abstract boolean handleCustom(ReadGraph g, UpdateOp op) throws DatabaseException;
+       
+       private void populate(ReadGraph g) throws DatabaseException{
+
+               for (UpdateOp op : updateOps.getOperations()) {
+                       if (!handleCustom(g, op)) {
+                               if (op.isAdd()) {
+                                       addNode(g, null,op.getResource());
+                               } else {
+                                       addNode(g, op.getResource(), null);
+                               }
+                       }
+               }
+               
+       }
+
+}