Coverage Report - org.openpermis.editor.policy.ApplicationState
 
Classes in this File Line Coverage Branch Coverage Complexity
ApplicationState
68%
49/72
41%
14/34
2.353
 
 1  
 /*
 2  
  * Copyright (c) 2009, Swiss Federal Department of Defence Civil Protection and Sport
 3  
  *                     (http://www.vbs.admin.ch)
 4  
  * Copyright (c) 2009, Ergon Informatik AG (http://www.ergon.ch)
 5  
  * All rights reserved.
 6  
  *
 7  
  * Licensed under the Open Permis License which accompanies this distribution,
 8  
  * and is available at http://www.openpermis.org/BSDlicenceKent.txt
 9  
  */
 10  
 package org.openpermis.editor.policy;
 11  
 
 12  
 import java.beans.PropertyChangeListener;
 13  
 import java.beans.PropertyChangeSupport;
 14  
 import java.io.File;
 15  
 
 16  
 /**
 17  
  * Describes persistent application state.
 18  
  * @since 0.1.0
 19  
  */
 20  
 public final class ApplicationState {
 21  
         
 22  
         //---- State
 23  
         
 24  
         /**
 25  
          * The working directory of the application.
 26  
          * @since 0.1.0
 27  
          */
 28  
         private String workingDirectory;
 29  
         
 30  
         /**
 31  
          * List of recent files, never {@code null}.
 32  
          * @since 0.1.0
 33  
          */
 34  
         private String[] recentFiles;
 35  
         
 36  
         /**
 37  
          * The property change support for bound properties.
 38  
          * @since 0.1.0
 39  
          */
 40  
         private final PropertyChangeSupport propertyChangeSupport;
 41  
         
 42  
         //---- Constructors
 43  
         
 44  
         /**
 45  
          * Creates a new application state.
 46  
          * @since 0.1.0
 47  
          */
 48  7
         public ApplicationState () {
 49  7
                 this.recentFiles = new String[0];
 50  7
                 this.propertyChangeSupport = new PropertyChangeSupport(this);
 51  7
         }
 52  
         
 53  
         //---- Methods
 54  
         
 55  
         /**
 56  
          * Adds a property change listener that gets notified on bound property changes.
 57  
          * <p>The same listener object may be added more than once, and will be called
 58  
          * as many times as it is added. If <code>listener</code> is {@code null}, no exception 
 59  
          * is thrown and no action is taken.</p>
 60  
          * @param listener the listener to add.
 61  
          * @since 0.1.0
 62  
          */
 63  
         public void addPropertyChangeListener (PropertyChangeListener listener) {
 64  6
                 this.propertyChangeSupport.addPropertyChangeListener(listener);
 65  6
         }
 66  
 
 67  
         /**
 68  
          * Removes the specified property change listener.
 69  
          * <p>If <code>listener</code> was added more than once to the same event source, 
 70  
          * it will be notified one less time after being removed. If <code>listener</code> is 
 71  
          * {@code null}, or was never added, no exception is thrown and no action is taken.</p>
 72  
          * @param listener the listener to remove.
 73  
          * @since 0.1.0
 74  
          */
 75  
         public void removePropertyChangeListener (PropertyChangeListener listener) {
 76  0
                 this.propertyChangeSupport.removePropertyChangeListener(listener);
 77  0
         }
 78  
 
 79  
         /**
 80  
          * Returns the working directory bean property.
 81  
          * <p>Use the {@link #getWorkingDirectoryFile() file version} if you are interested
 82  
          * in an actual {@link File} object.</p>
 83  
          * @return the working directory bean property.
 84  
          * @see #getWorkingDirectoryFile()
 85  
          * @since 0.1.0
 86  
          */
 87  
         public String getWorkingDirectory () {
 88  3
                 return this.workingDirectory;
 89  
         }
 90  
         
 91  
         /**
 92  
          * Sets the working directory bean property.
 93  
          * <p>Use the {@link #setWorkingDirectoryFile(File) file version} if your source
 94  
          * is an actual {@link File} object.</p>
 95  
          * @param workingDirectory the working directory bean property.
 96  
          * @see #setWorkingDirectoryFile(File)
 97  
          * @since 0.1.0
 98  
          */
 99  
         public void setWorkingDirectory (String workingDirectory) {
 100  2
                 final String oldWorkingDirectory = this.workingDirectory;
 101  2
                 this.workingDirectory = workingDirectory;
 102  2
                 this.propertyChangeSupport.firePropertyChange(
 103  
                         "workingDirectory", oldWorkingDirectory, this.workingDirectory
 104  
                 );
 105  2
         }
 106  
         
 107  
         /**
 108  
          * Returns the application working directory as file.
 109  
          * <p>Convenience method for the working directory bean property.</p>
 110  
          * @return the application working directory as file.
 111  
          * @see #getWorkingDirectory()
 112  
          * @since 0.1.0
 113  
          */
 114  
         public File getWorkingDirectoryFile () {
 115  0
                 if (this.workingDirectory != null && this.workingDirectory.length() > 0) {
 116  0
                         final File directory = new File(this.workingDirectory);
 117  0
                         if (directory.isDirectory()) {
 118  0
                                 return directory;
 119  
                         }
 120  
                 }
 121  
                 // Fallback, use the current system working directory.
 122  0
                 return new File(System.getProperty("user.dir"));
 123  
         }
 124  
         
 125  
         /**
 126  
          * Sets the application working directory from the given file.
 127  
          * <p>If the file denotes a directory it is used as is, in case of a plain
 128  
          * file the parent directory is chosen.</p>
 129  
          * <p>Convenience method for the working directory bean property.</p>
 130  
          * @param file the working directory to set.
 131  
          * @see #setWorkingDirectory(String)
 132  
          * @since 0.1.0
 133  
          */
 134  
         public void setWorkingDirectoryFile (File file) {
 135  0
                 if (file == null) {
 136  0
                         this.workingDirectory = null;
 137  0
                 } else if (file.isFile()) {
 138  0
                         this.workingDirectory = file.getParent();
 139  0
                 } else if (file.isFile()) {
 140  0
                         this.workingDirectory = file.getPath();
 141  
                 }
 142  0
         }
 143  
         
 144  
         /**
 145  
          * Returns a recent files entry at the specified index.
 146  
          * @param index the index of the recent files entry to retrieve.
 147  
          * @return the recent files entry requested or {@code null} if there is no such entry.
 148  
          * @since 0.1.0
 149  
          */
 150  
         public String getRecentFiles (int index) {
 151  1
                 if (index < 0 || index >= this.recentFiles.length) {
 152  0
                         return null;
 153  
                 }
 154  1
                 return this.recentFiles[index];
 155  
         }
 156  
         
 157  
         /**
 158  
          * Returns the number of recent files stored at this application state.
 159  
          * @return the number of recent files stored at this application state.
 160  
          * @since 0.1.0
 161  
          */
 162  
         public int getRecentFilesCount () {
 163  14
                 return this.recentFiles.length;
 164  
         }
 165  
         
 166  
         /**
 167  
          * Returns a clone of the recent files list of this application state.
 168  
          * @return the recent files list requested, guaranteed not to be {@code null}.
 169  
          * @since 0.1.0
 170  
          */
 171  
         public String[] getRecentFiles () {
 172  26
                 return this.recentFiles.clone();
 173  
         }
 174  
         
 175  
         /**
 176  
          * Checks if the specified recent files index is valid.
 177  
          * @param index the index to check.
 178  
          * @throws IllegalArgumentException if the index is not valid.
 179  
          * @since 0.1.0
 180  
          */
 181  
         private void assertValidRecentFilesIndex (int index) {
 182  4
                 if (index < 0 || index >= this.recentFiles.length) {
 183  1
                         throw new IllegalArgumentException(
 184  
                                 "Invalid recent files index [" + index + 
 185  
                                 "] (maximum is [" + getRecentFilesCount() + "]."
 186  
                         );
 187  
                 }
 188  3
         }
 189  
         
 190  
         /**
 191  
          * Sets the recent files entry at the specified index.
 192  
          * @param index the index of the file entry to set, [0..{@link #getRecentFilesCount()}[.
 193  
          * @param file the file to entry to set, {@code null} to remove the entry.
 194  
          * @throws IllegalArgumentException if the index is not a valid index.
 195  
          * @see #getRecentFilesCount()
 196  
          * @since 0.1.0
 197  
          */
 198  
         public void setRecentFiles (int index, String file) {
 199  3
                 if (file == null) {
 200  2
                         removeRecentFiles(index);
 201  1
                         return;
 202  
                 }
 203  1
                 assertValidRecentFilesIndex(index);
 204  1
                 final String oldFile = this.recentFiles[index];
 205  1
                 this.recentFiles[index] = file;
 206  1
                 this.propertyChangeSupport.fireIndexedPropertyChange(
 207  
                         "recentFiles", index, oldFile, file
 208  
                 );
 209  1
         }
 210  
         
 211  
         /**
 212  
          * Convenience method to remove the file entry at the specified index.
 213  
          * <p>This method changes the whole recent files list.</p>
 214  
          * @param index the index of the file entry to set, [0..{@link #getRecentFilesCount()}[.
 215  
          * @throws IllegalArgumentException if the index is not a valid index.
 216  
          * @since 0.1.0
 217  
          */
 218  
         public void removeRecentFiles (int index) {
 219  3
                 assertValidRecentFilesIndex(index);
 220  2
                 final String[] newFiles = new String[this.recentFiles.length - 1];
 221  2
                 System.arraycopy(this.recentFiles, 0, newFiles, 0, index);
 222  2
                 System.arraycopy(this.recentFiles, index + 1, newFiles, index, newFiles.length - index);
 223  2
                 setRecentFiles(newFiles);
 224  2
         }
 225  
         
 226  
         /**
 227  
          * Convenience method to add a file entry to the recent files list.
 228  
          * <p>This method does nothing if the file entry is {@code null} or there is already a
 229  
          * file entry equal to the one specified contained.</p>
 230  
          * <p>This method changes the whole recent files list.</p>
 231  
          * @param file the file entry to add, may be {@code null}.
 232  
          * @since 0.1.0
 233  
          */
 234  
         public void addRecentFiles (String file) {
 235  6
                 if (file == null) {
 236  0
                         return;
 237  
                 }
 238  15
                 for (int i = 0; i < this.recentFiles.length; i++) {
 239  12
                         if (this.recentFiles[i].equals(file)) {
 240  
                                 // Already contained, move to front.
 241  
                                 // (Generate new array to guarantee property change event.)
 242  3
                                 final String[] newFiles = this.recentFiles.clone();
 243  3
                                 System.arraycopy(this.recentFiles, 0, newFiles, 1, i);
 244  3
                                 newFiles[0] = this.recentFiles[i];
 245  3
                                 setRecentFiles(newFiles);
 246  3
                                 return;
 247  
                         }
 248  
                 }
 249  3
                 final String[] newFiles = new String[this.recentFiles.length + 1];
 250  3
                 System.arraycopy(this.recentFiles, 0, newFiles, 1, this.recentFiles.length);
 251  3
                 newFiles[0] = file;
 252  3
                 setRecentFiles(newFiles);
 253  3
         }
 254  
         
 255  
         /**
 256  
          * Sets the recent files list of this application state.
 257  
          * @param files the new files list to set, {@code null} to set an empty files list.
 258  
          * @since 0.1.0
 259  
          */
 260  
         public void setRecentFiles (String[] files) {
 261  13
                 final String[] oldFiles = getRecentFiles();
 262  13
                 this.recentFiles = files == null ? new String[0] : files.clone();
 263  13
                 this.propertyChangeSupport.firePropertyChange(
 264  
                         "recentFiles", oldFiles, this.recentFiles
 265  
                 );
 266  13
         }
 267  
         
 268  
         /**
 269  
          * Returns a string representation for the recent files list.
 270  
          * @return the string representation for the recent files list.
 271  
          * @since 0.1.0
 272  
          */
 273  
         private String getRecentFilesAsString () {
 274  0
                 final StringBuilder sb = new StringBuilder("[");
 275  0
                 for (String file : this.recentFiles) {
 276  0
                         if (sb.length() > 1) {
 277  0
                                 sb.append(",");
 278  
                         }
 279  0
                         sb.append(file);
 280  
                 }
 281  0
                 return sb.append("]").toString();
 282  
         }
 283  
         
 284  
         //---- Object
 285  
         
 286  
         /**
 287  
          * @since 0.1.0
 288  
          */
 289  
         @Override
 290  
         public String toString () {
 291  0
                 return new StringBuilder("ApplicationState[").
 292  
                         append("workingDirectory=").append(getWorkingDirectory()).
 293  
                         append(",recentFiles=").append(getRecentFilesAsString()).
 294  
                         append("]").toString();
 295  
         }
 296  
         
 297  
 }