/** * 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 org.freecolandroid.xml.stream.XMLStreamException; import org.freecolandroid.xml.stream.XMLStreamReader; import org.freecolandroid.xml.stream.XMLStreamWriter; /** * Contains a message about a change in the model. */ public class ModelMessage extends StringTemplate { /** Constants describing the type of message. */ public static enum MessageType { DEFAULT(null), WARNING("model.option.guiShowWarning"), SONS_OF_LIBERTY("model.option.guiShowSonsOfLiberty"), GOVERNMENT_EFFICIENCY("model.option.guiShowGovernmentEfficiency"), WAREHOUSE_CAPACITY("model.option.guiShowWarehouseCapacity"), UNIT_IMPROVED("model.option.guiShowUnitImproved"), UNIT_DEMOTED("model.option.guiShowUnitDemoted"), UNIT_LOST("model.option.guiShowUnitLost"), UNIT_ADDED("model.option.guiShowUnitAdded"), BUILDING_COMPLETED("model.option.guiShowBuildingCompleted"), FOREIGN_DIPLOMACY("model.option.guiShowForeignDiplomacy"), MARKET_PRICES("model.option.guiShowMarketPrices"), LOST_CITY_RUMOUR(null), // Displayed during the turn MISSING_GOODS("model.option.guiShowMissingGoods"), TUTORIAL("model.option.guiShowTutorial"), COMBAT_RESULT(null), // No option, always display GIFT_GOODS("model.option.guiShowGifts"), DEMANDS("model.option.guiShowDemands"), GOODS_MOVEMENT("model.option.guiShowGoodsMovement"); private String optionName; MessageType(String optionName) { this.optionName = optionName; } public String getOptionName() { return optionName; } } private String ownerId; /* deprecated */ private String sourceId; private String displayId; private MessageType messageType; private boolean beenDisplayed = false; public ModelMessage() { // empty constructor } /** * Creates a new <code>ModelMessage</code>. * * @param id The ID of the message to display. * @param source The source of the message. This is what the * message should be associated with. * @param display The Object to display. */ public ModelMessage(String id, FreeColGameObject source, FreeColObject display) { this(MessageType.DEFAULT, id, source, display); } /** * Creates a new <code>ModelMessage</code>. * * @param messageType The type of this model message. * @param id The ID of the message to display. * @param source The source of the message. This is what the * message should be associated with. */ public ModelMessage(MessageType messageType, String id, FreeColGameObject source) { this(messageType, id, source, getDefaultDisplay(messageType, source)); } /** * Creates a new <code>ModelMessage</code>. * * @param id The ID of the message to display. * @param source The source of the message. This is what the * message should be associated with. */ public ModelMessage(String id, FreeColGameObject source) { this(MessageType.DEFAULT, id, source, getDefaultDisplay(MessageType.DEFAULT, source)); } /** * Creates a new <code>ModelMessage</code>. * * @param messageType The type of this model message. * @param id The ID of the message to display. * @param source The source of the message. This is what the * message should be associated with. * @param display The object to display. */ public ModelMessage(MessageType messageType, String id, FreeColGameObject source, FreeColObject display) { super(id, TemplateType.TEMPLATE); this.messageType = messageType; this.sourceId = source.getId(); this.displayId = (display != null) ? display.getId() : source.getId(); this.ownerId = null; } /** * Set the <code>DefaultId</code> value. * * @param newDefaultId The new DefaultId value. * @return a <code>ModelMessage</code> value */ @Override public final ModelMessage setDefaultId(final String newDefaultId) { super.setDefaultId(newDefaultId); return this; } /** * Returns the default display object for the given type. * * @param messageType The type to find the default display object for. * @param source The source object * @return An object to be displayed for the message. */ static private FreeColObject getDefaultDisplay(MessageType messageType, FreeColGameObject source) { FreeColObject o = null; switch (messageType) { case SONS_OF_LIBERTY: case GOVERNMENT_EFFICIENCY: o = source.getSpecification().getGoodsType("model.goods.bells"); break; case UNIT_IMPROVED: case UNIT_DEMOTED: case UNIT_LOST: case UNIT_ADDED: case LOST_CITY_RUMOUR: case COMBAT_RESULT: case DEMANDS: case GOODS_MOVEMENT: o = source; break; case BUILDING_COMPLETED: o = source.getSpecification().getGoodsType("model.goods.hammers"); break; case DEFAULT: case WARNING: case WAREHOUSE_CAPACITY: case FOREIGN_DIPLOMACY: case MARKET_PRICES: case MISSING_GOODS: case TUTORIAL: case GIFT_GOODS: default: if (source instanceof Player) { o = source; } break; } return o; } /** * Checks if this <code>ModelMessage</code> has been displayed. * * @return <i>true</i> if this <code>ModelMessage</code> has been * displayed. * @see #setBeenDisplayed */ public boolean hasBeenDisplayed() { return beenDisplayed; } /** * Sets the <code>beenDisplayed</code> value of this * <code>ModelMessage</code>. This is used to avoid showing the * same message twice. * * @param beenDisplayed Should be set to <code>true</code> after the * message has been displayed. */ public void setBeenDisplayed(boolean beenDisplayed) { this.beenDisplayed = beenDisplayed; } /** * Gets the ID of the source of the message. * * @return The source of the message. */ public String getSourceId() { return sourceId; } /** * Sets the ID of the source object. * * @param sourceId A new source ID. */ public void setSourceId(String sourceId) { this.sourceId = sourceId; } /** * Gets the ID of the object to display. * * @return The ID of the object to display. */ public String getDisplayId() { return displayId; } /** * Sets the ID of the object to display. * * @param displayId A new display ID. */ public void setDisplayId(String displayId) { this.displayId = displayId; } /** * Gets the messageType of the message to display. * * @return The messageType. */ public MessageType getMessageType() { return messageType; } /** * Sets the type of the message. * * @param messageType The new messageType. */ public void setMessageType(MessageType messageType) { this.messageType = messageType; } public String getMessageTypeName() { return "model.message." + messageType.toString(); } /** * Switch the source (and display if it is the same) to a new * object. Called when an object becomes invalid. * * @param newSource A new source. */ public void divert(FreeColGameObject newSource) { if (displayId == sourceId) displayId = newSource.getId(); sourceId = newSource.getId(); } /** * Compatibility hack. Do not use. */ public String getOwnerId() { return ownerId; } /** * Compatibility hack. Do not use. */ public void setOwnerId(String ownerId) { this.ownerId = ownerId; } /** * Add a new key and replacement to the ModelMessage. This is * only possible if the ModelMessage is of type TEMPLATE. * * @param key a <code>String</code> value * @param value a <code>String</code> value * @return a <code>ModelMessage</code> value */ public ModelMessage add(String key, String value) { super.add(key, value); return this; } /** * Add a replacement value without a key to the ModelMessage. * This is only possible if the ModelMessage is of type LABEL. * * @param value a <code>String</code> value * @return a <code>ModelMessage</code> value */ public ModelMessage add(String value) { super.add(value); return this; } /** * Add a new key and replacement to the ModelMessage. The * replacement must be a proper name. This is only possible if the * ModelMessage is of type TEMPLATE. * * @param key a <code>String</code> value * @param value a <code>String</code> value * @return a <code>ModelMessage</code> value */ public ModelMessage addName(String key, String value) { super.addName(key, value); return this; } /** * Add a replacement value without a key to the ModelMessage. * The replacement must be a proper name. This is only possible * if the ModelMessage is of type LABEL. * * @param value a <code>String</code> value * @return a <code>ModelMessage</code> value */ public ModelMessage addName(String value) { super.addName(value); return this; } /** * Add a key and an integer value to replace it to this * StringTemplate. * * @param key a <code>String</code> value * @param amount an <code>int</code> value * @return a <code>ModelMessage</code> value */ public ModelMessage addAmount(String key, int amount) { super.addAmount(key, amount); return this; } /** * Add a key and a StringTemplate to replace it to this * StringTemplate. * * @param key a <code>String</code> value * @param template a <code>StringTemplate</code> value * @return a <code>ModelMessage</code> value */ public ModelMessage addStringTemplate(String key, StringTemplate template) { super.addStringTemplate(key, template); return this; } /** * Add a StringTemplate to this LABEL StringTemplate. * * @param template a <code>StringTemplate</code> value * @return a <code>ModelMessage</code> value */ public ModelMessage addStringTemplate(StringTemplate template) { super.addStringTemplate(template); return this; } /** * Checks if this <code>ModelMessage</code> is equal to another * <code>ModelMessage</code>. * * @param o The <code>Object</code> to compare. * @return <i>true</i> if the sources, message IDs and data are equal. */ @Override public boolean equals(Object o) { if (o instanceof ModelMessage) { ModelMessage m = (ModelMessage) o; if (sourceId.equals(m.sourceId) && getId().equals(m.getId()) && messageType == m.messageType) { return super.equals(m); } } return false; } @Override public int hashCode() { int value = 1; value = 37 * value + sourceId.hashCode(); value = 37 * value + getId().hashCode(); value = 37 * value + messageType.ordinal(); value = 37 * value + super.hashCode(); return value; } /** * This method writes an XML-representation of this object to * the given stream. * * @param out The target stream. * @throws XMLStreamException if there are any problems writing * to the stream. */ protected void toXMLImpl(XMLStreamWriter out) throws XMLStreamException { super.toXML(out, getXMLElementTagName()); } /** * Write the attributes of this object to a stream. * * @param out The target stream. * @throws XMLStreamException if there are any problems writing * to the stream. */ @Override protected void writeAttributes(XMLStreamWriter out) throws XMLStreamException { super.writeAttributes(out); if (ownerId != null) { out.writeAttribute("owner", ownerId); } out.writeAttribute("source", sourceId); if (displayId != null) { out.writeAttribute("display", displayId); } out.writeAttribute("messageType", messageType.toString()); out.writeAttribute("hasBeenDisplayed", String.valueOf(beenDisplayed)); } /** * Initialize this object from an XML-representation of this object. * * @param in The input stream with the XML. * @exception XMLStreamException if a problem was encountered * during parsing. */ public void readFromXMLImpl(XMLStreamReader in) throws XMLStreamException { super.readAttributes(in); // Remove this when the 0.9.x save hack (in Game.java) is gone. ownerId = in.getAttributeValue(null, "owner"); messageType = Enum.valueOf(MessageType.class, getAttribute(in, "messageType", MessageType.DEFAULT.toString())); beenDisplayed = Boolean.parseBoolean(in.getAttributeValue(null, "hasBeenDisplayed")); sourceId = in.getAttributeValue(null, "source"); displayId = in.getAttributeValue(null, "display"); super.readChildren(in); } /** * Debug helper. */ @Override public String toString() { StringBuilder sb = new StringBuilder("ModelMessage<" + hashCode() + ", "); sb.append(((sourceId == null) ? "null" : sourceId) + ", "); sb.append(((displayId == null) ? "null" : displayId) + ", "); sb.append(super.toString()); sb.append(", " + messageType + " >"); return sb.toString(); } /** * Gets the tag name of the root element representing this object. * * @return "modelMessage" */ public static String getXMLElementTagName() { return "modelMessage"; } }