Vector buildings = new Vector(); Hashtable infernos = new Hashtable();
Vector<Building> buildings = new Vector<Building>(); Hashtable<Coords,InfernoTracker> infernos = new Hashtable<Coords,InfernoTracker>();
    public static IBoard decode( ParsedXML node, IGame game ) {        String attrStr = null;        int attrVal = 0;        Board retVal = null;        Vector buildings = new Vector();        Hashtable infernos = new Hashtable();        int height = 0;        int width = 0;        IHex[] hexes = null;        Coords coords = null;        boolean roadsAutoExit = false;        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.                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;    }