net.geco.model.iojson.PersistentStore.java Source code

Java tutorial

Introduction

Here is the source code for net.geco.model.iojson.PersistentStore.java

Source

/**
 * Copyright (c) 2012 Simon Denier
 * Released under the MIT License (see LICENSE file)
 */
package net.geco.model.iojson;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.util.Collection;
import java.util.Date;
import java.util.Map.Entry;

import net.geco.basics.GecoResources;
import net.geco.basics.TimeManager;
import net.geco.model.Category;
import net.geco.model.Club;
import net.geco.model.Course;
import net.geco.model.CourseSet;
import net.geco.model.Factory;
import net.geco.model.HeatSet;
import net.geco.model.Pool;
import net.geco.model.Punch;
import net.geco.model.Registry;
import net.geco.model.ResultType;
import net.geco.model.Runner;
import net.geco.model.RunnerRaceData;
import net.geco.model.RunnerResult;
import net.geco.model.Section;
import net.geco.model.Section.SectionType;
import net.geco.model.SectionTraceData;
import net.geco.model.Stage;
import net.geco.model.Status;
import net.geco.model.Trace;
import net.geco.model.TraceData;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * @author Simon Denier
 * @since Dec 26, 2012
 *
 */
public final class PersistentStore {

    public static final String STORE_FILE = "store.json"; //$NON-NLS-1$

    public static final String JSON_SCHEMA_VERSION = "2.2"; //$NON-NLS-1$

    private static final boolean DEBUG = false;

    public String getStorePath(String baseDir) {
        return baseDir + GecoResources.sep + STORE_FILE;
    }

