1 package net.mograsim.logic.model.model;
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.HashMap;
8 import java.util.Objects;
9 import java.util.function.Consumer;
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;
15 public class LogicModel
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;
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;
30 private Runnable redrawHandler;
32 protected LogicModel()
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);
41 componentAddedListeners = new ArrayList<>();
42 componentRemovedListeners = new ArrayList<>();
43 wireAddedListeners = new ArrayList<>();
44 wireRemovedListeners = new ArrayList<>();
45 redrawHandlerChangedListeners = new ArrayList<>();
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.
52 * @author Daniel Kirschten
54 protected void componentCreated(ModelComponent component, Runnable destroyed)
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);
65 * Destroyes the given component, removes it from the list of components and calls all componentRemovedListeners.
67 * @author Daniel Kirschten
69 protected void destroyComponent(ModelComponent component)
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);
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.
83 * @author Daniel Kirschten
85 protected void wireCreated(ModelWire wire, Runnable destroyed)
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);
96 * Destroys the given wire, removes it from the list of wires and calls all wireRemovedListeners.
98 * @author Daniel Kirschten
100 protected void destroyWire(ModelWire wire)
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);
110 public Map<String, ModelComponent> getComponentsByName()
112 return componentsUnmodifiable;
115 public Map<String, ModelWire> getWiresByName()
117 return wiresUnmodifiable;
120 public ModelComponent getComponentByName(String name)
122 return components.get(name);
125 @SuppressWarnings("unchecked")
126 public <T extends ModelComponent> T getComponentByName(String name, Class<T> expectedComponentClass)
128 ModelComponent comp = components.get(name);
129 Objects.requireNonNull(comp, "Invaild path, component " + name + " not found");
130 if (expectedComponentClass.isInstance(comp))
132 throw new IllegalArgumentException("The component " + name + " is not an instance of " + expectedComponentClass);
135 public ModelWire getWireByName(String name)
137 return wires.get(name);
140 public <T extends ModelComponent> T getComponentBySubmodelPath(String path, Class<T> modelClass)
142 int firstDot = path.indexOf('.');
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);
150 public ModelWire getWireBySubmodelPath(String path)
152 int firstDot = path.indexOf('.');
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);
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);}
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);}
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));}
180 public void setRedrawHandler(Runnable handler)
182 this.redrawHandler = handler;
183 callRedrawHandlerChangedListener(handler);
186 public Runnable getRedrawHandler()
188 return redrawHandler;
191 public void requestRedraw()
193 if (redrawHandler != null)