importer.Archive.java Source code

Java tutorial

Introduction

Here is the source code for importer.Archive.java

Source

/*
 * This file is part of Importer.
 *
 *  Importer 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.
 *
 *  Importer 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 Importer.  If not, see <http://www.gnu.org/licenses/>.
 *  (c) copyright Desmond Schmidt 2015
 */

package importer;

import calliope.core.constants.Database;
import java.io.File;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import calliope.core.constants.JSONKeys;
import calliope.core.constants.Formats;
import calliope.core.database.Connector;
import calliope.exception.AeseException;
import importer.exception.ImporterException;
import edu.luc.nmerge.mvd.MVD;
import edu.luc.nmerge.mvd.Version;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.json.simple.JSONArray;

/**
 * A set of CorCode or CorTex files, each a version of the same work, 
 * indexed by the group-path/shortname separated by "/"
 * @author desmond
 */
public class Archive extends HashMap<String, char[]> {
    String author;
    String title;
    String description;
    StringBuilder log;
    String style;
    String version1;
    String format;
    String encoding;
    HashMap<String, String> nameMap;
    static HashMap<String, String> humanKeyMap;
    static {
        humanKeyMap = new HashMap<String, String>();
        humanKeyMap.put("add0", "level 1 addition");
        humanKeyMap.put("del1", "level 2 deletion");
        humanKeyMap.put("del2", "level 3 deletion");
        humanKeyMap.put("add1", "level 2 addition");
        humanKeyMap.put("del3", "level 4 deletion");
        humanKeyMap.put("add2", "level 3 addition");
        humanKeyMap.put("rdg1", "layer 2");
        humanKeyMap.put("rdg2", "layer 3");
    }

    /**
     * Create an archive
     * @param title the title of the work
     * @param author the full author's name
     * @param format the format (changes to MVD if more than 1 version)
     * @param encoding defaults to UTF-8
     */
    public Archive(String title, String author, String format, String encoding) {
        this.title = title;
        this.author = author;
        this.log = new StringBuilder();
        this.style = "default";
        this.nameMap = new HashMap<String, String>();
        this.format = format;
        this.encoding = (encoding == null) ? "UTF-8" : encoding;
        StringBuilder sb = new StringBuilder(title);
        description = sb.toString();
    }

    public String getEncoding() {
        return this.encoding;
    }

    /**
     * Only works after resource has been written
     * @return the default version
     */
    public String getVersion1() {
        return this.version1;
    }

    /**
     * Add a long name to our map for later use
     * @param key the groups+version short name key
     * @param longName its long name
     */
    public void addLongName(String key, String longName) {
        nameMap.put(key, longName);
    }

    /**
     * Using the project version info set long names for each short name
     * @param docid the project docid
     * @throws ImporterException 
     */
    public void setVersionInfo(String docid) throws ImporterException {
        try {
            String project = Connector.getConnection().getFromDb(Database.PROJECTS, docid);
            if (project == null) {
                String[] parts = docid.split("/");
                if (parts.length == 3)
                    docid = parts[0] + "/" + parts[1];
                else
                    throw new Exception("Couldn't find project " + docid);
                project = Connector.getConnection().getFromDb(Database.PROJECTS, docid);
                if (project == null)
                    throw new Exception("Couldn't find project " + docid);
            }
            JSONObject jObj = (JSONObject) JSONValue.parse(project);
            if (jObj.containsKey(JSONKeys.VERSIONS)) {
                JSONArray versions = (JSONArray) jObj.get(JSONKeys.VERSIONS);
                for (int i = 0; i < versions.size(); i++) {
                    JSONObject version = (JSONObject) versions.get(i);
                    Set<String> keys = version.keySet();
                    Iterator<String> iter = keys.iterator();
                    while (iter.hasNext()) {
                        String key = iter.next();
                        nameMap.put(key, (String) version.get(key));
                    }
                }
            }
        } catch (Exception e) {
            throw new ImporterException(e);
        }
    }

    public void setStyle(String style) {
        this.style = style;
    }

    /**
     * Get the log report of this archive's merging activities
     * @return a string
     */
    public String getLog() {
        return log.toString();
    }

