* a valid <code>Board</code>.
*/
public static IBoard decode(ParsedXML node, IGame game) {
String attrStr = null;
int attrVal = 0;
Board retVal = null;
Vector<Building> buildings = new Vector<Building>();
Hashtable<Coords, InfernoTracker> infernos = new Hashtable<Coords, InfernoTracker>();
int height = 0;
int width = 0;
IHex[] hexes = null;
Coords coords = null;
Enumeration<?> subnodes = null;
ParsedXML subnode = null;
// Did we get a null node?
if (null == node) {
throw new IllegalArgumentException("The board is null.");
}
// Make sure that the node is for a Board object.
if (!node.getName().equals("board")) {
throw new IllegalStateException("Not passed a board node.");
}
// TODO : perform version checking.
// Walk the board node's children.
Enumeration<?> children = node.elements();
while (children.hasMoreElements()) {
ParsedXML child = (ParsedXML) children.nextElement();
String childName = child.getName();
// Handle null child names.
if (null == childName) {
// No-op.
}
// Did we find the boardData node?
else if (childName.equals("boardData")) {
// There should be only one boardData node.
if (null != hexes) {
throw new IllegalStateException(
"More than one 'boardData' node in a board node.");
}
// Get the number of boardData.
attrStr = child.getAttribute("height");
if (null == attrStr) {
throw new IllegalStateException(
"Couldn't decode the boardData for a board node.");
}
// Try to pull the height from the attribute string
try {
attrVal = Integer.parseInt(attrStr);
} catch (NumberFormatException exp) {
throw new IllegalStateException(
"Couldn't get an integer from " + attrStr);
}
height = attrVal;
// Do we have a valid value?
if (height < 0 || height > Board.BOARD_MAX_HEIGHT) {
throw new IllegalStateException(
"Illegal value for height: " + attrStr);
}
// Get the number of boardData.
attrStr = child.getAttribute("width");
if (null == attrStr) {
throw new IllegalStateException(
"Couldn't decode the boardData for a board node.");
}
// Try to pull the width from the attribute string
try {
attrVal = Integer.parseInt(attrStr);
} catch (NumberFormatException exp) {
throw new IllegalStateException(
"Couldn't get an integer from " + attrStr);
}
width = attrVal;
// Do we have a valid value?
if (width < 0 || width > Board.BOARD_MAX_WIDTH) {
throw new IllegalStateException("Illegal value for width: "
+ attrStr);
}
// Read the "roadsAutoExit" attribute.
// unused, and therefore removed.
// roadsAutoExit = StringUtil.parseBoolean(
// child.getAttribute("roadsAutoExit") );
// Create an array to hold all the boardData.
hexes = new IHex[height * width];
// Walk through the subnodes, parsing out hex nodes.
int numHexes = 0;
subnodes = child.elements();
while (subnodes.hasMoreElements()) {
// Is this a "hex" node?
subnode = (ParsedXML) subnodes.nextElement();
if (subnode.getName().equals("hex")) {
// Are there too many hex nodes?
if (hexes.length == numHexes) {
throw new IllegalStateException(
"Too many hexes in a board node.");
}
// Parse out this hex node.
hexes[numHexes] = HexEncoder.decode(subnode, game);
// Increment the number of boardData.
numHexes++;
} // End found-"hex"-node
} // Look at the next subnode.
// Have we found enough hex nodes?
if (numHexes < hexes.length) {
throw new IllegalStateException(
"Not enough hexes in a board node.");
}
} // End found-"boardData"-node
// Did we find the infernos node?
else if (childName.equals("infernos")) {
subnodes = child.elements();
while (subnodes.hasMoreElements()) {
subnode = (ParsedXML) subnodes.nextElement();
if (subnode.getName().equals("inferno")) {
coords = null;
InfernoTracker tracker = new InfernoTracker();
// Try to find the inferno detail nodes.
Enumeration<?> details = subnode.elements();
while (details.hasMoreElements()) {
ParsedXML detail = (ParsedXML) details
.nextElement();
// Have we found the coords detail?
if (detail.getName().equals("coords")) {
coords = CoordsEncoder.decode(detail, game);
}
// Have we found the Arrow IV inferno detail?
else if (detail.getName().equals("arrowiv")) {
// Get the burn turns attribute.
attrStr = detail.getAttribute("turns");
if (null == attrStr) {
throw new IllegalStateException(
"Couldn't decode the burn turns for an Arrow IV inferno round.");
}
// Try to pull the value from the string
try {
attrVal = Integer.parseInt(attrStr);
} catch (NumberFormatException exp) {
throw new IllegalStateException(
"Couldn't get an integer from "
+ attrStr);
}
// Add the number of Arrow IV burn turns.
tracker.add(InfernoTracker.INFERNO_IV_TURN,
attrVal);
} // End found-arrowiv-detail
// Have we found the standard inferno entry?
else if (detail.getName().equals("standard")) {
// Get the burn turns attribute.
attrStr = detail.getAttribute("turns");
if (null == attrStr) {
throw new IllegalStateException(
"Couldn't decode the burn turns for a standard inferno round.");
}
// Try to pull the value from the string
try {
attrVal = Integer.parseInt(attrStr);
} catch (NumberFormatException exp) {
throw new IllegalStateException(
"Couldn't get an integer from "
+ attrStr);
}
// Add the number of standard burn turns.
tracker.add(InfernoTracker.STANDARD_TURN,
attrVal);
} // End found-standard-detail
} // Handle the next detail node.
// We *did* find the coords, right?
if (null == coords) {
throw new IllegalStateException(
"Couldn't decode the coordinates for an inferno round.");
}
// Add this inferno tracker to the hashtable.
infernos.put(coords, tracker);
} // End found-"inferno"-subnode
} // Check the next subnode
} // End found-"infernos"-child
// Did we find the buildings node?
else if (childName.equals("buildings")) {
subnodes = child.elements();
while (subnodes.hasMoreElements()) {
subnode = (ParsedXML) subnodes.nextElement();
if (subnode.getName().equals("building")) {
Building bldg = BuildingEncoder.decode(subnode, game);
if (null != bldg) {
buildings.addElement(bldg);
}
}
} // Handle the next building
}
} // Look at the next child.
// Did we find all needed child nodes?
if (null == hexes) {
throw new IllegalStateException(
"Couldn't locate the boardData for a board node.");
}
// Construct the board.
retVal = new Board(width, height, hexes, buildings, infernos);
// Return the board for this node.
return retVal;
}