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