/*
* Force.java
*
* Copyright (c) 2011 Jay Lawson <jaylawson39 at yahoo.com>. All rights reserved.
*
* This file is part of MekHQ.
*
* MekHQ 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 3 of the License, or
* (at your option) any later version.
*
* MekHQ 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 MekHQ. If not, see <http://www.gnu.org/licenses/>.
*/
package mekhq.campaign.force;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import java.util.Vector;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import mekhq.MekHQ;
import mekhq.MekHqXmlUtil;
import mekhq.campaign.Campaign;
import mekhq.campaign.unit.Unit;
/**
* this is a hierarchical object that represents forces from the TO&E using
* strings rather than unit objects. This makes it static and thus usable to
* keep track of forces involved in completed scenarios
*
* @author Jay Lawson <jaylawson39 at yahoo.com>
*/
public class ForceStub implements Serializable {
private static final long serialVersionUID = -7283462987261602481L;
// pathway to force icon
public static final String ROOT_ICON = "-- General --";
public static final String ICON_NONE = "None";
private String iconCategory = ROOT_ICON;
private String iconFileName = ICON_NONE;
private LinkedHashMap<String, Vector<String>> iconMap = new LinkedHashMap<String, Vector<String>>();
private String name;
private Vector<ForceStub> subForces;
private Vector<UnitStub> units;
public ForceStub() {
name = "";
subForces = new Vector<ForceStub>();
units = new Vector<UnitStub>();
}
public ForceStub(Force force, Campaign c) {
name = force.getFullName();
subForces = new Vector<ForceStub>();
units = new Vector<UnitStub>();
iconCategory = force.getIconCategory();
iconFileName = force.getIconFileName();
iconMap = force.getIconMap();
for(Force sub : force.getSubForces()) {
ForceStub stub = new ForceStub(sub, c);
//stub.setParentForce(this);
subForces.add(stub);
}
for(UUID uid : force.getUnits()) {
Unit u = c.getUnit(uid);
if(null != u) {
units.add(new UnitStub(u));
}
}
}
public String toString() {
return name;
}
public Vector<Object> getAllChildren() {
Vector<Object> children = new Vector<Object>();
children.addAll(subForces);
children.addAll(units);
return children;
}
public String getIconCategory() {
return iconCategory;
}
public String getIconFileName() {
return iconFileName;
}
public LinkedHashMap<String, Vector<String>> getIconMap() {
return iconMap;
}
public void setIconMap(LinkedHashMap<String, Vector<String>> iconMap) {
this.iconMap = iconMap;
}
public void writeToXml(PrintWriter pw1, int indent) {
pw1.println(MekHqXmlUtil.indentStr(indent) + "<forceStub>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<name>"
+MekHqXmlUtil.escape(name)
+"</name>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<iconCategory>"
+MekHqXmlUtil.escape(iconCategory)
+"</iconCategory>");
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<iconFileName>"
+MekHqXmlUtil.escape(iconFileName)
+"</iconFileName>");
if (iconCategory.equals(Force.ROOT_LAYERED)) {
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<iconHashMap>");
for (Map.Entry<String, Vector<String>> entry : iconMap.entrySet()) {
if (null != entry.getValue() && !entry.getValue().isEmpty()) {
pw1.println(MekHqXmlUtil.indentStr(indent+2)
+"<iconentry key=\""
+MekHqXmlUtil.escape(entry.getKey())
+"\">");
for (String value : entry.getValue()) {
pw1.println(MekHqXmlUtil.indentStr(indent+2)
+"<value name=\""
+MekHqXmlUtil.escape(value)
+"\"/>");
}
pw1.println(MekHqXmlUtil.indentStr(indent+2)
+"</iconentry>");
}
}
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"</iconHashMap>");
}
if(units.size() > 0) {
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<units>");
for(UnitStub ustub : units) {
ustub.writeToXml(pw1, indent+2);
}
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"</units>");
}
if(subForces.size() > 0) {
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"<subforces>");
for(ForceStub sub : subForces) {
sub.writeToXml(pw1, indent+2);
}
pw1.println(MekHqXmlUtil.indentStr(indent+1)
+"</subforces>");
}
pw1.println(MekHqXmlUtil.indentStr(indent) + "</forceStub>");
}
public static ForceStub generateInstanceFromXML(Node wn) {
ForceStub retVal = null;
try {
retVal = new ForceStub();
NodeList nl = wn.getChildNodes();
for (int x=0; x<nl.getLength(); x++) {
Node wn2 = nl.item(x);
if (wn2.getNodeName().equalsIgnoreCase("name")) {
retVal.name = wn2.getTextContent();
} else if (wn2.getNodeName().equalsIgnoreCase("iconCategory")) {
retVal.iconCategory = wn2.getTextContent();
} else if (wn2.getNodeName().equalsIgnoreCase("iconHashMap")) {
processIconMapNodes(retVal, wn2);
} else if (wn2.getNodeName().equalsIgnoreCase("iconFileName")) {
retVal.iconFileName = wn2.getTextContent();
} else if (wn2.getNodeName().equalsIgnoreCase("units")) {
NodeList nl2 = wn2.getChildNodes();
for (int y=0; y<nl2.getLength(); y++) {
Node wn3 = nl2.item(y);
// If it's not an element node, we ignore it.
if (wn3.getNodeType() != Node.ELEMENT_NODE)
continue;
if (!wn3.getNodeName().equalsIgnoreCase("unitStub")) {
// Error condition of sorts!
// Errr, what should we do here?
MekHQ.logMessage("Unknown node type not loaded in ForceStub nodes: "+wn3.getNodeName());
continue;
}
retVal.units.add(UnitStub.generateInstanceFromXML(wn3));
}
} else if (wn2.getNodeName().equalsIgnoreCase("subforces")) {
NodeList nl2 = wn2.getChildNodes();
for (int y=0; y<nl2.getLength(); y++) {
Node wn3 = nl2.item(y);
// If it's not an element node, we ignore it.
if (wn3.getNodeType() != Node.ELEMENT_NODE)
continue;
if (!wn3.getNodeName().equalsIgnoreCase("forceStub")) {
// Error condition of sorts!
// Errr, what should we do here?
MekHQ.logMessage("Unknown node type not loaded in ForceStub nodes: "+wn3.getNodeName());
continue;
}
retVal.addSubForce(generateInstanceFromXML(wn3));
}
}
}
} catch (Exception ex) {
// Errrr, apparently either the class name was invalid...
// Or the listed name doesn't exist.
// Doh!
MekHQ.logError(ex);
}
return retVal;
}
private static void processIconMapNodes(ForceStub retVal, Node wn) {
NodeList nl = wn.getChildNodes();
for (int x=0; x<nl.getLength(); x++) {
Node wn2 = nl.item(x);
// If it's not an element node, we ignore it.
if (wn2.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
NamedNodeMap attrs = wn2.getAttributes();
Node keyNode = attrs.getNamedItem("key");
String key = keyNode.getTextContent();
Vector<String> values = null;
if (wn2.hasChildNodes()) {
values = processIconMapSubNodes(wn2);
}
retVal.getIconMap().put(key, values);
}
}
private static Vector<String> processIconMapSubNodes(Node wn) {
Vector<String> values = new Vector<String>();
NodeList nl = wn.getChildNodes();
for (int x=0; x<nl.getLength(); x++) {
Node wn2 = nl.item(x);
// If it's not an element node, we ignore it.
if (wn2.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
NamedNodeMap attrs = wn2.getAttributes();
Node keyNode = attrs.getNamedItem("name");
String key = keyNode.getTextContent();
if (null != key && !key.isEmpty()) {
values.add(key);
}
}
return values;
}
public void addSubForce(ForceStub sub) {
subForces.add(sub);
}
}