/** * Copyright (C) 2002-2012 The FreeCol Team * * This file is part of FreeCol. * * FreeCol 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. * * FreeCol 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 FreeCol. If not, see <http://www.gnu.org/licenses/>. */ package net.sf.freecol.common.model; import java.util.ArrayList; import java.util.EnumMap; import java.util.List; import java.util.Map; import org.freecolandroid.xml.stream.XMLStreamConstants; import org.freecolandroid.xml.stream.XMLStreamException; import org.freecolandroid.xml.stream.XMLStreamReader; import org.freecolandroid.xml.stream.XMLStreamWriter; public class UnitTypeChange extends FreeColObject { /** * Describe newUnitType here. */ private UnitType newUnitType; public static enum ChangeType { EDUCATION, NATIVES, EXPERIENCE, LOST_CITY, PROMOTION, CREATION, ENTER_COLONY, INDEPENDENCE, CLEAR_SKILL, DEMOTION, CAPTURE, UNDEAD } public static final Map<ChangeType, String> tags = new EnumMap<ChangeType, String>(ChangeType.class); static { tags.put(ChangeType.EDUCATION, "learnInSchool"); tags.put(ChangeType.NATIVES, "learnFromNatives"); tags.put(ChangeType.EXPERIENCE, "learnFromExperience"); tags.put(ChangeType.LOST_CITY, "learnInLostCity"); tags.put(ChangeType.PROMOTION, "promotion"); tags.put(ChangeType.CLEAR_SKILL, "clearSkill"); tags.put(ChangeType.DEMOTION, "demotion"); tags.put(ChangeType.CAPTURE, "capture"); tags.put(ChangeType.CREATION, "creation"); tags.put(ChangeType.ENTER_COLONY, "enterColony"); tags.put(ChangeType.INDEPENDENCE, "independence"); tags.put(ChangeType.UNDEAD, "undead"); } protected int turnsToLearn = 0; protected Map<ChangeType, Integer> changeTypes = new EnumMap<ChangeType, Integer>(ChangeType.class); /** * A list of Scopes limiting the applicability of this Feature. */ private List<Scope> scopes = new ArrayList<Scope>(); public UnitTypeChange() { // empty constructor } /** * Creates a new <code>UnitTypeChange</code> instance. * * @param in a <code>XMLStreamReader</code> value * @param specification a <code>Specification</code> value * @exception XMLStreamException if an error occurs */ public UnitTypeChange(XMLStreamReader in, Specification specification) throws XMLStreamException { setId(in.getAttributeValue(null, ID_ATTRIBUTE_TAG)); readAttributes(in, specification); readChildren(in, specification); } /** * Returns the probability of a change taking place (defaults to * zero). At the moment, this probability only applies to the * ChangeTypes EXPERIENCE and PROMOTION. * * @param type a <code>ChangeType</code> value * @return an <code>int</code> value */ public final int getProbability(ChangeType type) { Integer result = changeTypes.get(type); return (result == null) ? 0 : result; } public List<Scope> getScopes() { return scopes; } public Map<ChangeType, Integer> getChangeTypes() { return changeTypes; } /** * Describe <code>asResultOf</code> method here. * * @param type a <code>ChangeType</code> value * @return a <code>boolean</code> value */ public boolean asResultOf(ChangeType type) { return changeTypes.containsKey(type) && changeTypes.get(type) > 0; } /** * Describe <code>appliesTo</code> method here. * * @param player a <code>Player</code> value * @return a <code>boolean</code> value */ public boolean appliesTo(Player player) { if (scopes.isEmpty()) { return true; } else { for (Scope scope : scopes) { if (scope.appliesTo(player)) { return true; } } return false; } } /** * Get the <code>TurnsToLearn</code> value. * * @return an <code>int</code> value */ public final int getTurnsToLearn() { return turnsToLearn; } /** * Set the <code>TurnsToLearn</code> value. * * @param newTurnsToLearn The new TurnsToLearn value. */ public final void setTurnsToLearn(final int newTurnsToLearn) { this.turnsToLearn = newTurnsToLearn; } public boolean canBeTaught() { return asResultOf(ChangeType.EDUCATION) && turnsToLearn > 0; } /** * Get the <code>NewUnitType</code> value. * * @return an <code>UnitType</code> value */ public final UnitType getNewUnitType() { return newUnitType; } /** * Set the <code>NewUnitType</code> value. * * @param newNewUnitType The new NewUnitType value. */ public final void setNewUnitType(final UnitType newNewUnitType) { this.newUnitType = newNewUnitType; } /** * This method writes an XML-representation of this object to * the given stream. * * @param out The target stream. * @exception XMLStreamException if there are any problems writing * to the stream. */ protected void toXMLImpl(XMLStreamWriter out) throws XMLStreamException { out.writeStartElement(getXMLElementTagName()); if (newUnitType != null) { out.writeAttribute("unit", newUnitType.getId()); } if (turnsToLearn != UNDEFINED) { out.writeAttribute("turnsToLearn", Integer.toString(turnsToLearn)); } for (Map.Entry<ChangeType, Integer> entry : changeTypes.entrySet()) { out.writeAttribute(tags.get(entry.getKey()), entry.getValue().toString()); } out.writeEndElement(); } /** * Initialize this object from an XML-representation of this object. * * @param in The XML input stream. * @param specification A <code>Specification</code> to use. * @throws XMLStreamException if a problem was encountered * during parsing. */ @Override protected void readAttributes(XMLStreamReader in, Specification specification) throws XMLStreamException { String newTypeId = in.getAttributeValue(null, "unit"); if (newTypeId == null) { newUnitType = null; } else { newUnitType = specification.getType(newTypeId, UnitType.class); turnsToLearn = getAttribute(in, "turnsToLearn", UNDEFINED); if (turnsToLearn > 0) { changeTypes.put(ChangeType.EDUCATION, 100); } // @compat 0.9.x for (ChangeType type : ChangeType.values()) { String value = in.getAttributeValue(null, tags.get(type)); if (value != null) { if(value.equalsIgnoreCase("false")) { changeTypes.put(type, 0); } else if (value.equalsIgnoreCase("true")) { changeTypes.put(type, 100); } else { changeTypes.put(type, Math.max(0, Math.min(100, new Integer(value)))); } } } // end compatibility code } } /** * Reads the children of this object from an XML stream. * * @param in The XML input stream. * @param specification A <code>Specification</code> to use. * @throws XMLStreamException if a problem was encountered * during parsing. */ @Override protected void readChildren(XMLStreamReader in, Specification specification) throws XMLStreamException { while (in.nextTag() != XMLStreamConstants.END_ELEMENT) { String nodeName = in.getLocalName(); if ("scope".equals(nodeName)) { scopes.add(new Scope(in)); } } } /** * Returns the tag name of the root element representing this object. * * @return "upgrade". */ public static final String getXMLElementTagName() { return "upgrade"; } }