Java tutorial
/* * 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(); } }