Coverage Report - org.homeunix.thecave.buddi.model.impl.ModelFactory
 
Classes in this File Line Coverage Branch Coverage Complexity
ModelFactory
28%
50/175
26%
13/50
4.75
 
 1  
 /*
 2  
  * Created on Aug 28, 2007 by wyatt
 3  
  */
 4  
 package org.homeunix.thecave.buddi.model.impl;
 5  
 
 6  
 import java.beans.XMLDecoder;
 7  
 import java.io.File;
 8  
 import java.io.FileInputStream;
 9  
 import java.io.IOException;
 10  
 import java.io.InputStream;
 11  
 import java.util.Collections;
 12  
 import java.util.Date;
 13  
 import java.util.HashMap;
 14  
 import java.util.Map;
 15  
 import java.util.logging.Logger;
 16  
 
 17  
 import javax.swing.JOptionPane;
 18  
 
 19  
 import org.homeunix.thecave.buddi.Const;
 20  
 import org.homeunix.thecave.buddi.i18n.BuddiKeys;
 21  
 import org.homeunix.thecave.buddi.i18n.keys.BudgetCategoryTypes;
 22  
 import org.homeunix.thecave.buddi.i18n.keys.BudgetExpenseDefaultKeys;
 23  
 import org.homeunix.thecave.buddi.i18n.keys.BudgetIncomeDefaultKeys;
 24  
 import org.homeunix.thecave.buddi.i18n.keys.ButtonKeys;
 25  
 import org.homeunix.thecave.buddi.i18n.keys.TypeCreditDefaultKeys;
 26  
 import org.homeunix.thecave.buddi.i18n.keys.TypeDebitDefaultKeys;
 27  
 import org.homeunix.thecave.buddi.model.Account;
 28  
 import org.homeunix.thecave.buddi.model.AccountType;
 29  
 import org.homeunix.thecave.buddi.model.BudgetCategory;
 30  
 import org.homeunix.thecave.buddi.model.BudgetCategoryType;
 31  
 import org.homeunix.thecave.buddi.model.Document;
 32  
 import org.homeunix.thecave.buddi.model.ScheduledTransaction;
 33  
 import org.homeunix.thecave.buddi.model.Source;
 34  
 import org.homeunix.thecave.buddi.model.Split;
 35  
 import org.homeunix.thecave.buddi.model.Transaction;
 36  
 import org.homeunix.thecave.buddi.model.TransactionSplit;
 37  
 import org.homeunix.thecave.buddi.plugin.api.exception.InvalidValueException;
 38  
 import org.homeunix.thecave.buddi.plugin.api.exception.ModelException;
 39  
 import org.homeunix.thecave.buddi.plugin.api.util.TextFormatter;
 40  
 import org.homeunix.thecave.buddi.util.BuddiCryptoFactory;
 41  
 import org.homeunix.thecave.buddi.util.OperationCancelledException;
 42  
 import org.homeunix.thecave.buddi.view.dialogs.BuddiPasswordDialog;
 43  
 
 44  
 import ca.digitalcave.moss.application.document.exception.DocumentLoadException;
 45  
 import ca.digitalcave.moss.common.DateUtil;
 46  
 import ca.digitalcave.moss.common.OperatingSystemUtil;
 47  
 import ca.digitalcave.moss.crypto.CipherException;
 48  
 import ca.digitalcave.moss.crypto.IncorrectDocumentFormatException;
 49  
 import ca.digitalcave.moss.crypto.IncorrectPasswordException;
 50  
 
 51  
 /**
 52  
  * The factory for all model objects.  It is highly recommended to use this
 53  
  * class instead of the constructors, for all model objects.
 54  
  * 
 55  
  * @author wyatt
 56  
  *
 57  
  */
 58  0
 public class ModelFactory {
 59  
 
 60  
         public static Map<String, BudgetCategoryType> budgetPeriodTypes;
 61  
 
 62  
         /**
 63  
          * Returns the budget category type of the given type, or null if it 
 64  
          * does not exist.
 65  
          * @param name
 66  
          * @return
 67  
          */
 68  
         public static BudgetCategoryType getBudgetCategoryType(BudgetCategoryTypes type){
 69  24263
                 return getBudgetCategoryType(type.toString());
 70  
         }
 71  
 
 72  
         /**
 73  
          * Returns the budget category type of the given name, or null if it 
 74  
          * does not exist.
 75  
          * @param name
 76  
          * @return
 77  
          */
 78  
         public static BudgetCategoryType getBudgetCategoryType(String name){
 79  24263
                 if (budgetPeriodTypes == null){
 80  2986
                         budgetPeriodTypes = new HashMap<String, BudgetCategoryType>();
 81  2986
                         budgetPeriodTypes.put(BudgetCategoryTypes.BUDGET_CATEGORY_TYPE_MONTH.toString(), new BudgetCategoryTypeMonthly());
 82  2986
                         budgetPeriodTypes.put(BudgetCategoryTypes.BUDGET_CATEGORY_TYPE_WEEK.toString(), new BudgetCategoryTypeWeekly());
 83  2986
                         budgetPeriodTypes.put(BudgetCategoryTypes.BUDGET_CATEGORY_TYPE_SEMI_MONTH.toString(), new BudgetCategoryTypeSemiMonthly());
 84  2986
                         budgetPeriodTypes.put(BudgetCategoryTypes.BUDGET_CATEGORY_TYPE_QUARTER.toString(), new BudgetCategoryTypeQuarterly());
 85  2986
                         budgetPeriodTypes.put(BudgetCategoryTypes.BUDGET_CATEGORY_TYPE_SEMI_YEAR.toString(), new BudgetCategoryTypeSemiYearly());
 86  2986
                         budgetPeriodTypes.put(BudgetCategoryTypes.BUDGET_CATEGORY_TYPE_YEAR.toString(), new BudgetCategoryTypeYearly());
 87  
                 }
 88  
 
 89  24263
                 return budgetPeriodTypes.get(name);
 90  
         }
 91  
 
 92  
         /**
 93  
          * Creates a new Account with the given values
 94  
          * @param name
 95  
          * @param type
 96  
          * @return
 97  
          * @throws InvalidValueException
 98  
          */
 99  
         public static Account createAccount(String name, AccountType type) throws InvalidValueException {
 100  0
                 Account a = new AccountImpl();
 101  
 
 102  0
                 a.setName(name);
 103  0
                 a.setAccountType(type);
 104  
 
 105  0
                 return a;
 106  
         }
 107  
         
 108  2986
         private static Split split = new SplitImpl();
 109  
         public static Split createSplit() throws InvalidValueException {
 110  0
                 return split;
 111  
         }
 112  
         
 113  
         public static TransactionSplit createTransactionSplit(Source source, long amount) throws InvalidValueException {
 114  103
                 TransactionSplit t = new TransactionSplitImpl();
 115  
                 
 116  103
                 t.setSource(source);
 117  103
                 t.setAmount(amount);
 118  
                 
 119  103
                 return t;
 120  
         }
 121  
 
 122  
         /**
 123  
          * Creates a new AccountType with the given values
 124  
          * @param name
 125  
          * @param credit
 126  
          * @return
 127  
          * @throws InvalidValueException
 128  
          */
 129  
         public static AccountType createAccountType(String name, boolean credit) throws InvalidValueException {
 130  27306
                 AccountType at = new AccountTypeImpl();
 131  
 
 132  27306
                 at.setName(name);
 133  27306
                 at.setCredit(credit);
 134  
 
 135  27306
                 return at;
 136  
         }
 137  
 
 138  
         /**
 139  
          * Creates a new BudgetCategory with the given values
 140  
          * @param name
 141  
          * @param type
 142  
          * @param income
 143  
          * @return
 144  
          * @throws InvalidValueException
 145  
          */
 146  
         public static BudgetCategory createBudgetCategory(String name, BudgetCategoryType type, boolean income) throws InvalidValueException {
 147  30340
                 BudgetCategory bc = new BudgetCategoryImpl();
 148  
 
 149  30340
                 bc.setName(name);
 150  30340
                 bc.setPeriodType(type);
 151  30340
                 bc.setIncome(income);
 152  
 
 153  30340
                 return bc;
 154  
         }
 155  
 
 156  
         /**
 157  
          * Creates a new data model, with some default types and categories.
 158  
          */
 159  
         public static Document createDocument() throws ModelException {
 160  
                 Document document;
 161  3034
                 if (getAutoSaveLocation(null).exists() && getAutoSaveLocation(null).canRead()){
 162  0
                         Logger.getLogger(ModelFactory.class.getName()).info("Autosave file found; prompting user if we should use it or not");
 163  
 
 164  0
                         String[] options = new String[2];
 165  0
                         options[0] = TextFormatter.getTranslation(ButtonKeys.BUTTON_YES);
 166  0
                         options[1] = TextFormatter.getTranslation(ButtonKeys.BUTTON_NO);
 167  
 
 168  0
                         if (JOptionPane.showOptionDialog(
 169  
                                         null, 
 170  
                                         TextFormatter.getTranslation(BuddiKeys.MESSAGE_AUTOSAVE_FILE_FOUND),
 171  
                                         TextFormatter.getTranslation(BuddiKeys.MESSAGE_AUTOSAVE_FILE_FOUND_TITLE),
 172  
                                         JOptionPane.YES_NO_OPTION,
 173  
                                         JOptionPane.QUESTION_MESSAGE,
 174  
                                         null,
 175  
                                         options,
 176  
                                         options[0]
 177  
                         ) == 0) {  //The index of the Yes button.
 178  
                                 try {
 179  0
                                         document = createDocument(getAutoSaveLocation(null));
 180  0
                                         document.setFile(null);
 181  0
                                         document.setChanged();
 182  0
                                         Logger.getLogger(ModelFactory.class.getName()).info("User decided to load AutoSave file");
 183  0
                                         return document;
 184  
                                 }
 185  0
                                 catch (DocumentLoadException dle){
 186  0
                                         Logger.getLogger(ModelFactory.class.getName()).warning("Error opening auto save file.  Continuing on to create normal file.");
 187  
                                 }
 188  0
                                 catch (OperationCancelledException oce){
 189  0
                                         Logger.getLogger(ModelFactory.class.getName()).finest("User cancelled opening auto save file.  Continuing on to create normal file.");
 190  0
                                 }
 191  
                         }
 192  
                         else {
 193  0
                                 Logger.getLogger(ModelFactory.class.getName()).info("User decided not to load AutoSave file.  It will be removed the next time this file is saved.");
 194  
                         }
 195  
                 }
 196  
 
 197  3034
                 document = new DocumentImpl();
 198  3034
                 document.setFile(null); //A null dataFile will prompt for location on first save.
 199  
 
 200  24272
                 for (BudgetExpenseDefaultKeys s : BudgetExpenseDefaultKeys.values()){
 201  21238
                         BudgetCategory bc = ModelFactory.createBudgetCategory(s.toString(), new BudgetCategoryTypeMonthly(), false); 
 202  21238
                         document.addBudgetCategory(bc);
 203  
                 }
 204  12136
                 for (BudgetIncomeDefaultKeys s : BudgetIncomeDefaultKeys.values()){
 205  9102
                         document.addBudgetCategory(ModelFactory.createBudgetCategory(s.toString(), new BudgetCategoryTypeMonthly(), true));
 206  
                 }
 207  
 
 208  15170
                 for (TypeDebitDefaultKeys s : TypeDebitDefaultKeys.values()){
 209  12136
                         document.addAccountType(ModelFactory.createAccountType(s.toString(), false));
 210  
                 }
 211  
 
 212  18204
                 for (TypeCreditDefaultKeys s : TypeCreditDefaultKeys.values()){
 213  15170
                         document.addAccountType(ModelFactory.createAccountType(s.toString(), true));
 214  
                 }        
 215  
 
 216  
                 //Refresh the UID Map...
 217  3034
                 document.refreshUidMap();
 218  
                 
 219  
                 //Do some sanity checks.  If this returns anything, display it.
 220  3034
                 String errors = document.doSanityChecks();
 221  3034
                 if (errors != null)
 222  0
                         JOptionPane.showMessageDialog(null, errors);
 223  
 
 224  
                 //Update all balances...
 225  3034
                 document.updateAllBalances();
 226  
 
 227  
                 //Sort lists...
 228  3034
                 Collections.sort(document.getAccounts());
 229  3034
                 Collections.sort(document.getAccountTypes());
 230  3034
                 Collections.sort(document.getBudgetCategories());
 231  3034
                 Collections.sort(document.getTransactions());
 232  3034
                 Collections.sort(document.getScheduledTransactions());
 233  
 
 234  
                 //Allow changes to start firing
 235  3034
                 document.finishBatchChange();
 236  
 
 237  
                 //Fire a change event
 238  3034
                 document.setChanged();
 239  
 
 240  
                 //Return to calling code... the model is correctly loaded.
 241  3034
                 return document;
 242  
         }
 243  
 
 244  
         /**
 245  
          * Attempts to load a data model from file.  Works with Buddi 3 format.  To load a
 246  
          * legacy format, use ModelConverter to get a Bean object, and call the constructor which
 247  
          * takes a DataModelBean.
 248  
          * @param file File to load
 249  
          * @throws DocumentLoadException
 250  
          */
 251  
         public static Document createDocument(File file) throws DocumentLoadException, OperationCancelledException {
 252  
                 DocumentImpl document;
 253  
 
 254  
                 //Which file to actually load from.  Initially set to the given file, but
 255  
                 // this may be changed if we find an autosave document and the user wants 
 256  
                 // to load it.
 257  0
                 File fileToLoad = file;
 258  
 
 259  0
                 if (file == null)
 260  0
                         throw new DocumentLoadException("Error loading model: specfied file is null.");
 261  
 
 262  0
                 if (!file.exists())
 263  0
                         throw new DocumentLoadException("File " + file + " does not exist.");
 264  
 
 265  0
                 if (!file.canRead())
 266  0
                         throw new DocumentLoadException("File " + file + " cannot be opened for reading.");
 267  
 
 268  0
                 if (getAutoSaveLocation(file).exists() && getAutoSaveLocation(file).canRead()){
 269  0
                         Logger.getLogger(ModelFactory.class.getName()).info("Autosave file found; prompting user if we should use it or not");
 270  
 
 271  0
                         String[] options = new String[2];
 272  0
                         options[0] = TextFormatter.getTranslation(ButtonKeys.BUTTON_YES);
 273  0
                         options[1] = TextFormatter.getTranslation(ButtonKeys.BUTTON_NO);
 274  
 
 275  0
                         if (JOptionPane.showOptionDialog(
 276  
                                         null, 
 277  
                                         TextFormatter.getTranslation(BuddiKeys.MESSAGE_AUTOSAVE_FILE_FOUND),
 278  
                                         TextFormatter.getTranslation(BuddiKeys.MESSAGE_AUTOSAVE_FILE_FOUND_TITLE),
 279  
                                         JOptionPane.YES_NO_OPTION,
 280  
                                         JOptionPane.QUESTION_MESSAGE,
 281  
                                         null,
 282  
                                         options,
 283  
                                         options[0]
 284  
                         ) == 0) {  //The index of the Yes button.
 285  0
                                 fileToLoad = getAutoSaveLocation(file);
 286  0
                                 Logger.getLogger(ModelFactory.class.getName()).info("User decided to load AutoSave file");
 287  
                         }
 288  
                         else {
 289  0
                                 Logger.getLogger(ModelFactory.class.getName()).info("User decided not to load AutoSave file.  It will be removed the next time this file is saved.");
 290  
                         }
 291  
                 }
 292  
 
 293  0
                 Logger.getLogger(ModelFactory.class.getName()).finest("Trying to load file " + fileToLoad);
 294  
 
 295  
                 try {
 296  
                         InputStream is;
 297  0
                         BuddiCryptoFactory factory = new BuddiCryptoFactory();
 298  0
                         char[] password = null;
 299  
 
 300  
                         //Loop until the user gets the password correct, hits cancel, 
 301  
                         // or some other error occurs.
 302  
                         while (true) {
 303  
                                 try {
 304  0
                                         is = factory.getDecryptedStream(new FileInputStream(fileToLoad), password);
 305  
 
 306  
                                         //Attempt to decode the XML within the (now hopefully un-encrypted) data file. 
 307  0
                                         XMLDecoder decoder = new XMLDecoder(is);
 308  0
                                         Object o = decoder.readObject();
 309  0
                                         if (o instanceof DocumentImpl){
 310  0
                                                 document = (DocumentImpl) o;
 311  
                                         }
 312  
                                         else {
 313  0
                                                 throw new IncorrectDocumentFormatException("Could not find a DataModelBean object in the data file!");
 314  
                                         }
 315  0
                                         is.close();
 316  
 
 317  
                                         //Refresh the UID Map...
 318  0
                                         document.refreshUidMap();
 319  
 
 320  
                                         //This will let us know where to save the file to.  Even if we found
 321  
                                         // an autosave file, we want to save the file to the new location, 
 322  
                                         // so we don't use the fileToLoad variable.
 323  0
                                         document.setFile(file);
 324  
 
 325  
                                         //Update all balances...
 326  0
                                         document.updateAllBalances();
 327  
 
 328  
                                         //Store the password
 329  0
                                         document.setPassword(password);
 330  
 
 331  
                                         //Check for scheduled transactions
 332  0
                                         document.updateScheduledTransactions();
 333  
 
 334  
 
 335  
 
 336  
 
 337  
                                         //The old data format (before 2.9.11.0) used a string representation of a date
 338  
                                         // object as the key to the Budget Category amount map.  Unfortunately, this
 339  
                                         // meant that in different time zones, you would have different start dates
 340  
                                         // for budget periods!
 341  
                                         //We fix this in 2.9.11.0.  For backwards compatibility (to make sure that 
 342  
                                         // you can still load all the old format of date), we have to convert them
 343  
                                         // here at file load.
 344  
                                         //We should be able to remove this early in the 3.0 branch (or possible even 
 345  
                                         // at 3.0.0.0 itself, depending on how long it stays in Dev branch).
 346  0
                                         for (BudgetCategory bc : document.getBudgetCategories()) {
 347  0
                                                 boolean changed = false;
 348  0
                                                 Map<String, Long> newAmountMap = new HashMap<String, Long>();
 349  
 
 350  
                                                 //Iterate through all budget periods, and check the 
 351  
                                                 // 
 352  0
                                                 for (String key : ((BudgetCategoryImpl) bc).getAmounts().keySet()) {
 353  0
                                                         String[] splitKey = key.split(":");
 354  0
                                                         if (splitKey.length == 2){
 355  0
                                                                 changed = true;
 356  0
                                                                 Date dateKey = new Date(Long.parseLong(splitKey[1]));
 357  0
                                                                 Logger.getLogger(ModelFactory.class.getName()).finest("dateKey: " + dateKey);
 358  0
                                                                 long amount = ((BudgetCategoryImpl) bc).getAmounts().get(key);
 359  0
                                                                 String newDateKey = 
 360  
                                                                         bc.getBudgetPeriodType().getName() 
 361  
                                                                         + ":" + DateUtil.getYear(dateKey)
 362  
                                                                         + ":" + DateUtil.getMonth(dateKey)
 363  
                                                                         + ":" + DateUtil.getDay(dateKey);
 364  0
                                                                 newAmountMap.put(newDateKey, amount);
 365  0
                                                         }
 366  0
                                                         else if (splitKey.length == 4){
 367  0
                                                                 newAmountMap.put(key, ((BudgetCategoryImpl) bc).getAmounts().get(key));
 368  
                                                         }
 369  0
                                                 }
 370  
 
 371  0
                                                 if (changed){
 372  0
                                                         Logger.getLogger(ModelFactory.class.getName()).warning("Your data file has been updated to address bug #1811038.  Included inline are the details of the changes:\n\n"
 373  
                                                                         + "New Map:\n" + newAmountMap + "\n\n"
 374  
                                                                         + "Old Map:\n" + ((BudgetCategoryImpl) bc).getAmounts());
 375  
 
 376  0
                                                         ((BudgetCategoryImpl) bc).setAmounts(newAmountMap);
 377  
                                                 }
 378  0
                                         }
 379  
 
 380  
 
 381  
 
 382  
                                         //As a precaution for the bug fix above, we are also changing our internal 
 383  
                                         // representation of Date objects for Transactions to Strings.  This is done
 384  
                                         // automatically when a date is read; to force this, we read every date here.
 385  0
                                         for (Transaction t : document.getTransactions()) {
 386  0
                                                 t.getDate();
 387  
                                         }
 388  
 
 389  
 
 390  
 
 391  
                                         //Sort lists...
 392  0
                                         Collections.sort(document.getAccounts());
 393  0
                                         Collections.sort(document.getAccountTypes());
 394  0
                                         Collections.sort(document.getBudgetCategories());
 395  0
                                         Collections.sort(document.getTransactions());
 396  0
                                         Collections.sort(document.getScheduledTransactions());
 397  
 
 398  
                                         //Allow changes to start firing
 399  0
                                         document.finishBatchChange();
 400  
 
 401  
                                         //Fire a change event
 402  0
                                         document.setChanged();
 403  0
                                         document.resetChanged();
 404  
 
 405  
                                         //Return to calling code... the model is correctly loaded.
 406  0
                                         return document;
 407  
                                 }
 408  0
                                 catch (IncorrectPasswordException ipe){
 409  
                                         //The password was not correct.  Prompt for a new one.
 410  0
                                         BuddiPasswordDialog passwordDialog = new BuddiPasswordDialog();
 411  0
                                         password = passwordDialog.askForPassword(false, true);
 412  
 
 413  
                                         //User hit cancel.  Cancel loading, and pass control to calling code. 
 414  
                                         // Calling code will possibly prompt for a new file.
 415  0
                                         if (password == null)
 416  0
                                                 throw new OperationCancelledException("User cancelled file load.");
 417  
                                 }
 418  0
                                 catch (IncorrectDocumentFormatException ife){
 419  
                                         //The document we are trying to load does not have the proper header.
 420  
                                         // This is not a valid Buddi3 data file.
 421  0
                                         throw new DocumentLoadException("Incorrect document format", ife);
 422  
                                 }
 423  0
                                 catch (ModelException me){
 424  0
                                         throw new DocumentLoadException("Model exception", me);
 425  0
                                 }
 426  
                         }
 427  
                 }
 428  0
                 catch (CipherException ce){
 429  
                         //If we get here, something is very wrong.  Perhaps the platform does not support
 430  
                         // the encryption we have chosen, or something else is wrong.
 431  0
                         throw new DocumentLoadException(ce);
 432  
                 }
 433  0
                 catch (IOException ioe){
 434  
                         //If we get here, chances are good that the file is not valid.
 435  0
                         throw new DocumentLoadException(ioe);
 436  
                 }
 437  
         }
 438  
 
 439  
 
 440  
 
 441  
         /**
 442  
          * Creates a new ScheduledTransaction with the given values
 443  
          * @return
 444  
          * @throws InvalidValueException
 445  
          */
 446  
         public static ScheduledTransaction createScheduledTransaction(String name, String message, Date startDate, Date endDate, String frequencyType, int scheduleDay, int scheduleWeek, int scheduleMonth, String description, long amount, Source from, Source to) throws InvalidValueException {
 447  
 
 448  0
                 ScheduledTransaction st = new ScheduledTransactionImpl();
 449  
 
 450  0
                 st.setScheduleName(name);
 451  0
                 st.setMessage(message);
 452  0
                 st.setStartDate(startDate);
 453  0
                 if (endDate != null)
 454  0
                         st.setEndDate(endDate);
 455  0
                 st.setFrequencyType(frequencyType);
 456  0
                 st.setScheduleDay(scheduleDay);
 457  0
                 st.setScheduleWeek(scheduleWeek);
 458  0
                 st.setScheduleMonth(scheduleMonth);
 459  
 //                st.setDate(date);
 460  0
                 st.setDescription(description);
 461  0
                 st.setAmount(amount);
 462  0
                 st.setFrom(from);
 463  0
                 st.setTo(to);
 464  
 
 465  0
                 return st;
 466  
         }
 467  
 
 468  
         /**
 469  
          * Creates a new Transaction with the given values
 470  
          * @param date
 471  
          * @param description
 472  
          * @param amount
 473  
          * @param from
 474  
          * @param to
 475  
          * @return
 476  
          * @throws InvalidValueException
 477  
          */
 478  
         public static Transaction createTransaction(Date date, String description, long amount, Source from, Source to) throws InvalidValueException {
 479  0
                 Transaction t = new TransactionImpl();
 480  
 
 481  0
                 t.setDate(date);
 482  0
                 t.setDescription(description);
 483  0
                 t.setAmount(amount);
 484  0
                 t.setFrom(from);
 485  0
                 t.setTo(to);
 486  
 
 487  0
                 return t;
 488  
         }
 489  
 
 490  
 
 491  
         /**
 492  
          * Returns the auto save file locaton for the given base file.  If the base file
 493  
          * is null, return the Preferences directory and a filename of "AutosaveData.buddi3autosave";
 494  
          * if the base file is not null, return the location of the data file, with the extension
 495  
          * changed from .buddi3 to .buddi3autosave.
 496  
          * @param baseFile
 497  
          * @return
 498  
          */
 499  
         public static File getAutoSaveLocation(File baseFile){
 500  3034
                 if (baseFile == null)
 501  3034
                         return OperatingSystemUtil.getUserFile("Buddi", "AutosaveData" + Const.AUTOSAVE_FILE_EXTENSION);
 502  
                 else {
 503  0
                         String autoSaveLocationString = baseFile.getAbsolutePath();
 504  0
                         autoSaveLocationString = 
 505  
                                 autoSaveLocationString.replaceAll(
 506  
                                                 Const.DATA_FILE_EXTENSION + "$", "");
 507  0
                         autoSaveLocationString = 
 508  
                                 autoSaveLocationString 
 509  
                                 + Const.AUTOSAVE_FILE_EXTENSION;
 510  0
                         return new File(autoSaveLocationString);
 511  
                 }
 512  
         }
 513  
 }