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=7cd2afd06784e49dacdd1b7a2d31b721af66357f;hb=910cc5b113065eea0b3785e3140bb89d0fc86dd8;hp=bf391d49e52e8a1fd367f1fbbfac29758b696314;hpb=6fd88055dcf1a4982cc607222e77907a786173a8;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 bf391d4..7cd2afd 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,9 @@ package org.simantics.interop.update.model; +import java.util.ArrayDeque; import java.util.ArrayList; -import java.util.HashSet; +import java.util.Collections; +import java.util.Deque; import java.util.List; import java.util.Map.Entry; @@ -11,10 +13,12 @@ import org.simantics.db.Resource; import org.simantics.db.Session; import org.simantics.db.Statement; import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.ReadRequest; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.util.Layer0Utils; import org.simantics.db.request.Read; import org.simantics.interop.test.GraphChanges; +import org.simantics.interop.test.GraphChanges.Modification; import org.simantics.interop.test.GraphComparator; import org.simantics.utils.datastructures.Pair; @@ -36,7 +40,10 @@ public abstract class ModelUpdate { private UpdateTree updateTree3; private UpdateList updateList3; + private UpdateNode3 updateNode3; + private List filters = new ArrayList(); + private List userFilters = new ArrayList(); boolean init = false; @@ -56,7 +63,7 @@ public abstract class ModelUpdate { this.oldModel = oldModel; this.newModel = newModel; this.originalModel = originalModel; - addFilters(filters); +// addFilters(filters); if (originalModel != null) { // tree way comparison // compare the original and the old model @@ -66,7 +73,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); @@ -77,7 +84,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); @@ -119,9 +126,12 @@ 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) { @@ -131,16 +141,118 @@ public abstract class ModelUpdate { 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(ChangeFilter2 filter) { + userFilters.add(filter); + } + + /** + * Removes an user filter. Use refreshUserFilters() to apply the changes. + * @param filter + */ + public void removeUserFilter(ChangeFilter2 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) { + if (changes2 != null && changes3 != null) { + getUpdateTree3(); + } + getSession().syncRequest(new ReadRequest() { + + @Override + public void run(ReadGraph graph) throws DatabaseException { + for (PropertyChange change : updateList.getChanges()) { + boolean visible = true; + for (ChangeFilter2 filter : userFilters) { + if (!filter.accept(graph, change)) { + visible = false; + break; + } + } + change.setVisible(visible); + } + if (updateTree3 != null) { + Deque stack = new ArrayDeque<>(); + stack.add(getUpdateNode3()); + while (!stack.isEmpty()) { + UpdateNode3 n = stack.pop(); + boolean visible = true; + for (ChangeFilter2 filter : userFilters) { + if (!filter.accept(graph, n)) { + visible = false; + break; + } + } + n.setVisible(visible); + for (UpdateNode3 c : n.getChildren()) + stack.push(c); + } + } else { + + Deque stack = new ArrayDeque<>(); + stack.add(updateTree.getRootNode()); + while (!stack.isEmpty()) { + UpdateNode n = stack.pop(); + boolean visible = true; + for (ChangeFilter2 filter : userFilters) { + if (!filter.accept(graph, n)) { + visible = false; + break; + } + } + n.setVisible(visible); + for (UpdateNode c : n.getChildren()) + stack.push(c); + } + } + } + }); + } + } 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()); - } - - protected void addFilters(List filters) { - + return new UpdateList(changes, changes.getModifications()); } public Resource getOldModel() { @@ -193,15 +305,21 @@ public abstract class ModelUpdate { updateList3 = getUpdateList(changes3); return updateList3; } + + public UpdateNode3 getUpdateNode3() throws DatabaseException { + if (updateNode3 == null && changes2 != null && changes3 != null) { + updateNode3 = UpdateNode3.getCombinedTree(this); + } + return updateNode3; + } 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); } @@ -209,82 +327,123 @@ 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 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 (Modification mod : changes.getModifications()) { + + boolean accept = true; + for (ChangeFilter filter : filters) { + if (!filter.accept(g, mod)) { + accept = false; + break; + } + } + if (accept) + modifications.add(mod); + } + List deletions = new ArrayList(); + for (Statement del : changes.getDeletions()) { + + boolean accept = true; + for (ChangeFilter filter : filters) { + if (!filter.acceptDeletion(g, del)) { + accept = false; + break; + } + } + if (accept) + deletions.add(del); + } + List additions = new ArrayList(); + for (Statement del : changes.getAdditions()) { + + boolean accept = true; + for (ChangeFilter filter : filters) { + if (!filter.acceptAddition(g, del)) { + accept = false; + break; + } + } + if (accept) + additions.add(del); + } + + GraphChanges newChanges = new GraphChanges(changes.getResource1(),changes.getResource2(),deletions, additions, modifications, changes.getComparable()); + return newChanges; + } + } + + /** + * Interface for built-in filters that are used for processing raw change data before forming UpdateTree + UpdateList + * @author luukkainen + * + */ + public interface ChangeFilter { + public boolean accept(ReadGraph g, Modification change) throws DatabaseException; + public boolean acceptAddition(ReadGraph g, Statement addition) throws DatabaseException; + public boolean acceptDeletion(ReadGraph g, Statement deletion) throws DatabaseException; } /** - * 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. + * Interface for user defined filters. * - * @param g - * @param changes - * @return - * @throws DatabaseException + * This filter only affects visible flags. + * + * @author luukkainen + * */ - 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; + public interface ChangeFilter2 { + public boolean accept(ReadGraph g, PropertyChange change) throws DatabaseException; + public boolean accept(ReadGraph g, UpdateNode change) throws DatabaseException; + public boolean accept(ReadGraph g, UpdateNode3 change) throws DatabaseException; } @@ -308,12 +467,12 @@ public abstract class ModelUpdate { } @Override - public boolean accept(ReadGraph g, Pair change) throws DatabaseException { + public boolean accept(ReadGraph g, Modification change) throws DatabaseException { //filter floating point values that have less than 1% difference. - if (!g.hasValue(change.first.getObject()) || !g.hasValue(change.second.getObject())) + if (!g.hasValue(change.getLeftStm().getObject()) || !g.hasValue(change.getRightStm().getObject())) return true; - Object v1 = g.getValue(change.first.getObject()); - Object v2 = g.getValue(change.second.getObject()); + Object v1 = g.getValue(change.getLeftStm().getObject()); + Object v2 = g.getValue(change.getRightStm().getObject()); if (v1 instanceof Double && v2 instanceof Double) { double d1 = (Double)v1; @@ -329,6 +488,16 @@ public abstract class ModelUpdate { return true; } + + @Override + public boolean acceptAddition(ReadGraph g, Statement addition) throws DatabaseException { + return true; + } + + @Override + public boolean acceptDeletion(ReadGraph g, Statement deletion) throws DatabaseException { + return true; + } } public void defaultSelections() { @@ -341,8 +510,8 @@ public abstract class ModelUpdate { } - for (Pair pair : updateList.getChanges()) { - updateList.addSelected(pair); + for (PropertyChange pair : updateList.getChanges()) { + pair.select(true); } // preserve user-made changes (by removing selections) @@ -358,17 +527,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.second)) { + 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); } } }