View Javadoc

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 }