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