importer.handler.post.ImporterPostHandler.java Source code

Java tutorial

Introduction

Here is the source code for importer.handler.post.ImporterPostHandler.java

Source

/* This file is part of calliope.
 *
 *  calliope 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 2 of the License, or
 *  (at your option) any later version.
 *
 *  calliope 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 calliope.  If not, see <http://www.gnu.org/licenses/>.
 */
package importer.handler.post;

import importer.handler.ImporterHandler;
import calliope.core.exception.DbException;
import importer.exception.PathException;
import calliope.core.Utils;
import importer.constants.Service;
import javax.servlet.http.HttpServletResponse;
import calliope.core.database.Connector;
import calliope.core.constants.*;
import calliope.exception.AeseException;
import calliope.core.database.Connection;
import importer.Archive;
import importer.exception.ImporterException;
import importer.constants.Config;
import importer.constants.Params;
import importer.handler.post.stages.File;
import importer.handler.post.stages.ImageFile;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.io.InputStream;
import java.util.Locale;
import java.util.UUID;
import importer.constants.Filters;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

/**
 * Handle a POST request
 * @author desmond
 */
public class ImporterPostHandler extends ImporterHandler {
    StringBuilder log;
    String style;
    String filterName;
    String database;
    String splitterName;
    String stripperName;
    /** hard hyphen exceptions */
    String hhExceptions;
    boolean similarityTest;
    String dict;
    /** uploaded xslt file contents */
    String xslt;
    boolean demo;
    /** text filter config */
    String textName;
    /** title of work */
    String title;
    HashMap<String, String> nameMap;
    HashMap<String, String> jsonKeys;
    ArrayList<File> files;
    ArrayList<ImageFile> images;
    static String DEFAULT_STYLE = "TEI/default";

    public ImporterPostHandler() {
        nameMap = new HashMap<String, String>();
        jsonKeys = new HashMap<String, String>();
        filterName = Filters.EMPTY;
        dict = Locale.getDefault().toString();
        encoding = "UTF-8";
        stripperName = "default";
        splitterName = "default";
        textName = "default";
        files = new ArrayList<File>();
        images = new ArrayList<ImageFile>();
        log = new StringBuilder();
        similarityTest = false;
        title = "untitled";
    }

    /**
     * Reduce the docid to its first two or three components
     * @param docid the raw docid
     * @param numParts number of components starting from the left
     * @return the reduced docid suitable for a project
     */
    protected String trimDocid(String docid, int numParts) {
        StringBuilder sb = new StringBuilder();
        String[] parts = docid.split("/");
        for (int i = 0; i < numParts; i++) {
            if (sb.length() > 0)
                sb.append("/");
            sb.append(parts[i]);
        }
        return sb.toString();
    }

    /**
     * Add metadata automatically
     * @param version1 the default version of the MVD
     */
    protected void addMetadata(String version1) throws ImporterException {
        try {
            JSONObject docMetadata = new JSONObject();
            JSONObject projectMetadata = null;
            docMetadata.put(JSONKeys.DOCID, docid);
            docMetadata.put(JSONKeys.ENCODING, encoding);
            String section = getSection();
            if (section.length() > 0)
                docMetadata.put(JSONKeys.SECTION, section);
            String subSection = getSubsection();
            if (subSection.length() > 0)
                docMetadata.put(JSONKeys.SUBSECTION, subSection);
            docMetadata.put(JSONKeys.VERSION1, version1);
            // add title 
            String project = Connector.getConnection().getFromDb(Database.PROJECTS, trimDocid(docid, 3));
            if (project == null)
                project = Connector.getConnection().getFromDb(Database.PROJECTS, trimDocid(docid, 2));
            if (project != null) {
                projectMetadata = (JSONObject) JSONValue.parse(project);
                docMetadata.put(JSONKeys.AUTHOR, projectMetadata.get(JSONKeys.AUTHOR));
            } else
                docMetadata.put(JSONKeys.AUTHOR, getAuthor());
            if (projectMetadata != null && projectMetadata.get(JSONKeys.WORK) != null && title.equals("untitled"))
                docMetadata.put(JSONKeys.TITLE, projectMetadata.get(JSONKeys.WORK));
            else
                docMetadata.put(JSONKeys.TITLE, title);
            Connector.getConnection().putToDb(Database.METADATA, docid, docMetadata.toJSONString());
        } catch (Exception e) {
            throw new ImporterException(e);
        }
    }

