The final restructured version for automatic build using maven tycho
[Mograsim.git] / plugins / net.mograsim.logic.model / src / net / mograsim / logic / model / model / LogicModel.java
1 package net.mograsim.logic.model.model;
2
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.HashMap;
6 import java.util.List;
7 import java.util.Map;
8 import java.util.Objects;
9 import java.util.function.Consumer;
10
11 import net.mograsim.logic.model.model.components.ModelComponent;
12 import net.mograsim.logic.model.model.components.submodels.SubmodelComponent;
13 import net.mograsim.logic.model.model.wires.ModelWire;
14
15 public class LogicModel
16 {
17         private final Map<String, ModelComponent> components;
18         private final Map<String, Runnable> componentDestroyFunctions;
19         private final Map<String, ModelComponent> componentsUnmodifiable;
20         private final Map<String, ModelWire> wires;
21         private final Map<String, Runnable> wireDestroyFunctions;
22         private final Map<String, ModelWire> wiresUnmodifiable;
23
24         private final List<Consumer<? super ModelComponent>> componentAddedListeners;
25         private final List<Consumer<? super ModelComponent>> componentRemovedListeners;
26         private final List<Consumer<? super ModelWire>> wireAddedListeners;
27         private final List<Consumer<? super ModelWire>> wireRemovedListeners;
28         private final List<Consumer<? super Runnable>> redrawHandlerChangedListeners;
29
30         private Runnable redrawHandler;
31
32         protected LogicModel()
33         {
34                 components = new HashMap<>();
35                 componentDestroyFunctions = new HashMap<>();
36                 componentsUnmodifiable = Collections.unmodifiableMap(components);
37                 wires = new HashMap<>();
38                 wireDestroyFunctions = new HashMap<>();
39                 wiresUnmodifiable = Collections.unmodifiableMap(wires);
40
41                 componentAddedListeners = new ArrayList<>();
42                 componentRemovedListeners = new ArrayList<>();
43                 wireAddedListeners = new ArrayList<>();
44                 wireRemovedListeners = new ArrayList<>();
45                 redrawHandlerChangedListeners = new ArrayList<>();
46         }
47
48         /**
49          * Adds the given component to the list of components and calls all componentAddedListeners. Don't call this method from application
50          * code as it is automatically called in {@link ModelComponent}'s constructor.
51          * 
52          * @author Daniel Kirschten
53          */
54         protected void componentCreated(ModelComponent component, Runnable destroyed)
55         {
56                 if (components.containsKey(component.getName()))
57                         throw new IllegalStateException("Don't add the same component twice!");
58                 components.put(component.getName(), component);
59                 componentDestroyFunctions.put(component.getName(), destroyed);
60                 callComponentAddedListeners(component);
61                 requestRedraw();
62         }
63
64         /**
65          * Destroyes the given component, removes it from the list of components and calls all componentRemovedListeners.
66          * 
67          * @author Daniel Kirschten
68          */
69         protected void destroyComponent(ModelComponent component)
70         {
71                 componentDestroyFunctions.get(component.getName()).run();
72                 if (!components.containsKey(component.getName()))
73                         throw new IllegalStateException("Don't remove the same component twice!");
74                 components.remove(component.getName());
75                 callComponentRemovedListeners(component);
76                 requestRedraw();
77         }
78
79         /**
80          * Adds the given wire to the list of wires and calls all wireAddedListeners. Don't call this method from application code as it is
81          * automatically called in {@link ModelWire}'s constructor.
82          * 
83          * @author Daniel Kirschten
84          */
85         protected void wireCreated(ModelWire wire, Runnable destroyed)
86         {
87                 if (wires.containsKey(wire.name))
88                         throw new IllegalStateException("Don't add the same wire twice!");
89                 wires.put(wire.name, wire);
90                 wireDestroyFunctions.put(wire.name, destroyed);
91                 callWireAddedListeners(wire);
92                 requestRedraw();
93         }
94
95         /**
96          * Destroys the given wire, removes it from the list of wires and calls all wireRemovedListeners.
97          * 
98          * @author Daniel Kirschten
99          */
100         protected void destroyWire(ModelWire wire)
101         {
102                 wireDestroyFunctions.get(wire.name).run();
103                 if (!wires.containsKey(wire.name))
104                         throw new IllegalStateException("Don't remove the same wire twice!");
105                 wires.remove(wire.name);
106                 callWireRemovedListeners(wire);
107                 requestRedraw();
108         }
109
110         public Map<String, ModelComponent> getComponentsByName()
111         {
112                 return componentsUnmodifiable;
113         }
114
115         public Map<String, ModelWire> getWiresByName()
116         {
117                 return wiresUnmodifiable;
118         }
119
120         public ModelComponent getComponentByName(String name)
121         {
122                 return components.get(name);
123         }
124
125         @SuppressWarnings("unchecked")
126         public <T extends ModelComponent> T getComponentByName(String name, Class<T> expectedComponentClass)
127         {
128                 ModelComponent comp = components.get(name);
129                 Objects.requireNonNull(comp, "Invaild path, component " + name + " not found");
130                 if (expectedComponentClass.isInstance(comp))
131                         return (T) comp;
132                 throw new IllegalArgumentException("The component " + name + " is not an instance of " + expectedComponentClass);
133         }
134
135         public ModelWire getWireByName(String name)
136         {
137                 return wires.get(name);
138         }
139
140         public <T extends ModelComponent> T getComponentBySubmodelPath(String path, Class<T> modelClass)
141         {
142                 int firstDot = path.indexOf('.');
143                 if (firstDot == -1)
144                         return getComponentByName(path, modelClass);
145                 String first = path.substring(0, firstDot);
146                 String rest = path.substring(firstDot + 1);
147                 return getComponentByName(first, SubmodelComponent.class).submodel.getComponentBySubmodelPath(rest, modelClass);
148         }
149
150         public ModelWire getWireBySubmodelPath(String path)
151         {
152                 int firstDot = path.indexOf('.');
153                 if (firstDot == -1)
154                         return getWireByName(path);
155                 String first = path.substring(0, firstDot);
156                 String rest = path.substring(firstDot + 1);
157                 return getComponentByName(first, SubmodelComponent.class).submodel.getWireBySubmodelPath(rest);
158         }
159
160         // @formatter:off
161         public void addComponentAddedListener         (Consumer<? super ModelComponent> listener) {componentAddedListeners      .add   (listener);}
162         public void addComponentRemovedListener       (Consumer<? super ModelComponent> listener) {componentRemovedListeners    .add   (listener);}
163         public void addWireAddedListener              (Consumer<? super ModelWire     > listener) {wireAddedListeners           .add   (listener);}
164         public void addWireRemovedListener            (Consumer<? super ModelWire     > listener) {wireRemovedListeners         .add   (listener);}
165         public void addRedrawHandlerChangedListener   (Consumer<? super Runnable      > listener) {redrawHandlerChangedListeners.add   (listener);}
166
167         public void removeComponentAddedListener      (Consumer<? super ModelComponent> listener) {componentAddedListeners      .remove(listener);}
168         public void removeComponentRemovedListener    (Consumer<? super ModelComponent> listener) {componentRemovedListeners    .remove(listener);}
169         public void removeWireAddedListener           (Consumer<? super ModelWire     > listener) {wireAddedListeners           .remove(listener);}
170         public void removeWireRemovedListener         (Consumer<? super ModelWire     > listener) {wireRemovedListeners         .remove(listener);}
171         public void removeRedrawHandlerChangedListener(Consumer<? super Runnable      > listener) {redrawHandlerChangedListeners.remove(listener);}
172
173         private void callComponentAddedListeners     (ModelComponent c) {componentAddedListeners      .forEach(l -> l.accept(c));}
174         private void callComponentRemovedListeners   (ModelComponent c) {componentRemovedListeners    .forEach(l -> l.accept(c));}
175         private void callWireAddedListeners          (ModelWire      w) {wireAddedListeners           .forEach(l -> l.accept(w));}
176         private void callWireRemovedListeners        (ModelWire      w) {wireRemovedListeners         .forEach(l -> l.accept(w));}
177         private void callRedrawHandlerChangedListener(Runnable       r) {redrawHandlerChangedListeners.forEach(l -> l.accept(r));}
178         // @formatter:on
179
180         public void setRedrawHandler(Runnable handler)
181         {
182                 this.redrawHandler = handler;
183                 callRedrawHandlerChangedListener(handler);
184         }
185
186         public Runnable getRedrawHandler()
187         {
188                 return redrawHandler;
189         }
190
191         public void requestRedraw()
192         {
193                 if (redrawHandler != null)
194                         redrawHandler.run();
195         }
196 }