001 /** =====================================================================
002 *
003 * File Name : $Id: Main.java,v 1.10 2008/01/14 17:00:47 cb Exp $
004 *
005 * Description
006 * -----------
007 *
008 * See javadoc comment
009 *
010 * =====================================================================
011 *
012 * @Author : Craige Bevil
013 * Control Software Group
014 * Isaac Newton Group of Telescopes
015 *
016 * =====================================================================
017 *
018 * Modification Log
019 *
020 * Vers Date Author Reason
021 * ---- ---- ------ ------
022 * 1 C.Bevil First Release
023 *
024 * Commissioning Notes
025 * -------------------
026 *
027 * None
028 *
029 * =====================================================================
030 *
031 * @Version : $Id: Main.java,v 1.10 2008/01/14 17:00:47 cb Exp $
032 *
033 * @Author : $Author: cb $
034 *
035 * Header : $Header: /opt/INGsrc/src/CVS/softproj/FaultDatabase/src/FaultDatabase/FaultDatabase/src/GWTApplication/client/Main.java,v 1.10 2008/01/14 17:00:47 cb Exp $
036 *
037 * Log : $Log: Main.java,v $
038 * Log : Revision 1.10 2008/01/14 17:00:47 cb
039 * Log : Resize the root panel on window resize
040 * Log :
041 * Log : Revision 1.9 2007/12/12 15:24:50 cb
042 * Log : Added the quick help
043 * Log :
044 * Log : Revision 1.8 2007/10/22 11:40:11 cb
045 * Log : Used GWTEXT dialogs
046 * Log :
047 * Log : Revision 1.7 2007/10/08 09:32:50 cb
048 * Log : Modified to allow and review the user to change the faults which he is
049 * Log : subscribed to.
050 * Log :
051 * Log : Revision 1.6 2007/09/06 07:59:18 cb
052 * Log : Updated to support the concept of a single FaultUpdateMonitor
053 * Log : throughout the entire application so we do not hammer the database
054 * Log : when looking for updated faults.
055 * Log :
056 * Log : Revision 1.5 2007/08/17 14:26:42 cb
057 * Log : Updated for lastest prototype incorporating a lot of Nikos comments
058 * Log :
059 * Log : Revision 1.4 2007/08/01 13:00:05 cb
060 * Log : First prototype after import
061 * Log :
062 * Log : Revision 1.3 2007/07/25 16:10:34 cb
063 * Log : Added support for a URL parameter EditFault which will allow the user
064 * Log : to modify a fault straight away from an HTML page.
065 * Log :
066 * Log : Revision 1.2 2007/07/13 10:54:06 cb
067 * Log : Complete interface prototype
068 * Log :
069 * Log : Revision 1.1.1.1 2007/06/01 08:33:26 cb
070 * Log : Imported using TkCVS
071 * Log :
072 *
073 * =====================================================================*/
074
075
076 package GWTApplication.client;
077
078 import com.google.gwt.core.client.EntryPoint;
079 import com.google.gwt.core.client.GWT;
080 import com.google.gwt.user.client.*;
081 import com.google.gwt.user.client.rpc.*;
082 import com.google.gwt.user.client.ui.*;
083 import com.google.gwt.i18n.client.*;
084 import com.google.gwt.user.client.ui.FlexTable.*;
085 import com.google.gwt.user.client.ui.HTMLTable.*;
086
087 import org.gwtwidgets.client.util.*;
088
089 import com.gwtext.client.core.EventObject;
090 import com.gwtext.client.util.Format;
091 import com.gwtext.client.widgets.MessageBox;
092 import com.gwtext.client.widgets.MessageBoxConfig;
093
094 import java.util.*;
095
096 /**
097 * This is the main entry point for the fault database application
098 * client. The code generates the user interface which will be
099 * translated to AJAX/java script which will be subsequently deployed
100 * into the web browsers.
101 *
102 * @author cb
103 * @version $Id: Main.java,v 1.10 2008/01/14 17:00:47 cb Exp $
104 */
105
106 public class Main implements EntryPoint, FDBLoginListener, TabListener, WindowCloseListener, WindowResizeListener {
107
108 /**
109 * Used to check the database intermittingly and report back to
110 * listeners which faults they are displaying have changed so that
111 * they may update their view accordingly.
112 */
113
114 private FaultUpdateMonitor faultUpdateMonitor = null;
115
116 /**
117 * Indicator which will be used to show that we are busy
118 */
119
120 private BusyIndicator busyIndicator = new BusyIndicator();
121
122 /**
123 * This class will be used for internationalization so that we can
124 * flick between the locales of English and Spanish.
125 */
126
127 protected InternationalizationConstants internationalizationConstants = (InternationalizationConstants) GWT.create(InternationalizationConstants.class);
128
129 /**
130 * This is the service which will be used to access the servlet
131 * which is running in the tomcat container
132 */
133
134 protected FaultServiceAsync svc;
135
136 /**
137 * This is the main tab bar which will contain for each form in
138 * the Fault management system a tab which can be used to access
139 * that form
140 */
141
142 private TabPanel MainTabBar;
143
144 /**
145 * This is an instance of the quick view report object which will form one tab
146 */
147
148 private QuickViewReport quickViewPanel;
149
150 /**
151 * This is an instance of the managed system object which will
152 * allow the Privileged user to be able to administer the system.
153 */
154
155 private ManageSystem manageSystemPanel;
156
157 /**
158 * This is an instance of the new fault form object which will
159 * allow the user to enter a new fault into the system
160 */
161
162 private NewFaultForm createNewFaultPanel;
163
164 /**
165 * This is an instance of the search form object which will allow
166 * the user to perform a search across the data contained within
167 * the fault management system
168 */
169
170 private SearchForm searchPanel;
171
172 /**
173 * This is an instance of the Modify fault object which will allow
174 * the user to Update and append to an existing fault in the
175 * system.
176 */
177
178 private ModifyFormPanel modifyFormPanel;
179
180 /**
181 * This is the login panel which the user will be greeted with he
182 * first logs onto the system
183 */
184
185 private LoginPanel loginPanel;
186
187 /**
188 * Contains the details of the authentication which was performed
189 * by the user.
190 */
191
192 private AuthenticationDetails UserAuthentication;
193
194 /**
195 * This class is a listener class which is called when the user
196 * clicks upon the help link in the main panel and is used to
197 * display quick help associated with the application
198 * @author Craige Bevil
199 */
200
201 class QuickHelpListener implements ClickListener {
202
203 /**
204 * This is called when the user clicks on the hyperlink
205 * associated with the help link on the main page and results
206 * in the quick help dialog window being displayed.
207 * @param sender This is the widget that raised this event.
208 */
209
210 public void onClick (final Widget sender) {
211
212 QuickHelpDialog quickHelpDialog = new QuickHelpDialog("quickHelp_" + internationalizationConstants.locale() + ".html");
213
214 quickHelpDialog.showHelpDialog();
215 }
216 }
217
218 /**
219 * Called before a tab is selected. We prevent the user selecting
220 * the update tab when there are no faults being edited.
221 * @param sender The tab panel which sent the event
222 * @param tabIndex This is the index of the panel which was
223 * selected.
224 * @return boolean false if the user is to be blocked from
225 * selecting the tab selected.
226 */
227
228 public boolean onBeforeTabSelected(final SourcesTabEvents sender, final int tabIndex) {
229
230 // If the user is using the system as user guest then we do
231 // not mind if he selects tab 0 as the update fault tab does
232 // not exist.
233
234 if (UserAuthentication.UserId.equalsIgnoreCase(FaultDatabaseConstants.GUEST)) {
235 return true;
236 }
237
238 if (tabIndex == 0 && modifyFormPanel.getNumberOfFaultsBeingEdited() == 0) {
239 MessageBox.alert(internationalizationConstants.information(),internationalizationConstants.noFaultsBeingEdited());
240 return false;
241 }
242
243 return true;
244 }
245
246 /**
247 * Called when the user is about to close down the window, we need
248 * to make sure that he really does want to leave the page. This
249 * is to save the user unwillingly losing unsaved changes.
250 */
251
252 public String onWindowClosing() {
253 return internationalizationConstants.youMayLoseUnsavedChanges();
254 }
255
256 /**
257 * Called when the user closes down the window. We don't do
258 * anything here. This method does nothing and is simply to
259 * satisfy the interface requirements.
260 */
261
262 public void onWindowClosed() {
263 }
264
265 /**
266 * Called when the tab has been selected but we do nothing
267 * @param sender The tab panel which sent the event
268 * @param tabIndex This is the index of the panel which was
269 * selected.
270 */
271
272 public void onTabSelected (final SourcesTabEvents sender, final int tabIndex) {
273 }
274
275 /**
276 * This implements the expected interface of the login listener
277 * which will be called when the user logs onto the system for the
278 * first time. The main interface of the application will be built
279 * through this method.
280 *
281 * @param UserAuthentication Contains the details of the user that
282 * has logged onto the system and his levels of priviledge
283 */
284
285 public void userLoggedIn (final AuthenticationDetails UserAuthentication) {
286
287 Hyperlink changePasswordLink = null;
288
289 Hyperlink updateFaultSubscriptionLink = null;
290
291 Hyperlink quickHelpLink = null;
292
293 busyIndicator.showBusy(true);
294
295 this.UserAuthentication = UserAuthentication;
296
297 // Now add a listener in case the user tries to navigate away
298 // from the page without saving his changes
299
300 Window.addWindowCloseListener(this);
301
302 // Now we need to remove the panel which contains the login
303 // panel and replace it with the tab bar which the user will
304 // use to interact with the system. Which panels will be
305 // displayed depends on the level of priviledge that he has
306
307 RootPanel.get().remove(loginPanel);
308
309 // Now create the main interface that the user is going to use
310 // to interact with the system
311
312 MainTabBar = new TabPanel();
313
314 // We add a listener to make sure that the user does not
315 // select tabs when he should not (i.e. in the case of
316 // selecting the update tab when there are not faults to be
317 // edited.
318
319 MainTabBar.addTabListener(this);
320
321 // Now create the various tabs which will be used by the
322 // system
323
324 // If the user has ING user priviledge then he will able to
325 // modify faults in the system
326
327 for (int i=0; i < UserAuthentication.PriviledgeLevels.size();i++) {
328
329 // Only if the user has logged onto the system using his
330 // user name can he modify faults
331
332 if (((String)UserAuthentication.PriviledgeLevels.get(i)).equalsIgnoreCase(FaultDatabaseConstants.INGUSERPRIVILEDGE)) {
333
334 // Allow the user to change faults
335
336 modifyFormPanel = new ModifyFormPanel(MainTabBar,svc,UserAuthentication);
337
338 // Allow the user to change his password
339
340 changePasswordLink = new Hyperlink(internationalizationConstants.changePassword(),"ChangePassword");
341
342 ChangePasswordListener changePasswordListener = new ChangePasswordListener(UserAuthentication);
343
344 changePasswordLink.addClickListener(changePasswordListener);
345
346 // Allow the user to edit his list of subscribed faults
347
348 updateFaultSubscriptionLink = new Hyperlink(internationalizationConstants.updateFaultSubscription(),"UpdateSubscriptionList");
349
350 UpdateFaultSubscriptionListener updateFaultSubscriptionListener = new UpdateFaultSubscriptionListener(UserAuthentication);
351
352 updateFaultSubscriptionLink.addClickListener(updateFaultSubscriptionListener);
353
354 }
355 }
356
357 // Register a monitor on the faults which will be used for
358 // checking the database to see if it has been updated with
359 // new or modified faults.
360
361 faultUpdateMonitor = new FaultUpdateMonitor(svc);
362
363 // Schedule the updater to check for new faults every 10
364 // seconds as this query can be done really quickly by the
365 // server
366
367 faultUpdateMonitor.scheduleRepeating(7500);
368
369 // Create the quick view search panel
370
371 quickViewPanel = new QuickViewReport(MainTabBar,svc,modifyFormPanel,UserAuthentication,faultUpdateMonitor);
372
373 // If the user has admin priviledges then let him modify the
374 // administration data
375
376 for (int i=0; i < UserAuthentication.PriviledgeLevels.size();i++) {
377
378 if (((String)UserAuthentication.PriviledgeLevels.get(i)).equalsIgnoreCase(FaultDatabaseConstants.ADMINPRIVILEDGE)) {
379 manageSystemPanel = new ManageSystem(MainTabBar,svc,UserAuthentication);
380 }
381 }
382
383 // Now create the form in which the use will enter the details of the new fault
384
385 createNewFaultPanel = new NewFaultForm(MainTabBar,svc,UserAuthentication);
386
387 // Create the form in which the user will enter the details of the search
388
389 searchPanel = new SearchForm(MainTabBar,svc,UserAuthentication,modifyFormPanel,faultUpdateMonitor);
390
391 MainTabBar.selectTab(1);
392
393 // Now add the name of the user which has logged onto the
394 // system at the top of the window and if applicable, add a
395 // link which will allow the user to change his password
396
397 final FlexTable headerTable = new FlexTable();
398 final RowFormatter tableRowFormatter = (RowFormatter)headerTable.getRowFormatter();
399
400 if (UserAuthentication.Surname.equals(FaultDatabaseConstants.GUEST)) {
401 headerTable.setText(0,0,internationalizationConstants.user() + " : " + internationalizationConstants.guest() + " | ");
402 } else {
403 headerTable.setText(0,0,internationalizationConstants.user() + " : " + UserAuthentication.Name + " " + UserAuthentication.Surname + " | ");
404 }
405
406 // Now add the link which will allow the user to log out of the system
407
408 headerTable.setHTML(0,1,"<a href=\"Main.html\">" + internationalizationConstants.signOut() + "</a> | ");
409
410 // Now add a link which will allow the user to get quick help
411 // on the system
412
413 quickHelpLink = new Hyperlink(internationalizationConstants.help(),"Help");
414
415 QuickHelpListener quickHelpLinkListener = new QuickHelpListener();
416
417 quickHelpLink.addClickListener(quickHelpLinkListener);
418
419 headerTable.setWidget(0,3,quickHelpLink);
420 headerTable.setHTML(0,4,"|");
421
422 // If the user is logged in as anybody other than guest then
423 // we allow him to change his password
424
425 if (changePasswordLink != null) {
426 headerTable.setWidget(0,5,changePasswordLink);
427 }
428
429 // If the user has logged in as himself then we give him the
430 // chance to update to update the list of faults which he is subscribed to
431
432 if (updateFaultSubscriptionLink != null) {
433 headerTable.setHTML(0,6,"|");
434
435 headerTable.setWidget(0,7,updateFaultSubscriptionLink);
436 }
437
438 headerTable.setStyleName("HeaderStyle");
439
440
441 tableRowFormatter.setStyleName(0,"headerBox");
442
443 // Now add the main tab bar to the root panel of the browser window
444
445 RootPanel.get().add(headerTable);
446 RootPanel.get().add(MainTabBar);
447
448 MainTabBar.setWidth("98%");
449 MainTabBar.setHeight("100%");
450
451 // Find out if in the URL for the page include a URL parameter
452 // FaultID which indicates a fault to be updated. If so we
453 // initialise the update form panel with a tab which contains
454 // the fault to be edited if the user has the adequate
455 // priviledge to update the fault.
456
457 final String temp = WindowUtils.getLocation().getParameter("EditFault");
458
459 if (temp != null) {
460
461 // Ensure that the fault id is actually an integer
462
463 int faultId = -1;
464
465 boolean validFaultIdFound = false;
466
467 try {
468 faultId = Integer.parseInt(temp);
469 validFaultIdFound = true;
470 } catch (NumberFormatException e) {
471 MessageBox.alert(internationalizationConstants.information(),"Unable to edit fault as fault number specified " + temp + " is invalid");
472 }
473
474 boolean userAuthorised = false;
475
476 // We have to do this as we can only use variables
477 // declared as final in the innner class
478
479 final int faultNumber = faultId;
480
481 if (validFaultIdFound) {
482
483 for (int i=0; i < UserAuthentication.PriviledgeLevels.size();i++) {
484
485 // Only if the user has logged onto the system
486 // using his user name can he modify faults
487
488 if (((String)UserAuthentication.PriviledgeLevels.get(i)).equalsIgnoreCase(FaultDatabaseConstants.INGUSERPRIVILEDGE)) {
489
490 userAuthorised = true;
491
492 // Now we need to establish if the fault that
493 // has been specified exists and if it does
494 // then we can build the tab which will be
495 // used to hold the fault
496
497 svc.faultExists(faultNumber,true,new AsyncCallback() {
498
499 // If the fault does exist in the
500 // database then we can allow the user
501 // to edit it
502
503 public void onSuccess (final Object result) {
504
505 if (((Boolean)result).booleanValue()) {
506 modifyFormPanel.addNewFaultTab(faultNumber);
507
508 // Select the update tab panel so that the user
509 // can edit it straight away
510
511 MainTabBar.selectTab(0);
512
513 } else {
514 MessageBox.alert(internationalizationConstants.information(),internationalizationConstants.unableToFindFaultInDatabase(faultNumber));
515 }
516 }
517
518 public void onFailure (Throwable ex)
519 {
520 MessageBox.alert(internationalizationConstants.information(),"Unable to edit fault " + faultNumber);
521 }
522 });
523
524 break;
525 }
526 }
527
528 if (!userAuthorised) {
529 MessageBox.alert(internationalizationConstants.information(),internationalizationConstants.userDoesNotSufficientPriviledge());
530 }
531 }
532 }
533
534 busyIndicator.showBusy(false);
535
536 }
537
538 /**
539 * Called when the main window is resized
540 */
541
542 public void onWindowResized (int width, int height) {
543
544 final RootPanel rootPanel = RootPanel.get();
545
546 rootPanel.setSize(Math.max(width - rootPanel.getAbsoluteLeft(), 0) + "px",Math.max(height - rootPanel.getAbsoluteTop(), 0) + "px");
547 }
548
549 /**
550 * This is the entry point of the client side of the system. This
551 * is the method which is called by the web browser when it is
552 * loaded for the first and boots the system.
553 */
554
555 public void onModuleLoad() {
556
557 // Now test out the object which will be used to communicate
558 // with the servlet on the tomcat server
559
560 final FaultServiceAsync svc = (FaultServiceAsync) GWT.create(FaultService.class);
561 final ServiceDefTarget endPoint = (ServiceDefTarget) svc;
562
563 endPoint.setServiceEntryPoint(GWT.getModuleBaseURL() + "/faultService");
564
565 // Now create a login screen which will be used by the user to
566 // enter the his login credentials for the system. After he
567 // has entered his user credentials, the user will then be
568 // exposed to the rest of the system
569
570 this.svc = svc;
571
572 loginPanel = new LoginPanel(svc,this);
573
574 final RootPanel rootPanel = RootPanel.get();
575
576 rootPanel.add(loginPanel);
577 rootPanel.setWidth("100%");
578
579 Window.setTitle("ING Fault Management System");
580 Window.setMargin("2px");
581
582 Window.addWindowResizeListener(this);
583
584 }
585 }
586