possibility to remove artifacts generated by meviz index
[meviz.git] / src / main / java / eu / svjatoslav / meviz / htmlindexer / FilesystemIndexer.java
1 /*
2  * Meviz - Various tools collection to work with multimedia.
3  * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
4  * 
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of version 2 of the GNU General Public License
7  * as published by the Free Software Foundation.
8  */
9
10 package eu.svjatoslav.meviz.htmlindexer;
11
12 import java.io.File;
13 import java.io.FileNotFoundException;
14 import java.io.IOException;
15 import java.io.UnsupportedEncodingException;
16 import java.util.ArrayList;
17 import java.util.HashSet;
18 import java.util.List;
19
20 import org.apache.log4j.Logger;
21
22 import eu.svjatoslav.commons.file.IOHelper;
23 import eu.svjatoslav.commons.network.UrlParamEncoder;
24 import eu.svjatoslav.meviz.htmlindexer.metadata.Dimension;
25 import eu.svjatoslav.meviz.htmlindexer.metadata.DirectoryMetadata;
26 import eu.svjatoslav.meviz.htmlindexer.metadata.MetadadaHelper;
27 import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.AbstractFile;
28 import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.DirectoryFile;
29 import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.GeneralFile;
30 import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.Picture;
31
32 /**
33  * Main class of HTML indexer.
34  */
35
36 public class FilesystemIndexer extends AbstractIndexer {
37
38         public static final Logger logger = Logger
39                         .getLogger(FilesystemIndexer.class);
40
41         private final HashSet<String> validMetadataFiles = new HashSet<String>();
42
43         private final File directoryToIndex;
44
45         private String thumbnailsPath;
46
47         private File metadataFile;
48
49         private DirectoryMetadata metadata;
50
51         private final List<String> pathElements;
52
53         private HashSet<Layout> layouts;
54
55         private final CommandlineHandler commandlineHandler;
56
57         public FilesystemIndexer(final File directoryToIndex,
58                         final CommandlineHandler commandlineHandler,
59                         final List<String> pathElements) throws IOException,
60                         ImageFormatError {
61
62                 this.directoryToIndex = directoryToIndex;
63                 this.commandlineHandler = commandlineHandler;
64                 this.pathElements = pathElements;
65
66                 if (!directoryToIndex.canRead())
67                         return;
68
69                 validMetadataFiles.add(Constants.METADATA_FILE_NAME);
70
71                 initializeThumbnailsDirectory();
72                 loadOrCreateMetadata();
73
74                 initializeLayouts();
75
76                 updateMetadata();
77
78                 metadata.removeUnusedMetadataEntries();
79
80                 generateHtmlFromMetadata(layouts);
81
82                 removeUnusedThumbnailFiles();
83
84                 // save directory metadata
85                 if (metadata.changed)
86                         MetadadaHelper.saveDirectoryMetadata(metadataFile, metadata);
87
88         }
89
90         public boolean canWriteIndexFile(final File indexFile)
91                         throws FileNotFoundException, IOException {
92
93                 if (!indexFile.exists())
94                         return true;
95
96                 return Utils.isMevizGeneratedIndexFile(indexFile);
97         }
98
99         public void cleanupUnusedMetadataFiles() {
100                 final File thumbnailsDirectory = new File(thumbnailsPath);
101
102                 for (final File file : thumbnailsDirectory.listFiles())
103                         if (!validMetadataFiles.contains(file.getName()))
104                                 file.delete();
105         }
106
107         public void generateHtmlFromMetadata(final HashSet<Layout> layouts) {
108                 // Generate HTML from metadata
109                 for (final Layout layout : layouts)
110                         try {
111                                 final File indexFile = Utils.getLayoutIndexFile(layout,
112                                                 directoryToIndex);
113
114                                 if (canWriteIndexFile(indexFile)) {
115
116                                         indexForLayout(layout);
117
118                                         IOHelper.overwriteFileIfContentDiffers(indexFile, layout
119                                                         .getHtml(true, true).getBytes());
120                                 }
121                         } catch (final Exception e) {
122                                 logger.error("Error writing index file. ", e);
123                         }
124         }
125
126         public List<String> getChildPath(final File file) {
127
128                 final List<String> result = new ArrayList<String>();
129                 result.addAll(pathElements);
130                 result.add(file.getName());
131
132                 return result;
133         }
134
135         @Override
136         public String getDirectoryUrl(final AbstractFile directory,
137                         final IndexingContext context) {
138                 return directory.fileName + "/index.html";
139         }
140
141         @Override
142         public String getParentDirectoryUrl(final IndexingContext context) {
143                 return "../index.html";
144         }
145
146         @Override
147         public String getThumbnailUrl(final Picture picture,
148                         final Dimension desiredDimension, final IndexingContext context) {
149
150                 // in case thumbnail size was equal to original, then return original
151                 // file path
152                 if (picture.getDimensions().equals(desiredDimension))
153                         return picture.fileName;
154
155                 final String thumbnailFileName = picture
156                                 .getRelativeThumbnailFileName(desiredDimension);
157
158                 validMetadataFiles.add(thumbnailFileName);
159                 final File thumbnailFile = new File(thumbnailsPath + thumbnailFileName);
160
161                 if (!thumbnailFile.exists()) {
162
163                         final File originalFile = new File(
164                                         directoryToIndex.getAbsolutePath() + "/" + picture.fileName);
165
166                         // generate new thumbnail
167                         Picture.makeThumbnail(originalFile, thumbnailFile,
168                                         desiredDimension.getAwtDimension());
169                 }
170                 return Constants.THUMBNAILS_DIRECTORY_NAME + "/"
171                                 + UrlParamEncoder.encode(thumbnailFileName);
172         }
173
174         public void indexForLayout(final Layout layout)
175                         throws UnsupportedEncodingException {
176
177                 for (final AbstractFile abstractFile : metadata.getFiles())
178                         if (abstractFile instanceof GeneralFile) {
179
180                                 if (isOgv(abstractFile.getFileExtension()))
181                                         layout.enlistOgv(abstractFile);
182                                 else
183                                         layout.enlistFile(abstractFile);
184
185                         } else if (abstractFile instanceof Picture)
186                                 layout.enlistImage(abstractFile);
187                         else if (abstractFile instanceof DirectoryFile)
188                                 layout.enlistDirectory(abstractFile);
189
190         }
191
192         public void initializeLayouts() {
193
194                 layouts = Utils.getLayouts();
195
196                 final String galleryTitle = commandlineHandler.getGalleryTitle();
197
198                 for (final Layout layout : layouts)
199                         layout.init(galleryTitle, pathElements, this, new IndexingContext(
200                                         "", "."));
201         }
202
203         public void initializeThumbnailsDirectory() {
204                 final File thumbnailsDirectory = Utils
205                                 .getThumbnailsDirectory(directoryToIndex);
206
207                 if (!thumbnailsDirectory.exists())
208                         thumbnailsDirectory.mkdirs();
209         }
210
211         public void loadOrCreateMetadata() {
212                 metadataFile = new File(thumbnailsPath + Constants.METADATA_FILE_NAME);
213
214                 metadata = MetadadaHelper.initDirectoryMetadata(metadataFile);
215         }
216
217         private void removeUnusedThumbnailFiles() {
218
219                 final File thumbnailsDirectory = new File(thumbnailsPath);
220
221                 for (final File file : thumbnailsDirectory.listFiles())
222                         if (!validMetadataFiles.contains(file.getName()))
223                                 file.delete();
224
225         }
226
227         public void updateMetadata() throws IOException, ImageFormatError {
228
229                 final File[] directoryContent = directoryToIndex.listFiles();
230
231                 for (final File file : directoryContent)
232                         if (shallFileBeIndexed(file)) {
233
234                                 metadata.ensureFileMetainfoIsUpToDate(directoryToIndex, file);
235
236                                 if (file.isDirectory())
237                                         new FilesystemIndexer(file, commandlineHandler,
238                                                         getChildPath(file));
239                         }
240         }
241 }