View Javadoc

1   package cz.cuni.amis.pogamut.base.agent.module;
2   
3   import java.util.logging.Level;
4   import java.util.logging.Logger;
5   
6   import cz.cuni.amis.pogamut.base.agent.IAgent;
7   import cz.cuni.amis.pogamut.base.component.IComponent;
8   import cz.cuni.amis.pogamut.base.component.bus.IComponentBus;
9   import cz.cuni.amis.pogamut.base.component.controller.ComponentControlHelper;
10  import cz.cuni.amis.pogamut.base.component.controller.ComponentController;
11  import cz.cuni.amis.pogamut.base.component.controller.ComponentDependencies;
12  import cz.cuni.amis.pogamut.base.component.controller.ComponentDependencyType;
13  import cz.cuni.amis.pogamut.base.component.controller.ComponentState;
14  import cz.cuni.amis.pogamut.base.component.controller.IComponentControlHelper;
15  import cz.cuni.amis.utils.NullCheck;
16  import cz.cuni.amis.utils.exception.PogamutException;
17  import cz.cuni.amis.utils.flag.ImmutableFlag;
18  import cz.cuni.amis.utils.token.Token;
19  import cz.cuni.amis.utils.token.Tokens;
20  
21  /**
22   * Ancestor of all agent modules that contains {@link ComponentController} and defines protected methods for the control of
23   * the module's lifecycle ({@link AgentModule#start()}, {@link AgentModule#stop()}, {@link AgentModule#pause()}, {@link AgentModule#resume()},
24   * {@link AgentModule#kill()} and {@link AgentModule#reset()}). Override them when needed.
25   * 
26   * @author Jimmy
27   *
28   * @param <AGENT>
29   */
30  public abstract class AgentModule<AGENT extends IAgent> implements IComponent {
31  	
32  	private static int moduleNumber = 0;
33  	private static Object moduleNumberMutex = new Object();
34  	
35  	protected final AGENT agent;
36  	protected Logger log;
37  	protected final ComponentController controller;
38  	protected final IComponentBus eventBus;
39  	
40  	private final Token componentId;
41  	
42  	/**
43  	 * Initialize agent module - it will start {@link ComponentDependencyType}.STARTS_WITH the agent.
44  	 * @param agent
45  	 */
46  	public AgentModule(AGENT agent) {
47  		this(agent, null);
48  	}
49  	
50  	/**
51  	 * Initialize agent module - it will start {@link ComponentDependencyType}.STARTS_WITH the agent.
52  	 * @param agent
53  	 * @param log should be used, if <i>null</i> is provided, it is created automatically
54  	 */
55  	public AgentModule(AGENT agent, Logger log) {
56  		this(agent, log, null);
57  	}
58  	
59  	/**
60  	 * Initialize agent module with custom dependencies.
61  	 * @param agent
62  	 * @param log which should be used, if <i>null</i> is provided, it is created automatically
63  	 * @param dependencies
64  	 */
65  	public AgentModule(AGENT agent, Logger log, ComponentDependencies dependencies) {
66  		this.agent = agent;
67  		NullCheck.check(agent, "agent");
68  		this.componentId = initComponentId();
69  		NullCheck.check(this.componentId, "componentId initialization");
70  		if (log == null) {
71  			this.log = agent.getLogger().getCategory(this);
72  		} else {
73  			this.log = log;
74  		}
75  		this.eventBus = agent.getEventBus();				
76  		if (dependencies == null) {
77  			dependencies = new ComponentDependencies(ComponentDependencyType.STARTS_WITH).add(agent);
78  		}
79  		this.controller = new ComponentController(this, control, this.eventBus, this.log, dependencies);
80  		this.eventBus.register(this);
81  	}
82  	
83  	/**
84  	 * Returns a logger used by the AgentModule. AgentModule always has a logger, even if you do 
85  	 * not supply it with one (it will allocate one on its own).
86  	 * @return
87  	 */
88  	public Logger getLog() {
89  		return log;
90  	}
91  	
92  	/**
93  	 * Returns token made from simple name of the module's class.
94  	 * <p><p>
95  	 * Called during the construction of the module, called only once (and even before your constructors take effect)!
96  	 * 
97  	 * @return component id
98  	 */
99  	protected Token initComponentId() {
100 		synchronized(moduleNumberMutex) {
101 			return Tokens.get(this.getClass().getSimpleName() + (moduleNumber++));
102 		}
103 	}
104 	
105 	@Override
106 	public Token getComponentId() {
107 		return componentId;
108 	}
109 	
110 	/**
111 	 * Whether the component is running.
112 	 * @return
113 	 * @see ComponentController#isRunning()
114 	 */
115 	public boolean isRunning() {
116 		return controller.isRunning();
117 	}
118 
119 	/**
120 	 * Returns state of the component.
121 	 * @return
122 	 */
123 	public ImmutableFlag<ComponentState> getState() {
124 		return controller.getState();
125 	}
126 	
127 	@Override
128 	public String toString() {
129 		if (this == null) return "AgentModule-instantiating";
130 		return getClass().getSimpleName();
131 	}
132 
133 	private IComponentControlHelper control = new ComponentControlHelper() {
134 		
135 		public void startPaused() throws PogamutException {
136 			AgentModule.this.start(true);
137 		}
138 		
139 		@Override
140 		public void start() throws PogamutException {
141 			AgentModule.this.start(false);
142 		}
143 		
144 		@Override
145 		public void stop() throws PogamutException {
146 			AgentModule.this.stop();
147 		}
148 		
149 		@Override
150 		public void kill() {
151 			AgentModule.this.kill();
152 		}
153 		
154 		@Override
155 		public void reset() {
156 			AgentModule.this.reset();
157 		}		
158 		
159 		@Override
160 		public void pause() {
161 			AgentModule.this.pause();
162 		}
163 		
164 		@Override
165 		public void resume() {
166 			AgentModule.this.resume();
167 		}
168 		
169 	};
170 	
171 	/**
172 	 * Starts the agent module. (Called even if starting to paused state.)
173 	 */
174 	protected void start(boolean startToPaused) {
175 	}
176 	
177 	/**
178 	 * Stops the agent module.
179 	 * <p><p>
180 	 * Calls {@link AgentModule#cleanUp()}.
181 	 */
182 	protected void stop() {
183 		cleanUp();
184 	}
185 	
186 	/**
187 	 * Kills the agent module.
188 	 * <p><p>
189 	 * Calls {@link AgentModule#cleanUp()}.
190 	 */
191 	protected void kill() {
192 		cleanUp();
193 	}
194 	
195 	/**
196 	 * Pauses the agent module.
197 	 */
198 	protected void pause() {
199 	}
200 
201 	/**
202 	 * Resumes the agent module.
203 	 */
204 	protected void resume() {
205 	}
206 	
207 	/**
208 	 * Resets the agent module so it may be reused.
209 	 * <p><p>
210 	 * Calls {@link AgentModule#cleanUp()}.
211 	 */
212 	protected void reset() {
213 		cleanUp();
214 	}
215 	
216 	/**
217 	 * Hook where to perform clean up of data structures of the module.
218 	 * <p><p>
219 	 * Called from {@link AgentModule#stop()}, {@link AgentModule#kill()}, {@link AgentModule#reset()}.
220 	 */
221 	protected void cleanUp() {		
222 		if (log != null && log.isLoggable(Level.INFO)) log.info("Cleaning up!");
223 	}
224 
225 }