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