    /**
     * Add a batch of annotations to the database
     * @param notes an array of annotation objects
     * @param clean if true remove old annotations for this docid
     * @throws AeseException 
     */
    protected void addAnnotations(ArrayList notes, boolean clean) throws ImporterException {
        try {
            Connection conn = Connector.getConnection();
            if (clean) {
                // remove all existing annotations for this document
                String[] docids = conn.listDocuments("annotations", docid + "/.*", JSONKeys.DOCID);
                for (int i = 0; i < docids.length; i++)
                    conn.removeFromDb("annotations", docids[i]);
            }
            // ensure that the annotations are all unique
            HashSet<String> unique = new HashSet<String>();
            String[] docids = conn.listDocuments("annotations", docid + "/.*", JSONKeys.DOCID);
            for (int i = 0; i < docids.length; i++)
                unique.add(docids[i]);
            for (int i = 0; i < notes.size(); i++) {
                String fullId = docid + "/" + UUID.randomUUID().toString();
                while (unique.contains(fullId))
                    fullId = docid + "/" + UUID.randomUUID().toString();
                conn.putToDb("annotations", docid, notes.get(i).toString());
                unique.add(docid);
            }
        } catch (DbException e) {
            throw new ImporterException(e);
        }
    }

    /**
     * Add the archive to the database
     * @param archive the archive
     * @param db cortex or corcode
     * @param suffix the suffix to append
     * @throws ImporterException 
     */
    protected void addToDBase(Archive archive, String db, String suffix) throws ImporterException {
        try {
            // now get the json docs and add them at the right docid
            if (!archive.isEmpty()) {
                String path;
                if (suffix.length() > 0)
                    path = docid + "/" + suffix;
                else
                    path = docid;
                if (db.equals("corcode"))
                    path += "/default";
                Connector.getConnection().putToDb(db, path, archive.toResource(db));
                log.append(archive.getLog());
            } else
                log.append("No " + db + " created (empty)\n");
        } catch (Exception e) {
            throw new ImporterException(e);
        }
    }

    /**
     * Parse the import params from the request
     * @param request the http request
     */
    void parseImportParams(HttpServletRequest request) throws AeseException {
        try {
            FileItemFactory factory = new DiskFileItemFactory();
            // Create a new file upload handler
            ServletFileUpload upload = new ServletFileUpload(factory);
            // Parse the request
            List items = upload.parseRequest(request);
            for (int i = 0; i < items.size(); i++) {
                FileItem item = (FileItem) items.get(i);
                if (item.isFormField()) {
                    String fieldName = item.getFieldName();
                    if (fieldName != null) {
                        String contents = item.getString();
                        if (fieldName.equals(Params.DOCID)) {
                            if (contents.startsWith("/")) {
                                contents = contents.substring(1);
                                int pos = contents.indexOf("/");
                                if (pos != -1) {
                                    database = contents.substring(0, pos);
                                    contents = contents.substring(pos + 1);
                                }
                            }
                            docid = contents;
                        } else if (fieldName.startsWith(Params.SHORT_VERSION))
                            nameMap.put(fieldName.substring(Params.SHORT_VERSION.length()), item.getString());
                        else if (fieldName.equals(Params.LC_STYLE) || fieldName.equals(Params.STYLE)
                                || fieldName.equals(Params.CORFORM)) {
                            jsonKeys.put(fieldName.toLowerCase(), contents);
                            style = contents;
                        } else if (fieldName.equals(Params.DEMO)) {
                            if (contents != null && contents.equals("brillig"))
                                demo = false;
                            else
                                demo = true;
                        } else if (fieldName.equals(Params.TITLE))
                            title = contents;
                        else if (fieldName.equals(Params.FILTER))
                            filterName = contents.toLowerCase();
                        else if (fieldName.equals(Params.SIMILARITY))
                            similarityTest = contents != null && contents.equals("1");
                        else if (fieldName.equals(Params.SPLITTER))
                            splitterName = contents;
                        else if (fieldName.equals(Params.STRIPPER))
                            stripperName = contents;
                        else if (fieldName.equals(Params.TEXT))
                            textName = contents.toLowerCase();
                        else if (fieldName.equals(Params.DICT))
                            dict = contents;
                        else if (fieldName.equals(Params.ENCODING))
                            encoding = contents;
                        else if (fieldName.equals(Params.HH_EXCEPTIONS))
                            hhExceptions = contents;
                        else
                            jsonKeys.put(fieldName, contents);
                    }
                } else if (item.getName().length() > 0) {
                    try {
                        // assuming that the contents are text
                        //item.getName retrieves the ORIGINAL file name
                        String type = item.getContentType();
                        if (type != null && type.startsWith("image/")) {
                            InputStream is = item.getInputStream();
                            ByteHolder bh = new ByteHolder();
                            while (is.available() > 0) {
                                byte[] b = new byte[is.available()];
                                is.read(b);
                                bh.append(b);
                            }
                            ImageFile iFile = new ImageFile(item.getName(), item.getContentType(), bh.getData());
                            images.add(iFile);
                        } else {
                            byte[] rawData = item.get();
                            guessEncoding(rawData);
                            //System.out.println(encoding);
                            File f = new File(item.getName(), new String(rawData, encoding));
                            files.add(f);
                        }
                    } catch (Exception e) {
                        throw new AeseException(e);
                    }
                }
            }
            if (style == null)
                style = DEFAULT_STYLE;
        } catch (Exception e) {
            throw new AeseException(e);
        }
    }

