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