package org.simantics.interop.update.model;
+import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Deque;
import java.util.List;
import java.util.Map.Entry;
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 UpdateList updateList3;
private List<ChangeFilter> filters = new ArrayList<ChangeFilter>();
+ private List<ChangeFilter> userFilters = new ArrayList<ChangeFilter>();
boolean init = false;
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
showWarning(result2.second);
comparator2.test(getSession());
changes2 = comparator2.getChanges();
- changes2 = getSession().syncRequest(new FilterChangesRead(changes2));
+ changes2 = getSession().syncRequest(new FilterChangesRead(changes2, filters));
updateTree2 = getUpdateTree(changes2);
updateList2 = getUpdateList(changes2);
showWarning(result3.second);
comparator3.test(getSession());
changes3 = comparator3.getChanges();
- changes3 = getSession().syncRequest(new FilterChangesRead(changes3));
+ changes3 = getSession().syncRequest(new FilterChangesRead(changes3, filters));
}
Pair<GraphComparator,String> result = getChanges(oldModel,newModel);
}
comparator.test(getSession());
changes = comparator.getChanges();
- changes = getSession().syncRequest(new FilterChangesRead(changes));
+ changes = getSession().syncRequest(new FilterChangesRead(changes, filters));
updateTree = getUpdateTree(changes);
updateList = getUpdateList(changes);
+ if (userFilters.size() != 0) {
+ refreshUserFilters();
+ }
if (originalModel != null) {
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);
+
+ }
+
+ /**
+ * 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 void refreshUserFilters() throws DatabaseException{
+ // use user filters to set visible flags of changes.
+ // First, set all changes visible.
+ Deque<UpdateNode> 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<ChangeFilter> combined = new ArrayList<>(filters);
+ combined.addAll(userFilters);
+ GraphChanges filteredChanges = getSession().syncRequest(new FilterChangesRead(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<UpdateNode, UpdateNode> 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<UpdateNode, UpdateNode> entry : comparable.getEntries()) {
+ applyVisibleFlags(entry.getKey(), entry.getValue());
+ }
+ }
+ private void applyVisibleFlags(Collection<PropertyChange> l, Collection<PropertyChange> r) {
+ BijectionMap<PropertyChange, PropertyChange> comparable = new BijectionMap<>();
+ for (PropertyChange lc : l) {
+ for (PropertyChange rc : r) {
+ if (comparable.containsRight(rc))
+ continue;
+ if (lc.getFirst().equals(rc.getFirst())) {
+ comparable.map(lc, rc);
+ }
+ }
+ }
+ for (PropertyChange lc : l) {
+ if (!comparable.containsLeft(lc))
+ lc.setVisible(false);
+ }
+
+ }
protected abstract Pair<GraphComparator,String> getChanges(Resource r1, Resource r2) throws DatabaseException;
protected abstract UpdateTree getUpdateTree(GraphChanges changes) throws DatabaseException;
return new UpdateList(changes, changes.getModifications());
}
- protected void addFilters(List<ChangeFilter> filters) {
-
- }
-
public Resource getOldModel() {
return oldModel;
}
private class FilterChangesRead implements Read<GraphChanges> {
private GraphChanges changes;
- public FilterChangesRead(GraphChanges changes) {
+ private List<ChangeFilter> filters;
+
+ public FilterChangesRead(GraphChanges changes, List<ChangeFilter> 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<Pair<Statement,Statement>> modifications = new ArrayList<Pair<Statement,Statement>>();
- for (Pair<Statement, Statement> 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 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<Pair<Statement,Statement>> modifications = new ArrayList<Pair<Statement,Statement>>();
+
+ for (Pair<Statement, Statement> 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<Statement, Statement> change) throws DatabaseException;