/**
* 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.Set;
import java.util.logging.Logger;
import org.freecolandroid.xml.stream.XMLStreamException;
import org.freecolandroid.xml.stream.XMLStreamReader;
import org.freecolandroid.xml.stream.XMLStreamWriter;
/**
* Represents a locatable goods of a specified type and quantity.
*/
public class Resource extends TileItem {
private static Logger logger = Logger.getLogger(Resource.class.getName());
private ResourceType type;
private int quantity;
/**
* Creates a standard <code>Resource</code>-instance.
*
* This constructor asserts that the game, tile and type are valid.
*
* @param game The <code>Game</code> in which this object belongs.
* @param tile The <code>Tile</code> on which this object sits.
* @param type The <code>ResourceType</code> of this Resource.
* @param quantity an <code>int</code> value
*/
public Resource(Game game, Tile tile, ResourceType type, int quantity) {
super(game, tile);
if (type == null) {
throw new IllegalArgumentException("Parameter 'type' must not be 'null'.");
}
this.type = type;
this.quantity = quantity;
}
/**
* Creates a standard <code>Resource</code>-instance.
*
* This constructor asserts that the game, tile and type are valid.
*
* @param game The <code>Game</code> in which this object belongs.
* @param tile The <code>Tile</code> on which this object sits.
* @param type The <code>ResourceType</code> of this Resource.
*/
public Resource(Game game, Tile tile, ResourceType type) {
this(game, tile, type, type.getMaxValue());
}
public Resource(Game game, XMLStreamReader in) throws XMLStreamException {
super(game, in);
readFromXML(in);
}
/**
* Returns a textual representation of this object.
* @return A <code>String</code> of either:
* <ol>
* <li>QUANTITY RESOURCETYPE (eg. 250 Minerals) if there is a limited quantity
* <li>RESOURCETYPE (eg. Game) if it is an unlimited resource
* </ol>
*/
public String toString() {
if (quantity > -1) {
return Integer.toString(quantity) + " " + getType().getId();
} else {
return getType().getId();
}
}
public String getNameKey() {
return getType().getNameKey();
}
/**
* Returns the <code>ResourceType</code> of this Resource.
*/
public ResourceType getType() {
return type;
}
/**
* Returns the current quantity.
*/
public int getQuantity() {
return quantity;
}
/**
* Returns the current quantity.
*/
public void setQuantity(int newQuantity) {
quantity = newQuantity;
}
/**
* Get the <code>ZIndex</code> value.
*
* @return an <code>int</code> value
*/
public final int getZIndex() {
return RESOURCE_ZINDEX;
}
/**
* Returns the best GoodsType
*/
public GoodsType getBestGoodsType() {
return type.getBestGoodsType();
}
/**
* Returns the bonus (checking available stock) for next turn.
* @param goodsType The GoodsType to check
* @param unitType an <code>UnitType</code> value
* @param potential Potential of Tile + Improvements
* @return an <code>int</code> value
*/
public int getBonus(GoodsType goodsType, UnitType unitType, int potential) {
Set<Modifier> productionBonus = type.getProductionModifier(goodsType, unitType);
int bonusAmount = (int) FeatureContainer.applyModifierSet(potential, null, productionBonus) - potential;
if (quantity > -1 && bonusAmount > quantity) {
return potential + quantity;
} else {
return potential + bonusAmount;
}
}
/**
* Reduces the available quantity by the bonus output of <code>GoodsType</code>.
* @param goodsType The GoodsType to check
* @param unitType an <code>UnitType</code> value
* @param potential Potential of Tile + Improvements
* @return an <code>int</code> value
*/
public int useQuantity(GoodsType goodsType, UnitType unitType, int potential) {
// Return -1 here if not limited resource?
return useQuantity(getBonus(goodsType, unitType, potential) - potential);
}
/**
* Reduces the value <code>quantity</code>.
* @param usedQuantity The quantity that was used up.
* @return The final value of quantity.
*/
public int useQuantity(int usedQuantity) {
if (quantity >= usedQuantity) {
quantity -= usedQuantity;
} else if (quantity == -1) {
logger.warning("useQuantity called for unlimited resource");
} else {
// Shouldn't generally happen. Do something more drastic here?
logger.severe("Insufficient quantity in " + this);
quantity = 0;
}
return quantity;
}
/**
* {@inheritDoc}
*/
public boolean isTileTypeAllowed(TileType tileType) {
return tileType.canHaveResourceType(getType());
}
/* TODO: what was this for? Named resources, such as Lost Crazy Russian Gold Mine?
public void setName(String newName) {
// do nothing
}
*/
/**
* This method writes an XML-representation of this object to the given
* stream.
*
* <br>
* <br>
*
* Only attributes visible to the given <code>Player</code> will be added
* to that representation if <code>showAll</code> is set to
* <code>false</code>.
*
* @param out The target stream.
* @param player The <code>Player</code> this XML-representation should be
* made for, or <code>null</code> if
* <code>showAll == true</code>.
* @param showAll Only attributes visible to <code>player</code> will be
* added to the representation if <code>showAll</code> is set
* to <i>false</i>.
* @param toSavedGame If <code>true</code> then information that is only
* needed when saving a game is added.
* @throws XMLStreamException if there are any problems writing to the
* stream.
*/
@Override
protected void toXMLImpl(XMLStreamWriter out, Player player,
boolean showAll, boolean toSavedGame)
throws XMLStreamException {
// Start element:
out.writeStartElement(getXMLElementTagName());
// Add attributes:
out.writeAttribute(ID_ATTRIBUTE, getId());
out.writeAttribute("tile", getTile().getId());
out.writeAttribute("type", getType().getId());
out.writeAttribute("quantity", Integer.toString(quantity));
// End element:
out.writeEndElement();
}
/**
* Initialize this object from an XML-representation of this object.
*
* @param in The input stream with the XML.
* @throws XMLStreamException if a problem was encountered during parsing.
*/
@Override
protected void readFromXMLImpl(XMLStreamReader in)
throws XMLStreamException {
setId(in.getAttributeValue(null, ID_ATTRIBUTE));
tile = getFreeColGameObject(in, "tile", Tile.class);
type = getSpecification().getResourceType(in.getAttributeValue(null, "type"));
quantity = Integer.parseInt(in.getAttributeValue(null, "quantity"));
in.nextTag();
}
/**
* Gets the tag name of the root element representing this object.
*
* @return "resource".
*/
public static String getXMLElementTagName() {
return "resource";
}
}