package tmcsim.cadmodels;
import java.util.LinkedList;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import tmcsim.common.ScriptException;
import tmcsim.common.CADEnums.CADScreenNum;
import tmcsim.common.CADEnums.CADScreenType;
import tmcsim.common.CADProtocol.CAD_COMMANDS;
import tmcsim.common.CADProtocol.DATA_TAGS;
/**
* RoutedMessageModel is a CADScreenModel object containing data that is
* displayed in the RoutedMessage CAD Screen. Data included in this
* object includes a list of CADRoutedMessages, the index of the current
* message item, and a boolean flag to designate whether the current message
* has been deleted. The addModelObject() method is used to update the model
* data with new information. The nextQueue(), deleteQueue(), and prevQueue()
* methods are used to control which message is the "current" message.
*
* This element parses and creates the following XML schema in its toXML() and
* fromXML() methods. The ROOT element is the parameter for those methods.
* See the class description for the CADScreenModel XML schema.
*
*
*
*
*
*
*
*
*
* @see CADScreenModel
* @author Matthew Cechini
* @version
*/
public class RoutedMessageModel extends CADScreenModel {
/** LinkedList containing received routed messages. */
private LinkedList messageList = null;
/**
* A manually incremented and decremented iterating count. Initial value
* is 0 to point to the first element in the messageList. As the list is
* traversed, added to, and removed from, this count always contains the value
* of the current message that is being displayed.
*/
private int currentListItem = 0;
/**
* Flag to designate whether the current message has been deleted by the
* user. The currentListItem counter is not updated when a queue is
* deleted until nextQueue() or prevQueue() is called. This allows a
* message to remain on the screen after it has been deleted.
*/
private boolean messageDeleted = false;
/**
* Constructor.
*
* @param num CADScreenNum for this model.
* @param messages New list of messags.
*/
public RoutedMessageModel(CADScreenNum num, LinkedList messages) {
super(CADScreenType.TO_ROUTED_MESSAGE, num);
messageList = new LinkedList();
messageList.addAll(messages);
}
/**
* Constructor. Parse the model data from the parameter node.
*
* @param newNode XML node containing model data.
* @throws ScriptException if there is an error in parsing the node.
*/
public RoutedMessageModel(Node newNode) throws ScriptException {
super(CADScreenType.TO_ROUTED_MESSAGE, CADScreenNum.ONE);
messageList = new LinkedList();
fromXML(newNode);
}
/**
* Returns the number of routed messages received to this CAD Client model.
*
* @return int number of messages that have been sent to this terminal and
* retreived from the coordinator.
*/
public int getMessageCount() {
return messageList.size();
}
/**
* Append a new message to the local linked list of CADRoutedMessages.
*
* @param updateMessages Vector of CADRoutedMessage objects that have been
* sent to this CAD terminal.
*/
public void addModelObject(Object o) {
messageList.add((CADRoutedMessage)o);
}
/**
* Method returns the routed message that was last viewed, or if this is the first
* time a method is being viewed, then the first message will be returned.
* This message may only be called if the numberOfMessages() returns a value
* greater than 0. If there are no messages, this method will throw an
* IndexOutOfBoundsException.
*
* @return CADRoutedMessage
*/
public CADRoutedMessage getCurrentMessage() throws IndexOutOfBoundsException {
return messageList.get(currentListItem);
}
/**
* Method is called to advance to the next queued message object. Update the
* message list and current message counter if a message has been deleted. If the
* currentListItem count is at the end of the message list, then start over
* at the beginning, otherwise increase the count by one.
* This method is only to be called if numberOfMessages() returns a value
* greater than 0.
*/
public boolean nextQueue() {
//update the counter if a the previous queue message was deleted
if(messageDeleted) {
messageList.remove(currentListItem);
currentListItem--;
if(currentListItem > messageList.size() - 1 ||
currentListItem < 0) {
currentListItem = 0;
}
messageDeleted = false;
}
if(messageList.size() > 0) {
if(currentListItem == messageList.size() - 1)
currentListItem = 0;
else
currentListItem++;
return true;
}
else
return false;
}
/**
* If the message being deleted is currently being viewed, set the messageDeleted
* flag to true so that the queued message will be deleted when nextQueue()
* or prevQueue() is called next. Else, if the message being deleted
* does exist in this model's list of messages, remove that message. Update
* the currentListItem counter if the message deleted is at a position
* prior to the current message.
*
* @param delMsg Queue message being deleted
*/
public void deleteQueue(CADRoutedMessage delMsg) {
int msgIndex = messageList.indexOf(delMsg);
if(msgIndex == currentListItem) {
messageDeleted = true;
}
else if(msgIndex != -1) {
messageList.remove(delMsg);
if(currentListItem > msgIndex)
currentListItem--;
}
//else msgIndex == -1 Msg already removed
}
/**
* Method is called to back up to the previous queued message object.
* Update the message list and current message counter if a message
* has been deleted. If the currentListItem count is at the beginning
* of the message list, then move to the end, otherwise decrease the
* count by one. This method is only to be called if numberOfMessages()
* returns a value greater than 0.
*/
public boolean prevQueue() {
//update the counter if a the previous queue message was deleted
if(messageDeleted) {
messageList.remove(currentListItem);
currentListItem--;
if(currentListItem > messageList.size() - 1 ||
currentListItem < 0){
currentListItem = 0;
}
messageDeleted = false;
}
if(messageList.size() > 0) {
if(currentListItem == 0)
currentListItem = messageList.size() - 1;
else
currentListItem--;
return true;
}
else
return false;
}
/**
* Determine if this routed message is a forwarded incident update.
* @return True if this message is an incident update, false if not.
*/
public boolean isIncidentUpdate() {
return messageList.get(currentListItem).incidentUpdate;
}
public void toXML(Element currElem) {
//if this is an update, then the xmloutput is contained within
//the message text
if(getCurrentMessage().incidentUpdate) {
}
//else send the current message only
else {
Document theDoc = currElem.getOwnerDocument();
Element modelElem = theDoc.createElement(CAD_COMMANDS.ROUTED_MESSAGE.fullName);
baseToXML(modelElem);
Element originElem = theDoc.createElement(DATA_TAGS.ORIGIN.tag);
originElem.appendChild(theDoc.createTextNode(String.valueOf(getCurrentMessage().fromPosition)));
modelElem.appendChild(originElem);
Element destElem = theDoc.createElement(DATA_TAGS.DESTINATION.tag);
destElem.appendChild(theDoc.createTextNode(String.valueOf(getCurrentMessage().toPosition)));
modelElem.appendChild(destElem);
Element msgElem = theDoc.createElement(DATA_TAGS.ORIGIN.tag);
msgElem.appendChild(theDoc.createTextNode(getCurrentMessage().message));
modelElem.appendChild(msgElem);
currElem.appendChild(modelElem);
}
}
public void fromXML(Node modelNode) throws ScriptException {
messageList.clear();
currentListItem = 0;
CADRoutedMessage newMessage = new CADRoutedMessage(0, 0, "", false);
modelNode = modelNode.getFirstChild();
baseFromXML(modelNode);
modelNode = modelNode.getNextSibling();
newMessage.fromPosition = Integer.parseInt(modelNode.getTextContent());
modelNode = modelNode.getNextSibling();
newMessage.toPosition = Integer.parseInt(modelNode.getTextContent());
modelNode = modelNode.getNextSibling();
newMessage.message = modelNode.getTextContent();
messageList.add(newMessage);
}
}