001 /* PAVLOV -- Multiple Choice Study System 002 * Copyright (C) 2000 - 2004 T.J. Willis 003 * 004 * This program is free software; you can redistribute it and/or 005 * modify it under the terms of the GNU General Public License 006 * as published by the Free Software Foundation; either version 2 007 * of the License, or (at your option) any later version. 008 * 009 * This program is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 * GNU General Public License for more details. 013 * 014 * You should have received a copy of the GNU General Public License 015 * along with this program; if not, write to the Free Software 016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. 017 * 018 * $Header: /cvsroot/pavlov/net/sourceforge/pavlov/main/AbstractPavlovApplication.java,v 1.9 2004/06/27 08:11:09 tj_willis Exp $ 019 */ 020 package net.sourceforge.pavlov.main; 021 022 import java.util.MissingResourceException; 023 import java.util.ResourceBundle; 024 import net.sourceforge.pavlov.event.*; 025 import net.sourceforge.pavlov.main.standalone.ResourceBroker; 026 import net.sourceforge.pavlov.library.AbstractLibrary; 027 import net.sourceforge.pavlov.library.LibraryLoader; 028 import net.sourceforge.pavlov.pluglets.*; 029 import net.sourceforge.pavlov.pluglets.feedback.velocity.*; 030 import net.sourceforge.pavlov.pluglets.strategy.*; 031 import net.sourceforge.pavlov.user.*; 032 import org.apache.log4j.*; 033 034 /** 035 * An abstract class that handles most of the work of a Pavlov Application, 036 * whether it be applet, servlet, client-server, or standalone. 037 * 038 * @author <a href="mailto:tj_willis@users.sourceforge.net">T.J. Willis</a> 039 * @version 1.0 040 */ 041 public abstract class AbstractPavlovApplication 042 implements LogonListener 043 { 044 045 // FIXED: factor out JFrame 046 /** 047 * The current user. 048 * 049 */ 050 protected User user; //FIXED: de-static all fields 051 /** 052 * The user's name, used before login. 053 * 054 */ 055 protected String userName; 056 /** 057 * The user's password, used before login. 058 * 059 */ 060 protected String password; 061 /** 062 * The directory containing book files. 063 * 064 */ 065 protected String libraryFile;// = "library"; //^ 066 /** 067 * Describe variable <code>library</code> here. 068 * 069 */ 070 protected AbstractLibrary library; 071 //static ResourceBundle resources = null; 072 /** 073 * Describes the quiz in progress, if any. 074 * 075 */ 076 protected Quiz quiz; 077 078 private Category cat 079 = Category.getInstance(AbstractPavlovApplication.class.getName()); 080 081 /** 082 * Manages Velocity feedback pluglets. 083 */ 084 protected VelocityPlugletLoader velocityPlugins; 085 /** 086 * Manages non-Velocity feedback pluglets. 087 * 088 */ 089 protected PlugletLoader feedbackPlugins; // FIXED: can't be static 090 /** 091 * Manages question selection strategy pluglets. 092 * 093 */ 094 protected StrategyLoader strategyPlugins;// FIXED: can't be static 095 /** 096 * Manages tool pluglets. 097 * 098 */ 099 protected PlugletLoader toolPluglets; // FIXED: can't be static 100 101 102 protected ResourceBroker rb; 103 104 /** 105 * Creates a new <code>AbstractPavlovApplication</code> instance. 106 * 107 * @param args[] a <code>String</code> value 108 */ 109 protected AbstractPavlovApplication(final String args[]) 110 { 111 rb = ResourceBroker.getInstance(); 112 libraryFile = rb.getString(rb.LIBRARY_DIR); 113 // FIXME; should be in Pavlov.java 114 processArguments(args); 115 BasicConfigurator.configure(); 116 } 117 118 119 protected void setup(){ 120 showSplashScreen(); 121 newSetStatus(33,rb.STATUS_LOADING_PLUGLETS); 122 loadPluglets(); 123 newSetStatus(40,rb.STATUS_LOADING_LIBRARY); 124 library = loadLibrary(); 125 newSetStatus(50,rb.STATUS_LOGGING_IN); 126 login(userName,password); 127 } 128 129 // HERE 130 private void login(final User u){ 131 if( u == null) return; // FIXME: IllegalArgumentException? 132 //cat.debug("in step 2"); 133 setUser(u); 134 newSetStatus(60, rb.STATUS_VALIDATING_STATISTICS); 135 validate(user, library); 136 //newSetStatus(70, rb.STATUS_CONFIGURING_THEMES); 137 //configureThemes(); 138 newSetStatus(90, rb.STATUS_CREATING_LIBRARY_VIEW); 139 createQuizSelector(); 140 loginFinished(); 141 newSetStatus(95, rb.STATUS_CLOSING_SPLASH_SCREEN); 142 closeSplashScreen(); 143 } 144 145 146 /** 147 * Describe <code>loginFinished</code> method here. 148 * 149 */ 150 protected abstract void loginFinished(); 151 152 private void login(final String name, final String pass) { 153 User u = null; 154 if(name != null && pass != null) { 155 try { 156 LocalUserFile luf = new LocalUserFile(name); 157 if(luf.exists()){ 158 u = luf.read(pass); 159 if(u!=null){ 160 login(u); 161 return; 162 } 163 } 164 } catch (Exception ex) { 165 warn(rb.LOGIN_ERROR,ex); 166 // fall through to u==null below 167 } 168 } 169 170 if(u==null){ 171 // FIXED: implement 172 showLoginController(this); 173 } 174 175 } 176 177 178 protected abstract void showLoginController(AbstractPavlovApplication abs); 179 180 protected void warn(String key,Exception ex){ 181 cat.warn(rb.getString(key),ex); 182 } 183 private void setUser(final User u) { 184 user = u; 185 setUserName(u.getName()); 186 //setPassword(u.getPassword()); 187 } 188 189 // for logincontroller's callback 190 /** 191 * The LoginController calls this when the user has finished logging in. 192 * 193 * @param event a <code>LogonEvent</code> value 194 */ 195 public void logonAttempt(final LogonEvent event) 196 { 197 login(event.getUser()); 198 } 199 200 /** 201 * Describe <code>getQuiz</code> method here. 202 * 203 * @return a <code>Quiz</code> value 204 */ 205 public Quiz getQuiz() 206 { 207 return quiz; 208 } 209 210 /** 211 * Describe <code>setQuiz</code> method here. 212 * 213 * @param q a <code>Quiz</code> value 214 */ 215 public void setQuiz(final Quiz q) 216 { 217 quiz = q; 218 strategyPlugins.addStrategyListener(quiz); 219 quiz.setStrategy(strategyPlugins.getCurrentStrategy()); 220 } 221 222 /** 223 * Returns the library which is supplying questions. 224 * 225 * @return an <code>AbstractLibrary</code> value 226 */ 227 public AbstractLibrary getLibrary() 228 { 229 return library; 230 } 231 232 /** 233 * Asks the user if he's sure he wants to quit. Delegates to 234 * getUIBuilder.confirmQuit(). 235 * 236 * @return a <code>boolean</code> value 237 */ 238 protected abstract boolean confirmQuit(); 239 240 /** 241 * Creates the UI widget that allows the user to select a chapter to 242 * start a quiz. 243 * 244 */ 245 public abstract void createQuizSelector(); 246 /** 247 * Returns the active user. 248 * 249 * @return an <code>User</code> value 250 */ 251 public final User getUser() { return user; } 252 253 254 255 256 257 //============================================================= 258 // override these methods for client-server versions 259 /** 260 * Coordinates the users question data with question in the 261 * active library. 262 * 263 * @param u an <code>User</code> value 264 * @param l an <code>AbstractLibrary</code> value 265 */ 266 protected void validate(User u, AbstractLibrary l) 267 { 268 assert u != null : rb.getString(rb.USER_NULL);//"User is null!"; 269 assert l != null : rb.getString(rb.LIBRARY_NULL);//"Library is null!"; 270 u.validate(l); 271 } 272 273 /** 274 * Reads in the library. 275 * 276 * @return an <code>AbstractLibrary</code> value 277 */ 278 protected final AbstractLibrary loadLibrary() 279 { 280 return LibraryLoader.loadLibrary(libraryFile); 281 } 282 283 284 /** 285 * Returns the named resource value or the given default, if the 286 * resource value is unavailable. 287 * 288 * @param key a <code>String</code> value 289 * @param def a <code>String</code> value 290 * @return a <code>String</code> value 291 */ 292 public String getResourceString(final String key, final String def) 293 { 294 return rb.getString(key,def); 295 } 296 297 /** 298 * Loads all the feedback, strategy, and tool pluglets. 299 * 300 */ 301 public abstract void loadPluglets(); 302 303 //============================================================= 304 305 306 /** 307 * Shows the user startup status, delegates to getUIBuilder()'s setStatus. 308 * 309 * @param pos an <code>int</code> value 310 * @param msg a <code>String</code> value 311 */ 312 public abstract void setStatus(final int pos, final String msg); 313 314 public abstract void newSetStatus(final int pos, final String key); 315 316 317 /** 318 * Keep the user entertained and informed during startup. 319 * 320 */ 321 protected abstract void showSplashScreen(); 322 323 324 /** 325 * Called when startup is finished, delegates to UIBuilder's 326 * closeSplashScreen. 327 * 328 */ 329 protected abstract void closeSplashScreen(); 330 331 332 /** 333 * Sets the user name, useful only before login. 334 * 335 * @param na a <code>String</code> value 336 */ 337 public final void setUserName(final String na) { 338 userName = na; 339 } 340 341 /** 342 * Sets the user password, useful only before login. 343 * 344 * @param na a <code>String</code> value 345 */ 346 public final void setPassword(final String na) { 347 password = na; 348 } 349 350 /** 351 * Sets the feedbackpluglets as answerListeners for the quiz. 352 * 353 * @param theQuiz a <code>Quiz</code> value 354 */ 355 public void registerFeedbackPlugins(Quiz theQuiz) 356 { 357 if(feedbackPlugins!=null) { 358 feedbackPlugins.addToAnswerEventProducer(theQuiz); 359 } 360 if(velocityPlugins!=null){ 361 velocityPlugins.addToAnswerEventProducer(theQuiz); 362 } 363 } 364 365 366 /** 367 * Process command line arguments. 368 * 369 * @param args a <code>String[]</code> value 370 */ 371 public void processArguments(final String[] args) 372 { 373 if(args==null) return; 374 for (String x : args) { 375 if (x.startsWith("-u=") || x.startsWith("--user=")) { 376 String s = x.substring(x.indexOf('=') + 1); 377 378 setUserName(s); 379 } else if (x.startsWith("-p=") || x.startsWith("--password=")) { 380 String s = x.substring(x.indexOf('=') + 1); 381 382 setPassword(s); 383 } else if (x.startsWith("-h") || x.startsWith("--help")) { 384 String s = "\njava -jar pavlov-1.1.jar"; 385 386 System.out.println(s); 387 System.out.println(" -h --help Show this help info"); 388 System.out.println(" -u=name --user=name Specify user"); 389 System.out.println(" -p=pass --password=pw Specify password"); 390 } 391 } 392 } 393 394 /** 395 * Save's the user's progress. 396 * 397 */ 398 public final void saveUser() 399 { 400 try { 401 user.save(); 402 } catch (Exception ex) { 403 warn(rb.USER_SAVING_ERROR, ex); 404 } 405 } 406 407 /** 408 * Ask the user if he really wants to quit. 409 * 410 * @param confirm a <code>boolean</code> value 411 */ 412 public final void niceQuit(boolean confirm) 413 { 414 if(confirm){ 415 if( !confirmQuit()) return; 416 saveUser(); 417 } 418 System.exit(0); 419 } 420 421 422 /** 423 * Show the user that his answer was incorrect. 424 * 425 * @param msg a <code>String</code> value 426 */ 427 public abstract void showIncorrectDialog(String msg); 428 429 } 430