Package de.chris_soft.nanoarchive

Source Code of de.chris_soft.nanoarchive.FileSystemArchive_YYYY_MM_DD

/**
* NanoDoA - File based document archive
*
* Copyright (C) 2011-2012 Christian Packenius, christian.packenius@googlemail.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package de.chris_soft.nanoarchive;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Properties;
import de.chris_soft.utilities.FileUtils;
import de.chris_soft.utilities.FulltextIndexAndSearchUtils;
import de.chris_soft.utilities.LogUtils;

/**
* Archive system that stores documentes as files in the file system.
* @author Christian Packenius.
*/
public class FileSystemArchive_YYYY_MM_DD implements Archive {
  /**
   * Root directory where the document files are stored in sub directories.
   */
  private final File rootDirectory;

  /**
   * Full text index system.
   */
  final FulltextIndexAndSearchUtils fulltextIndex;

  /**
   * Konstruktor.
   * @param rootDirectory Root directory for archiving files.
   * @throws IOException
   */
  public FileSystemArchive_YYYY_MM_DD(File rootDirectory) throws IOException {
    File fulltextIndexDir = new File(rootDirectory, "fulltextIndex");
    checkRootDirectory(rootDirectory, fulltextIndexDir);
    this.rootDirectory = rootDirectory;
    fulltextIndex = new FulltextIndexAndSearchUtils(fulltextIndexDir);
  }

  private void checkRootDirectory(File rootDirectory, File fulltextIndexDir) throws IOException {
    rootDirectory.mkdirs();
    fulltextIndexDir.mkdirs();
    if (!rootDirectory.exists()) {
      throw new IllegalArgumentException("Can't create " + rootDirectory.getCanonicalPath() + " as directory!");
    }
    if (!rootDirectory.isDirectory()) {
      throw new IllegalArgumentException("No directory: " + rootDirectory.getCanonicalPath() + "!");
    }
  }

  /**
   * @see de.chris_soft.nanoarchive.Archive#store(java.io.File, java.lang.String, java.util.Properties)
   */
  @Override
  public String store(File document, String fulltext, Properties metadata) throws IOException {
    String subDirectoryPath = getSubDirectoryPathForDocument(metadata);
    String id = getFileNamesFromDocument(metadata);
    String ext = FileUtils.getFileExtension(document);
    try {
      return storeTripleFiles(document, fulltext, metadata, subDirectoryPath, id, ext);
    } catch (IOException ioe) {
      File dir = getDirectoryFromSubDirPath(subDirectoryPath);
      removeTripleFiles(dir, id, ext);
      throw ioe;
    }
  }

  private String getFileNamesFromDocument(Properties metadata) {
    String name = metadata.getProperty(Metadata.DOCUMENT_ID);
    return name;
  }

  private String storeTripleFiles(File document, String fulltext, Properties metadata, String subDirectoryPath, String id,
      String ext) throws IOException {
    if (ext.equals("fulltext") || ext.equals("metadata")) {
      throw new IllegalArgumentException("File to be archived must not have extension .fulltext or .metadata!");
    }
    File dir = getDirectoryFromSubDirPath(subDirectoryPath);
    File archivedFile = new File(dir, id + "." + ext);
    FileUtils.copyFile(document, archivedFile);
    if (document.length() != archivedFile.length()) {
      String docPath = document.getCanonicalPath();
      String afPath = archivedFile.getCanonicalPath();
      String errmsg = docPath + " could not be stored as " + afPath + "!";
      throw new IOException(errmsg);
    }
    createFulltextIndex(fulltext, subDirectoryPath, id);
    FileUtils.storeProperties(new File(dir, id + ".metadata"), metadata);
    return archivedFile.getCanonicalPath();
  }

  private void createFulltextIndex(String fulltext, String subDirectoryPath, String id) throws IOException {
    // FileUtils.storeStringInFile(new File(dir, id + ".fulltext"), fulltext);
    fulltextIndex.add(subDirectoryPath + "/" + id, fulltext);
  }

  private void removeTripleFiles(File dir, String id, String ext) {
    FileUtils.deleteFile(new File(dir, id + "." + ext));
    FileUtils.deleteFile(new File(dir, id + ".fulltext"));
    FileUtils.deleteFile(new File(dir, id + ".metadata"));
  }

  private String getSubDirectoryPathForDocument(Properties metadata) {
    String docID = metadata.getProperty(Metadata.DOCUMENT_ID);
    docID = docID.replace("-", "");
    long longDocID = Long.parseLong(docID);
    return getSubDirectoryPathFromUniqueDocID(longDocID);
  }