    /**
     * Wrap the log in some HTML
     * @return the wrapped log
     */
    String wrapLog() {
        StringBuilder sb = new StringBuilder();
        sb.append("<html><body>");
        sb.append("<h3>LOG</h3>");
        sb.append("<p class=\"docid\"> DocID: ");
        sb.append(docid);
        sb.append("</p><p class=\"log\">");
        sb.append(log.toString().replace("\n", "<br>"));
        sb.append("</p>");
        sb.append("</body></html>");
        return sb.toString();
    }

    /**
     * Fetch the specified config from the database. If not there, check 
     * for default configs progressively higher up.
     * @param kind the config kind: text, xslt or xml
     * @param path the path to the config
     * @return the loaded config document
     */
    public static String getConfig(Config kind, String path) //throws AeseException
    {
        try {
            String doc = null;
            String configDocId = kind.toString() + "/" + path;
            while (doc == null) {
                doc = Connector.getConnection().getFromDb(Database.CONFIG, configDocId.toLowerCase());
                if (doc == null) {
                    String[] parts = configDocId.split("/");
                    if (parts.length == 1)
                        throw new AeseException("config not found: " + configDocId);
                    else {
                        String oldDocId = configDocId;
                        StringBuilder sb = new StringBuilder();
                        int N = (parts[parts.length - 1].equals(Formats.DEFAULT)) ? 2 : 1;
                        // recurse up the path
                        for (int i = 0; i < parts.length - N; i++) {
                            sb.append(parts[i]);
                            sb.append("/");
                        }
                        if (sb.length() == 0) {
                            sb.append(kind);
                            sb.append("/");
                        }
                        configDocId = sb.toString() + Formats.DEFAULT;
                        if (oldDocId.equals(configDocId))
                            throw new AeseException("config " + oldDocId + " not found");
                    }
                }
            }
            return doc;
        } catch (Exception e) {
            //            AeseException he;
            //            if ( e instanceof AeseException )
            //                he = (AeseException) e ;
            //            else
            //                he = new AeseException( e );
            //            throw he;
            // just return empty config
            return "{}";
        }
    }

    public void handle(HttpServletRequest request, HttpServletResponse response, String urn)
            throws ImporterException {
        String prefix = Utils.first(urn);
        if (prefix != null && prefix.length() > 0) {
            int pos = urn.indexOf(prefix);
            if (urn.length() > pos + prefix.length())
                urn = urn.substring(pos + prefix.length() + 1);
            else
                urn = "";
            if (prefix.equals(Service.LITERAL))
                new UploadHandler().handle(request, response, urn);
            else if (prefix.equals(Service.XML))
                new XMLImportHandler().handle(request, response, urn);
            else if (prefix.equals(Service.HTML))
                new HTMLImportHandler().handle(request, response, urn);
            else if (prefix.equals(Service.TEXT))
                new TextImportHandler().handle(request, response, urn);
            else if (prefix.equals(Service.MIXED))
                new MixedImportHandler().handle(request, response, urn);
            else if (prefix.equals(Service.UPLOAD))
                new UploadHandler().handle(request, response, Utils.pop(urn));
            else
                throw new ImporterException("Unknown service " + prefix);
        } else
            throw new PathException("Invalid urn " + urn);
    }
}