mml.handler.scratch.ScratchVersionSet.java Source code

Java tutorial

Introduction

Here is the source code for mml.handler.scratch.ScratchVersionSet.java

Source

/*
 * This file is part of MML.
 *
 *  MML 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.
 *
 *  MML 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 MML.  If not, see <http://www.gnu.org/licenses/>.
 *  (c) copyright Desmond Schmidt 2016
 */
package mml.handler.scratch;

import calliope.core.Utils;
import calliope.core.constants.Database;
import calliope.core.constants.Formats;
import calliope.core.database.*;
import calliope.core.exception.DbException;
import mml.exception.MMLException;
import java.util.HashMap;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import org.json.simple.*;
import calliope.core.constants.JSONKeys;
import calliope.core.database.Connector;
import edu.luc.nmerge.mvd.MVD;
import edu.luc.nmerge.mvd.MVDFile;
import mml.handler.get.Layers;

/**
 * A set of ScratchVersions with all the same docid and dbase
 * @author desmond
 */
public class ScratchVersionSet {
    ScratchVersion[] list;
    HashMap<String, Object> otherFields;
    String docid;
    String version1;
    String body;
    String format;

    /**
     * Create a version set
     * @param list the list of scratch versions
     * @param format their format
     */
    public ScratchVersionSet(ScratchVersion[] list) {
        this.list = list;
        this.otherFields = new HashMap<String, Object>();
        this.format = "TEXT";
        this.docid = list[0].docid;
        this.version1 = list[0].version;
    }

    public int size() {
        int num = 0;
        for (int i = 0; i < list.length; i++) {
            num += list[i].size();
        }
        return num;
    }

    public void setFormat() throws MMLException {
        String dbase = getDbase();
        if (this.size() > 1) {
            if (dbase.equals(Database.CORTEX))
                this.format = "MVD/TEXT";
            else if (dbase.equals(Database.CORCODE))
                this.format = "MVD/STIL";
            else
                throw new MMLException("Invalid database " + dbase);
        } else if (dbase.equals(Database.CORTEX))
            this.format = Formats.TEXT;
        else if (dbase.equals(Database.CORCODE))
            this.format = Formats.STIL;
        else
            throw new MMLException("Invalid database " + dbase);
    }

    private void parseResource(String resource) {
        JSONObject jObj = (JSONObject) JSONValue.parse(resource);
        this.otherFields = new HashMap<String, Object>();
        Set<String> keys = jObj.keySet();
        Iterator<String> iter = keys.iterator();
        while (iter.hasNext()) {
            String key = iter.next();
            if (key.equals(JSONKeys._ID))
                continue;
            else if (key.equals(JSONKeys.DOCID))
                docid = (String) jObj.get(JSONKeys.DOCID);
            else if (key.equals(JSONKeys.BODY))
                body = (String) jObj.get(JSONKeys.BODY);
            else if (key.equals(JSONKeys.VERSION1))
                version1 = (String) jObj.get(JSONKeys.VERSION1);
            else if (key.equals(JSONKeys.FORMAT))
                format = (String) jObj.get(JSONKeys.FORMAT);
            else
                otherFields.put(key, jObj.get(key));
        }
    }

    String[] listVersions(MVD mvd) {
        int nversions = mvd.numVersions();
        String[] array = new String[nversions];
        for (int i = 0; i < nversions; i++) {
            short id = (short) (i + 1);
            String groupPath = mvd.getGroupPath(id);
            String shortName = mvd.getVersionShortName(id);
            array[i] = groupPath + "/" + shortName;
        }
        return array;
    }

    /**
     * Create a scratchversionset from a database record
     * @param resource the dbase resource fetched from the database
     * @param dbase the dbase collection name it was from
     */
    public ScratchVersionSet(String resource, String dbase) {
        parseResource(resource);
        if (format.contains("MVD")) {
            MVD mvd = MVDFile.internalise(body);
            HashMap<String, ScratchVersion> map = new HashMap<String, ScratchVersion>();
            String[] all = listVersions(mvd);
            for (short i = 1; i <= mvd.numVersions(); i++) {
                String vid = mvd.getVersionId(i);
                String localLongName = mvd.getLongNameForVersion(i);
                // the ONLY names in memory are upgraded ones
                String layerName = Layers.upgradeLayerName(all, vid);
                int num = ScratchVersion.layerNumber(layerName);
                String shortName = Layers.stripLayer(layerName);
                ScratchVersion sv = map.get(shortName);
                char[] data = mvd.getVersion(i);
                if (sv == null) {
                    sv = new ScratchVersion(shortName, localLongName, docid, dbase, null, false);
                    sv.addLayer(data, num);
                    map.put(shortName, sv);
                } else if (!sv.containsLayer(num))
                    sv.addLayer(data, num);
            }
            // convert to list
            list = new ScratchVersion[map.size()];
            Collection<ScratchVersion> coll = map.values();
            coll.toArray(list);
        } else // single version/layer
        {
            if (version1 == null)
                version1 = "/base";
            if (docid != null && body != null) {
                String longName = null;
                if (otherFields.containsKey(JSONKeys.LONGNAME))
                    longName = (String) otherFields.get(JSONKeys.LONGNAME);
                if (otherFields.containsKey(JSONKeys.DESCRIPTION))
                    longName = (String) otherFields.get(JSONKeys.DESCRIPTION);
                if (longName == null)
                    longName = "Version " + version1;
                ScratchVersion sv = new ScratchVersion(version1, longName, docid, dbase, null, false);
                sv.addLayer(body.toCharArray(), Integer.MAX_VALUE);
                appendToList(sv);
            }
        }
    }

