package org.simantics.interop.update.model; import java.util.HashMap; import java.util.Map; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.Session; import org.simantics.db.common.request.ResourceRead; import org.simantics.db.exception.DatabaseException; import org.simantics.db.request.Read; import org.simantics.interop.test.GraphChanges; public class UpdateTree { private UpdateNode rootNode; private Map nodes; private GraphChanges changes; private UpdateOperations updateOps; public UpdateTree(ReadGraph g, GraphChanges changes, UpdateOperations updateOps) throws DatabaseException { this.changes = changes; this.nodes = new HashMap(); this.rootNode = createNode(g, UpdateStatus.EXIST, changes.getResource1()); nodes.put(changes.getResource1(), rootNode); nodes.put(changes.getResource2(), rootNode); this.updateOps = updateOps; this.updateOps.populate(g); populate(g); this.rootNode.sort(); } public UpdateTree(Session session, GraphChanges changes, UpdateOperations updateOps) throws DatabaseException { this(session, changes, updateOps, new NullProgressMonitor()); } public UpdateTree(Session session, GraphChanges changes, UpdateOperations updateOps, IProgressMonitor monitor) throws DatabaseException { this.changes = changes; this.nodes = new HashMap(); this.rootNode = session.syncRequest(new NodeRequest(UpdateStatus.EXIST, changes.getResource1())); nodes.put(changes.getResource1(), rootNode); nodes.put(changes.getResource2(), rootNode); this.updateOps = updateOps; this.updateOps.populate(session, monitor); populate(session, monitor); if (monitor.isCanceled()) { this.changes = null; this.nodes.clear(); this.updateOps = null; this.rootNode = null; } else { this.rootNode.sort(); } } private class NodeRequest extends ResourceRead { UpdateStatus status; public NodeRequest(UpdateStatus status, Resource r) { super(r); this.status = status; } @Override public UpdateNode perform(ReadGraph graph) throws DatabaseException { return createNode(graph, status, resource); } } public UpdateOperations getUpdateOps() { return updateOps; } public UpdateNode getRootNode() { return rootNode; } public GraphChanges getChanges() { return changes; } protected UpdateNode createNode(ReadGraph g, UpdateStatus status, Resource r) throws DatabaseException { return new UpdateNode(g,status, r); } protected UpdateNode createNode(ReadGraph g, UpdateStatus status, UpdateOp op) throws DatabaseException{ return new UpdateNode(g,status, op); } private UpdateNode createNode(ReadGraph g, Resource r1, Resource r2) throws DatabaseException { UpdateNode node = null; if (r1 != null && r2 != null) { UpdateOp op = updateOps.getUpdateOp(r1); if (op == null) op = updateOps.getUpdateOp(r2); if (op == null) node = createNode(g, UpdateStatus.EXIST, r1); else node = createNode(g, UpdateStatus.EXIST, op); nodes.put(r1, node); nodes.put(r2, node); } else if (r1 != null) { node = createNode(g,UpdateStatus.DELETED ,updateOps.getUpdateOp(r1)); nodes.put(r1, node); } else if (r2 != null) { node = createNode(g,UpdateStatus.NEW, updateOps.getUpdateOp(r2)); nodes.put(r2, node); } return node; } public UpdateNode addNode(ReadGraph g, Resource r1, Resource r2) throws DatabaseException { if (nodes.containsKey(r1)) return nodes.get(r1); if (nodes.containsKey(r2)) return nodes.get(r2); UpdateNode node = createNode(g, r1, r2); connectParent(g,node); return node; } public UpdateNode getNode(Resource r) { return nodes.get(r); } protected 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) { parent = getOrCreate(g, parentResource); if (parent == null) return false; //parent.setStatus(Status.CONTAINS); parent.addChild(node); node = parent; parent = null; } else { parent.addChild(node); return true; } } } protected UpdateNode getOrCreate(ReadGraph g, Resource parentResource) throws DatabaseException { UpdateNode parent = nodes.get(parentResource); if (parent == null) { if (changes.getComparable().containsLeft(parentResource)) { parent = createNode(g, parentResource, changes.getComparable().getRight(parentResource)); } else if (changes.getComparable().containsRight(parentResource)) { parent = createNode(g, changes.getComparable().getLeft(parentResource) ,parentResource); } else { return null; } //parent.setStatus(Status.CONTAINS } return parent; } protected boolean handleCustom(ReadGraph g, UpdateOp op) throws DatabaseException { return false; } protected void populate(ReadGraph g) throws DatabaseException{ for (UpdateOp op : updateOps.getOperations()) { populate(g, op); } } protected void populate(ReadGraph g, UpdateOp op) throws DatabaseException{ if (!handleCustom(g, op)) { if (op.isAdd()) { addNode(g, null,op.getResource()); } else if (op.isDelete()){ addNode(g, op.getResource(), null); } else if (op.isChange()) { Resource o = op.getResource(); Resource l = getChanges().getComparable().containsLeft(o) ? o :getChanges().getComparable().getLeft(o); Resource r = getChanges().getComparable().containsRight(o) ? o :getChanges().getComparable().getRight(o); addNode(g, l, r); } } } protected void populate(Session session, IProgressMonitor monitor) throws DatabaseException{ int i = 0; while (i < updateOps.getOperations().size()) { if (monitor.isCanceled()) return; i = session.syncRequest(new PopulateRead(i)); } } protected class PopulateRead implements Read { int s; public PopulateRead(int s) { this.s = s; } public Integer perform(ReadGraph graph) throws DatabaseException { int l = s + 100; if (l > updateOps.getOperations().size()) l = updateOps.getOperations().size(); for (int i = s; i < l; i++) { UpdateOp op = updateOps.getOperations().get(i); populate(graph, op); } return l; } } }