Fixed another bug in DelegatingSubcomponentHighLevelStateHandler
[Mograsim.git] / plugins / net.mograsim.logic.model / src / net / mograsim / logic / model / snippets / highlevelstatehandlers / standard / subcomponent / DelegatingSubcomponentHighLevelStateHandler.java
1 package net.mograsim.logic.model.snippets.highlevelstatehandlers.standard.subcomponent;
2
3 import java.util.function.Consumer;
4
5 import net.mograsim.logic.model.model.components.ModelComponent;
6 import net.mograsim.logic.model.model.components.submodels.SubmodelComponent;
7 import net.mograsim.logic.model.serializing.IdentifyParams;
8 import net.mograsim.logic.model.snippets.SnippetDefinintion;
9 import net.mograsim.logic.model.snippets.highlevelstatehandlers.standard.StandardHighLevelStateHandlerSnippetSuppliers;
10
11 public class DelegatingSubcomponentHighLevelStateHandler implements SubcomponentHighLevelStateHandler
12 {
13         private final SubmodelComponent parentComponent;
14         private ModelComponent delegateTarget;
15         private String prefix;
16
17         public DelegatingSubcomponentHighLevelStateHandler(SubmodelComponent component)
18         {
19                 this(component, null);
20         }
21
22         public DelegatingSubcomponentHighLevelStateHandler(SubmodelComponent component,
23                         DelegatingSubcomponentHighLevelStateHandlerParams params)
24         {
25                 this.parentComponent = component;
26                 if (params != null)
27                 {
28                         // TODO document this
29                         if (params.delegateTarget == null)
30                                 setDelegateTarget(parentComponent);
31                         else
32                         {
33                                 ModelComponent delegateTarget = parentComponent.submodel.getComponentsByName().get(params.delegateTarget);
34                                 if (delegateTarget == null)
35                                         throw new NullPointerException("No subcomponent with name " + params.delegateTarget);
36                                 setDelegateTarget(delegateTarget);
37                         }
38                         setPrefix(params.prefix);
39                 }
40                 parentComponent.submodel.addComponentRemovedListener(c ->
41                 {
42                         if (delegateTarget == c)
43                                 delegateTarget = null;
44                 });
45         }
46
47         public void set(ModelComponent delegateTarget, String prefix)
48         {
49                 setDelegateTarget(delegateTarget);
50                 setPrefix(prefix);
51         }
52
53         public void setDelegateTarget(ModelComponent delegateTarget)
54         {
55                 if (delegateTarget == null || delegateTarget == parentComponent)
56                         this.delegateTarget = parentComponent;
57                 else if (parentComponent.submodel.getComponentsByName().get(delegateTarget.getName()) == delegateTarget)
58                         this.delegateTarget = delegateTarget;
59                 else
60                         throw new IllegalArgumentException(
61                                         "Can only set components belonging to the submodel of the parent component of this handler or the parent component itself as the delegate target");
62         }
63
64         public ModelComponent getDelegateTarget()
65         {
66                 return delegateTarget;
67         }
68
69         public void setPrefix(String prefix)
70         {
71                 this.prefix = prefix;
72         }
73
74         public String getPrefix()
75         {
76                 return prefix;
77         }
78
79         @Override
80         public Object getHighLevelState(String subStateID)
81         {
82                 checkTarget();
83                 return delegateTarget.getHighLevelState(getDelegateTargetHighLevelStateID(subStateID));
84         }
85
86         @Override
87         public void setHighLevelState(String subStateID, Object newState)
88         {
89                 checkTarget();
90                 delegateTarget.setHighLevelState(getDelegateTargetHighLevelStateID(subStateID), newState);
91         }
92
93         @Override
94         public void addListener(String subStateID, Consumer<Object> stateChanged)
95         {
96                 checkTarget();
97                 delegateTarget.addHighLevelStateListener(getDelegateTargetHighLevelStateID(subStateID), stateChanged);
98         }
99
100         @Override
101         public void removeListener(String subStateID, Consumer<Object> stateChanged)
102         {
103                 checkTarget();
104                 delegateTarget.removeHighLevelStateListener(getDelegateTargetHighLevelStateID(subStateID), stateChanged);
105         }
106
107         private void checkTarget()
108         {
109                 if (delegateTarget == null)
110                         throw new IllegalStateException("Delegating to a component that was destroyed");
111         }
112
113         private String getDelegateTargetHighLevelStateID(String subStateID)
114         {
115                 return prefix == null ? subStateID : prefix + '.' + subStateID;
116         }
117
118         @Override
119         public String getIDForSerializing(IdentifyParams idParams)
120         {
121                 return "delegating";
122         }
123
124         @Override
125         public DelegatingSubcomponentHighLevelStateHandlerParams getParamsForSerializing(IdentifyParams idParams)
126         {
127                 checkTarget();
128                 DelegatingSubcomponentHighLevelStateHandlerParams params = new DelegatingSubcomponentHighLevelStateHandlerParams();
129                 params.delegateTarget = delegateTarget == parentComponent ? null : delegateTarget.getName();
130                 params.prefix = prefix;
131                 return params;
132         }
133
134         public static class DelegatingSubcomponentHighLevelStateHandlerParams
135         {
136                 public String delegateTarget;
137                 public String prefix;
138         }
139
140         static
141         {
142                 StandardHighLevelStateHandlerSnippetSuppliers.subcomponentHandlerSupplier
143                                 .setSnippetSupplier(DelegatingSubcomponentHighLevelStateHandler.class.getCanonicalName(), SnippetDefinintion
144                                                 .create(DelegatingSubcomponentHighLevelStateHandlerParams.class, DelegatingSubcomponentHighLevelStateHandler::new));
145         }
146 }