/** * 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.HashMap; import java.util.List; import java.util.Map; public class ProductionMap { public class ProductionTree { /** * The abstract goods all other types of goods in this tree are * finally stored as. */ private AbstractGoods root; /** * The abstract goods that are actually produced. */ private List<AbstractGoods> leafs; public ProductionTree(AbstractGoods root, AbstractGoods... leafs) { if (leafs.length > 0) { this.leafs = new ArrayList<AbstractGoods>(); int amount = root.getAmount(); for (AbstractGoods leaf : leafs) { this.leafs.add(new AbstractGoods(leaf)); amount += leaf.getAmount(); } this.root = new AbstractGoods(root.getType(), amount); } else { this.root = new AbstractGoods(root); } } /** * Get the <code>Root</code> value. * * @return an <code>AbstractGoods</code> value */ public final AbstractGoods getRoot() { return root; } /** * Set the <code>Root</code> value. * * @param newRoot The new Root value. */ public final void setRoot(final AbstractGoods newRoot) { this.root = newRoot; } /** * Get the <code>Leafs</code> value. * * @return a <code>List<AbstractGoods></code> value */ public final List<AbstractGoods> getLeafs() { return leafs; } /** * Set the <code>Leafs</code> value. * * @param newLeafs The new Leafs value. */ public final void setLeafs(final List<AbstractGoods> newLeafs) { this.leafs = newLeafs; } public void add(AbstractGoods goods) { if (goods.getType().getStoredAs() != root.getType()) { throw new IllegalArgumentException(goods.getType().getId() + " is not stored as " + root.getType()); } else { for (AbstractGoods leaf : leafs) { if (leaf.getType() == goods.getType()) { leaf.setAmount(leaf.getAmount() + goods.getAmount()); root.setAmount(root.getAmount() + goods.getAmount()); return; } } leafs.add(new AbstractGoods(goods)); root.setAmount(root.getAmount() + goods.getAmount()); } } public int remove(AbstractGoods goods) { int consumed = goods.getAmount(); if (goods.getType() == root.getType()) { if (consumed > root.getAmount()) { consumed = root.getAmount(); root.setAmount(0); } else { root.setAmount(root.getAmount() - consumed); } for (AbstractGoods leaf : leafs) { leaf.setAmount(Math.min(leaf.getAmount(), root.getAmount())); } } else { for (AbstractGoods leaf : leafs) { if (leaf.getType() == goods.getType()) { if (consumed > leaf.getAmount()) { consumed = leaf.getAmount(); leaf.setAmount(0); } else { leaf.setAmount(leaf.getAmount() - consumed); } root.setAmount(root.getAmount() - consumed); break; } } } return consumed; } public AbstractGoods get(GoodsType type) { if (root.getType() == type) { return root; } else { for (AbstractGoods leaf : leafs) { if (leaf.getType() == type) { return new AbstractGoods(type, leaf.getAmount()); } } } return null; } } private Map<GoodsType, Object> cache = new HashMap<GoodsType, Object>(); public AbstractGoods get(GoodsType type) { Object value = cache.get(type); if (value == null) { return new AbstractGoods(type, 0); } else if (value instanceof Integer) { return new AbstractGoods(type, (Integer) value); } else { return ((ProductionTree) value).get(type); } } public void add(AbstractGoods goods) { GoodsType goodsType = goods.getType(); Object value = cache.get(goodsType); if (value == null) { // no entry yet GoodsType rootType = goodsType.getStoredAs(); if (rootType == goodsType) { cache.put(goodsType, goods.getAmount()); } else { // is leaf of production tree value = cache.get(rootType); if (value instanceof ProductionTree) { // entry is already present ((ProductionTree) value).add(goods); } else { // add new root entry Integer amount = (value == null) ? 0 : (Integer) value; value = new ProductionTree(new AbstractGoods(rootType, amount), goods); cache.put(rootType, value); } // add the same entry for the goods type itself cache.put(goodsType, value); } } else if (value instanceof Integer) { cache.put(goodsType, (Integer) value + goods.getAmount()); } else { ((ProductionTree) value).add(goods); } } public void remove(AbstractGoods goods) { Object value = cache.get(goods.getType()); if (value instanceof ProductionTree) { ((ProductionTree) value).remove(goods); } else { add(new AbstractGoods(goods.getType(), -goods.getAmount())); } } public void add(List<AbstractGoods> goods) { for (AbstractGoods g : goods) { add(g); } } public void remove(List<AbstractGoods> goods) { for (AbstractGoods g : goods) { remove(g); } } }