package com.drakulo.games.ais.core.io;
import java.io.File;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import com.drakulo.games.ais.core.Resource;
import com.drakulo.games.ais.core.building.BuildingData;
import com.drakulo.games.ais.core.building.BuildingLevelData;
import com.drakulo.games.ais.core.building.BuildingType;
import com.drakulo.games.ais.core.delayed.SpecialActionManager;
public class BuildingIO {
private static final String FILE_EXT = ".xml";
private static Map<String, BuildingData> buildingDatas = new HashMap<String, BuildingData>();
public static void loadBuildingsData() throws AisIOException {
File folder = new File("./data/buildings");
String[] configs = folder.list();
File currentFile;
BuildingData currentData;
for (String confName : configs) {
if (!confName.endsWith(FILE_EXT)) {
// Ignore non config files
continue;
}
currentFile = new File("./data/buildings/" + confName);
currentData = load(currentFile);
buildingDatas.put(confName, currentData);
}
}
/**
* Retreive building data from cache
*
* @param type
* the building type
* @return the building data
*/
public static BuildingData getBuildingData(BuildingType type) {
return buildingDatas.get(type.toString() + FILE_EXT);
}
public static void save(String fileName, BuildingData data) {
Element levels = new Element("levels");
Map<Integer, BuildingLevelData> levelsData = data.getLevelData();
Set<Integer> keys = levelsData.keySet();
for (Integer key : keys) {
levels.addContent(handleLevelData(levelsData.get(key), key));
}
Element root = new Element("building");
root.addContent(levels);
XMLOutputter output = new XMLOutputter(Format.getPrettyFormat());
try {
output.output(new Document(root), new FileOutputStream(fileName
+ FILE_EXT));
} catch (Exception e) {
e.printStackTrace();
}
}
@SuppressWarnings("unchecked")
public static BuildingData load(File f) throws AisIOException {
SAXBuilder sxb = new SAXBuilder();
try {
Document document = sxb.build(f);
Element root = document.getRootElement();
BuildingData data = new BuildingData();
List<Element> levels = root.getChild("levels").getChildren("level");
for (Element levelElement : levels) {
String value = levelElement.getAttributeValue("value");
Integer level = "".equals(value) ? 0 : Integer.valueOf(value);
data.putData(level, buildLevelData(levelElement));
}
return data;
} catch (NumberFormatException e) {
throw new AisIOException("Invalid file format for : " + f.getName());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@SuppressWarnings("unchecked")
private static BuildingLevelData buildLevelData(Element root) {
BuildingLevelData levelData = new BuildingLevelData();
// Production
Element production = root.getChild("production");
levelData.setProduction(buildResourceMap(production));
// Consumption
Element consumption = root.getChild("consumption");
levelData.setConsumption(buildResourceMap(consumption));
// Store
Element store = root.getChild("store");
levelData.setStoreCapacity(buildResourceMap(store));
// Upgrade
Element upgrade = root.getChild("upgrade");
levelData.setUpgradeCost(buildResourceMap(upgrade));
// Technologies needed to upgrade
Element techs = root.getChild("technologies");
if (techs == null) {
levelData.setTechnologiesNeeded(null);
} else {
List<String> technologies = new ArrayList<String>();
List<Element> children = techs.getChildren("technology");
for (Element elem : children) {
technologies.add(elem.getText());
}
levelData.setTechnologiesNeeded(technologies);
}
// Special actions
Element actions = root.getChild("special");
if (actions == null) {
levelData.setSpecialActions(null);
} else {
List<String> actionList = new ArrayList<String>();
List<Element> children = actions.getChildren("action");
for (Element elem : children) {
// Create the special action
String name = elem.getChildText("name");
int duration = Integer.valueOf(elem.getChildText("duration"))
.intValue();
Map<Resource, BigDecimal> costMap = buildResourceMap(elem
.getChild("cost"));
String gfxKey = elem.getChildText("gfx");
String i18nKey = elem.getChildText("i18n");
SpecialActionManager.create(name, duration, costMap, gfxKey,
i18nKey);
actionList.add(name);
}
levelData.setSpecialActions(actionList);
}
return levelData;
}
private static Map<Resource, BigDecimal> buildResourceMap(Element root) {
Map<Resource, BigDecimal> map = new HashMap<Resource, BigDecimal>();
Resource[] resources = Resource.values();
for (Resource r : resources) {
Element e = root.getChild(r.toString().toLowerCase());
if (e == null) {
map.put(r, BigDecimal.ZERO);
} else {
map.put(r, BigDecimal.valueOf(Long.valueOf(e.getText())));
}
}
return map;
}
private static Element handleLevelData(BuildingLevelData data, Integer level) {
Element levelElement = new Element("level");
levelElement.setAttribute("value", String.valueOf(level));
Element production = produceResourceNode(data.getProduction(),
"production");
Element consumption = produceResourceNode(data.getConsumption(),
"consumption");
Element storeCapacity = produceResourceNode(data.getStoreCapacity(),
"store");
Element upgrade = produceResourceNode(data.getUpgradeCost(), "upgrade");
levelElement.addContent(production);
levelElement.addContent(consumption);
levelElement.addContent(storeCapacity);
levelElement.addContent(upgrade);
return levelElement;
}
private static Element produceResourceNode(Map<Resource, BigDecimal> data,
String containerName) {
Element container = new Element(containerName);
for (Resource r : data.keySet()) {
Element item = new Element(r.toString().toLowerCase());
item.setText(String.valueOf(data.get(r)));
container.addContent(item);
}
return container;
}
}