+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012 -- 2019, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 3 of the GNU Lesser General Public License
+ * or later as published by the Free Software Foundation.
+*/
+
+package eu.svjatoslav.meviz.htmlindexer.indexer;
+
+import eu.svjatoslav.commons.file.IOHelper;
+import eu.svjatoslav.meviz.htmlindexer.*;
+import eu.svjatoslav.meviz.htmlindexer.layouts.Layout;
+import eu.svjatoslav.meviz.htmlindexer.metadata.Dimension;
+import eu.svjatoslav.meviz.htmlindexer.metadata.DirectoryMetadata;
+import eu.svjatoslav.meviz.htmlindexer.metadata.MetadadaHelper;
+import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.AbstractFile;
+import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.Picture;
+import org.apache.log4j.Logger;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+
+/**
+ * Main class of HTML indexer.
+ */
+
+public class FilesystemIndexer extends AbstractIndexer {
+
+ private static final Logger logger = Logger
+ .getLogger(FilesystemIndexer.class);
+
+ private final HashSet<String> validMetadataFiles = new HashSet<>();
+
+ private final File directoryToIndex;
+ private final List<String> pathElements;
+ private final CommandlineHandler commandlineHandler;
+ private File metadataFile;
+ private DirectoryMetadata metadata;
+ private HashSet<Layout> layouts;
+
+ public FilesystemIndexer(final File directoryToIndex,
+ final CommandlineHandler commandlineHandler,
+ final List<String> pathElements) throws Exception {
+
+ this.directoryToIndex = directoryToIndex;
+ this.commandlineHandler = commandlineHandler;
+ this.pathElements = pathElements;
+
+ if (!directoryToIndex.canRead())
+ return;
+
+ validMetadataFiles.add(Constants.METADATA_FILE_NAME);
+
+ initializeThumbnailsDirectory();
+ loadOrCreateMetadata();
+
+ initializeLayouts();
+
+ updateMetadata();
+
+ metadata.removeUnusedMetadataEntries();
+
+ generateHtmlFromMetadata(layouts);
+
+ removeUnusedThumbnailFiles();
+
+ // save directory metadata
+ if (metadata.changed)
+ MetadadaHelper.saveDirectoryMetadata(metadataFile, metadata);
+
+ }
+
+ private boolean canWriteIndexFile(final File indexFile)
+ throws IOException {
+
+ return !indexFile.exists() || Utils.isMevizGeneratedIndexFile(indexFile);
+
+ }
+
+ private void generateHtmlFromMetadata(final HashSet<Layout> layouts) {
+ // Generate HTML from metadata
+ for (final Layout layout : layouts)
+ try {
+ final File indexFile = Utils.getLayoutIndexFile(layout,
+ directoryToIndex);
+
+ if (canWriteIndexFile(indexFile)) {
+
+ compileHtml(layout, metadata);
+
+ IOHelper.overwriteFileIfContentDiffers(indexFile, layout
+ .getHtml(true, true, metadata).getBytes());
+ }
+ } catch (final Exception e) {
+ logger.error("Error writing index file. ", e);
+ }
+ }
+
+ private List<String> getChildPath(final File file) {
+
+ final List<String> result = new ArrayList<>();
+ result.addAll(pathElements);
+ result.add(file.getName());
+
+ return result;
+ }
+
+ @Override
+ public String getDirectoryUrl(final AbstractFile directory,
+ final IndexingContext context) {
+ return Utils.urlEncode(directory.fileName) + "/index.html";
+ }
+
+ @Override
+ public String getParentDirectoryUrl(final IndexingContext context) {
+ return "../index.html";
+ }
+
+ @Override
+ public String getThumbnailUrl(final Picture picture,
+ final Dimension desiredDimension, final IndexingContext context) {
+
+ // in case thumbnail size was equal to original, then return original
+ // file path
+ if (picture.getDimensions().equals(desiredDimension))
+ return picture.fileName;
+
+ final String thumbnailFileName = picture
+ .getRelativeThumbnailFileName(desiredDimension);
+
+ validMetadataFiles.add(thumbnailFileName);
+ final File thumbnailFile = new File(
+ Utils.getThumbnailsDirectoryPath(directoryToIndex)
+ + thumbnailFileName);
+
+ if (!thumbnailFile.exists()) {
+
+ final File originalFile = new File(
+ directoryToIndex.getAbsolutePath() + "/" + picture.fileName);
+
+ // generate new thumbnail
+ Picture.makeThumbnail(originalFile, thumbnailFile,
+ desiredDimension.getAwtDimension());
+ }
+ return Constants.THUMBNAILS_DIRECTORY_NAME + "/"
+ + Utils.urlEncode(thumbnailFileName);
+ }
+
+ private void initializeLayouts() {
+
+ layouts = Utils.getLayouts();
+
+ final String galleryTitle = commandlineHandler.getGalleryTitle();
+
+ for (final Layout layout : layouts)
+ layout.init(galleryTitle, pathElements, this, new IndexingContext(
+ "", "."));
+ }
+
+ private void initializeThumbnailsDirectory() {
+ final File thumbnailsDirectory = Utils
+ .getThumbnailsDirectory(directoryToIndex);
+
+ if (!thumbnailsDirectory.exists())
+ thumbnailsDirectory.mkdirs();
+ }
+
+ private void loadOrCreateMetadata() {
+
+ metadataFile = new File(
+ Utils.getThumbnailsDirectoryPath(directoryToIndex)
+ + Constants.METADATA_FILE_NAME);
+
+ metadata = MetadadaHelper.initDirectoryMetadata(metadataFile);
+ }
+
+ private void removeUnusedThumbnailFiles() {
+
+ for (final File file : Utils.getThumbnailsDirectory(directoryToIndex)
+ .listFiles())
+ if (!validMetadataFiles.contains(file.getName()))
+ file.delete();
+
+ }
+
+ private void updateMetadata() throws Exception {
+
+ for (final File file : directoryToIndex.listFiles())
+ if (shallFileBeIndexed(file)) {
+
+ metadata.ensureFileMetadataIsUpToDate(directoryToIndex, file);
+
+ if (file.isDirectory())
+ new FilesystemIndexer(file, commandlineHandler,
+ getChildPath(file));
+ }
+ }
+}