better error handling
[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 File metadataFile;
46
47         private DirectoryMetadata metadata;
48
49         private final List<String> pathElements;
50
51         private HashSet<Layout> layouts;
52
53         private final CommandlineHandler commandlineHandler;
54
55         public FilesystemIndexer(final File directoryToIndex,
56                         final CommandlineHandler commandlineHandler,
57                         final List<String> pathElements) throws Exception {
58
59                 this.directoryToIndex = directoryToIndex;
60                 this.commandlineHandler = commandlineHandler;
61                 this.pathElements = pathElements;
62
63                 if (!directoryToIndex.canRead())
64                         return;
65
66                 validMetadataFiles.add(Constants.METADATA_FILE_NAME);
67
68                 initializeThumbnailsDirectory();
69                 loadOrCreateMetadata();
70
71                 initializeLayouts();
72
73                 updateMetadata();
74
75                 metadata.removeUnusedMetadataEntries();
76
77                 generateHtmlFromMetadata(layouts);
78
79                 removeUnusedThumbnailFiles();
80
81                 // save directory metadata
82                 if (metadata.changed)
83                         MetadadaHelper.saveDirectoryMetadata(metadataFile, metadata);
84
85         }
86
87         public boolean canWriteIndexFile(final File indexFile)
88                         throws FileNotFoundException, IOException {
89
90                 if (!indexFile.exists())
91                         return true;
92
93                 return Utils.isMevizGeneratedIndexFile(indexFile);
94         }
95
96         public void generateHtmlFromMetadata(final HashSet<Layout> layouts) {
97                 // Generate HTML from metadata
98                 for (final Layout layout : layouts)
99                         try {
100                                 final File indexFile = Utils.getLayoutIndexFile(layout,
101                                                 directoryToIndex);
102
103                                 if (canWriteIndexFile(indexFile)) {
104
105                                         indexForLayout(layout);
106
107                                         IOHelper.overwriteFileIfContentDiffers(indexFile, layout
108                                                         .getHtml(true, true).getBytes());
109                                 }
110                         } catch (final Exception e) {
111                                 logger.error("Error writing index file. ", e);
112                         }
113         }
114
115         public List<String> getChildPath(final File file) {
116
117                 final List<String> result = new ArrayList<String>();
118                 result.addAll(pathElements);
119                 result.add(file.getName());
120
121                 return result;
122         }
123
124         @Override
125         public String getDirectoryUrl(final AbstractFile directory,
126                         final IndexingContext context) {
127                 return directory.fileName + "/index.html";
128         }
129
130         @Override
131         public String getParentDirectoryUrl(final IndexingContext context) {
132                 return "../index.html";
133         }
134
135         @Override
136         public String getThumbnailUrl(final Picture picture,
137                         final Dimension desiredDimension, final IndexingContext context) {
138
139                 // in case thumbnail size was equal to original, then return original
140                 // file path
141                 if (picture.getDimensions().equals(desiredDimension))
142                         return picture.fileName;
143
144                 final String thumbnailFileName = picture
145                                 .getRelativeThumbnailFileName(desiredDimension);
146
147                 validMetadataFiles.add(thumbnailFileName);
148                 final File thumbnailFile = new File(
149                                 Utils.getThumbnailsDirectoryPath(directoryToIndex)
150                                 + thumbnailFileName);
151
152                 if (!thumbnailFile.exists()) {
153
154                         final File originalFile = new File(
155                                         directoryToIndex.getAbsolutePath() + "/" + picture.fileName);
156
157                         // generate new thumbnail
158                         Picture.makeThumbnail(originalFile, thumbnailFile,
159                                         desiredDimension.getAwtDimension());
160                 }
161                 return Constants.THUMBNAILS_DIRECTORY_NAME + "/"
162                 + UrlParamEncoder.encode(thumbnailFileName);
163         }
164
165         public void indexForLayout(final Layout layout)
166                         throws UnsupportedEncodingException {
167
168                 for (final AbstractFile abstractFile : metadata.getFiles())
169                         if (abstractFile instanceof GeneralFile) {
170
171                                 if (isOgv(abstractFile.getFileExtension()))
172                                         layout.enlistOgv(abstractFile);
173                                 else
174                                         layout.enlistFile(abstractFile);
175
176                         } else if (abstractFile instanceof Picture)
177                                 layout.enlistImage((Picture) abstractFile);
178                         else if (abstractFile instanceof DirectoryFile)
179                                 layout.enlistDirectory(abstractFile);
180
181         }
182
183         public void initializeLayouts() {
184
185                 layouts = Utils.getLayouts();
186
187                 final String galleryTitle = commandlineHandler.getGalleryTitle();
188
189                 for (final Layout layout : layouts)
190                         layout.init(galleryTitle, pathElements, this, new IndexingContext(
191                                         "", "."));
192         }
193
194         public void initializeThumbnailsDirectory() {
195                 final File thumbnailsDirectory = Utils
196                                 .getThumbnailsDirectory(directoryToIndex);
197
198                 if (!thumbnailsDirectory.exists())
199                         thumbnailsDirectory.mkdirs();
200         }
201
202         public void loadOrCreateMetadata() {
203
204                 metadataFile = new File(
205                                 Utils.getThumbnailsDirectoryPath(directoryToIndex)
206                                 + Constants.METADATA_FILE_NAME);
207
208                 metadata = MetadadaHelper.initDirectoryMetadata(metadataFile);
209         }
210
211         private void removeUnusedThumbnailFiles() {
212
213                 for (final File file : Utils.getThumbnailsDirectory(directoryToIndex)
214                                 .listFiles())
215                         if (!validMetadataFiles.contains(file.getName()))
216                                 file.delete();
217
218         }
219
220         public void updateMetadata() throws Exception {
221
222                 for (final File file : directoryToIndex.listFiles())
223                         if (shallFileBeIndexed(file)) {
224
225                                 metadata.ensureFileMetainfoIsUpToDate(directoryToIndex, file);
226
227                                 if (file.isDirectory())
228                                         new FilesystemIndexer(file, commandlineHandler,
229                                                         getChildPath(file));
230                         }
231         }
232 }