X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.structural.synchronization.client%2Fsrc%2Forg%2Fsimantics%2Fstructural%2Fsynchronization%2Fbase%2FMappingBase.java;h=78678b5054d95b2559ef8ff6f37bbc6f7b4650e0;hb=72d52b5910e1ed0141b6768ef700e7321ac05553;hp=ec72aa6b3fcf36c855eeece65a2dd537551162c6;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/base/MappingBase.java b/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/base/MappingBase.java index ec72aa6b3..78678b505 100644 --- a/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/base/MappingBase.java +++ b/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/base/MappingBase.java @@ -1,218 +1,222 @@ -package org.simantics.structural.synchronization.base; - -import gnu.trove.map.hash.THashMap; -import gnu.trove.procedure.TObjectObjectProcedure; -import gnu.trove.procedure.TObjectProcedure; -import gnu.trove.set.hash.THashSet; - -import java.io.PrintWriter; - -/** - * The entry point to the mapping structure between Simantics database and a - * designated solver. It is used to synchronize changes from Simantics to the - * solver. - * - * @author Hannu Niemistö - */ -abstract public class MappingBase> { - - abstract public T getConfiguration(); - - /** - * Set of all components indexed by their UID. - */ - transient protected THashMap configurationByUid; - - /** - * Set of components whose removal is delayed because they might - * have been moved somewhere else. - */ - transient THashSet pendingRemoval = new THashSet(); - - /** - * This is a structure that is used to return the state of the removed modules - * when the removal is undone. - */ - public transient StateUndoContextBase undoContext; - - public transient ComponentFactory componentFactory; - - /** - * The synchronization has processed all change sets before this change set - * (excluding this change set). - * It means that next synchronization operation should start examining changes - * made in this revision and revisions after this. - */ - public long currentRevision; - - /** - * Tells whether the uids in the components can be used - * in the synchronization. This is normally true, but - * may be set temporarily false when export/import:in - * the model. - */ - private boolean trustUids; - - public MappingBase() { - this(null, -1L, false); - } - - public MappingBase(T configuration, boolean trustUids) { - this(configuration, -1L, trustUids); - } - - public MappingBase(T configuration, long currentRevision, boolean trustUids) { - undoContext = createUndoContext(); - componentFactory = createComponentFactory(); - if(trustUids) - createConfigurationById(configuration); - this.currentRevision = currentRevision; - this.trustUids = trustUids; - } - - abstract public StateUndoContextBase createUndoContext(); - abstract public ComponentFactory createComponentFactory(); - - protected void createConfigurationById(T configuration) { - THashMap configurationByUid = new THashMap(); - browseConfiguration(configurationByUid, configuration); - this.configurationByUid = configurationByUid; - } - - private void browseConfiguration( - THashMap configurationByUid, - T configuration) { - configurationByUid.put(configuration.uid, configuration); - for(T child : configuration.getChildren()) { - browseConfiguration(configurationByUid, child); - child.parent = configuration; - } - } - - public T detachOrCreateComponent(String uid) { - T result = configurationByUid.get(uid); - if(result == null) { - result = componentFactory.create(uid); - configurationByUid.put(uid, result); - } - else { - if(result.getParent() == null) - pendingRemoval.remove(result); - else - result.getParent().detachByUid(uid); - } - return result; - } - - /** - * Marks that the component should be removed. The actual removal - * is delayed until the call of {@link #removePending} so that if the - * component is not actually removed but moved or renamed, we don't lose - * its state. - */ - public void addPendingRemoval(T component) { - pendingRemoval.add(component); - } - - public void printUidMap() { - printUidMap(new PrintWriter(System.out)); - } - - public void printUidMap(final PrintWriter out) { - out.println("Component tree"); - out.print(" "); - getConfiguration().printConfiguration(out, 1); - if(configurationByUid != null) { - out.println("UIDs"); - configurationByUid.forEachEntry(new TObjectObjectProcedure() { - @Override - public boolean execute(String a, T b) { - out.println(" " + a + " (" + b.solverComponentName + ", " + b.componentId + ", " + b.uid + ")"); - return true; - } - }); - } - } - - /** - * Removes the component recursively. - */ - public void remove(final Solver solver, T component) { - if(configurationByUid != null) - configurationByUid.remove(component.uid); - if(component.getChildMap() != null) - component.getChildMap().forEachValue(new TObjectProcedure() { - @Override - public boolean execute(T child) { - remove(solver, child); - return true; - } - }); - if(component.componentId > 0 && !component.attached) - solver.remove(component.componentId); - } - - /** - * Saves undo state recursively - */ - public void saveUndoState(final Solver solver, T component) { - if(component.getChildMap() != null) - component.getChildMap().forEachValue(new TObjectProcedure() { - @Override - public boolean execute(T child) { - saveUndoState(solver, child); - return true; - } - }); - else if(component.componentId > 0 && !component.attached) - undoContext.saveState(solver, component.componentId, component.uid); - } - - /** - * Removes components that are marked pending with {@link #addPendingRemoval} method. - */ - public void removePending(final Solver solver) { - pendingRemoval.forEach(new TObjectProcedure() { - @Override - public boolean execute(T component) { - saveUndoState(solver, component); - return true; - } - }); - pendingRemoval.forEach(new TObjectProcedure() { - @Override - public boolean execute(T component) { - remove(solver, component); - return true; - } - }); - pendingRemoval.clear(); - } - - /** - * Changes the {@link #trustUids} flag. - */ - public void setTrustUids(boolean trustUids) { - if(trustUids != this.trustUids) { - this.trustUids = trustUids; - if(trustUids) { - T configuration = getConfiguration(); - if(configuration != null) - createConfigurationById(configuration); - } - } - if(!trustUids) - configurationByUid = null; - } - - public boolean getTrustUids() { - return trustUids; - } - - public void dispose() { - if (configurationByUid != null) - configurationByUid.clear(); - pendingRemoval.clear(); - } - -} +package org.simantics.structural.synchronization.base; + +import gnu.trove.map.hash.THashMap; +import gnu.trove.procedure.TObjectObjectProcedure; +import gnu.trove.procedure.TObjectProcedure; +import gnu.trove.set.hash.THashSet; + +import java.io.PrintWriter; + +/** + * The entry point to the mapping structure between Simantics database and a + * designated solver. It is used to synchronize changes from Simantics to the + * solver. + * + * @author Hannu Niemistö + */ +abstract public class MappingBase> { + + abstract public T getConfiguration(); + + /** + * Set of all components indexed by their UID. + */ + transient protected THashMap configurationByUid; + + /** + * Set of components whose removal is delayed because they might + * have been moved somewhere else. + */ + transient THashSet pendingRemoval = new THashSet(); + + /** + * This is a structure that is used to return the state of the removed modules + * when the removal is undone. + */ + public transient StateUndoContextBase undoContext; + + public transient ComponentFactory componentFactory; + + /** + * The synchronization has processed all change sets before this change set + * (excluding this change set). + * It means that next synchronization operation should start examining changes + * made in this revision and revisions after this. + */ + public long currentRevision; + + /** + * Tells whether the uids in the components can be used + * in the synchronization. This is normally true, but + * may be set temporarily false when export/import:in + * the model. + */ + private boolean trustUids; + + public MappingBase() { + this(null, -1L, false); + } + + public MappingBase(T configuration, boolean trustUids) { + this(configuration, -1L, trustUids); + } + + public MappingBase(T configuration, long currentRevision, boolean trustUids) { + undoContext = createUndoContext(); + componentFactory = createComponentFactory(); + if(trustUids) + createConfigurationById(configuration); + this.currentRevision = currentRevision; + this.trustUids = trustUids; + } + + abstract public StateUndoContextBase createUndoContext(); + abstract public ComponentFactory createComponentFactory(); + + protected void createConfigurationById(T configuration) { + THashMap configurationByUid = new THashMap(); + browseConfiguration(configurationByUid, configuration); + this.configurationByUid = configurationByUid; + } + + private void browseConfiguration( + THashMap configurationByUid, + T configuration) { + configurationByUid.put(configuration.uid, configuration); + for(T child : configuration.getChildren()) { + browseConfiguration(configurationByUid, child); + child.parent = configuration; + } + } + + public T detachOrCreateComponent(String uid) { + T result = configurationByUid.get(uid); + if(result == null) { + result = componentFactory.create(uid); + configurationByUid.put(uid, result); + } + else { + if(result.getParent() == null) + pendingRemoval.remove(result); + else + result.getParent().detachByUid(uid); + } + return result; + } + + /** + * Marks that the component should be removed. The actual removal + * is delayed until the call of {@link #removePending} so that if the + * component is not actually removed but moved or renamed, we don't lose + * its state. + */ + public void addPendingRemoval(T component) { + pendingRemoval.add(component); + } + + public void printUidMap() { + printUidMap(new PrintWriter(System.out)); + } + + public void printUidMap(final PrintWriter out) { + out.println("Component tree"); + out.print(" "); + getConfiguration().printConfiguration(out, 1); + if(configurationByUid != null) { + out.println("UIDs"); + configurationByUid.forEachEntry(new TObjectObjectProcedure() { + @Override + public boolean execute(String a, T b) { + out.println(" " + a + " (" + b.solverComponentName + ", " + b.componentId + ", " + b.uid + ")"); + return true; + } + }); + } + } + + /** + * Removes the component recursively. + */ + public void remove(final Solver solver, T component) { + if(configurationByUid != null) + configurationByUid.remove(component.uid); + if(component.getChildMap() != null) + component.getChildMap().forEachValue(new TObjectProcedure() { + @Override + public boolean execute(T child) { + remove(solver, child); + return true; + } + }); + if(component.componentId > 0 && !component.attached) + solver.remove(component.componentId); + } + + /** + * Saves undo state recursively + */ + public void saveUndoState(final Solver solver, T component) { + if(component.getChildMap() != null) + component.getChildMap().forEachValue(new TObjectProcedure() { + @Override + public boolean execute(T child) { + saveUndoState(solver, child); + return true; + } + }); + else if(component.componentId > 0 && !component.attached) + undoContext.saveState(solver, component.componentId, component.uid); + } + + /** + * Removes components that are marked pending with {@link #addPendingRemoval} method. + */ + public void removePending(final Solver solver) { + pendingRemoval.forEach(new TObjectProcedure() { + @Override + public boolean execute(T component) { + saveUndoState(solver, component); + return true; + } + }); + pendingRemoval.forEach(new TObjectProcedure() { + @Override + public boolean execute(T component) { + remove(solver, component); + return true; + } + }); + pendingRemoval.clear(); + } + + /** + * Changes the {@link #trustUids} flag. + */ + public void setTrustUids(boolean trustUids) { + if(trustUids != this.trustUids) { + this.trustUids = trustUids; + if(trustUids) { + T configuration = getConfiguration(); + if(configuration != null) + createConfigurationById(configuration); + } + } + if(!trustUids) + configurationByUid = null; + } + + public boolean getTrustUids() { + return trustUids; + } + + public void dispose() { + if (configurationByUid != null) + configurationByUid.clear(); + pendingRemoval.clear(); + } + + public boolean hasPendingRemovals() { + return !pendingRemoval.isEmpty(); + } + +}