+++ /dev/null
-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<T extends ComponentBase<T>> {
-
- abstract public T getConfiguration();
-
- /**
- * Set of all components indexed by their UID.
- */
- transient protected THashMap<String, T> configurationByUid;
-
- /**
- * Set of components whose removal is delayed because they might
- * have been moved somewhere else.
- */
- transient THashSet<T> pendingRemoval = new THashSet<T>();
-
- /**
- * 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<T> 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<T> createComponentFactory();
-
- protected void createConfigurationById(T configuration) {
- THashMap<String, T> configurationByUid = new THashMap<String, T>();
- browseConfiguration(configurationByUid, configuration);
- this.configurationByUid = configurationByUid;
- }
-
- private void browseConfiguration(
- THashMap<String, T> 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<String, T>() {
- @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<T>() {
- @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<T>() {
- @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<T>() {
- @Override
- public boolean execute(T component) {
- saveUndoState(solver, component);
- return true;
- }
- });
- pendingRemoval.forEach(new TObjectProcedure<T>() {
- @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();
- }
-
-}