1 package cz.cuni.amis.pogamut.base.component.controller;
2
3 import cz.cuni.amis.pogamut.base.component.IComponent;
4 import cz.cuni.amis.pogamut.base.component.bus.event.IFatalErrorEvent;
5 import cz.cuni.amis.pogamut.base.component.bus.event.IPausedEvent;
6 import cz.cuni.amis.pogamut.base.component.bus.event.IPausingEvent;
7 import cz.cuni.amis.pogamut.base.component.bus.event.IStoppedEvent;
8 import cz.cuni.amis.pogamut.base.component.bus.event.IStoppingEvent;
9 import cz.cuni.amis.pogamut.base.component.exception.ComponentKilledException;
10 import cz.cuni.amis.utils.exception.PogamutInterruptedException;
11 import cz.cuni.amis.utils.flag.ImmutableFlag;
12 import cz.cuni.amis.utils.flag.WaitForFlagChange;
13
14 /**
15 * Base interface for component controllers, be it {@link IComponentController} or {@link ISharedComponentController}.
16 * <p><p>
17 * The component controller base interface is meant to provide a gateway for starting/stopping/pausing/resuming the component and
18 * querying the component current {@link ComponentState}.
19 * <p><p>
20 * Use {@link AbstractComponentControllerBase} abstraction for the implementation of custom controllers.
21 *
22 * @author Jimmy
23 */
24 public interface IComponentControllerBase<COMPONENT extends IComponent> extends IComponent {
25
26 /**
27 * Returns last fatal error event that has triggered the system failure.
28 */
29 public IFatalErrorEvent getFatalError();
30
31 /**
32 * Whether the component has been started, is not stopped or killed, may be paused.
33 * @return component is running
34 */
35 public boolean isRunning();
36
37 /**
38 * Whether the component is paused (or is pausing/resuming).
39 * @return
40 */
41 public boolean isPaused();
42
43 /**
44 * Returns state of the controlled component (state of the component life-cycle).
45 * <p><p>
46 * It returns flag - therefore you may use {@link WaitForFlagChange} to synchronize on the flag changes in other threads or use
47 * awaitState() method.
48 * @return immutable flag
49 */
50 public ImmutableFlag<ComponentState> getState();
51
52 /**
53 * Whether the component is in one of 'states'.
54 * @param states
55 * @return
56 */
57 public boolean inState(ComponentState... states);
58
59 /**
60 * Whether the component is not in any of 'states'.
61 * @param states
62 * @return
63 */
64 public boolean notInState(ComponentState... states);
65
66 /**
67 * Waits until the component reaches one of 'states' or KILLING / KILLED state is reached.
68 * <p><p>
69 * If KILLING / KILLED state is not among 'states' then reaching of this state will throw {@link ComponentKilledException} exception.
70 * <p><p>
71 * If interrupted, {@link PogamutInterruptedException} is thrown.
72 *
73 * @param state
74 * @return reached component state
75 * @throws ComponentKilledException
76 */
77 public ComponentState awaitState(ComponentState... states);
78
79 /**
80 * Waits until the component reaches one of 'states' or KILLING / KILLED state is reached.
81 * <p><p>
82 * If KILLING / KILLED state is not among 'states' then reaching of this state will throw {@link ComponentKilledException} exception.
83 * <p><p>
84 * If interrupted, {@link PogamutInterruptedException} is thrown.
85 * <p><p>
86 * If times out, null is returned.
87 *
88 * @param millis
89 * @param state
90 * @return reached component state
91 * @throws ComponentKilledException
92 */
93 public ComponentState awaitState(long timeoutMillis, ComponentState... states);
94
95 /**
96 * Provides the way to manually start the component.
97 */
98 public void manualStart(String reason);
99
100 /**
101 * Provides the way to manually start the component into paused state.
102 */
103 public void manualStartPaused(String reason);
104
105 /**
106 * Provides the way to stop the component (constructor of this controller).
107 * <p><p>
108 * Note that you should not use {@link IComponentControlHelper}.stop() alone to stop your component
109 * as it won't produce {@link IStoppingEvent} and {@link IStoppedEvent}.
110 * <p><p>
111 * If you require your component to stop prematurely - call this method.
112 *
113 * @param reason why the component is stopping
114 */
115 public void manualStop(String reason);
116
117 /**
118 * Provides the way to kill the component (constructor of this controller).
119 * <p><p>
120 * Note that you should not use {@link IComponentControlHelper}.kill() alone to stop your component
121 * as it won't produce {@link IFatalErrorEvent}.
122 * <p><p>
123 * If you require your component to stop prematurely - call this method.
124 *
125 * @param reason why the component is stopping
126 */
127 public void manualKill(String reason);
128
129 /**
130 * Provides the way to pause the component (constructor of this controller).
131 * <p><p>
132 * Note that you should not use {@link IComponentControlHelper}.pause() alone to stop your component
133 * as it won't produce {@link IPausingEvent} and {@link IPausedEvent}.
134 *
135 * @param reason why the component is pausing
136 */
137 public void manualPause(String reason);
138
139 /**
140 * Provides the way to pause the component (constructor of this controller).
141 * <p><p>
142 * Note that you should not use {@link IComponentControlHelper}.pause() alone to stop your component
143 * as it won't produce {@link IPausingEvent} and {@link IPausedEvent}.
144 *
145 * @param reason why the component is pausing
146 */
147 public void manualResume(String reason);
148
149 /**
150 * Broadcasts fatal error with controlled component as source.
151 * <p><p>
152 * Sets state to KILLING, broadcasts {@link IFatalErrorEvent} and then sets the state to KILLED.
153 * <p><p>
154 * <b>WARNING:</b> Note that the ComponentController assumes that you will kill your component
155 * yourself before or after you call this method. Therefore the components kill() method won't be called. That's because
156 * whenever fatal error occurs, the component is in undefined state and you have to decide what to do based
157 * on that fatal error.
158 *
159 * @param message
160 */
161 public void fatalError(String message);
162
163 /**
164 * Broadcasts fatal error with controlled component as source.
165 * <p><p>
166 * Sets state to KILLING, broadcasts {@link IFatalErrorEvent} and then sets the state to KILLED.
167 * <p><p>
168 * <b>WARNING:</b> Note that the ComponentController assumes that you will kill your component
169 * yourself before or after you call this method. Therefore the components kill() method won't be called. That's because
170 * whenever fatal error occurs, the component is in undefined state and you have to decide what to do based
171 * on that fatal error.
172 *
173 * @param message
174 * @param e
175 */
176 public void fatalError(String message, Throwable e);
177
178 /**
179 * Returns controlled component instance.
180 * @return controlled component
181 */
182 public COMPONENT getComponent();
183
184 /**
185 * Returns component control with lifecycle methods of the component controlled by this instance. I.e., methods that are
186 * directly controlling the component {@link IComponentController#getComponent()}.
187 * <p><p>
188 * IT IS DISCOURAGED TO USE METHODS OF THE {@link IComponentControlHelper} DIRECTLY! IT DEFIES THE PURPOSE OF THE CONTROLLER TOTALLY
189 * AND THE CONTROLLER WILL PROBABLY WON'T COPE WITH SUCH BEHAVIOR.
190 * <p><p>
191 * But what the hell, if it solves your problem, go ahead ;-)
192 *
193 * @return
194 */
195 public IComponentControlHelper getComponentControl();
196
197 /**
198 * Tells whether the controller sends events about the state of the component, i.e., whether it should automatically send
199 * starting/stopping events or not.
200 * <p><p>
201 * DEFAULT: TRUE (the controller is broadcasting events as default)
202 * <p><p>
203 * Exception: {@link IComponentControllerBase#fatalError(String)} and {@link IComponentControllerBase#fatalError(String, Throwable)}
204 * must always send fatal error!
205 *
206 * @return
207 */
208 public boolean isBroadcastingEvents();
209
210 /**
211 * Enables (== true) / Disables (== false) sending events about the state of the component, i.e., whether it should automatically send
212 * starting/stopping events or not.
213 * <p><p>
214 * Exception: {@link IComponentControllerBase#fatalError(String)} and {@link IComponentControllerBase#fatalError(String, Throwable)}
215 * must always send fatal error!
216 *
217 * @param broadcastEvents Enables (== true) / Disables (== false)
218 */
219 public void setBroadcastingEvents(boolean broadcastEvents);
220
221 }