View Javadoc

1   /*
2    * $HeadURL: $
3    * $Date: $
4    * $Revision: $
5    * $Author: $
6    * 
7    * Copyright (c) 2005 MindTree Consulting Ltd. 
8    * 
9    * This file is part of Insight.
10   * 
11   * Insight is free software: you can redistribute it and/or modify it under the 
12   * terms of the GNU General Public License as published by the Free Software 
13   * Foundation, either version 3 of the License, or (at your option) any later 
14   * version.
15   * 
16   * Insight is distributed in the hope that it will be useful, but 
17   * WITHOUT ANY WARRANTY; without even the implied warranty of 
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General 
19   * Public License for more details.
20   * 
21   * You should have received a copy of the GNU General Public License along with 
22   * Insight.  If not, see <http://www.gnu.org/licenses/>.
23   */
24  package com.mindtree.techworks.insight;
25  
26  import java.util.ArrayList;
27  import java.util.HashMap;
28  import java.util.Iterator;
29  import java.util.List;
30  import java.util.Map;
31  
32  import com.mindtree.techworks.insight.gui.Insight;
33  import com.mindtree.techworks.insight.gui.Presentation;
34  import com.mindtree.techworks.insight.gui.action.IAction;
35  import com.mindtree.techworks.insight.gui.widgets.StatusBar;
36  import com.mindtree.techworks.insight.model.ILogEventModelMutator;
37  import com.mindtree.techworks.insight.model.IMutatorListener;
38  import com.mindtree.techworks.insight.model.LogEventModel;
39  import com.mindtree.techworks.insight.pagination.IPage;
40  import com.mindtree.techworks.insight.spi.LogEvent;
41  
42  /**
43  *
44  * The <code>Controller</code> class is the Mediator between the various Presentation
45  * instances in the GUI. It also acts as the bridge between the GUI components
46  * and the control and model components such as the Appender implementation(s).
47  * All Presentation instances must register with this Controller using
48  * <p>
49  * #regsiterPresentation(Presentation presentation)
50  * <p>
51  * @author  Regunath B
52  * @version 1.0, 04/10/25
53  * @see com.mindtree.techworks.insight.gui.Presentation
54  */
55  
56  public class Controller implements IMutatorListener {
57  	
58  	/**
59  	 * The Insight instance that created this Controller
60  	 */
61  	private Insight insight;
62  
63  	/**
64  	 * Map hashed by UIDs of Presentation instances containing 
65  	 * lists of presentations that have been registered.
66  	 */
67  	private Map presentationMap = new HashMap();
68  
69  	/**
70  	 * List of Presentation instances controlled by this Controller
71  	 */
72  	private List presentationList = new ArrayList();
73  	
74  	/**
75  	 * List of active IAction instances 
76  	 */
77  	private List actionsList = new ArrayList();
78  
79  	/**
80  	 * Root Model
81  	 */	
82  	private LogEventModel rootLogEventModel;
83  
84  	/**
85  	 * Current/Active Model
86  	 */	
87  	private LogEventModel currentLogEventModel;
88  	
89  	/**
90  	 * Type of the mutator, if any.
91  	 */
92  	private int mutatorType;
93  	
94  	/**
95  	 * The status for the scroll lock, if any
96  	 */
97  	private boolean scrollLock = false;
98  	
99  	/**
100 	 * Constructor for this class
101 	 * @param insight the Insight instance that created this Controller
102 	 */
103 	public Controller(Insight insight) {
104 		this.insight = insight;
105 	}
106 
107 	/**
108 	 * Regsiters the specified Presentation with this Controller
109 	 * @param presentation the Presentation instance to be registered with this Controller
110 	 */
111 	public void registerPresentation(Presentation presentation) {
112 		presentationList.add(presentation);
113 	}
114 
115 	/**
116 	 * Regsiters the specified IAction with this Controller
117 	 * @param action the IAction instance to be registered with this Controller
118 	 */
119 	public void registerAction(IAction action) {
120 		actionsList.add(action);
121 		action.setEnabled(evaluateActionEnable(IAction.STARTUP, action));
122 	}
123 	
124 	/**
125 	 * Gets the Presentation identified by the specified cllass name
126 	 * @param className the Class name of the Presentation required
127 	 * @return the registered Presentation identified by the specified class name
128 	 * @throws RuntimeException in case the Presentation is not found or has not been registered yet
129 	 */
130 	public Presentation getPresentation(String className) {
131 		Iterator iterator = presentationList.iterator();
132 		while(iterator.hasNext()) {
133 			Presentation presentation = (Presentation)iterator.next();
134 			if (presentation.getClass().getName().equals(className)) {
135 				return presentation;
136 			}
137 		}
138 		throw new RuntimeException("No registered Presentation with name : " + className);
139 	}
140 
141 	/**
142 	 * Registers the specified listener Presentation for call back when widgets
143 	 * on the source Presentation change.
144 	 * @param sourcePresentation the source Presentation where the widget change would occur 
145 	 * @param listener the listener Presentation that is interested in widget changes on the source
146 	 */
147 	public void registerWidgetChangeListener(Presentation sourcePresentation, Presentation listener) {
148 		List listenerList = (List)presentationMap.get(sourcePresentation.getUID());
149 		if (listenerList == null) {
150 			listenerList = new ArrayList();
151 			presentationMap.put(sourcePresentation.getUID(),listenerList);
152 		}
153 		listenerList.add(listener);
154 	}
155 	
156 	/**
157 	 * Called by registered Presentation instances when widgets in them undergo a change
158 	 * @param sourcePresentation the Presentation where the change occurred
159 	 * @param widgetId unique id that identifies the widget in the Presentation
160 	 * @param data optional data returned by the Presentation in the context of the widget change
161 	 */
162 	public void fireWidgetChanged(Presentation sourcePresentation, int widgetId, Object data) {
163 		List listenerList = (List)presentationMap.get(sourcePresentation.getUID());
164 		Iterator iterator = listenerList.iterator();
165 		while(iterator.hasNext()) {
166 			((Presentation)iterator.next()).notifyWidgetStateChange(sourcePresentation, widgetId, data);
167 		}
168 	}
169 
170 	/**
171 	 * Notifies this Controller that an event was processed by the Appender.
172 	 * This Controller passes this event to registered Presentation instances that
173 	 * can handle run-time updates of event data.
174 	 * @param event data describing the event that was processed by the Appender
175 	 */
176 	public void notifyLogEventOccurred(LogEvent event) {
177 		Iterator iterator = presentationList.iterator();
178 		while(iterator.hasNext()) {
179 			Presentation p = (Presentation)iterator.next();
180 			if (p.doesProcessRealTimeUpdates()) {
181 				p.processRealTimeUpdate(event);
182 			}
183 		}
184 		setStatus();
185 	}
186 	
187 	/**
188 	 * Notifies this Controller to reset the displays of all registered
189 	 * Presentation implementations.
190 	 */
191 	public void resetPresentations() {
192 		Iterator iterator = presentationList.iterator();
193 		while(iterator.hasNext()) {
194 			Presentation p = (Presentation)iterator.next();
195 			p.resetWidgets();
196 		}		
197 	}
198 	/**
199 	 * @return Returns the insight.
200 	 */
201 	public Insight getInsight() {
202 		return insight;
203 	}
204 	
205 	/**
206 	 * @return Returns the currentLogEventModel.
207 	 */
208 	public LogEventModel getCurrentLogEventModel() {
209 		return this.currentLogEventModel;
210 	}
211 	
212 	/**
213 	 * Sets the specified LogEventModel as the current model
214 	 * @param logEventModel The currentLogEventModel to set.
215 	 * @param pageNumber the page number to be loaded as the current page
216 	 * @param selectedEventIndex the index of the selected LogEvent
217 	 */
218 	public void setCurrentLogEventModel(LogEventModel logEventModel, long pageNumber, long selectedEventIndex) {
219 		if(!logEventModel.equals(rootLogEventModel)){
220 			logEventModel.setPreviousLogEventModel(this.currentLogEventModel);	
221 		}
222 		logEventModel.clearSearchResults();
223 		this.currentLogEventModel = logEventModel;
224 		setSelectedEvent(pageNumber, selectedEventIndex);
225 	}
226 	
227 	/**
228 	 * Sets the selection to the indicated log event
229 	 * @param pageNumber the page number to be loaded as the current page
230 	 * @param selectedEventIndex the index of the selected LogEvent
231 	 */
232 	public void setSelectedEvent(long pageNumber, long selectedEventIndex) {
233 		this.currentLogEventModel.getPageSet().loadPageByNumber(pageNumber);
234 		firePageChanged(selectedEventIndex);			
235 	}
236 
237 
238 	/**
239 	 * Sets the specified LogEventModel as the current model
240 	 * @param logEventModel The currentLogEventModel to set.
241 	 */
242 	public void setCurrentLogEventModel(LogEventModel logEventModel) {
243 		// Load the first page and set the selection index to -1 after setting the specified
244 		// model as the current model
245 		setCurrentLogEventModel(logEventModel, 1, -1);
246 	}
247 	
248 	/**
249 	 * Clears the current event model. Replaces the current model with its
250 	 * predecessor model. Also resets the presentations.
251 	 */
252 	public void clearCurrentModel(){
253 		resetPresentations();
254 		getCurrentLogEventModel().clear();
255 		if(getCurrentLogEventModel().getPreviousLogEventModel() != null){			
256 			this.currentLogEventModel = getCurrentLogEventModel().getPreviousLogEventModel();
257 			this.currentLogEventModel.clearSearchResults();
258 			// Load the first page of the model
259 			this.currentLogEventModel.getPageSet().loadPageByNumber(1);
260 			firePageChanged();			
261 		} else {
262 			// take the buttons to the start state
263 			actionPerformed(IAction.STARTUP);
264 		}
265 	 }
266 
267 	/**
268 	 * @return Returns the rootLogEventModel.
269 	 */
270 	public LogEventModel getRootLogEventModel() {
271 		return rootLogEventModel;
272 	}
273 	
274 	/**
275 	 * @param rootLogEventModel The rootLogEventModel to set.
276 	 */
277 	public void setRootLogEventModel(LogEventModel rootLogEventModel) {
278 		this.rootLogEventModel = rootLogEventModel;
279 		// set the current model to the specified root model as well
280 		this.currentLogEventModel = rootLogEventModel;
281 		this.currentLogEventModel.clearSearchResults();
282 	}
283 
284 	/**
285 	 * Informs this Controller that the current page has changed.
286 	 * All presentations are notified to reflect the page change
287 	 */
288 	public void firePageChanged() {
289 		IPage page = this.currentLogEventModel.getPageSet().getCurrentPage();
290 		Iterator iterator = presentationList.iterator();
291 		while(iterator.hasNext()) {
292 			Presentation p = (Presentation)iterator.next();
293 			p.displayPage(page, -1);
294 		}
295 		setStatus();
296 	}	
297 	
298 	/**
299 	 * Informs this Controller that the current page has changed.
300 	 * All presentations sre notified to reflect the page change and
301 	 * LogEvent at the specified selectedEventIndex is highlighted 
302 	 * @param selectedEventIndex the index of the selected LogEvent
303 	 */
304 	public void firePageChanged(long selectedEventIndex) {
305 		IPage page = this.currentLogEventModel.getPageSet().getCurrentPage();
306 		Iterator iterator = presentationList.iterator();
307 		while(iterator.hasNext()) {
308 			Presentation p = (Presentation)iterator.next();
309 			p.displayPage(page, selectedEventIndex);
310 		}
311 		setStatus();		
312 	}
313 
314 	/**
315 	 * Sets the status display for Insight
316 	 */
317 	public void setStatus(){
318   	    StatusBar.getInstance().setStatisticsDisplayText(this.currentLogEventModel.getStatus());
319 	}
320 	
321 	/**
322 	 * Call back method using which the controller will be notifed by 
323 	 * any LogEventModelMutators starts mutating the LogEventModel 
324 	 * @see IMutatorListener#startMutating()
325 	 */
326 	public void startMutating (int mutatorType) {
327 		this.mutatorType = mutatorType;
328 		actionPerformed(IAction.MUTATION);
329 	}
330 
331 	/**
332 	 * Call back method using which the controller will be notifed by 
333 	 * any LogEventModelMutators ends mutating the LogEventModel
334 	 * @see IMutatorListener#endMutating(int)
335 	 */
336 	public void endMutating (int infoFlag) {
337 		// enable buttons only if atleast one log event has been interpreted
338 		if (infoFlag == ILogEventModelMutator.SUCCESS) {
339 			actionPerformed(IAction.NO_CONSTRAINTS);
340 		} else {
341 			// if a previous model exists, activate it and enable all buttons
342 			if (this.currentLogEventModel.getPreviousLogEventModel() != null) {
343 				setCurrentLogEventModel(this.currentLogEventModel.getPreviousLogEventModel());
344 				actionPerformed(IAction.NO_CONSTRAINTS);
345 			} else {
346 				if (this.currentLogEventModel.getPageSet().getLastPage().getLogEventList().size() > 0) { 
347 					// some data exists from a previous success load/mutation
348 					actionPerformed(IAction.NO_CONSTRAINTS);					
349 				} else {
350 					// the application is in startup state
351 					actionPerformed(IAction.STARTUP);
352 				}
353 			}
354 		}
355 	}
356 	
357 	/**
358 	 * Informs this Controller that an action of the specified type has been
359 	 * performed. This Controller controls enabling and disabling of affected
360 	 * action widgets based on the specified action type
361 	 * @param actionType the valid action type as defined in IAction
362 	 * @see IAction
363 	 */
364 	public void actionPerformed(int actionType) {
365 		Iterator iterator = actionsList.iterator();
366 		while(iterator.hasNext()) {
367 			IAction action = (IAction)iterator.next();
368 			action.setEnabled(evaluateActionEnable(actionType, action));
369 		}
370 	}
371 	
372 	/**
373 	 * Helper method that evaluates if the enable/disable effect on the 
374 	 * specified IAction by the occurrence of an action of the specified action
375 	 * type
376 	 * @param actionType type of the action that occurred
377 	 * @param action the IAction to be evaluated for enabling
378 	 * @return true if the specified IAction can be enabled, false otherwise
379 	 */
380 	private boolean evaluateActionEnable(int actionType, IAction action) {
381 		boolean enable = false;
382 		int mutualExclusionType = IAction.NONE;
383 		for (int i = 0; i < IAction.MUTUAL_EXCLUSION_TYPES.length; i++) {
384 			if (IAction.MUTUAL_EXCLUSION_TYPES[i][0] == action.getType()) {
385 				mutualExclusionType = IAction.MUTUAL_EXCLUSION_TYPES[i][1];
386 				break;
387 			}
388 		}				
389 		if (((action.getType() & actionType) == actionType)  &&
390 			((action.getType() & actionType) != mutualExclusionType)){		
391 			enable = true;
392 		}
393 		return enable;
394 	}
395 	
396 	/**
397 	 * Returns the type of the active mutator, if any
398 	 * @return Returns the mutatorType.
399 	 */
400 	public int getMutatorType() {
401 		return mutatorType;
402 	}
403 	
404 	/**
405 	 * Sets the status of the scroll lock. 
406 	 * @param lock boolean true for scroll lock, false otherwise
407 	 */
408 	public void setScrollLock(boolean lock) {
409 		this.scrollLock = lock;
410 		this.currentLogEventModel.getPageSet().setMutatorType(this.scrollLock ?
411 				ILogEventModelMutator.NON_TAILING_MUTATOR : ILogEventModelMutator.TAILING_MUTATOR);
412 		Iterator iterator = presentationList.iterator();
413 		while(iterator.hasNext()) {
414 			Presentation p = (Presentation)iterator.next();
415 			p.setScrollLock(this.scrollLock);
416 		}
417 	}
418 	
419 	/**
420 	 * Returns the status of the scroll lock
421 	 * @return Returns the scrollLock.
422 	 */
423 	public boolean isScrollLock() {
424 		return scrollLock;
425 	}
426 }