075186edf0c4e79556814cf9c907410ee891da13
[meviz.git] / src / main / java / eu / svjatoslav / meviz / htmlindexer / indexer / FilesystemIndexer.java
1 /*
2  * Meviz - Various tools collection to work with multimedia. Author: Svjatoslav Agejenko.
3  * This project is released under Creative Commons Zero (CC0) license.
4  */
5
6
7 package eu.svjatoslav.meviz.htmlindexer.indexer;
8
9 import eu.svjatoslav.commons.file.IOHelper;
10 import eu.svjatoslav.meviz.htmlindexer.*;
11 import eu.svjatoslav.meviz.htmlindexer.layouts.Layout;
12 import eu.svjatoslav.meviz.htmlindexer.metadata.Dimension;
13 import eu.svjatoslav.meviz.htmlindexer.metadata.DirectoryMetadata;
14 import eu.svjatoslav.meviz.htmlindexer.metadata.MetadadaHelper;
15 import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.AbstractFile;
16 import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.Picture;
17 import org.apache.log4j.Logger;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.util.ArrayList;
22 import java.util.HashSet;
23 import java.util.List;
24
25 import static eu.svjatoslav.meviz.htmlindexer.Constants.THUMBNAILS_DIRECTORY_NAME;
26 import static eu.svjatoslav.meviz.htmlindexer.Utils.getThumbnailsDirectoryPath;
27 import static eu.svjatoslav.meviz.htmlindexer.Utils.urlEncode;
28 import static eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.Picture.makeThumbnail;
29
30 /**
31  * Main class of HTML indexer.
32  */
33
34 public class FilesystemIndexer extends AbstractIndexer {
35
36     private static final Logger logger = Logger
37             .getLogger(FilesystemIndexer.class);
38
39     private final HashSet<String> validMetadataFiles = new HashSet<>();
40
41     private final File directoryToIndex;
42     private final List<String> pathElements;
43     private final CommandlineHandler commandlineHandler;
44     private File metadataFile;
45     private DirectoryMetadata metadata;
46     private HashSet<Layout> layouts;
47
48     public FilesystemIndexer(final File directoryToIndex,
49                              final CommandlineHandler commandlineHandler,
50                              final List<String> pathElements) throws Exception {
51
52         this.directoryToIndex = directoryToIndex;
53         this.commandlineHandler = commandlineHandler;
54         this.pathElements = pathElements;
55
56         if (!directoryToIndex.canRead())
57             return;
58
59         validMetadataFiles.add(Constants.METADATA_FILE_NAME);
60
61         initializeThumbnailsDirectory();
62         loadOrCreateMetadata();
63
64         initializeLayouts();
65
66         updateMetadata();
67
68         metadata.removeUnusedMetadataEntries();
69
70         generateHtmlFromMetadata(layouts);
71
72         removeUnusedThumbnailFiles();
73
74         // save directory metadata
75         if (metadata.changed)
76             MetadadaHelper.saveDirectoryMetadata(metadataFile, metadata);
77
78     }
79
80     private boolean canWriteIndexFile(final File indexFile)
81             throws IOException {
82
83         return !indexFile.exists() || Utils.isMevizGeneratedIndexFile(indexFile);
84
85     }
86
87     private void generateHtmlFromMetadata(final HashSet<Layout> layouts) {
88         for (final Layout layout : layouts)
89             try {
90                 final File indexFile = Utils.getLayoutIndexFile(layout,
91                         directoryToIndex);
92
93                 if (canWriteIndexFile(indexFile)) {
94
95                     compileHtml(layout, metadata);
96
97                     IOHelper.overwriteFileIfContentDiffers(indexFile, layout
98                             .getHtml(true, true, metadata).getBytes());
99                 }
100             } catch (final Exception e) {
101                 logger.error("Error writing index file. ", e);
102             }
103     }
104
105     private List<String> getChildPath(final File file) {
106
107         final List<String> result = new ArrayList<>();
108         result.addAll(pathElements);
109         result.add(file.getName());
110
111         return result;
112     }
113
114     @Override
115     public String getDirectoryUrl(final AbstractFile directory,
116                                   final IndexingContext context) {
117         return urlEncode(directory.fileName) + "/index.html";
118     }
119
120     @Override
121     public String getParentDirectoryUrl(final IndexingContext context) {
122         return "../index.html";
123     }
124
125     @Override
126     public String getThumbnailUrl(final Picture picture,
127                                   final Dimension desiredDimension, final IndexingContext context) {
128
129         // in case thumbnail size was equal to original, then return original
130         // file path
131         if (picture.getDimensions().equals(desiredDimension))
132             return picture.fileName;
133
134         final String thumbnailFileName = picture
135                 .getRelativeThumbnailFileName(desiredDimension);
136
137         validMetadataFiles.add(thumbnailFileName);
138         final File thumbnailFile = new File(
139                 getThumbnailsDirectoryPath(directoryToIndex) + thumbnailFileName);
140
141         if (!thumbnailFile.exists()) {
142
143             final File originalFile = new File(
144                     directoryToIndex.getAbsolutePath() + "/" + picture.fileName);
145
146             makeThumbnail(originalFile, thumbnailFile, desiredDimension.getAwtDimension());
147         }
148         return THUMBNAILS_DIRECTORY_NAME + "/" + urlEncode(thumbnailFileName);
149     }
150
151     private void initializeLayouts() {
152
153         layouts = Utils.getLayouts();
154
155         final String galleryTitle = commandlineHandler.getGalleryTitle();
156
157         for (final Layout layout : layouts)
158             layout.init(galleryTitle, pathElements, this, new IndexingContext(
159                     "", "."));
160     }
161
162     private void initializeThumbnailsDirectory() {
163         final File thumbnailsDirectory = Utils
164                 .getThumbnailsDirectory(directoryToIndex);
165
166         if (!thumbnailsDirectory.exists())
167             thumbnailsDirectory.mkdirs();
168     }
169
170     private void loadOrCreateMetadata() {
171
172         metadataFile = new File(
173                 getThumbnailsDirectoryPath(directoryToIndex)
174                         + Constants.METADATA_FILE_NAME);
175
176         metadata = MetadadaHelper.initDirectoryMetadata(metadataFile);
177     }
178
179     private void removeUnusedThumbnailFiles() {
180
181         for (final File file : Utils.getThumbnailsDirectory(directoryToIndex)
182                 .listFiles())
183             if (!validMetadataFiles.contains(file.getName()))
184                 file.delete();
185
186     }
187
188     private void updateMetadata() throws Exception {
189
190         for (final File file : directoryToIndex.listFiles())
191             if (shallFileBeIndexed(file)) {
192
193                 metadata.ensureFileMetadataIsUpToDate(directoryToIndex, file);
194
195                 if (file.isDirectory())
196                     new FilesystemIndexer(file, commandlineHandler,
197                             getChildPath(file));
198             }
199     }
200 }