* a valid <code>Packet</code>.
* @throws <code>NumberFormatException</code> if the value of a numeric
* data element is not in a valid format.
*/
public static Packet decode(ParsedXML node, IGame game) {
Packet packet = null;
int command = 0;
Object[] data = null;
// Make sure we got a valid packet.
if (null == node) {
throw new IllegalArgumentException("The passed node is null.");
}
if (!node.getName().equals("packet")) {
throw new IllegalStateException(
"The passed node is not for a packet.");
}
// Figure out what type of packet this is.
String commandStr = node.getAttribute("type");
if (null == commandStr) {
throw new IllegalStateException(
"Could not determine the packet type.");
}
command = Integer.parseInt(commandStr);
// TODO : perform version checking.
// Walk the packet node's children. Try to find a "packetData" node.
Enumeration<?> children = node.elements();
while (children.hasMoreElements()) {
ParsedXML subNode = (ParsedXML) children.nextElement();
if (subNode.getName().equals("packetData")) {
// How many data elements are in the packet data?
final int count = Integer.parseInt(subNode
.getAttribute("count"));
data = new Object[count];
// Do we need to unzip the data elements?
Enumeration<?> dataElements = null;
if (subNode.getAttribute("isGzipped").equals("true")) {
// Try to find the zipped content.
String cdata = subNode.getContent();
if (null == cdata) {
Enumeration<?> cdataEnum = subNode.elements();
while (cdataEnum.hasMoreElements() && null == cdata) {
final ParsedXML cdataNode = (ParsedXML) cdataEnum
.nextElement();
if (cdataNode.getTypeName().equals("text")) {
cdata = cdataNode.getContent();
} else if (cdataNode.getTypeName().equals("cdata")) {
cdata = cdataNode.getContent();
}
}
} // End look-for-cdata-nodes
// Did we find the zipped content?
if (null == cdata) {
throw new IllegalStateException(
"Could not find CDATA for packetData.");
}
// Yup. Unencode the data from Base64.
byte[] unBase64 = Base64.decodeToBytes(cdata);
InputStream parseStream;
try {
// Unzip the data.
parseStream = new GZIPInputStream(
new ByteArrayInputStream(unBase64));
} catch (IOException ioErr) {
StringBuffer iobuf = new StringBuffer();
iobuf.append("Could not unzip data elements: ").append(
ioErr.getMessage());
throw new IllegalStateException(iobuf.toString());
}
try {
/*******************************************************
* BEGIN debug code try { parseStream.mark(64000); int
* inChar = 0; while ( -1 != (inChar =
* parseStream.read()) ) { System.out.print( (char)
* inChar ); } System.out.println( "" );
* parseStream.reset(); } catch ( IOException debugErr ) {
* debugErr.printStackTrace(); } END debug code *
******************************************************/
// Parse the XML.
ParsedXML dummyNode = TinyParser.parseXML(parseStream);
dataElements = dummyNode.elements();
} catch (ParseException parseErr) {
StringBuffer parsebuf = new StringBuffer();
parsebuf.append("Could not parse data elements: ")
.append(parseErr.getMessage());
throw new IllegalStateException(parsebuf.toString());
}
} else {
// Nope. Just return the data elements.
dataElements = subNode.elements();
}
// Walk the children, and decode them into the data array.
for (int loop = 0; dataElements.hasMoreElements(); loop++) {
data[loop] = PacketEncoder.decodeData(
(ParsedXML) dataElements.nextElement(), game);
}
} // End found-packetData-element
} // Check the next child of the packet node.
// Create and return the packet.
if (null != data) {
packet = new Packet(command, data);
} else {
packet = new Packet(command);
}
return packet;
}