// // @(#)XMLProvinceParser.java 7/2002 // // Copyright 2002 Zachary DelProposto. All rights reserved. // Use is subject to license terms. // // // This program 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. // // This program 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 this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // Or from http://www.gnu.org/ // package dip.world.variant.parser; import dip.world.variant.data.ProvinceData; import dip.world.variant.data.BorderData; import dip.misc.Log; import java.io.*; import java.net.*; import java.util.*; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.ParserConfigurationException; import org.xml.sax.SAXException; import org.xml.sax.ErrorHandler; import org.w3c.dom.*; /** * Parses an XML ProvinceData description. * * * * */ public class XMLProvinceParser implements ProvinceParser { // Element constants public static final String EL_PROVINCES = "PROVINCES"; public static final String EL_PROVINCE = "PROVINCE"; public static final String EL_UNIQUENAME = "UNIQUENAME"; public static final String EL_ADJACENCY = "ADJACENCY"; public static final String EL_BORDER_DEFINITIONS = "BORDER_DEFINITIONS"; public static final String EL_BORDER = "BORDER"; // Attribute constants public static final String ATT_SHORTNAME = "shortname"; public static final String ATT_FULLNAME = "fullname"; public static final String ATT_NAME = "name"; public static final String ATT_TYPE = "type"; public static final String ATT_REFS = "refs"; public static final String ATT_CONVOYABLE_COAST = "isConvoyableCoast"; public static final String ATT_ID = "id"; public static final String ATT_DESCRIPTION = "description"; public static final String ATT_UNIT_TYPES = "unitTypes"; public static final String ATT_FROM = "from"; public static final String ATT_ORDER_TYPES = "orderTypes"; public static final String ATT_BASE_MOVE_MODIFIER = "baseMoveModifier"; public static final String ATT_BORDERS = "borders"; public static final String ATT_YEAR = "year"; public static final String ATT_SEASON = "season"; public static final String ATT_PHASE = "phase"; // instance variables private Document doc = null; private DocumentBuilder docBuilder = null; private List provinceList = null; private List borderList = null; /** Create an XMLProvinceParser */ public XMLProvinceParser(final DocumentBuilderFactory dbf) throws ParserConfigurationException { docBuilder = dbf.newDocumentBuilder(); docBuilder.setErrorHandler(new XMLErrorHandler()); FastEntityResolver.attach(docBuilder); provinceList = new ArrayList(100); borderList = new ArrayList(10); }// XMLProvinceParser() /** Parse the given input stream; parsed data available via <code>getProvinceData()</code> */ public void parse(InputStream is) throws IOException, SAXException { long time = System.currentTimeMillis(); provinceList.clear(); borderList.clear(); doc = docBuilder.parse(is); procProvinceData(); Log.printTimed(time, " province parse time: "); }// parse() /** Cleanup, clearing any references/resources */ public void close() { provinceList.clear(); borderList.clear(); }// close() /** Returns the ProvinceData objects, or an empty list. */ public ProvinceData[] getProvinceData() { return (ProvinceData[]) provinceList.toArray(new ProvinceData[provinceList.size()]); }// getProvinceData() /** Returns the BorderData objects, or an empty list. */ public BorderData[] getBorderData() { return (BorderData[]) borderList.toArray(new BorderData[borderList.size()]); }// getBorderData() /** Parse the XML */ private void procProvinceData() throws IOException, SAXException { // find root element Element root = doc.getDocumentElement(); // find all BORDER elements. We will use these later, via the borderMap NodeList borderNodes = root.getElementsByTagName(EL_BORDER); for(int i=0; i<borderNodes.getLength(); i++) { Element border = (Element) borderNodes.item(i); BorderData bd = new BorderData(); bd.setID( border.getAttribute(ATT_ID) ); bd.setDescription( border.getAttribute(ATT_DESCRIPTION) ); bd.setUnitTypes( border.getAttribute(ATT_UNIT_TYPES) ); bd.setFrom( border.getAttribute(ATT_FROM) ); bd.setOrderTypes( border.getAttribute(ATT_ORDER_TYPES) ); bd.setBaseMoveModifier( border.getAttribute(ATT_BASE_MOVE_MODIFIER) ); bd.setYear( border.getAttribute(ATT_YEAR) ); bd.setSeason( border.getAttribute(ATT_SEASON) ); bd.setPhase( border.getAttribute(ATT_PHASE) ); borderList.add(bd); } // find all PROVINCE elements NodeList provinceNodes = root.getElementsByTagName(EL_PROVINCE); for(int i=0; i<provinceNodes.getLength(); i++) { Element elProvince = (Element) provinceNodes.item(i); ProvinceData provinceData = new ProvinceData(); // create short/unique name list List nameList = new LinkedList(); // region attributes provinceData.setFullName( elProvince.getAttribute(ATT_FULLNAME) ); nameList.add( elProvince.getAttribute(ATT_SHORTNAME) ); // convoyable coast provinceData.setConvoyableCoast( Boolean.valueOf(elProvince.getAttribute(ATT_CONVOYABLE_COAST)).booleanValue() ); // borders data (optional); a list of references, seperated by commas/spaces String borders = elProvince.getAttribute(ATT_BORDERS).trim(); List borderList = new ArrayList(); StringTokenizer st = new StringTokenizer(borders, ", "); while(st.hasMoreTokens()) { borderList.add(st.nextToken()); } provinceData.setBorders(borderList); // adjacency data NodeList adjNodes = elProvince.getElementsByTagName(EL_ADJACENCY); String[] adjTypeNames = new String[adjNodes.getLength()]; String[] adjProvinceNames = new String[adjNodes.getLength()]; for(int j=0; j<adjNodes.getLength(); j++) { Element element = (Element) adjNodes.item(j); adjTypeNames[j] = element.getAttribute(ATT_TYPE); adjProvinceNames[j] = element.getAttribute(ATT_REFS); } provinceData.setAdjacentProvinceTypes(adjTypeNames); provinceData.setAdjacentProvinceNames(adjProvinceNames); // unique name(s) (if any) adjNodes = elProvince.getElementsByTagName(EL_UNIQUENAME); for(int j=0; j<adjNodes.getLength(); j++) { Element element = (Element) adjNodes.item(j); nameList.add( element.getAttribute(ATT_NAME) ); } // set all short & unique names provinceData.setShortNames(nameList); // add to list provinceList.add(provinceData); } }// procProvinceData() }// class XMLProvinceParser