  private String getSubDirectoryPathFromUniqueDocID(long uniqueDocID) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
    GregorianCalendar gc = new GregorianCalendar();
    gc.setTimeInMillis(uniqueDocID);
    String subDirectoryPath = sdf.format(gc.getTime());
    return subDirectoryPath;
  }

  private File getDirectoryFromSubDirPath(String subDirectoryPath) {
    subDirectoryPath = subDirectoryPath.replace('\\', '/');
    File dir = rootDirectory;
    while (!subDirectoryPath.isEmpty()) {
      int k = subDirectoryPath.indexOf('/');
      final String subDirName;
      if (k >= 0) {
        subDirName = subDirectoryPath.substring(0, k);
        subDirectoryPath = subDirectoryPath.substring(k + 1);
      }
      else {
        subDirName = subDirectoryPath;
        subDirectoryPath = "";
      }
      if (!subDirName.isEmpty()) {
        dir = new File(dir, subDirName);
      }
    }
    dir.mkdirs();
    return dir;
  }

  /**
   * @see de.chris_soft.nanoarchive.Archive#getRootDirectories()
   */
  @Override
  public List<String> getRootDirectories() {
    return FileUtils.getDirectoryNames(rootDirectory);
  }

  /**
   * @see de.chris_soft.nanoarchive.Archive#getDirectories(java.lang.String)
   */
  @Override
  public List<String> getDirectories(String parentSubDirName) {
    return FileUtils.getDirectoryNames(getDirectoryFromSubDirPath(parentSubDirName));
  }

  /**
   * @see de.chris_soft.nanoarchive.Archive#getFilesFromSubDirectory(java.lang.String)
   */
  @Override
  public List<String> getFilesFromSubDirectory(String subDirectoryPath) {
    return FileUtils.getFileNames(getDirectoryFromSubDirPath(subDirectoryPath));
  }

  /**
   * @see de.chris_soft.nanoarchive.Archive#getName()
   */
  @Override
  public String getName() throws IOException {
    return getClass().getSimpleName() + "::" + rootDirectory.getCanonicalPath();
  }

  /**
   * @see de.chris_soft.nanoarchive.Archive#documentSearch(java.lang.String, de.chris_soft.nanoarchive.DocumentFoundListener)
   */
  @Override
  public void documentSearch(final String searchTerm, final DocumentFoundListener listener) {
    final Archive archive = this;
    new Thread(new Runnable() {
      @Override
      public void run() {
        DocumentSearch search = new DocumentSearch(searchTerm, fulltextIndex, archive);
        try {
          search.searchDocuments(listener);
        } catch (Exception exception) {
          LogUtils.log(exception);
        }
      }
    }).start();
  }

  /**
   * @see de.chris_soft.nanoarchive.Archive#getMetadataFromDocID(java.lang.String)
   */
  @Override
  public Properties getMetadataFromDocID(String docID) {
    try {
      File file = getMetadataFileFromDocumentID(docID);
      return FileUtils.loadProperties(file);
    } catch (IOException exception) {
      LogUtils.log(exception);
      return new Properties();
    }
  }

  private File getMetadataFileFromDocumentID(String docID) {
    return new File(getDocumentBaseNameViaDocID(docID) + ".metadata");
  }

  private File getPdfFileFromDocumentID(String docID) {
    return new File(getDocumentBaseNameViaDocID(docID) + ".pdf");
  }

  /**
   * @see de.chris_soft.nanoarchive.Archive#getDocumentFileFromDocID(java.lang.String)
   */
  @Override
  public File getDocumentFileFromDocID(String docID) {
    return getPdfFileFromDocumentID(docID);
  }

  /**
   * @throws IOException
   * @see de.chris_soft.nanoarchive.Archive#deleteDocumentById(java.lang.String)
   */
  @Override
  public void deleteDocumentById(String documentID) throws IOException {
    FileUtils.deleteFile(getPdfFileFromDocumentID(documentID));
    FileUtils.deleteFile(getMetadataFileFromDocumentID(documentID));
    fulltextIndex.remove(documentID);
  }

  /**
   * @see de.chris_soft.nanoarchive.Archive#putMetadataViaDocID(java.lang.String, java.lang.String, java.lang.String)
   */
  @Override
  public void putMetadataViaDocID(String docID, String key, String value) throws IOException {
    Properties metadata = getMetadataFromDocID(docID);
    if (metadata != null) {
      metadata.setProperty(key, value);
      File file = getMetadataFileFromDocumentID(docID);
      FileUtils.storeProperties(file, metadata);
    }
  }

  private String getDocumentBaseNameViaDocID(String docID) {
    docID = docID.replace('\\', '/');
    int k = docID.lastIndexOf('/');
    if (k >= 0) {
      docID = docID.substring(k + 1);
    }
    k = docID.lastIndexOf('.');
    if (k >= 0) {
      docID = docID.substring(0, k);
    }
    long uniqueDocID = Long.parseLong(docID.replace("-", ""));
    String subDir = getSubDirectoryPathFromUniqueDocID(uniqueDocID);
    docID = subDir + "/" + docID;
    return rootDirectory.getAbsolutePath() + "/" + docID;
  }
}
TOP

Related Classes of de.chris_soft.nanoarchive.FileSystemArchive_YYYY_MM_DD

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.