    public void loadData(Stage stage, Factory factory) {
        Registry registry = new Registry();
        stage.setRegistry(registry);
        try {
            BufferedReader reader = GecoResources.getSafeReaderFor(getStorePath(stage.getBaseDir()));
            importDataIntoRegistry(new JSONStore(reader, K.MAXID), registry, factory);
            reader.close();
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void importDataIntoRegistry(JSONStore store, Registry registry, Factory factory) throws JSONException {
        importControls(store, registry);
        importCourseSets(store, registry, factory);
        importCourses(store, registry, factory);
        importCategories(store, registry, factory);
        importClubs(store, registry, factory);
        importHeatSets(store, registry, factory);
        importRunnersData(store, registry, factory);
    }

    public void importControls(JSONStore store, Registry registry) throws JSONException {
        if (store.has(K.CONTROLS)) { // MIRG 2.x -> 2.2
            JSONArray controls = store.getJSONArray(K.CONTROLS);
            for (int i = 0; i < controls.length(); i++) {
                JSONArray codeData = controls.getJSONArray(i);
                registry.setControlPenalty(codeData.getInt(0), new Date(codeData.getLong(1)));
            }
        }
    }

    public void importCourseSets(JSONStore store, Registry registry, Factory factory) throws JSONException {
        if (store.has(K.COURSESETS)) { // MIGR v2.x -> v2.2
            JSONArray coursesets = store.getJSONArray(K.COURSESETS);
            for (int i = 0; i < coursesets.length(); i++) {
                JSONObject c = coursesets.getJSONObject(i);
                CourseSet courseset = store.register(factory.createCourseSet(), c.getInt(K.ID));
                courseset.setName(c.getString(K.NAME));
                registry.addCourseSet(courseset);
            }
        }
    }

    public void importCourses(JSONStore store, Registry registry, Factory factory) throws JSONException {
        JSONArray courses = store.getJSONArray(K.COURSES);
        for (int i = 0; i < courses.length(); i++) {
            JSONObject c = courses.getJSONObject(i);
            Course course = store.register(factory.createCourse(), c.getInt(K.ID));
            course.setName(c.getString(K.NAME));
            course.setLength(c.getInt(K.LENGTH));
            course.setClimb(c.getInt(K.CLIMB));
            course.setMassStartTime(new Date(c.optLong(K.START, TimeManager.NO_TIME_l))); // MIGR v2.x -> v2.2
            course.setCourseSet(store.retrieve(c.optInt(K.COURSESET, 0), CourseSet.class));
            JSONArray codez = c.getJSONArray(K.CODES);
            int[] codes = new int[codez.length()];
            for (int j = 0; j < codes.length; j++) {
                codes[j] = codez.getInt(j);
            }
            course.setCodes(codes);
            if (c.has(K.SECTIONS)) {
                JSONArray sectionz = c.getJSONArray(K.SECTIONS);
                for (int j = 0; j < sectionz.length(); j++) {
                    JSONObject sectionTuple = sectionz.getJSONObject(j);
                    Section section = store.register(factory.createSection(), sectionTuple.getInt(K.ID));
                    section.setStartIndex(sectionTuple.getInt(K.START_ID));
                    section.setName(sectionTuple.getString(K.NAME));
                    section.setType(SectionType.valueOf(sectionTuple.getString(K.TYPE)));
                    section.setNeutralized(sectionTuple.optBoolean(K.NEUTRALIZED, false));
                    course.putSection(section);
                }
                course.refreshSectionCodes();
            }
            registry.addCourse(course);
        }
        registry.ensureAutoCourse(factory);
    }

    public void importCategories(JSONStore store, Registry registry, Factory factory) throws JSONException {
        JSONArray categories = store.getJSONArray(K.CATEGORIES);
        for (int i = 0; i < categories.length(); i++) {
            JSONObject c = categories.getJSONObject(i);
            Category category = store.register(factory.createCategory(), c.getInt(K.ID));
            category.setName(c.getString(K.NAME));
            category.setLongname(c.getString(K.LONG));
            category.setCourse(store.retrieve(c.optInt(K.COURSE, 0), Course.class));
            category.setCourseSet(store.retrieve(c.optInt(K.COURSESET, 0), CourseSet.class));
            registry.addCategory(category);
        }
    }

    public void importClubs(JSONStore store, Registry registry, Factory factory) throws JSONException {
        JSONArray clubs = store.getJSONArray(K.CLUBS);
        for (int i = 0; i < clubs.length(); i++) {
            JSONObject c = clubs.getJSONObject(i);
            Club club = store.register(factory.createClub(), c.getInt(K.ID));
            club.setName(c.getString(K.NAME));
            club.setShortname(c.getString(K.SHORT));
            registry.addClub(club);
        }
    }

    public void importHeatSets(JSONStore store, Registry registry, Factory factory) throws JSONException {
        JSONArray heatsets = store.getJSONArray(K.HEATSETS);
        for (int i = 0; i < heatsets.length(); i++) {
            JSONObject h = heatsets.getJSONObject(i);
            HeatSet heatset = factory.createHeatSet();
            heatset.setName(h.getString(K.NAME));
            heatset.setQualifyingRank(h.getInt(K.RANK));
            heatset.setSetType(ResultType.valueOf(h.getString(K.TYPE)));
            JSONArray heatz = h.getJSONArray(K.HEATS);
            String[] heats = new String[heatz.length()];
            for (int j = 0; j < heats.length; j++) {
                heats[j] = heatz.getString(j);
            }
            heatset.setHeatNames(heats);
            JSONArray poolz = h.getJSONArray(K.POOLS);
            Pool[] pools = new Pool[poolz.length()];
            for (int j = 0; j < pools.length; j++) {
                pools[j] = store.retrieve(poolz.getInt(j), Pool.class);
            }
            heatset.setSelectedPools(pools);
            registry.addHeatSet(heatset);
        }
    }

    public void importRunnersData(JSONStore store, Registry registry, Factory factory) throws JSONException {
        final int I_RUNNER = 0;
        final int I_ECARD = 1;
        final int I_RESULT = 2;
        JSONArray runnersData = store.getJSONArray(K.RUNNERS_DATA);
        for (int i = 0; i < runnersData.length(); i++) {
            JSONArray runnerTuple = runnersData.getJSONArray(i);

            JSONObject c = runnerTuple.getJSONObject(I_RUNNER);
            Runner runner = factory.createRunner();
            runner.setStartId(c.getInt(K.START_ID));
            runner.setFirstname(c.getString(K.FIRST));
            runner.setLastname(c.getString(K.LAST));
            runner.setEcard(c.getString(K.ECARD));
            runner.setClub(store.retrieve(c.getInt(K.CLUB), Club.class));
            runner.setCategory(store.retrieve(c.getInt(K.CAT), Category.class));
            runner.setCourse(store.retrieve(c.getInt(K.COURSE), Course.class));
            runner.setRegisteredStarttime(new Date(c.getLong(K.START)));
            runner.setArchiveId((Integer) c.opt(K.ARK));
            runner.setRentedEcard(c.optBoolean(K.RENT));
            runner.setNC(c.optBoolean(K.NC));
            registry.addRunner(runner);

            JSONObject d = runnerTuple.getJSONObject(I_ECARD);
            RunnerRaceData raceData = factory.createRunnerRaceData();
            raceData.setStarttime(new Date(d.getLong(K.START)));
            raceData.setFinishtime(new Date(d.getLong(K.FINISH)));
            raceData.setControltime(new Date(d.getLong(K.CHECK)));
            raceData.setReadtime(new Date(d.getLong(K.READ)));
            JSONArray p = d.getJSONArray(K.PUNCHES);
            Punch[] punches = new Punch[p.length() / 2];
            for (int j = 0; j < punches.length; j++) {
                punches[j] = factory.createPunch();
                punches[j].setCode(p.getInt(2 * j));
                punches[j].setTime(new Date(p.getLong(2 * j + 1)));
            }
            raceData.setPunches(punches);
            raceData.setRunner(runner);
            registry.addRunnerData(raceData);

            JSONObject r = runnerTuple.getJSONObject(I_RESULT);
            TraceData traceData = factory.createTraceData();
            traceData.setNbMPs(r.getInt(K.MPS));
            traceData.setNbExtraneous(r.optInt(K.EXTRA)); // MIGR v2.x -> v2.3
            JSONArray t = r.getJSONArray(K.TRACE);
            Trace[] trace = new Trace[t.length() / 2];
            for (int j = 0; j < trace.length; j++) {
                trace[j] = factory.createTrace(t.getString(2 * j), new Date(t.getLong(2 * j + 1)));
            }
            if (r.has(K.SECTION_DATA)) {
                SectionTraceData sectionData = (SectionTraceData) traceData;
                JSONArray sections = r.getJSONArray(K.SECTION_DATA);
                for (int j = 0; j < sections.length(); j++) {
                    JSONArray section = sections.getJSONArray(j);
                    sectionData.putSectionAt(store.retrieve(section.getInt(0), Section.class), section.getInt(1));
                }
            }
            JSONArray neut = r.getJSONArray(K.NEUTRALIZED);
            for (int j = 0; j < neut.length(); j++) {
                trace[neut.getInt(j)].setNeutralized(true);
            }
            traceData.setTrace(trace);
            raceData.setTraceData(traceData);

            RunnerResult result = factory.createRunnerResult();
            result.setRaceTime(r.optLong(K.RACE_TIME, TimeManager.NO_TIME_l)); // MIGR v2.x -> v2.2
            result.setResultTime(r.getLong(K.TIME));
            result.setStatus(Status.valueOf(r.getString(K.STATUS)));
            result.setTimePenalty(r.getLong(K.PENALTY));
            result.setManualTimePenalty(r.optLong(K.MANUAL_PENALTY, 0)); // MIGR v2.x -> v2.3
            raceData.setResult(result);
        }
    }

    public void saveData(Stage stage) {
        try {
            BufferedWriter writer = GecoResources.getSafeWriterFor(getStorePath(stage.getBaseDir()));
            exportDataToJson(stage, new JacksonSerializer(writer, DEBUG));
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void exportDataToJson(Stage stage, JSONSerializer json) throws IOException {
        json.startObject().field(K.VERSION, JSON_SCHEMA_VERSION);
        Registry registry = stage.registry();
        exportControls(json, registry);
        exportCourseSets(json, registry.getCourseSets());
        exportCourses(json, registry.getCourses());
        exportCategories(json, registry.getCategories());
        exportClubs(json, registry.getClubs());
        exportHeatSets(json, registry.getHeatSets());
        exportRunnersData(json, registry.getRunnersData());
        json.idMax(K.MAXID).endObject().close();
    }

    public void exportControls(JSONSerializer json, Registry registry) throws IOException {
        json.startArrayField(K.CONTROLS);
        for (Integer code : registry.getControls()) {
            json.startArray().value(code).value(registry.getControlPenalty(code)).endArray();
        }
        json.endArray();
    }

    public void exportCourseSets(JSONSerializer json, Collection<CourseSet> coursesets) throws IOException {
        json.startArrayField(K.COURSESETS);
        for (CourseSet courseset : coursesets) {
            json.startObject().id(K.ID, courseset).field(K.NAME, courseset.getName()).endObject();
        }
        json.endArray();
    }

    public void exportCourses(JSONSerializer json, Collection<Course> courses) throws IOException {
        json.startArrayField(K.COURSES);
        for (Course course : courses) {
            json.startObject().id(K.ID, course).field(K.NAME, course.getName()).field(K.LENGTH, course.getLength())
                    .field(K.CLIMB, course.getClimb()).field(K.START, course.getMassStartTime())
                    .optRef(K.COURSESET, course.getCourseSet()).startArrayField(K.CODES);
            for (int code : course.getCodes()) {
                json.value(code);
            }
            json.endArray().startArrayField(K.SECTIONS);
            for (Section section : course.getSections()) {
                json.startObject().id(K.ID, section).field(K.START_ID, section.getStartIndex())
                        .field(K.NAME, section.getName()).field(K.TYPE, section.getType().name())
                        .optField(K.NEUTRALIZED, section.neutralized()).endObject();
            }
            json.endArray().endObject();
        }
        json.endArray();
    }

    public void exportCategories(JSONSerializer json, Collection<Category> categories) throws IOException {
        json.startArrayField(K.CATEGORIES);
        for (Category cat : categories) {
            json.startObject().id(K.ID, cat).field(K.NAME, cat.getShortname()).field(K.LONG, cat.getLongname())
                    .optRef(K.COURSE, cat.getCourse()).optRef(K.COURSESET, cat.getCourseSet()).endObject();
        }
        json.endArray();
    }

    public void exportClubs(JSONSerializer json, Collection<Club> clubs) throws IOException {
        json.startArrayField(K.CLUBS);
        for (Club club : clubs) {
            json.startObject().id(K.ID, club).field(K.NAME, club.getName()).field(K.SHORT, club.getShortname())
                    .endObject();
        }
        json.endArray();
    }

    public void exportHeatSets(JSONSerializer json, Collection<HeatSet> heatsets) throws IOException {
        json.startArrayField(K.HEATSETS);
        for (HeatSet heatset : heatsets) {
            json.startObject().field(K.NAME, heatset.getName()).field(K.RANK, heatset.getQualifyingRank())
                    .field(K.TYPE, heatset.getSetType().name()).startArrayField(K.HEATS);
            for (String heatname : heatset.getHeatNames()) {
                json.value(heatname);
            }
            json.endArray().startArrayField(K.POOLS);
            for (Pool pool : heatset.getSelectedPools()) {
                json.ref(pool);
            }
            json.endArray().endObject();
        }
        json.endArray();
    }

    public void exportRunnersData(JSONSerializer json, Collection<RunnerRaceData> runnersData) throws IOException {
        json.startArrayField(K.RUNNERS_DATA);
        for (RunnerRaceData runnerData : runnersData) {
            json.startArray();
            Runner runner = runnerData.getRunner();
            json.startObject().field(K.START_ID, runner.getStartId()).field(K.FIRST, runner.getFirstname())
                    .field(K.LAST, runner.getLastname()).field(K.ECARD, runner.getEcard())
                    .ref(K.CLUB, runner.getClub()).ref(K.CAT, runner.getCategory())
                    .ref(K.COURSE, runner.getCourse()).field(K.START, runner.getRegisteredStarttime())
                    .optField(K.ARK, runner.getArchiveId()).optField(K.RENT, runner.rentedEcard())
                    .optField(K.NC, runner.isNC()).endObject();

            json.startObject().field(K.START, runnerData.getStarttime()).field(K.FINISH, runnerData.getFinishtime())
                    .field(K.CHECK, runnerData.getControltime()).field(K.READ, runnerData.getReadtime())
                    .startArrayField(K.PUNCHES);
            for (Punch punch : runnerData.getPunches()) {
                json.value(punch.getCode()).value(punch.getTime());
            }
            json.endArray().endObject();

            TraceData traceData = runnerData.getTraceData();
            RunnerResult result = runnerData.getResult();
            json.startObject().field(K.TIME, result.getResultTime()).field(K.STATUS, result.getStatus().name())
                    .field(K.MPS, traceData.getNbMPs()).field(K.EXTRA, traceData.getNbExtraneous())
                    .field(K.PENALTY, result.getTimePenalty())
                    .field(K.MANUAL_PENALTY, result.getManualTimePenalty())
                    .field(K.RACE_TIME, result.getRaceTime());

            Trace[] traceArray = traceData.getTrace();
            int nbNeut = 0;
            int[] neutralized = new int[traceArray.length];
            json.startArrayField(K.TRACE);
            for (int i = 0; i < traceArray.length; i++) {
                Trace trace = traceData.getTrace()[i];
                json.value(trace.getCode()).value(trace.getTime());
                if (trace.isNeutralized()) {
                    neutralized[nbNeut++] = i;
                }
            }
            json.endArray();
            if (traceData.hasSectionData()) {
                json.startArrayField(K.SECTION_DATA);
                for (Entry<Integer, Section> section : ((SectionTraceData) traceData).getSectionData()) {
                    json.startArray().ref(section.getValue()).value(section.getKey()).endArray();
                }
                json.endArray();
            }
            json.startArrayField(K.NEUTRALIZED);
            for (int i = 0; i < nbNeut; i++) {
                json.value(neutralized[i]);
            }
            json.endArray().endObject().endArray();
        }
        json.endArray();
    }

    public static class K {

        public static final String ID = "id";; //$NON-NLS-1$
        public static final String MAXID = "maxid";; //$NON-NLS-1$
        public static final String NAME = "name"; //$NON-NLS-1$
        public static final String VERSION = "version"; //$NON-NLS-1$

        public static final String CONTROLS = "controls"; //$NON-NLS-1$
        public static final String COURSES = "courses"; //$NON-NLS-1$
        public static final String LENGTH = "length"; //$NON-NLS-1$
        public static final String CLIMB = "climb"; //$NON-NLS-1$
        public static final String CODES = "codes"; //$NON-NLS-1$
        public static final String SECTIONS = "sections"; //$NON-NLS-1$
        public static final String COURSESETS = "coursesets"; //$NON-NLS-1$
        public static final String COURSESET = "courseset"; //$NON-NLS-1$

        public static final String CATEGORIES = "categories";; //$NON-NLS-1$
        public static final String LONG = "long"; //$NON-NLS-1$
        public static final String CLUBS = "clubs"; //$NON-NLS-1$
        public static final String SHORT = "short"; //$NON-NLS-1$

        public static final String HEATSETS = "heatsets"; //$NON-NLS-1$
        public static final String RANK = "rank"; //$NON-NLS-1$
        public static final String TYPE = "type"; //$NON-NLS-1$
        public static final String HEATS = "heats"; //$NON-NLS-1$
        public static final String POOLS = "pools"; //$NON-NLS-1$

        public static final String RUNNERS_DATA = "runnersData"; //$NON-NLS-1$

        public static final String START_ID;
        public static final String FIRST;
        public static final String LAST;
        public static final String ECARD;
        public static final String CLUB;
        public static final String CAT;
        public static final String COURSE;
        public static final String ARK;
        public static final String NC;
        public static final String RENT;

        public static final String START;
        public static final String FINISH;
        public static final String CHECK;
        public static final String READ;
        public static final String PUNCHES;

        public static final String TIME;
        public static final String STATUS;
        public static final String MPS;
        public static final String EXTRA;
        public static final String PENALTY;
        public static final String MANUAL_PENALTY;
        public static final String RACE_TIME;
        public static final String TRACE;
        public static final String SECTION_DATA;
        public static final String NEUTRALIZED;

        static {
            if (DEBUG) {
                START_ID = "startid"; //$NON-NLS-1$
                FIRST = "first"; //$NON-NLS-1$
                LAST = "last"; //$NON-NLS-1$
                ECARD = "ecard"; //$NON-NLS-1$
                CLUB = "club"; //$NON-NLS-1$
                CAT = "cat"; //$NON-NLS-1$
                COURSE = "course"; //$NON-NLS-1$
                ARK = "ark"; //$NON-NLS-1$
                RENT = "rent"; //$NON-NLS-1$
                NC = "nc"; //$NON-NLS-1$

                START = "start"; //$NON-NLS-1$
                FINISH = "finish"; //$NON-NLS-1$
                READ = "read"; //$NON-NLS-1$
                CHECK = "check"; //$NON-NLS-1$
                PUNCHES = "punches"; //$NON-NLS-1$

                TIME = "time"; //$NON-NLS-1$
                STATUS = "status"; //$NON-NLS-1$
                MPS = "mps"; //$NON-NLS-1$
                EXTRA = "extra"; //$NON-NLS-1$
                PENALTY = "penalty"; //$NON-NLS-1$
                MANUAL_PENALTY = "manual"; //$NON-NLS-1$
                RACE_TIME = "running"; //$NON-NLS-1$
                TRACE = "trace"; //$NON-NLS-1$
                SECTION_DATA = "section_data"; //$NON-NLS-1$
                NEUTRALIZED = "neut"; //$NON-NLS-1$
            } else {
                START_ID = "i"; //$NON-NLS-1$
                FIRST = "f"; //$NON-NLS-1$
                LAST = "l"; //$NON-NLS-1$
                ECARD = "e"; //$NON-NLS-1$
                CLUB = "u"; //$NON-NLS-1$
                CAT = "t"; //$NON-NLS-1$
                COURSE = "c"; //$NON-NLS-1$
                ARK = "a"; //$NON-NLS-1$
                RENT = "r"; //$NON-NLS-1$
                NC = "n"; //$NON-NLS-1$

                START = "s"; //$NON-NLS-1$
                FINISH = "f"; //$NON-NLS-1$
                READ = "r"; //$NON-NLS-1$
                CHECK = "c"; //$NON-NLS-1$
                PUNCHES = "p"; //$NON-NLS-1$

                TIME = "t"; //$NON-NLS-1$
                STATUS = "s"; //$NON-NLS-1$
                MPS = "m"; //$NON-NLS-1$
                EXTRA = "x"; //$NON-NLS-1$
                PENALTY = "p"; //$NON-NLS-1$
                MANUAL_PENALTY = "b"; //$NON-NLS-1$
                RACE_TIME = "u"; //$NON-NLS-1$
                TRACE = "r"; //$NON-NLS-1$
                SECTION_DATA = "o"; //$NON-NLS-1$
                NEUTRALIZED = "n"; //$NON-NLS-1$
            }
        }
    }

}