All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mycore.datamodel.ifs2.MCRStoreBrowserServlet Maven / Gradle / Ivy

There is a newer version: 2024.05
Show newest version
/*
 * This file is part of ***  M y C o R e  ***
 * See http://www.mycore.de/ for details.
 *
 * MyCoRe 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
 * (at your option) any later version.
 *
 * MyCoRe 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 MyCoRe.  If not, see .
 */

package org.mycore.datamodel.ifs2;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;

import org.jdom2.Document;
import org.jdom2.Element;
import org.mycore.common.content.MCRJDOMContent;
import org.mycore.datamodel.common.MCRXMLMetadataManager;
import org.mycore.frontend.servlets.MCRServlet;
import org.mycore.frontend.servlets.MCRServletJob;

/**
 * Browses the hierarchical structure of any MCRMetadataStore to allow
 * robots access to all metadata. The XML output is rendered to HTML
 * using storeBrowser.xsl. 
 * 
 * Some usage examples:
 * http://localhost:8291/storeBrowser/DocPortal_author/index.html
 * http://localhost:8291/storeBrowser/DocPortal_author/0041/09/index.html
 * 
 * The first path fragment following the servlet mapping storeBrowser/ 
 * must be the ID of the IFS2 metadata store, which is same as the
 * MCRObjectID base.
 * 
 * @author Frank L\u00FCtzenkirchen
 */
public class MCRStoreBrowserServlet extends MCRServlet {

    private static final long serialVersionUID = 1L;

    @Override
    protected void doGetPost(MCRServletJob job) throws Exception {
        String pathInfo = job.getRequest().getPathInfo();

        MCRStoreBrowserRequest sbr = new MCRStoreBrowserRequest(pathInfo);
        Document xml = sbr.buildResponseXML();

        getLayoutService().doLayout(job.getRequest(), job.getResponse(), new MCRJDOMContent(xml));
    }
}

class MCRStoreBrowserRequest {

    /** The slot path elements given from request, for example /0041/09/ */
    private List pathElements = new ArrayList<>();

    /** The store thats contents should be browsed */
    private MCRMetadataStore store;

    MCRStoreBrowserRequest(String pathInfo) throws Exception {
        StringTokenizer tokenizer = new StringTokenizer(pathInfo, "/");

        String storeID = tokenizer.nextToken();
        getStore(storeID);

        while (tokenizer.countTokens() > 1) {
            pathElements.add(tokenizer.nextToken());
        }
    }

    /** Gets the MCRMetadataStore for the given storeID */
    private void getStore(String storeID) throws Exception {
        if (storeID.contains("_")) {
            store = MCRXMLMetadataManager.instance().getStore(storeID);
        }
        // TODO: the store can never be null, instead an MCRPersistenceException is thrown
        if (store == null) {
            store = MCRStoreManager.getStore(storeID);
            if (store == null) {
                store = MCRStoreManager.createStore(storeID, MCRMetadataStore.class);
            }
        }
    }

    /** Builds the xml output to be rendered as response */
    Document buildResponseXML() throws Exception {
        File dir = getRequestedDirectory();

        String[] children = dir.list();
        Element xml = new Element("storeBrowser");
        if (children != null) {
            for (String child : children) {
                xml.addContent(buildXML(child));
            }
        }

        return new Document(xml);
    }

    /** 
     * Builds the xml output for a single child slot or object below the current browse level
     * 
     * @param child the file name of the slot directory or object metadata file in store
     */
    private Element buildXML(String child) throws Exception {
        return childIsSlot(child) ? buildSlotXML(child) : buildObjectXML(child);
    }

    /** 
     * Builds the xml output of a single object below the current slot directory to browse
     * 
     * @param child the file name of the object metadata file in store
     */
    private Element buildObjectXML(String child) throws IOException {
        String objectID = child.replace(".xml", "");
        int id = store.slot2id(child);
        String lastModified = getLastModifiedDate(id);

        Element xml = new Element("object");
        xml.setAttribute("id", objectID);
        xml.setAttribute("lastModified", lastModified);
        return xml;
    }

    /** 
     * Builds the xml output of a single child slot directory below the current slot to browse
     * 
     * @param slot the file name of the slot directory in store
     */
    private Element buildSlotXML(String slot) {
        Element xml = new Element("slot");
        xml.setAttribute("from", buildMinimumIDContained(slot));
        xml.setAttribute("path", slot);
        return xml;
    }

    /**
     * Returns the date of last modification for the given object id in store. 
     */
    private String getLastModifiedDate(int id) throws IOException {
        Date lastModified = store.retrieve(id).getLastModified();
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ROOT).format(lastModified);
    }

    /**
     * Returns the minimum ID of any object that can be stored below
     * the given slot directory.
     */
    private String buildMinimumIDContained(String slot) {
        StringBuilder sb = new StringBuilder();

        for (String token : pathElements) {
            sb.append(token);
        }
        sb.append(slot);

        while (sb.length() < store.getIDLength()) {
            sb.append("0");
        }

        int id = Integer.parseInt(sb.toString());
        id = Math.max(id, 1); // Minimum possible ID is 1, not 0
        return String.valueOf(id);
    }

    /**
     * Checks if the given file name represents a slot directory
     * 
     * @return true, if this is a slot directory, false if it is a object metadata file
     */
    private boolean childIsSlot(String child) {
        return child.length() < store.getIDLength();
    }

    /** Returns the directory in filesystem the requested slot path is mapped to in the store */
    private File getRequestedDirectory() {
        File dir = getBaseDir();
        for (String token : pathElements) {
            dir = new File(dir, token);
        }
        return dir;
    }

    /** Returns the base directory in the local filesystem the store to be browsed uses */
    private File getBaseDir() {
        return new File(store.getStoreConfig().getBaseDir());
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy