Code refactoring
[meviz.git] / src / main / java / eu / svjatoslav / meviz / htmlindexer / indexer / 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.indexer;
11
12 import eu.svjatoslav.commons.file.IOHelper;
13 import eu.svjatoslav.meviz.htmlindexer.*;
14 import eu.svjatoslav.meviz.htmlindexer.layouts.Layout;
15 import eu.svjatoslav.meviz.htmlindexer.metadata.Dimension;
16 import eu.svjatoslav.meviz.htmlindexer.metadata.DirectoryMetadata;
17 import eu.svjatoslav.meviz.htmlindexer.metadata.MetadadaHelper;
18 import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.AbstractFile;
19 import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.Picture;
20 import org.apache.log4j.Logger;
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.HashSet;
26 import java.util.List;
27
28 /**
29  * Main class of HTML indexer.
30  */
31
32 public class FilesystemIndexer extends AbstractIndexer {
33
34     private static final Logger logger = Logger
35             .getLogger(FilesystemIndexer.class);
36
37     private final HashSet<String> validMetadataFiles = new HashSet<>();
38
39     private final File directoryToIndex;
40     private final List<String> pathElements;
41     private final CommandlineHandler commandlineHandler;
42     private File metadataFile;
43     private DirectoryMetadata metadata;
44     private HashSet<Layout> layouts;
45
46     public FilesystemIndexer(final File directoryToIndex,
47                              final CommandlineHandler commandlineHandler,
48                              final List<String> pathElements) throws Exception {
49
50         this.directoryToIndex = directoryToIndex;
51         this.commandlineHandler = commandlineHandler;
52         this.pathElements = pathElements;
53
54         if (!directoryToIndex.canRead())
55             return;
56
57         validMetadataFiles.add(Constants.METADATA_FILE_NAME);
58
59         initializeThumbnailsDirectory();
60         loadOrCreateMetadata();
61
62         initializeLayouts();
63
64         updateMetadata();
65
66         metadata.removeUnusedMetadataEntries();
67
68         generateHtmlFromMetadata(layouts);
69
70         removeUnusedThumbnailFiles();
71
72         // save directory metadata
73         if (metadata.changed)
74             MetadadaHelper.saveDirectoryMetadata(metadataFile, metadata);
75
76     }
77
78     private boolean canWriteIndexFile(final File indexFile)
79             throws IOException {
80
81         return !indexFile.exists() || Utils.isMevizGeneratedIndexFile(indexFile);
82
83     }
84
85     private void generateHtmlFromMetadata(final HashSet<Layout> layouts) {
86         // Generate HTML from metadata
87         for (final Layout layout : layouts)
88             try {
89                 final File indexFile = Utils.getLayoutIndexFile(layout,
90                         directoryToIndex);
91
92                 if (canWriteIndexFile(indexFile)) {
93
94                     compileHtml(layout, metadata);
95
96                     IOHelper.overwriteFileIfContentDiffers(indexFile, layout
97                             .getHtml(true, true, metadata).getBytes());
98                 }
99             } catch (final Exception e) {
100                 logger.error("Error writing index file. ", e);
101             }
102     }
103
104     private List<String> getChildPath(final File file) {
105
106         final List<String> result = new ArrayList<>();
107         result.addAll(pathElements);
108         result.add(file.getName());
109
110         return result;
111     }
112
113     @Override
114     public String getDirectoryUrl(final AbstractFile directory,
115                                   final IndexingContext context) {
116         return Utils.urlEncode(directory.fileName) + "/index.html";
117     }
118
119     @Override
120     public String getParentDirectoryUrl(final IndexingContext context) {
121         return "../index.html";
122     }
123
124     @Override
125     public String getThumbnailUrl(final Picture picture,
126                                   final Dimension desiredDimension, final IndexingContext context) {
127
128         // in case thumbnail size was equal to original, then return original
129         // file path
130         if (picture.getDimensions().equals(desiredDimension))
131             return picture.fileName;
132
133         final String thumbnailFileName = picture
134                 .getRelativeThumbnailFileName(desiredDimension);
135
136         validMetadataFiles.add(thumbnailFileName);
137         final File thumbnailFile = new File(
138                 Utils.getThumbnailsDirectoryPath(directoryToIndex)
139                         + thumbnailFileName);
140
141         if (!thumbnailFile.exists()) {
142
143             final File originalFile = new File(
144                     directoryToIndex.getAbsolutePath() + "/" + picture.fileName);
145
146             // generate new thumbnail
147             Picture.makeThumbnail(originalFile, thumbnailFile,
148                     desiredDimension.getAwtDimension());
149         }
150         return Constants.THUMBNAILS_DIRECTORY_NAME + "/"
151                 + Utils.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                 Utils.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 }