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