]> gerrit.simantics Code Review - simantics/platform.git/blob
a3edea09e7ddc8fc89ee7d0b2b03cd4a016cf8f4
[simantics/platform.git] /
1 package org.simantics.structural.synchronization.base;
2
3 import gnu.trove.map.hash.THashMap;
4
5 import java.util.Collection;
6 import java.util.Collections;
7 import java.util.Map;
8
9 import org.simantics.databoard.binding.mutable.Variant;
10 import org.simantics.structural.synchronization.protocol.Connection;
11 import org.simantics.structural.synchronization.protocol.SerializedVariable;
12
13 abstract public class ModuleUpdaterBase<T extends ComponentBase<T>> {
14
15     public String moduleType;
16     public THashMap<String, PropertyUpdateRule<T>> propertyUpdateRules =
17             new THashMap<String, PropertyUpdateRule<T>>();
18     public THashMap<String, ConnectionUpdateRule<T>> connectionUpdateRules =
19             new THashMap<String, ConnectionUpdateRule<T>>();
20     public boolean isUserComponent;
21     public boolean isComposite;
22     
23     public ModuleUpdaterBase(String moduleType) {
24         this.moduleType = moduleType;
25     }
26     
27     public void addPropertyUpdateRule(PropertyUpdateRule<T> rule) {
28         propertyUpdateRules.put(rule.getPropertyName(), rule);
29     }
30     
31     public void addConnectionUpdateRule(ConnectionUpdateRule<T> rule) {
32         connectionUpdateRules.put(rule.getConnectionPointName(), rule);
33     }
34
35     public void create(ModuleUpdateContext<T> context, Collection<SerializedVariable> properties, Collection<Connection> connections) {
36         context.command = createAddCommandBuilder(context.getModuleName()); 
37         applyRules(context, true, properties, connections);
38     }
39     
40     abstract public CommandBuilder createAddCommandBuilder(String name);
41
42     public void update(ModuleUpdateContext<T> context, Collection<SerializedVariable> properties, Collection<Connection> connections) {
43         // Check that the module type matches
44         int moduleTypeId = context.getSolver().getModuleType(context.getModuleId());
45         String moduleTypeName = context.getSolver().getName(moduleTypeId);
46         if(!moduleTypeName.equals(moduleType)) {
47             context.getSolver().remove(context.getModuleId());
48             context.component.componentId = -1;
49             context.setModuleId(-1);
50             create(context, properties, connections);
51         }
52         
53         // Update
54         else {
55             context.command = createUpdateCommandBuilder(context.getModuleName());
56             applyRules(context, false, properties, connections);
57         }
58     }
59     
60     abstract public CommandBuilder createUpdateCommandBuilder(String name);
61     
62     private void applyRules(ModuleUpdateContext<T> context, boolean inCreate,
63             Collection<SerializedVariable> properties, Collection<Connection> connections) {
64         THashMap<String, Variant> propertyMap = new THashMap<String, Variant>(properties.size());
65         Map<String, Collection<String>> connectionMap = connections.isEmpty()
66                 ? Collections.<String, Collection<String>>emptyMap()
67                 : new THashMap<String, Collection<String>>(connections.size());
68         for(SerializedVariable property : properties)
69             propertyMap.put(property.name, property.value);
70         for(Connection connection : connections)
71             connectionMap.put(connection.relation, connection.connectionPoints);
72
73         context.incPendingCount(); // To prevent premature execution of the command
74         for(SerializedVariable property : properties) {
75             PropertyUpdateRule<T> rule = propertyUpdateRules.get(property.name);
76             if(rule != null)
77                 rule.apply(context, inCreate, propertyMap, connectionMap, property.value);
78             else if(property.name.equals("IsAttached"))
79                 ;
80             else
81                 if(SynchronizationEventHandlerBase.TRACE_EVENTS)
82                     System.out.println("    skipped property " + property.name + " " + property.toString());
83         }
84         if(inCreate) {
85             for(Connection connection : connections) {
86                 ConnectionUpdateRule<T> rule = connectionUpdateRules.get(connection.relation);
87                 if(rule != null)
88                     rule.apply(context, propertyMap, connection.connectionPoints);
89                 else
90                         if(SynchronizationEventHandlerBase.TRACE_EVENTS)
91                             System.out.println("    skipped connection " + connection.relation + " " + connection.connectionPoints);
92             }
93         }
94         else {
95             THashMap<String, ConnectionUpdateRule<T>> unusedConnectionUpdateRules =
96                     new THashMap<String, ConnectionUpdateRule<T>>(connectionUpdateRules);
97             for(Connection connection : connections) {
98                 ConnectionUpdateRule<T> rule = unusedConnectionUpdateRules.remove(connection.relation);
99                 if(rule != null)
100                     rule.apply(context, propertyMap, connection.connectionPoints);
101                 else
102                     if(SynchronizationEventHandlerBase.TRACE_EVENTS)
103                         System.out.println("    skipped connection " + connection.relation + " " + connection.connectionPoints);
104             }
105             for(ConnectionUpdateRule<T> rule : unusedConnectionUpdateRules.values())
106                 rule.apply(context, propertyMap, Collections.<String>emptyList());
107         }
108         context.decPendingCount();
109     }
110
111 }