package tmcsim.client;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import java.util.Vector;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import tmcsim.common.CADProtocol.CAD_COMMANDS;
import tmcsim.common.CADProtocol.CAD_FIELD_CODES;
import tmcsim.common.CADProtocol.DATA_TAGS;
/**
* CADCommandParser is used to parse user input from the CAD command line.
* The text is parsed for specific CAD command tokens and Field Codes
* as specified by the offical CAD syntax. The parseCommand() method
* is used to parse a command line into the XML command Element that
* will be sent to the CAD Simulator.
* TODO Where is this specified???
*
* @author Matthew Cechini
* @version
*/
public class CADCommandParser {
/**
* Inner class used in parsing CAD Command Lines.
* @author Matthew
*/
private class CommandItem {
/** Field Code Mnemonic. */
public String mnemonic;
/** Associated data. */
public String value;
public CommandItem(String m, String v) {
mnemonic = m;
value = v;
}
}
/**
* This method parses the parameter command line for CAD commands. The
* command text is tokenized by the '.' character, which is a delimiter
* for CAD commands. The first parsed token specifies which CAD
* command is being performed. If the token matches a valid CAD command,
* the remaining command line is parsed for other '.' delimeted information
* that accompanies that command.
* As the command line is parsed, XML Elements are added to the root
* parameter Element to create a command message that will be sent to
* the CAD Simulator. The individual XML schemas are viewable ????
* If the command line is not properly formed, an Exception is thrown.
* CAD Command syntax is viewable ????
* TODO Where are they available???
*
*
* The following table specifies the valid CAD command tokens, their
* associated CAD Command, the additional information, and error states.
*
*
*
*
* | CAD Command Token |
* CAD Command |
* Additional Information |
* Possible Errors |
*
*
* | IB |
* Incident Board |
* None |
* None |
*
*
* | II |
* Incident Inquiry |
* Numerical log number |
* Log number contains invalid characters. |
*
*
* | SA |
* Incident Summary By Area |
* None |
* None |
*
*
* | UI |
* Incident Update |
* 1) Numerical log number (optional)
* 2) CAD Field Codes with associated data |
* Missing Field Codes. |
*
*
* | TO |
* Routed Mssage |
* 1) Recipient CAD Position Numbers or Mnemonics
* 2) Message text |
* 1) Missing Recipients
* 2) Missing Message Field Code |
*
*
* | OF |
* Log Terminal Off |
* None |
* None |
*
*
*
*
*
* @param currElem Document Element to add command tags to.
* @param commandText Command line text to parse.
* @throws Exception
*/
public void parseCommand(Element currElem, String commandText) throws Exception {
StringTokenizer tokenizer = new StringTokenizer(commandText, ".");
String token;
Document theDoc = currElem.getOwnerDocument();
Element cmdElem = null;
if(tokenizer.countTokens() >= 1 && commandText.indexOf(".") != -1) {
token = tokenizer.nextToken();
//INCIDENT_BOARD Request
if(token.equals(CAD_COMMANDS.INCIDENT_BOARD.mnemonic)) {
cmdElem = theDoc.createElement(CAD_COMMANDS.INCIDENT_BOARD.fullName);
currElem.appendChild(cmdElem);
}
//INCIDENT_INQUIRY Request
else if(token.equals(CAD_COMMANDS.INCIDENT_INQUIRY.mnemonic)) {
try {
Integer logNumber = Integer.valueOf(tokenizer.nextToken().trim());
cmdElem = theDoc.createElement(CAD_COMMANDS.INCIDENT_INQUIRY.fullName);
cmdElem.appendChild(theDoc.createTextNode(logNumber.toString()));
currElem.appendChild(cmdElem);
} catch (Exception e) {
//catch NumberFormatException
throw new Exception();
}
}
//INCIDENT_SUMMARY Request
else if(token.equals(CAD_COMMANDS.INCIDENT_SUMMARY.mnemonic)) {
cmdElem = theDoc.createElement(CAD_COMMANDS.INCIDENT_SUMMARY.fullName);
currElem.appendChild(cmdElem);
}
//INCIDENT_UPDATE Request
else if(token.equals(CAD_COMMANDS.INCIDENT_UPDATE.mnemonic)) {
Vector commands = new Vector();
//ascertain if the next token is a number, if so, we're updating a
//specific log, else updating the current log(assuming we're looking at one)
cmdElem = theDoc.createElement(CAD_COMMANDS.INCIDENT_UPDATE.fullName);
currElem.appendChild(cmdElem);
try {
token = tokenizer.nextToken().trim();
Integer logNumber = new Integer(token);
cmdElem.setAttribute(DATA_TAGS.LOG_NUM.tag, logNumber.toString());
}
//"UI." missing information
catch (NoSuchElementException nsee) {throw new Exception();}
//UI.xxx where xxx not a number, assume UI.D/ format
catch (NumberFormatException nfe) {
commands.add(new CommandItem(token.substring(0,2), token.substring(2,token.length())));
}
while(tokenizer.hasMoreTokens()) {
token = tokenizer.nextToken().trim();
commands.add(new CommandItem(token.substring(0,2), token.substring(2,token.length())));
}
parseIncidentUpdate(cmdElem, commands);
}
//ROUTED_MESSAGE Request
else if(token.equals(CAD_COMMANDS.ROUTED_MESSAGE.mnemonic)) {
String message = "";
String destPositions = "";
//comma delimited
destPositions = tokenizer.nextToken();
//in case there is a . in the following text
while(tokenizer.hasMoreTokens())
message += tokenizer.nextToken();
if(message.substring(0,2).equalsIgnoreCase(CAD_FIELD_CODES.MESSAGE.mnemonic)) {
cmdElem = theDoc.createElement(CAD_COMMANDS.ROUTED_MESSAGE.fullName);
currElem.appendChild(cmdElem);
Element destElem = theDoc.createElement(DATA_TAGS.DESTINATION.tag);
destElem.appendChild(theDoc.createTextNode(destPositions));
cmdElem.appendChild(destElem);
Element msgElem = theDoc.createElement(DATA_TAGS.MESSAGE.tag);
msgElem.appendChild(theDoc.createTextNode(message.substring(2, message.length())));
cmdElem.appendChild(msgElem);
}
else throw new Exception();
}
//ENTER_INCIDENT Request
else if(token.equals(CAD_COMMANDS.ENTER_INCIDENT.mnemonic)) {
//TODO EI Implementation??
/*
Vector commands = new Vector();
cmdElem = theDoc.createElement(CAD_COMMANDS.ENTER_INCIDENT.fullName);
currElem.appendChild(cmdElem);
while(tokenizer.hasMoreTokens()) {
token = tokenizer.nextToken().trim();
commands.add(new CommandItem(token.substring(0,2), token.substring(2,token.length())));
}
parseIncidentUpdate(cmdElem, commands);
*/
}
//TERMINAL_OFF Request
else if(token.equals(CAD_COMMANDS.TERMINAL_OFF.mnemonic)) {
cmdElem = theDoc.createElement(CAD_COMMANDS.TERMINAL_OFF.fullName);
currElem.appendChild(cmdElem);
}
//APP_CLOSE Request
else if(token.equals(CAD_COMMANDS.APP_CLOSE.mnemonic)) {
cmdElem = theDoc.createElement(CAD_COMMANDS.APP_CLOSE.fullName);
currElem.appendChild(cmdElem);
}
else throw new Exception();
}
else {
try {
Integer cadLog = Integer.parseInt(commandText.trim());
cmdElem = theDoc.createElement(CAD_COMMANDS.INCIDENT_INQUIRY.fullName);
cmdElem.appendChild(theDoc.createTextNode(cadLog.toString()));
currElem.appendChild(cmdElem);
} catch (Exception e) {
throw new Exception();
}
}
}
/**
* This method iterates through the parameter Vector of CommandItem objects.
* For each object, the appropriate Incident information is extracted
* and added as a tag to the parameter XML Element.
*
* @param currElem XML Element to append Incident information tags to.
* @param commands Vector of CommandItems to parse for Incident information.
*/
public void parseIncidentUpdate(Element currElem, Vector commands) {
String witnessName = null;
String witnessAddr = null;
String witnessPhone = null;
Document theDoc = currElem.getOwnerDocument();
for(CommandItem item : commands) {
//Address of Witness
if(item.mnemonic.equals(CAD_FIELD_CODES.WITNESS_ADDRESS.mnemonic)) {
//System.out.print("A");
witnessAddr = item.value;
}
//Beat
else if(item.mnemonic.equals(CAD_FIELD_CODES.BEAT.mnemonic)) {
//System.out.print("B");
Element beatElem = theDoc.createElement(CAD_FIELD_CODES.BEAT.fullName);
beatElem.appendChild(theDoc.createTextNode(item.value));
currElem.appendChild(beatElem);
}
//Callbox
else if(item.mnemonic.equals(CAD_FIELD_CODES.CALLBOX.mnemonic)) {
//System.out.print("C");
//xmlOut.writeTag(CALLBOX, commandMap.get(key));
}
//Details
else if(item.mnemonic.equals(CAD_FIELD_CODES.DETAILS.mnemonic)) {
//System.out.print("D");
Element detailElem = theDoc.createElement(CAD_FIELD_CODES.DETAILS.fullName);
//if the details contains a '|' character, the text is sensitive. Remove
//the pipe and mark the detail as sensitive.
if(item.value.contains("|")) {
StringBuffer detailBuf = new StringBuffer();
detailBuf.append(item.value.substring(0, item.value.indexOf("|")));
detailBuf.append(item.value.substring(item.value.indexOf("|") + 1,
item.value.length()));
detailElem.setAttribute(DATA_TAGS.SENSITIVE.tag,
new Boolean(true).toString());
detailElem.appendChild(theDoc.createTextNode(detailBuf.toString()));
}
else {
detailElem.setAttribute(DATA_TAGS.SENSITIVE.tag,
new Boolean(false).toString());
detailElem.appendChild(theDoc.createTextNode(item.value));
}
currElem.appendChild(detailElem);
}
//Handling Unit
else if(item.mnemonic.equals(CAD_FIELD_CODES.HANDLING_UNIT.mnemonic)) {
//System.out.print("H");
Element unitElem = theDoc.createElement(CAD_FIELD_CODES.HANDLING_UNIT.fullName);
unitElem.appendChild(theDoc.createTextNode(item.value));
currElem.appendChild(unitElem);
}
//IncidentNumber
else if(item.mnemonic.equals(CAD_FIELD_CODES.INCIDENT_NUMBER.mnemonic)) {
//System.out.print("I");
currElem.setAttribute(CAD_FIELD_CODES.INCIDENT_NUMBER.fullName, item.value);
}
//Location
else if(item.mnemonic.equals(CAD_FIELD_CODES.LOCATION.mnemonic)) {
//System.out.print("L");
currElem.setAttribute(DATA_TAGS.FULL_LOCATION.tag, item.value);
currElem.setAttribute(DATA_TAGS.TRUNC_LOCATION.tag, item.value);
}
//Priority
else if(item.mnemonic.equals(CAD_FIELD_CODES.PRIORITY.mnemonic)) {
//System.out.print("P");
currElem.setAttribute(CAD_FIELD_CODES.PRIORITY.fullName, item.value);
}
//Routing mnemonic
else if(item.mnemonic.equals(CAD_FIELD_CODES.ROUTE.mnemonic)) {
//System.out.print("R");
Element unitElem = theDoc.createElement(CAD_FIELD_CODES.ROUTE.fullName);
unitElem.appendChild(theDoc.createTextNode(item.value));
currElem.appendChild(unitElem);
}
//Witness Phone Number
else if(item.mnemonic.equals(CAD_FIELD_CODES.WITNESS_PHONE.mnemonic)) {
//System.out.print("N");
witnessPhone = item.value;
}
//Type
else if(item.mnemonic.equals(CAD_FIELD_CODES.TYPE.mnemonic)) {
//System.out.print("T");
currElem.setAttribute(CAD_FIELD_CODES.TYPE.fullName, item.value);
}
//Tow
else if(item.mnemonic.equals(CAD_FIELD_CODES.TOW.mnemonic)) {
//System.out.print("V");
Element towElem = theDoc.createElement(CAD_FIELD_CODES.TOW.fullName);
towElem.appendChild(theDoc.createTextNode("name=\"" + item.value + "\""));
currElem.appendChild(towElem);
}
//Witness
else if(item.mnemonic.equals(CAD_FIELD_CODES.WITNESS.mnemonic)) {
//System.out.print("W");
witnessName = item.value;
}
}
if(witnessName != null)
{
Element witnessElem = theDoc.createElement(CAD_FIELD_CODES.WITNESS.fullName);
currElem.appendChild(witnessElem);
witnessElem.setAttribute(DATA_TAGS.WITNESS_NAME.tag, witnessName);
if(witnessAddr != null)
witnessElem.setAttribute(DATA_TAGS.WITNESS_ADDR.tag, witnessAddr);
if(witnessPhone != null)
witnessElem.setAttribute(DATA_TAGS.WITNESS_PHONE.tag, witnessPhone);
}
}
}