package net.sf.colossus.xmlparser; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; import java.util.logging.Level; import java.util.logging.Logger; import net.sf.colossus.util.ObjectCreationException; import net.sf.colossus.util.StaticResourceLoader; import net.sf.colossus.variant.AllCreatureType; import net.sf.colossus.variant.CreatureType; import net.sf.colossus.variant.CreatureTypeTitan; import net.sf.colossus.variant.HazardTerrain; import org.jdom.Attribute; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.input.SAXBuilder; /** * CreatureLoader loads the creature descriptions. * @author Romain Dolbeau * @version $Id: CreatureLoader.java 4053 2009-04-21 12:40:24Z dolbeau $ * @see net.sf.colossus.variant.CreatureType */ public class CreatureLoader implements AllCreatureType { private static final Logger LOGGER = Logger.getLogger(CreatureLoader.class .getName()); private static final String currentVersion = "2"; private final SortedSet<CreatureType> creatures; private final Map<String, CreatureType> byName = new TreeMap<String, CreatureType>(); public CreatureLoader() { this.creatures = new TreeSet<CreatureType>(); } // we need to cast since JDOM is not generified @SuppressWarnings("unchecked") public void fillCreatureLoader(InputStream creIS, List<String> varDirectoriesList) { SAXBuilder builder = new SAXBuilder(); try { Document doc = builder.build(creIS); Element root = doc.getRootElement(); Attribute v = root.getAttribute("version"); if ((v == null) || (!v.getValue().equals(currentVersion))) { LOGGER.severe("Wrong / missing version in Creature file."); } List<Element> lcreatures = root.getChildren("creature"); for (Element el : lcreatures) { handleCreature(el, varDirectoriesList); } } catch (JDOMException ex) { LOGGER.log(Level.SEVERE, "JDOM exception caught", ex); } catch (IOException ex) { LOGGER.log(Level.SEVERE, "IO exception caught", ex); } catch (ObjectCreationException ex) { LOGGER.log(Level.SEVERE, "Failed to create custom object", ex); } } /** Lookup attribute of name name in Element el, and return * its value as boolean. Assume lack of attribute means false. * @param el The element with the attribute (or not) * @param name The name of the attribute * @return The boolean value of the attribute, defaulting to false if absent */ private boolean getAttributeBoolean(Element el, String name) throws JDOMException { Attribute a = el.getAttribute(name); if (a == null) return false; return a.getBooleanValue(); } @SuppressWarnings("boxing") private void handleCreature(Element el, List<String> varDirectoriesList) throws JDOMException, ObjectCreationException { String name = el.getAttributeValue("name"); int power = el.getAttribute("power").getIntValue(); int skill = el.getAttribute("skill").getIntValue(); boolean rangestrikes = getAttributeBoolean(el, "rangestrikes"); boolean flies = getAttributeBoolean(el, "flies"); Set<HazardTerrain> nativeTerrains = new HashSet<HazardTerrain>(); for (HazardTerrain terrain : HazardTerrain.getAllHazardTerrains()) { if (getAttributeBoolean(el, terrain.getName())) { nativeTerrains.add(terrain); } } boolean slope = getAttributeBoolean(el, "slope"); boolean river = getAttributeBoolean(el, "river"); // maybe the next one should be split in its own attribute ? boolean water = getAttributeBoolean(el, "Lake"); // maybe the next one should be split in its own attribute ? boolean dune = getAttributeBoolean(el, "Sand"); boolean magic_missile = getAttributeBoolean(el, "magic_missile"); boolean summonable = getAttributeBoolean(el, "summonable"); boolean lord = getAttributeBoolean(el, "lord"); boolean demilord = getAttributeBoolean(el, "demilord"); int count = el.getAttribute("count").getIntValue(); String plural_name = el.getAttributeValue("plural_name"); String base_color = el.getAttributeValue("base_color"); int poison; try { poison = el.getAttribute("poison").getIntValue(); } catch (Exception e) { // Don't fail if older version doesn't have poison poison = 0; } int slows; try { slows = el.getAttribute("slows").getIntValue(); } catch (Exception e) { // Don't fail if older version doesn't have slows slows = 0; } String custom_class = el.getAttributeValue("special"); CreatureType creature = null; if (custom_class == null) { if (name.equals("Titan")) { creature = new CreatureTypeTitan(name, power, skill, rangestrikes, flies, nativeTerrains, slope, river, dune, water, magic_missile, summonable, lord, demilord, count, plural_name, base_color, poison, slows); } else { creature = new CreatureType(name, power, skill, rangestrikes, flies, nativeTerrains, slope, river, dune, water, magic_missile, summonable, lord, demilord, count, plural_name, base_color, poison, slows); } } else { Object[] parameters = new Object[19]; parameters[0] = name; parameters[1] = power; parameters[2] = skill; parameters[3] = rangestrikes; parameters[4] = flies; parameters[5] = nativeTerrains; parameters[6] = slope; parameters[7] = river; parameters[8] = dune; parameters[9] = water; parameters[10] = magic_missile; parameters[11] = summonable; parameters[12] = lord; parameters[13] = demilord; parameters[14] = count; parameters[15] = plural_name; parameters[16] = base_color; parameters[17] = poison; parameters[18] = slows; creature = (CreatureType)StaticResourceLoader.getNewObject( custom_class, varDirectoriesList, parameters); } this.creatures.add(creature); this.byName.put(name, creature); } public List<CreatureType> getCreatureTypesAsList() { return Collections.unmodifiableList(new ArrayList<CreatureType>( this.creatures)); } public SortedSet<CreatureType> getCreatureTypes() { return Collections.unmodifiableSortedSet(this.creatures); } public CreatureType getCreatureTypeByName(String name) { return this.byName.get(name); } }