package org.simantics.structural.synchronization.base; import java.util.Collection; import java.util.Collections; import java.util.Map; import org.simantics.databoard.binding.mutable.Variant; import org.simantics.structural.synchronization.protocol.Connection; import org.simantics.structural.synchronization.protocol.SerializedVariable; import org.simantics.structural.synchronization.utils.ComponentBase; import gnu.trove.map.hash.THashMap; abstract public class ModuleUpdaterBase> { public String moduleType; public THashMap> propertyUpdateRules = new THashMap>(); public THashMap> connectionUpdateRules = new THashMap>(); public boolean isUserComponent; public boolean isComposite; public String subprocessType; public ModuleUpdaterBase(String moduleType) { this.moduleType = moduleType; } public void addPropertyUpdateRule(PropertyUpdateRule rule) { propertyUpdateRules.put(rule.getPropertyName(), rule); } public void addConnectionUpdateRule(ConnectionUpdateRule rule) { connectionUpdateRules.put(rule.getConnectionPointName(), rule); } public void create(ModuleUpdateContext context, Collection properties, Collection connections) { context.command = createAddCommandBuilder(context.getModuleName()); applyRules(context, true, properties, connections); } abstract public CommandBuilder createAddCommandBuilder(String name); public void update(ModuleUpdateContext context, Collection properties, Collection connections) { // Check that the module type matches int moduleTypeId = context.getSolver().getModuleType(context.getModuleId()); String moduleTypeName = context.getSolver().getName(moduleTypeId); if(!moduleTypeName.equals(moduleType)) { context.getSolver().remove(context.getModuleId()); context.component.componentId = -1; context.setModuleId(-1); create(context, properties, connections); } // Update else { context.command = createUpdateCommandBuilder(context.getModuleName()); applyRules(context, false, properties, connections); } } abstract public CommandBuilder createUpdateCommandBuilder(String name); private void applyRules(ModuleUpdateContext context, boolean inCreate, Collection properties, Collection connections) { THashMap propertyMap = new THashMap(properties.size()); Map> connectionMap = connections.isEmpty() ? Collections.>emptyMap() : new THashMap>(connections.size()); for(SerializedVariable property : properties) propertyMap.put(property.name, property.value); for(Connection connection : connections) connectionMap.put(connection.relation, connection.connectionPoints); context.incPendingCount(); // To prevent premature execution of the command for(SerializedVariable property : properties) { PropertyUpdateRule rule = propertyUpdateRules.get(property.name); if(rule != null) rule.apply(context, inCreate, propertyMap, connectionMap, property.value); else if(property.name.equals("IsAttached")) ; else if(SynchronizationEventHandlerBase.TRACE_EVENTS) System.out.println(" skipped property " + property.name + " " + property.toString()); } if(inCreate) { for(Connection connection : connections) { ConnectionUpdateRule rule = connectionUpdateRules.get(connection.relation); if(rule != null) rule.apply(context, propertyMap, connection.connectionPoints); else if(SynchronizationEventHandlerBase.TRACE_EVENTS) System.out.println(" skipped connection " + connection.relation + " " + connection.connectionPoints); } } else { THashMap> unusedConnectionUpdateRules = new THashMap>(connectionUpdateRules); for(Connection connection : connections) { ConnectionUpdateRule rule = unusedConnectionUpdateRules.remove(connection.relation); if(rule != null) rule.apply(context, propertyMap, connection.connectionPoints); else if(SynchronizationEventHandlerBase.TRACE_EVENTS) System.out.println(" skipped connection " + connection.relation + " " + connection.connectionPoints); } for(ConnectionUpdateRule rule : unusedConnectionUpdateRules.values()) rule.apply(context, propertyMap, Collections.emptyList()); } context.decPendingCount(); } }