    /**
     * Split off the groups path if any
     * @param key the groups+short name separated by slashes
     * @return the groups name
     */
    private String getGroups(String key) {
        String[] parts = key.split("/");
        String groups = "";
        for (int i = 0; i < parts.length - 1; i++) {
            groups = parts[i];
            if (i < parts.length - 2)
                groups += "/";
        }
        return groups;
    }

    /**
     * Get the short name from a compound groups+short name
     * @param key the compound key
     * @return the bare short name at the end
     */
    private String getKey(String key) {
        String[] parts = key.split("/");
        key = parts[parts.length - 1];
        return key;
    }

    /** 
     * Convert the cryptic "add0" "del1" names into something intelligible
     * @param key the cryptic key
     * @return the human-readable version
     */
    private String translateKey(String key) {
        if (humanKeyMap.containsKey(key))
            return humanKeyMap.get(key);
        else
            return key;
    }

    /**
     * Try various ways to get the long name for the siglum
     * @param shortKey the version siglim
     * @return the long name of the version
     */
    String getLongName(String shortKey) {
        String longName = translateKey(shortKey);
        if (!longName.equals(shortKey))
            return longName;
        else if (nameMap.containsKey(shortKey))
            return nameMap.get(shortKey);
        else
            return "Version " + shortKey;
    }

    /**
     * Convert this archive to a resource, wrapped in JSON for storage
     * @param mvdName name of the MVD
     * @return a string representation of the MVD as a JSON document
     * @throws AeseException 
     */
    public String toResource(String mvdName) throws AeseException {
        try {
            String body;
            JSONObject doc = new JSONObject();
            if (size() == 1) {
                Set<String> keys = keySet();
                Iterator<String> iter = keys.iterator();
                String key = iter.next();
                char[] data = get(key);
                if (format.equals(Formats.MVD_STIL))
                    format = Formats.STIL;
                else if (format.equals(Formats.MVD_TEXT))
                    format = Formats.TEXT;
                body = new String(data);
                if (version1 == null)
                    version1 = key;
            } else {
                // more than 1 version: make an MVD 
                Set<String> keys = keySet();
                Iterator<String> iter = keys.iterator();
                MVD mvd = new MVD();
                mvd.setDescription(description);
                // go through the files, adding versions to the MVD
                short vId;
                long startTime = System.currentTimeMillis();
                while (iter.hasNext()) {
                    String key = iter.next();
                    String groups = getGroups(key);
                    String shortKey = getKey(key);
                    if (version1 == null) {
                        version1 = "/" + shortKey;
                        if (groups != null && groups.length() > 0)
                            version1 = "/" + groups + version1;
                    }
                    char[] data = get(key);
                    vId = (short) mvd.newVersion(shortKey, getLongName(shortKey), groups, Version.NO_BACKUP, false);
                    // tepmorary hack
                    mvd.setDirectAlign(true);
                    System.out.println("vid=" + vId + " shortKey=" + shortKey);
                    mvd.update(vId, data, true);
                }
                long diff = System.currentTimeMillis() - startTime;
                log.append("merged ");
                log.append(title);
                log.append(": ");
                log.append(mvdName);
                log.append(" in ");
                log.append(diff);
                log.append(" milliseconds\n");
                body = mvd.toString();
                if (body.length() == 0)
                    throw new AeseException("failed to create MVD");
                //format = Formats.MVD;
            }
            doc.put(JSONKeys.TITLE, title);
            doc.put(JSONKeys.VERSION1, version1);
            doc.put(JSONKeys.DESCRIPTION, description);
            doc.put(JSONKeys.AUTHOR, author);
            doc.put(JSONKeys.STYLE, style);
            doc.put(JSONKeys.FORMAT, format);
            doc.put(JSONKeys.BODY, body);
            //externalise(mvdName);
            return doc.toString();
        } catch (Exception e) {
            throw new AeseException(e);
        }
    }

    // for testing
    public void externalise(String name) throws Exception {
        Set<String> keys = keySet();
        Iterator<String> iter = keys.iterator();
        File dir = new File("/tmp/" + name + ".mvd");
        if (!dir.exists())
            dir.mkdir();
        while (iter.hasNext()) {
            String key = iter.next();
            String replacement = key.replace("/", "_");
            File dst = new File(dir, replacement);
            FileOutputStream fos = new FileOutputStream(dst);
            String str = new String(get(key));
            fos.write(str.getBytes("UTF-8"));
            fos.close();
        }
    }
}