View Javadoc
1   /**
2    * Copyright 2011, Aiki IT, FotoRenamer
3    * <p/>
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * <p/>
8    * http://www.apache.org/licenses/LICENSE-2.0
9    * <p/>
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.aikiit.fotorenamer.image;
17  
18  import com.google.common.collect.Lists;
19  import de.aikiit.fotorenamer.exception.InvalidDirectoryException;
20  import de.aikiit.fotorenamer.exception.NoFilesFoundException;
21  import de.aikiit.fotorenamer.exception.RenamingErrorException;
22  import de.aikiit.fotorenamer.gui.ProgressBar;
23  import de.aikiit.fotorenamer.util.LocalizationHelper;
24  import org.apache.logging.log4j.LogManager;
25  import org.apache.logging.log4j.Logger;
26  
27  import javax.swing.*;
28  import java.io.File;
29  import java.util.Arrays;
30  import java.util.List;
31  import java.util.concurrent.atomic.AtomicInteger;
32  
33  import static de.aikiit.fotorenamer.util.LocalizationHelper.getBundleString;
34  import static de.aikiit.fotorenamer.util.LocalizationHelper.getParameterizedBundleString;
35  
36  /**
37   * This class rerenames files in order to be able to play them back onto a camera
38   * device that is not able to deal with long filenames.
39   *
40   * @author hirsch, 08.12.2003
41   * @version 2004-01-08
42   */
43  public final class RemoveExifPrefixRenamer implements Runnable {
44      private static final Logger LOG =
45              LogManager.getLogger(RemoveExifPrefixRenamer.class);
46      /**
47       * Pattern applied to find already renamed image files.
48       * Should match: 20110507_180520_IMG_8192small.JPG
49       */
50      private static final String REPLACE_PATTERN = "\\d{8}[_]\\d{4}[_]";
51  
52      private final File currentDirectory;
53      private List<File> listOfFiles = Lists.newArrayList();
54      private ProgressBar progressBar = null;
55      private final AtomicInteger done = new AtomicInteger(0);
56  
57      /**
58       * Main constructor that takes a directory to work on.
59       *
60       * @param directory Directory to perform operation on.
61       * @throws InvalidDirectoryException If directory cannot be accessed
62       *                                   properly.
63       * @throws NoFilesFoundException     If directory is empty.
64       */
65      public RemoveExifPrefixRenamer(final String directory)
66              throws InvalidDirectoryException, NoFilesFoundException {
67          this.currentDirectory = new File(directory);
68          checkInputAndInitialize();
69          new Thread(this).start();
70      }
71  
72      /**
73       * Performs actual renaming/removing of date information from the
74       * filenames.
75       *
76       * @throws RenamingErrorException If any error occurs.
77       * @see #checkInputAndInitialize()
78       */
79      private void rename() throws RenamingErrorException {
80          for (final File listOfFile : this.listOfFiles) {
81              String name = LocalizationHelper.removeCrLf(listOfFile.getName());
82              String nameNeu = name.replaceFirst(REPLACE_PATTERN, "");
83  
84              // count files to be done
85              if (!nameNeu.equalsIgnoreCase(name)) {
86                  done.incrementAndGet();
87              }
88  
89              // update UI
90              this.progressBar.setProgress();
91              this.progressBar.setText(name);
92              this.progressBar.updateUI();
93  
94              // rename files only
95              if (listOfFile.isFile() && !listOfFile.renameTo(
96                      new File(listOfFile.getParent()
97                              + File.separatorChar + nameNeu))) {
98                  LOG.error("Problem with file " + listOfFile.getName());
99                  throw new RenamingErrorException(getParameterizedBundleString("fotorenamer.ui.rerename.error.detail",
100                         listOfFile.getName()));
101             }
102         }
103     }
104 
105     /**
106      * Checks whether current UI-configuration is valid in order to perform the
107      * renaming itself.
108      *
109      * @throws NoFilesFoundException     If the directory contains no files.
110      * @throws InvalidDirectoryException If the selected directory is not
111      *                                   accessible.
112      */
113     private void checkInputAndInitialize()
114             throws NoFilesFoundException, InvalidDirectoryException {
115         // valid directory
116         if (this.currentDirectory == null || !this.currentDirectory.isDirectory()) {
117             throw new InvalidDirectoryException("" + this.currentDirectory);
118         }
119 
120         final File[] files = this.currentDirectory.listFiles(
121                 new ImageFilenameFilter());
122 
123         // files available
124         if(files == null || files.length == 0) {
125             throw new NoFilesFoundException(this.currentDirectory);
126         }
127 
128         this.listOfFiles = Arrays.asList(files);
129     }
130 
131     /**
132      * Updates the UI and performs the renaming. All error handling is done in
133      * other methods.
134      *
135      * @see #rename()
136      */
137     public void run() {
138         this.progressBar = new ProgressBar(this.listOfFiles.size());
139 
140         try {
141             rename();
142         } catch (RenamingErrorException uf) {
143             JOptionPane.showMessageDialog(null, getParameterizedBundleString("fotorenamer.ui.rename.error", uf.getMessage()),
144                     getBundleString("fotorenamer.ui.rerename.error.title"),
145                     JOptionPane.ERROR_MESSAGE);
146             return;
147         }
148         this.progressBar.dispose();
149 
150         String statusMessage;
151         switch(this.done.get()) {
152             case 0:
153                 statusMessage = getParameterizedBundleString("fotorenamer.ui.rename.success.message.none", this.currentDirectory.getName());
154                 break;
155             case 1:
156                 statusMessage = getParameterizedBundleString("fotorenamer.ui.rename.success.message.one", this.currentDirectory.getName());
157                 break;
158             default:
159                 statusMessage = getParameterizedBundleString("fotorenamer.ui.rename.success.message", this.done, this.listOfFiles.size(), this.currentDirectory.getName());
160         }
161 
162         JOptionPane.showMessageDialog(null, statusMessage, getBundleString("fotorenamer.ui.rerename.success.title"),
163                 JOptionPane.INFORMATION_MESSAGE);
164     }
165 }