org.shaman.rpg.battle.monster.MonsterRaceLoader.java Source code

Java tutorial

Introduction

Here is the source code for org.shaman.rpg.battle.monster.MonsterRaceLoader.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package org.shaman.rpg.battle.monster;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.xml.transform.stream.StreamSource;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.Namespace;
import org.jdom2.input.SAXBuilder;
import org.jdom2.input.sax.XMLReaderJDOMFactory;
import org.jdom2.input.sax.XMLReaderXSDFactory;
import org.netbeans.api.annotations.common.StaticResource;
import org.openide.util.Exceptions;
import org.shaman.database.Database;
import org.shaman.database.util.DynamicContainer;
import org.shaman.database.util.DynamicList;

/**
 * Loads and saves monster races to xml.
 * @author Sebastian Wei
 */
public class MonsterRaceLoader {
    @StaticResource
    private static final String SCHEMA = "org/shaman/rpg/battle/monster/monster.xsd";

    private XMLReaderJDOMFactory xsdFactory;
    private SAXBuilder saxBuilder;
    private Namespace namespace;

    private MonsterRaceLoader() {
    }

    public static MonsterRaceLoader getInstance() {
        return MonsterRaceLoaderHolder.INSTANCE;
    }

    /**
     * Loads the monster races from database.
     * The database has to have a DynamicContainer containing MonsterRace-instances
     * as root. This method directly returns the backing array, so changes to this
     * database directly will reflect on the monster races and vice versa.
     * @param db the database to load
     * @return a list with the loaded races
     * @see #saveToDatabase(java.util.List) 
     */
    public List<MonsterRace> loadFromDatabase(Database<? extends DynamicList<MonsterRace>> db) {
        return db.getRoot();
    }

    /**
     * Saves the monster races to database.
     * @param attacks the races to save
     * @return the database containing the races
     * @see #loadFromDatabase(org.shaman.database.Database) 
     */
    public Database<? extends DynamicList<MonsterRace>> saveToDatabase(List<MonsterRace> attacks) {
        if (attacks instanceof ArrayList) {
            return new Database<DynamicList<MonsterRace>>(
                    new DynamicList<MonsterRace>((ArrayList<MonsterRace>) attacks));
        } else {
            return new Database<DynamicList<MonsterRace>>(
                    new DynamicList<MonsterRace>(new ArrayList<MonsterRace>(attacks)));
        }
    }

    private void initSaxBuilder() {
        if (saxBuilder == null) {
            //read schema
            InputStream in = null;
            try {
                in = new BufferedInputStream(MonsterRaceLoader.class.getClassLoader().getResourceAsStream(SCHEMA));
                StreamSource source = new StreamSource(in, SCHEMA);
                xsdFactory = new XMLReaderXSDFactory(source);
            } catch (JDOMException ex) {
                throw new ExceptionInInitializerError(ex);
            } finally {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException ex) {
                    } //ignore
                }
            }
            //create sax builder
            saxBuilder = new SAXBuilder(xsdFactory);
            //Create the namespace
            namespace = Namespace.getNamespace("Engine/Battle/MonsterRaces");
        }
    }

    /**
     * Loads the monster races from the specified xml file.
     * The xml file has to be valid against the xsd-schema.
     * @param xml the xml file
     * @return a list with all loaded monster races
     */
    public List<MonsterRace> loadFromXml(File xml) throws IOException, JDOMException {
        initSaxBuilder();
        return loadFromXml(saxBuilder.build(xml));
    }

    /**
     * Loads the monster races from the specified input stream.
     * This can be used to load the races from e.g. the class path. Note: the 
     * input stream might be closed automatically.
     * The xml file has to be valid against the xsd-schema.
     * @param xml the xml file
     * @return a list with all loaded monster races
     */
    public List<MonsterRace> loadFromXml(InputStream in) throws IOException, JDOMException {
        initSaxBuilder();
        return loadFromXml(saxBuilder.build(in));
    }

    private List<MonsterRace> loadFromXml(Document doc) {
        //the document is valid, so start with analysing it
        Collection<Element> races = doc.getRootElement().getChildren("MonsterRace", namespace);
        List<MonsterRace> list = new ArrayList<MonsterRace>(races.size());
        //load races
        for (Element e : races) {
            MonsterRace race = new MonsterRace();
            //load name
            race.setName(e.getChildTextTrim("name", namespace));
            //load element
            race.setElementID(Integer.valueOf(e.getChildTextTrim("element", namespace)));
            //load state values
            for (StateValue v : StateValue.values()) {
                if (v == StateValue.ATTACK_POINTS) {
                    continue; //ignore attack points
                }
                race.setStateValue(v, Integer.parseInt(e.getChildTextTrim(v.toString(), namespace)));
            }
            //TODO: custom attributes

            //add to list
            list.add(race);
        }

        return list;
    }

    private static class MonsterRaceLoaderHolder {

        private static final MonsterRaceLoader INSTANCE = new MonsterRaceLoader();
    }
}