X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.interop.update%2Fsrc%2Forg%2Fsimantics%2Finterop%2Fupdate%2Fmodel%2FModelUpdate.java;h=d76c47bdf655998c902de59f6f2b7f08c58f7bd8;hb=ab4fc05981803ce2c430f93f34b8b6a8f85a53ce;hp=0ddd4e40378b8bd543def326ed84926b1998be79;hpb=48789e733b91b0c337bd64b8e053c0ee79e0a374;p=simantics%2Finterop.git diff --git a/org.simantics.interop.update/src/org/simantics/interop/update/model/ModelUpdate.java b/org.simantics.interop.update/src/org/simantics/interop/update/model/ModelUpdate.java index 0ddd4e4..d76c47b 100644 --- a/org.simantics.interop.update/src/org/simantics/interop/update/model/ModelUpdate.java +++ b/org.simantics.interop.update/src/org/simantics/interop/update/model/ModelUpdate.java @@ -1,7 +1,10 @@ package org.simantics.interop.update.model; +import java.util.ArrayDeque; import java.util.ArrayList; -import java.util.HashSet; +import java.util.Collection; +import java.util.Collections; +import java.util.Deque; import java.util.List; import java.util.Map.Entry; @@ -16,20 +19,29 @@ import org.simantics.db.layer0.util.Layer0Utils; import org.simantics.db.request.Read; import org.simantics.interop.test.GraphChanges; import org.simantics.interop.test.GraphComparator; +import org.simantics.utils.datastructures.BijectionMap; import org.simantics.utils.datastructures.Pair; public abstract class ModelUpdate { - private GraphChanges changes; + private Resource oldModel; // old model that is going to be updated (User modified model) + private Resource newModel; // new model that contains the updates (New design model) + private Resource originalModel; // original model (optional) that is used for detecting and retaining user made changes (Old design model) + + private GraphChanges changes; // changes between old /new private UpdateTree updateTree; private UpdateList updateList; - private GraphChanges changes2; - private GraphChanges changes3; + private GraphChanges changes2; // changes between original / old private UpdateTree updateTree2; private UpdateList updateList2; + private GraphChanges changes3; // changes between original / new + private UpdateTree updateTree3; + private UpdateList updateList3; + private List filters = new ArrayList(); + private List userFilters = new ArrayList(); boolean init = false; @@ -37,8 +49,19 @@ public abstract class ModelUpdate { setInput(oldModel, newModel, null, false); } + /** + * Initialises the ModelUpdate with given input + * @param oldModel the model that is going to be updated (User modified model) + * @param newModel the model containing updates (New design model) + * @param originalModel the model that is used for detecting and retaining user made changes (Old design model). Parameter can be null. + * @param newDistinct when originalModel is given, additions to the old and the new model (when compared to the original model) are forced to be distinct. + * @throws DatabaseException + */ public void setInput(Resource oldModel, Resource newModel, Resource originalModel, boolean newDistinct) throws DatabaseException{ - addFilters(filters); + this.oldModel = oldModel; + this.newModel = newModel; + this.originalModel = originalModel; +// addFilters(filters); if (originalModel != null) { // tree way comparison // compare the original and the old model @@ -48,7 +71,7 @@ public abstract class ModelUpdate { showWarning(result2.second); comparator2.test(getSession()); changes2 = comparator2.getChanges(); - changes2 = getSession().syncRequest(new FilterChangesRead(changes2)); + changes2 = getSession().syncRequest(createFilterRead(changes2, filters)); updateTree2 = getUpdateTree(changes2); updateList2 = getUpdateList(changes2); @@ -59,7 +82,7 @@ public abstract class ModelUpdate { showWarning(result3.second); comparator3.test(getSession()); changes3 = comparator3.getChanges(); - changes3 = getSession().syncRequest(new FilterChangesRead(changes3)); + changes3 = getSession().syncRequest(createFilterRead(changes3, filters)); } Pair result = getChanges(oldModel,newModel); @@ -101,28 +124,155 @@ public abstract class ModelUpdate { } comparator.test(getSession()); changes = comparator.getChanges(); - changes = getSession().syncRequest(new FilterChangesRead(changes)); + changes = getSession().syncRequest(createFilterRead(changes, filters)); updateTree = getUpdateTree(changes); updateList = getUpdateList(changes); + if (userFilters.size() != 0) { + refreshUserFilters(); + } if (originalModel != null) { - createDefaultSelections(); + defaultSelections(); } init = true; } + public void addFilter(ChangeFilter filter) { + if (init) + throw new IllegalStateException("ModelUpdate has been initialized, adjusting filters is no longer possible."); + filters.add(filter); + + } + + public List getFilters() { + return Collections.unmodifiableList(filters); + } + + /** + * Adds an user filter. Use refreshUserFilters() to apply the changes. + * @param filter + */ + public void addUserFilter(ChangeFilter filter) { + userFilters.add(filter); + } + /** + * Removes an user filter. Use refreshUserFilters() to apply the changes. + * @param filter + */ + public void removeUserFilter(ChangeFilter filter) { + userFilters.remove(filter); + } + + /** + * Clears user filters. Use refreshUserFilters() to apply the changes. + */ + public void clearUserFilters() { + userFilters.clear(); + } + + public List getUserFilters() { + return userFilters; + } + + public void refreshUserFilters() throws DatabaseException{ + // use user filters to set visible flags of changes. + // First, set all changes visible. + Deque stack = new ArrayDeque<>(); + stack.push(updateTree.getRootNode()); + while (!stack.isEmpty()) { + UpdateNode n = stack.pop(); + n.setVisible(true); + stack.addAll(n.getChildren()); + } + for (PropertyChange pc : updateList.getChanges()) { + pc.setVisible(true); + } + if (userFilters.size() > 0) { + // Create filtered changes + List combined = new ArrayList<>(filters); + combined.addAll(userFilters); + GraphChanges filteredChanges = getSession().syncRequest(createFilterRead(changes, combined)); + UpdateTree updateTreeF = getUpdateTree(filteredChanges); + UpdateList updateListF = getUpdateList(filteredChanges); + // hide changes that are not contained within the filtered changes. + applyVisibleFlags(updateTree.getRootNode(), updateTreeF.getRootNode()); + applyVisibleFlags(updateList.getChanges(), updateListF.getChanges()); + } + } + + private void applyVisibleFlags(UpdateNode l, UpdateNode r) { + BijectionMap comparable = new BijectionMap<>(); + for (UpdateNode lc : l.getChildren()) { + for (UpdateNode rc : r.getChildren()) { + if (comparable.containsRight(rc)) + continue; + if (lc.getResource() != null) { + if (lc.getResource().equals(rc.getResource())) { + + comparable.map(lc, rc); + break; + } + } else if (rc.getResource() == null){ + UpdateOp lop = lc.getOp(); + UpdateOp rop = rc.getOp(); + if (lop.getStatement() != null && lop.getStatement().equals(rop.getStatement())) { + comparable.map(lc, rc); + break; + } + } + } + } + for (UpdateNode lc : l.getChildren()) { + if (!comparable.containsLeft(lc)) + lc.setVisible(false); + } + for (Entry entry : comparable.getEntries()) { + applyVisibleFlags(entry.getKey(), entry.getValue()); + } + } + + private void applyVisibleFlags(Collection l, Collection r) { + BijectionMap comparable = new BijectionMap<>(); + for (PropertyChange lc : l) { + for (PropertyChange rc : r) { + if (comparable.containsRight(rc)) + continue; + if (lc.getFirst() != null && lc.getFirst().equals(rc.getFirst())) { + comparable.map(lc, rc); + break; + } + if (lc.getSecond() != null && lc.getSecond().equals(rc.getSecond())) { + comparable.map(lc, rc); + break; + } + } + } + for (PropertyChange lc : l) { + if (!comparable.containsLeft(lc)) + lc.setVisible(false); + } + + } protected abstract Pair getChanges(Resource r1, Resource r2) throws DatabaseException; protected abstract UpdateTree getUpdateTree(GraphChanges changes) throws DatabaseException; protected UpdateList getUpdateList(GraphChanges changes) throws DatabaseException { - return new UpdateList(changes.getModifications()); + return new UpdateList(changes, changes.getModifications()); } - protected void addFilters(List filters) { - + public Resource getOldModel() { + return oldModel; + } + + public Resource getNewModel() { + return newModel; + } + + public Resource getOriginalModel() { + return originalModel; } public boolean isInit() { @@ -141,24 +291,36 @@ public abstract class ModelUpdate { public GraphChanges getChanges2() { return changes2; } - public GraphChanges getChanges3() { - return changes3; - } + public UpdateTree getUpdateTree2() { return updateTree2; } public UpdateList getUpdateList2() { return updateList2; } + + public GraphChanges getChanges3() { + return changes3; + } + + public UpdateTree getUpdateTree3() throws DatabaseException{ + if (updateTree3 == null && changes3 != null) + updateTree3 = getUpdateTree(changes3); + return updateTree3; + } + public UpdateList getUpdateList3() throws DatabaseException { + if (updateList3 == null && changes3 != null) + updateList3 = getUpdateList(changes3); + return updateList3; + } public void applyAll(WriteGraph graph) throws DatabaseException { Layer0Utils.addCommentMetadata(graph, "Apply all model updates"); graph.markUndoPoint(); - for (Pair mod : updateList.getChanges()) { - applyLiteralChange(graph, mod); + for (PropertyChange mod : updateList.getChanges()) { + mod.apply(graph); } - updateList.clear(); updateTree.getUpdateOps().applyAll(graph); } @@ -166,79 +328,73 @@ public abstract class ModelUpdate { public void applySelected(WriteGraph graph) throws DatabaseException { Layer0Utils.addCommentMetadata(graph, "Apply selected model updates"); graph.markUndoPoint(); - HashSet> changes = new HashSet<>(updateList.getSelected()); - for (Pair mod : changes) { - updateList.removeChange(mod); - applyLiteralChange(graph, mod); + for (PropertyChange mod : updateList.getChanges()) { + if (mod.selected()) + mod.apply(graph); } updateTree.getUpdateOps().applySelected(graph); } - protected void applyLiteralChange(WriteGraph graph, Pair mod) throws DatabaseException { - if (mod.second == null) { - graph.deny(mod.first); - return; - } - Resource s = changes.getComparable().getLeft(mod.second.getSubject()); - Resource pred = mod.second.getPredicate(); - if (graph.hasValue(mod.second.getObject())) { - Object value = graph.getValue(mod.second.getObject()); - graph.claimLiteral(s, pred, value); - } else { - graph.deny(s,pred); - } - } + protected Session getSession() { return Simantics.getSession(); } + public Read createFilterRead(GraphChanges changes, List filters) { + return new FilterChangesRead(changes, filters); + } + - private class FilterChangesRead implements Read { + public static class FilterChangesRead implements Read { private GraphChanges changes; - public FilterChangesRead(GraphChanges changes) { + private List filters; + + public FilterChangesRead(GraphChanges changes, List filters) { this.changes = changes; + this.filters = filters; } @Override public GraphChanges perform(ReadGraph graph) throws DatabaseException { return filterChanges(graph, changes); } - } - - /** - * Filters changes: - * 1. Changes that are not essential for model update (changes that can be found when the models are axcatly the same) - * 2. Runs custom filters for value changes. - * - * @param g - * @param changes - * @return - * @throws DatabaseException - */ - protected GraphChanges filterChanges(ReadGraph g, GraphChanges changes) throws DatabaseException - { - - List> modifications = new ArrayList>(); - for (Pair mod : changes.getModifications()) { - - boolean accept = true; - for (ChangeFilter filter : filters) { - if (!filter.accept(g, mod)) { - accept = false; - break; - } - } - if (accept) - modifications.add(mod); - } - GraphChanges newChanges = new GraphChanges(changes.getResource1(),changes.getResource2(),changes.getDeletions(), changes.getAdditions(), modifications, changes.getComparable()); - return newChanges; - } + /** + * Filters changes: + * 1. Changes that are not essential for model update (changes that can be found when the models are exactly the same) + * 2. Runs custom filters for value changes. + * + * @param g + * @param changes + * @return + * @throws DatabaseException + */ + protected GraphChanges filterChanges(ReadGraph g, GraphChanges changes) throws DatabaseException + { + + List> modifications = new ArrayList>(); + + for (Pair mod : changes.getModifications()) { + + boolean accept = true; + for (ChangeFilter filter : filters) { + if (!filter.accept(g, mod)) { + accept = false; + break; + } + } + if (accept) + modifications.add(mod); + } + GraphChanges newChanges = new GraphChanges(changes.getResource1(),changes.getResource2(),changes.getDeletions(), changes.getAdditions(), modifications, changes.getComparable()); + return newChanges; + } + } + public interface ChangeFilter { public boolean accept(ReadGraph g, Pair change) throws DatabaseException; @@ -288,15 +444,18 @@ public abstract class ModelUpdate { } } - protected void createDefaultSelections() { + public void defaultSelections() { + if (changes3 == null) { + return; + } // select all changes for (Entry op : updateTree.getUpdateOps().getResourceMap().entrySet()) { op.getValue().select(true); } - for (Pair pair : updateList.getChanges()) { - updateList.addSelected(pair); + for (PropertyChange pair : updateList.getChanges()) { + pair.select(true); } // preserve user-made changes (by removing selections) @@ -312,17 +471,17 @@ public abstract class ModelUpdate { } } - for (Pair pair : updateList.getChanges()) { - if (pair.first != null) { + for (PropertyChange pair : updateList.getChanges()) { + if (pair.getFirst() != null) { boolean found = false; - for (Pair pair2 : updateList2.getChanges()) { - if (pair.first.equals(pair2.first)) { + for (PropertyChange pair2 : updateList2.getChanges()) { + if (pair.getFirst() != null && pair.getFirst().equals(pair2.getSecond())) { found = true; break; } } if (found) { - updateList.removeSelected(pair); + pair.select(false); } } }