    private void appendToList(ScratchVersion sv) {
        if (list == null) {
            list = new ScratchVersion[1];
            list[0] = sv;
        } else {
            ScratchVersion[] newList = new ScratchVersion[list.length + 1];
            System.arraycopy(list, 0, newList, 0, list.length);
            newList[newList.length - 1] = sv;
            this.list = newList;
        }
    }

    public String getDocid() throws ArrayIndexOutOfBoundsException {
        if (this.list == null || this.list.length == 0)
            throw new ArrayIndexOutOfBoundsException("List is empty");
        return this.list[0].getDocid();
    }

    /**
     * Get the databse name this resource is assigned to
     * @return the name of a calliope database
     * @throws ArrayIndexOutOfBoundsException 
     */
    public String getDbase() throws ArrayIndexOutOfBoundsException {
        if (this.list == null || this.list.length == 0)
            throw new ArrayIndexOutOfBoundsException("List is empty");
        return this.list[0].getDbase();
    }

    /**
     * Get the default style for the docid
     * @param styleName the initial style name
     * @return an appropriate style name, or at least "default"
     */
    public static String getDefaultStyleName(String styleName) throws MMLException {
        try {
            Connection conn = Connector.getConnection();
            while (styleName != null && styleName.length() > 0) {
                String jStr = conn.getFromDb(Database.CORFORM, styleName);
                if (jStr != null)
                    break;
                else {
                    jStr = conn.getFromDb(Database.CORFORM, styleName + "/default");
                    if (jStr != null) {
                        styleName += "/default";
                        break;
                    } else
                        styleName = Utils.chomp((styleName));
                }
            }
        } catch (DbException e) {
            throw new MMLException(e);
        }
        if (styleName.length() == 0)
            styleName = "default";
        return styleName;
    }

    /**
     * Create a database resource without docid, _id fields
     * @return a JSON file
     * @throws MMLException 
     */
    public String toResource() throws MMLException {
        this.setFormat();
        //System.out.println(getDefaultStyleName());
        // create a JSONObject
        JSONObject jObj = new JSONObject();
        jObj.put(JSONKeys.FORMAT, format);
        if (list.length > 0) {
            // populate it with otherFields, version1, format
            version1 = list[0].getDefaultVersion();
            jObj.put(JSONKeys.VERSION1, version1);
            Set<String> keys = otherFields.keySet();
            Iterator<String> iter = keys.iterator();
            while (iter.hasNext()) {
                String key = iter.next();
                jObj.put(key, otherFields.get(key));
            }
            // create a new body field by merging all the versions into one MVD
        } else
            throw new MMLException("ScratchVersion list is empty");
        // check style is set optimally
        String styleName = (String) jObj.get(JSONKeys.STYLE);
        if (styleName == null || styleName.equals("default"))
            jObj.put(JSONKeys.STYLE, getDefaultStyleName(docid));
        // now build body
        if (list.length == 1 && list[0].isSimple())
            jObj.put(JSONKeys.BODY, list[0].getLayerString(Integer.MAX_VALUE));
        else {
            try {
                MVD mvd = new MVD();
                short vid = 1;
                if (otherFields.containsKey(JSONKeys.DESCRIPTION))
                    mvd.setDescription((String) otherFields.get(JSONKeys.DESCRIPTION));
                else if (otherFields.containsKey(JSONKeys.TITLE))
                    mvd.setDescription((String) otherFields.get(JSONKeys.TITLE));
                for (int i = 0; i < list.length; i++) {
                    int[] layers = list[i].getLayerNumbers();
                    for (int j = 0; j < layers.length; j++) {
                        String str = list[i].getLayerString(layers[j]);
                        String vPath = list[i].version + "/" + ScratchVersion.layerName(layers[j]);
                        String shortName = Utils.getShortName(vPath);
                        String groupName = Utils.getGroupName(vPath);
                        if (groupName.startsWith("/"))
                            groupName = groupName.substring(1);
                        mvd.newVersion(shortName, list[i].longName, groupName, (short) 0, false);
                        mvd.update(vid, str.toCharArray(), true);
                        vid++;
                    }
                }
                body = MVDFile.externalise(mvd);
                jObj.put(JSONKeys.BODY, body);
            } catch (Exception e) {
                throw new MMLException(e);
            }
        }
        return jObj.toJSONString();
    }

    /**
     * Replace our versions with those in other
     * @param other the other ScratchVersionSet
     */
    public void upsert(ScratchVersionSet other) {
        HashMap<String, ScratchVersion> map = new HashMap<String, ScratchVersion>();
        for (int i = 0; i < this.list.length; i++) {
            ScratchVersion sv = this.list[i];
            map.put(sv.version, sv);
        }
        for (int i = 0; i < other.list.length; i++) {
            map.put(other.list[i].version, other.list[i]);
        }
        ScratchVersion[] newList = new ScratchVersion[map.size()];
        Collection coll = map.values();
        int i = 0;
        Iterator iter = coll.iterator();
        while (iter.hasNext()) {
            ScratchVersion sv = (ScratchVersion) iter.next();
            newList[i++] = sv;
        }
        this.list = newList;
    }
}