]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/base/SynchronizationEventHandlerBase.java
Separate DB and non-DB code to different structural sync bundles
[simantics/platform.git] / bundles / org.simantics.structural.synchronization.client / src / org / simantics / structural / synchronization / base / SynchronizationEventHandlerBase.java
diff --git a/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/base/SynchronizationEventHandlerBase.java b/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/base/SynchronizationEventHandlerBase.java
deleted file mode 100644 (file)
index 7be353a..0000000
+++ /dev/null
@@ -1,430 +0,0 @@
-package org.simantics.structural.synchronization.base;
-
-import java.util.ArrayDeque;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Queue;
-
-import org.simantics.databoard.Bindings;
-import org.simantics.databoard.adapter.AdaptException;
-import org.simantics.db.exception.DatabaseException;
-import org.simantics.structural.synchronization.internal.Policy;
-import org.simantics.structural.synchronization.protocol.ChildInfo;
-import org.simantics.structural.synchronization.protocol.Connection;
-import org.simantics.structural.synchronization.protocol.SerializedVariable;
-import org.simantics.structural.synchronization.protocol.SynchronizationEventHandler;
-import org.simantics.structural.synchronization.protocol.SynchronizationException;
-import org.simantics.structural.synchronization.utils.ComponentBase;
-import org.simantics.structural.synchronization.utils.ComponentFactory;
-import org.simantics.structural.synchronization.utils.MappingBase;
-import org.simantics.structural.synchronization.utils.Solver;
-import org.slf4j.Logger;
-
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.set.hash.THashSet;
-
-/**
- * Handles synchronization events by updating the simulator designated by the
- * provided {@link Solver} instance.
- * 
- * @author Hannu Niemistö
- */
-public abstract class SynchronizationEventHandlerBase<T extends ComponentBase<T>> implements SynchronizationEventHandler {
-
-    public static final boolean TRACE_EVENTS = false;
-    
-    public final Solver solver;
-    protected final SolverNameUtil nameUtil;
-    protected final MappingBase<T> mapping;
-    final ModuleUpdaterFactoryBase<T> moduleUpdaterFactory;
-    final ComponentFactory<T> componentFactory;
-    public final ReferenceResolverBase<T> resolver;
-    private boolean didChanges = false;
-
-    protected T component; // Current active component
-    THashMap<String, ModuleUpdaterBase<T>> moduleUpdaters = new THashMap<>();
-    Queue<Runnable> postSynchronizationActions = new ArrayDeque<>();
-    protected THashMap<String, ComponentBase<T>> solverComponentNameToComponent = new THashMap<>();
-    
-    /**
-     * This is a set of components satisfying the following conditions
-     * <ul>
-     *     <li>beginComponent is called for their parents
-     *     <li>endComponent is not yet called for their parents
-     *     <li>beginComponent is not yet called for them
-     * </ul>
-     */
-    THashSet<T> potentiallyUpdatedComponents = new THashSet<>();
-
-    public SynchronizationEventHandlerBase(Solver solver, ReferenceResolverBase<T> resolver, SolverNameUtil nameUtil,
-            ComponentFactory<T> componentFactory, ModuleUpdaterFactoryBase<T> moduleUpdaterFactory, MappingBase<T> mapping) {
-        this.solver = solver;
-        this.nameUtil = nameUtil;
-        this.mapping = mapping;
-        this.componentFactory = componentFactory;
-        this.moduleUpdaterFactory = moduleUpdaterFactory;
-        this.resolver = resolver;
-    }
-    
-    @Override
-    public void beginSynchronization() {
-        if(TRACE_EVENTS) {
-            System.out.println("beginSynchronization()");
-            //mapping.printUidMap();
-        }
-        component = null;
-    }
-    
-    @Override
-    public void endSynchronization() {
-        try {
-            if(TRACE_EVENTS)
-                System.out.println("endSynchronization()");
-            if(component != null)
-                throw new SynchronizationException("beginComponent/endComponent calls do not match.");
-            
-            resolver.resolvePendingSelfReferences();
-            resolver.printPending();
-            
-            // Do removals
-            mapping.removePending(solver);
-            
-            // Post synchronization actions
-            Runnable action;
-            while((action = postSynchronizationActions.poll()) != null)
-                action.run();
-
-            // Rename modules to suggested names where possible.
-            nameUtil.applySuggestedNames((creationName, newName) -> {
-                ComponentBase<T> component = solverComponentNameToComponent.get(creationName);
-                if (component != null) {
-                    component.solverComponentName = newName;
-                }
-            });
-            solverComponentNameToComponent.clear();
-        } catch(Throwable e) {
-            Policy.logError(e);
-            throw new SynchronizationException(e);
-        }
-    }
-
-    private boolean isAttached(Collection<SerializedVariable> properties) {
-        for(SerializedVariable property : properties)
-            if(property.name.equals("IsAttached"))
-                try {
-                    return (Boolean)property.value.getValue(Bindings.BOOLEAN);
-                } catch (AdaptException e) {
-                    throw new SynchronizationException(e);
-                }
-        return false;
-    }
-    
-    private boolean isDesynchronized(Collection<SerializedVariable> properties) {
-        for(SerializedVariable property : properties)
-            if(property.name.equals("IsDesynchronized"))
-                try {
-                    return (Boolean)property.value.getValue(Bindings.BOOLEAN);
-                } catch (AdaptException e) {
-                    throw new SynchronizationException(e);
-                }
-        return false;
-    }
-    
-    @Override
-    public void beginComponent(String name, String typeId,
-            Collection<SerializedVariable> properties,
-            Collection<Connection> connections,
-            Collection<ChildInfo> children)
-                    throws SynchronizationException {
-        try {
-            if(TRACE_EVENTS) {
-                System.out.println("beginComponent("+name+", " + (component != null ? component.uid : "null") + "," + typeId + ")");
-                if(!children.isEmpty()) {
-                    System.out.println("    Children:");
-                    for(ChildInfo child : children)
-                        System.out.println("        " + child.name + " " + child.uid);
-                }
-                if(!connections.isEmpty()) {
-                    System.out.println("    Connections:");
-                    for(Connection connection : connections)
-                        System.out.println("        " + connection.relation + " " + connection.connectionPoints);
-                }
-            }
-            
-            String parentSolverComponentName;
-            
-            // Finds the composite
-            if(component == null) {
-                name = "COMP_ROOT";
-                parentSolverComponentName = "";
-                component = mapping.getConfiguration();
-                component.setModuleId(solver.getId(name));
-                component.solverComponentName = name;
-            }
-            else {
-                parentSolverComponentName = component.solverComponentName;
-                component = component.getChild(name);
-                if(component == null)
-                    throw new SynchronizationException("Didn't find '"+name+"'. "
-                            + "It should have been mentioned as a child in the parent beginComponent method.");
-            }
-            
-            potentiallyUpdatedComponents.remove(component);
-    
-            ModuleUpdaterBase<T> updater = null;
-            if(typeId != null) {
-                updater = moduleUpdaters.get(typeId);
-                if(updater == null)
-                    throw new SynchronizationException("Undefined typeId " + typeId + ".");
-            }
-            
-            // Handle composite
-            if(typeId == null || updater.isUserComponent || updater.isComposite) {
-                // Create or update a subprocess
-                int moduleId = component.getModuleId();
-                boolean justCreated = false;
-                if(isAttached(properties))
-                    ; // Subprocesses are not created for attached composites
-                else if(moduleId <= 0) {
-                    String subprocessName = nameUtil.getFreshName(
-                            parentSolverComponentName,
-                            getSubprocessName(name, properties));
-                    try {
-                       solver.addSubprocess(subprocessName, updater.subprocessType);
-                    } catch(Exception e) {
-                       reportProblem("Exception while adding subprocess.", e);
-                    }
-                    moduleId = solver.getId(subprocessName);
-                    if(moduleId <= 0)
-                        throw new SynchronizationException("Failed to create a subprocess " + subprocessName);
-                    component.setModuleId(moduleId);
-
-                    // TODO these two lines can be removed when IncludedInSimulation -property is given to all composites
-                    if(component.getParent() != null) {
-                       String parentName = solver.getName(component.getParent().getModuleId());
-                       solver.includeSubprocess(parentName, subprocessName);
-                       component.solverComponentName = subprocessName;
-                       solverComponentNameToComponent.put(subprocessName, component);
-                    }
-                    
-                    if(updater.isComposite) {
-                       final ModuleUpdateContext<T> context = new ModuleUpdateContext<T>(this, updater, component);
-                       updater.create(context, properties, connections);
-                    }
-                    
-                    justCreated = true;
-                    
-                } else {
-                       
-                    component.solverComponentName = nameUtil.ensureNameIsVariationOf(
-                            parentSolverComponentName, moduleId,
-                            getSubprocessName(name, properties));
-                    
-                    if(updater.isComposite) {
-                       final ModuleUpdateContext<T> context = new ModuleUpdateContext<T>(this, updater, component);
-                       updater.update(context, properties, connections);
-                    }
-                    
-                }
-                if(mapping.getTrustUids()) {
-                       // Create a new child map
-                       THashMap<String, T> newChildMap =
-                                       new THashMap<String, T>();
-                    for(ChildInfo info : children) {
-                        // Detach from the existing configuration the children with
-                        // the right uids or create new components if uid is unknown.
-                        T conf = mapping.detachOrCreateComponent(info.uid);
-                        newChildMap.put(info.name, conf);
-                        resolver.markPending(conf);
-                        potentiallyUpdatedComponents.add(conf);
-                    }
-        
-                    // Put old children not detached in the previous phase
-                    // to the pending removal set. They might have been
-                    // moved somewhere else.
-                    THashMap<String, T> oldChildMap =
-                            component.setChildMapAndReturnOld(newChildMap);
-                    resolver.unmarkPending(component);
-                    if(oldChildMap != null)
-                        for(T component : oldChildMap.values()) {
-                            component.clearParent();
-                            mapping.addPendingRemoval(component);
-                        }
-                }
-                // Alternative implementation when uids are not available.
-                else {
-                    // Create a new child map
-                    THashMap<String, T> newChildMap =
-                            new THashMap<String, T>();
-                    Map<String, T> oldChildMap =
-                            component.getChildMap();
-                    if(oldChildMap == null)
-                        oldChildMap = Collections.<String,T>emptyMap();
-                    for(ChildInfo info : children) {
-                        T conf = oldChildMap.remove(info.name);
-                        if(conf == null)
-                            conf = componentFactory.create(info.uid);
-                        else
-                            conf.uid = info.uid;
-                        newChildMap.put(info.name, conf);
-                        resolver.markPending(conf);
-                    }
-                    component.setChildMap(newChildMap);
-
-                    resolver.unmarkPending(component);
-                    if(oldChildMap != null)
-                        for(T component : oldChildMap.values()) {
-                            component.clearParent();
-                            mapping.addPendingRemoval(component);
-                        }
-                }
-
-                postCompositeAction(justCreated, properties, connections, updater);
-                
-            }
-            // Handle component
-            else {
-                if(!children.isEmpty())
-                    throw new SynchronizationException("Component with type " + typeId + " cannot have children.");
-                
-                boolean attached = isAttached(properties);
-                component.attached = attached;
-
-                // Create or update the component
-                final ModuleUpdateContext<T> context = new ModuleUpdateContext<T>(this, updater, component);
-                int moduleId = component.getModuleId();
-                if(moduleId <= 0) {
-                    if(attached) {
-                        component.attached = true;
-                        context.setModuleName(name);
-                        context.setModuleId(solver.getId(name));
-                        if(context.getModuleId() <= 0)
-                            reportProblem("Didn't find attached module " + name + ".");
-                        else if(!isDesynchronized(properties))
-                            updater.update(context, properties, connections);
-                        setDidChanges();
-                    }
-                    else {
-                        component.attached = false;
-                        context.setModuleName(nameUtil.getFreshName(parentSolverComponentName, name));
-                        context.addPostUpdateAction(new Runnable() {
-                            @Override
-                            public void run() {
-                                context.stateLoadedFromUndo = mapping.undoContext.loadState(solver,
-                                        context.component.componentId, 
-                                        context.component.uid);
-                            }
-                        });
-                        updater.create(context, properties, connections);
-                        solverComponentNameToComponent.put(context.getModuleName(), component);
-                    }
-                }
-                else if(!isDesynchronized(properties)) {
-                    context.setModuleName(nameUtil.ensureNameIsVariationOf(parentSolverComponentName,
-                            moduleId, name));
-                    updater.update(context, properties, connections);
-                }
-                else {
-                    resolver.unmarkPending(component);
-                }
-            }
-        } catch(Throwable e) {
-            Policy.logError(e);
-            throw new SynchronizationException(e);
-        }
-    }
-
-    private String getSubprocessName(String name,
-            Collection<SerializedVariable> properties) {
-        for(SerializedVariable property : properties)
-            if(property.name.equals("HasSubprocessName"))
-                try {
-                    String value = (String)property.value.getValue(Bindings.STRING);
-                    if (!value.isEmpty())
-                        return value;
-                } catch (AdaptException e) {
-                    // This is very improbable exception.
-                    // Just ignore it and return the name.
-                    e.printStackTrace();
-                    break;
-                }
-        return name;
-    }
-
-    @Override
-    public void endComponent() {
-        try {
-            if(TRACE_EVENTS)
-                System.out.println("endComponent(" + (component != null ? component.solverComponentName : "null") + ")");
-            if(component == null) return;
-            for(T child : component.getChildren())
-                if(potentiallyUpdatedComponents.remove(child))
-                    resolver.unmarkPending(child);
-            T parent = component.getParent();
-            if (parent == null && mapping.getConfiguration() != component)
-                throw new SynchronizationException("BUG: beginComponent/endComponent calls do not match.");
-            component = parent;
-        } catch(Throwable e) {
-            Policy.logError(e);
-            throw new SynchronizationException(e);
-        }
-    }
-
-    @Override
-    public void beginType(String id, Collection<SerializedVariable> properties) {
-        try {
-            /*if(TRACE_EVENTS)
-                System.out.println("beginType("+id+")");*/
-            ModuleUpdaterBase<T> updater;
-            try {
-                updater = moduleUpdaterFactory.createUpdater(id);
-            } catch (DatabaseException e) {
-                throw new RuntimeException(e);
-            }
-            if(updater == null)
-                throw new SynchronizationException("Failed to create module updater for id " + id + ".");
-            moduleUpdaters.put(id, updater);
-        } catch(Throwable e) {
-            Policy.logError(e);
-            throw new SynchronizationException(e);
-        }
-    }
-
-    @Override
-    public void endType() {
-        /*if(TRACE_EVENTS)
-            System.out.println("endType()");*/
-    }
-
-    public boolean getDidChanges() {
-        return didChanges;
-    }
-
-    public void setDidChanges() {
-        didChanges = true;
-    }
-
-    public void reportProblem(String description) {
-        getLogger().error(description);
-    }
-    
-    public void reportProblem(String description, Exception e) {
-        getLogger().error(description, e);
-    }
-    
-    public void addPostSynchronizationAction(Runnable action) {
-        postSynchronizationActions.add(action);
-    }
-    
-    protected void postCompositeAction(boolean justCreated, Collection<SerializedVariable> properties, 
-            Collection<Connection> connections, ModuleUpdaterBase<T> updater) throws Exception { 
-    }
-
-    
-    public long getFromRevision() {
-        return mapping.currentRevision;
-    }
-    
-    public abstract Logger getLogger();
-}