package de.ugoe.cs.eventbench.windows; import java.util.LinkedList; import java.util.List; import de.ugoe.cs.eventbench.data.Event; import de.ugoe.cs.eventbench.windows.data.WindowsEvent; import de.ugoe.cs.eventbench.windows.data.WindowsMessage; import de.ugoe.cs.util.console.Console; /** *

* Responsible to split sequences into subsequences, such that each subsequences * contains exactly one event. *

* * @author Steffen Herbold * @version 1.0 */ public class SequenceSplitter { /** *

* Contains the current subsequence. *

*/ private List currentSequence; /** *

* Number of messages in the current sequences, that signal that a key or * mouse button has been pressed down to which not yet a message has been * found, that signals that the button has been released. *

*/ private int openDowns; /** *

* Internal flag that signals if {@link #currentSequence} needs to be * initialized. *

*/ private boolean initMessages; /** *

* The {@link EventGenerator} used to convert the subsequences into * {@link Event}s *

*/ private EventGenerator tokenGenerator; /** *

* The event sequence generated. *

*/ private List actionSequence; /** *

* Constructor. Creates a new SequenceSplitter. *

*/ public SequenceSplitter() { currentSequence = new LinkedList(); openDowns = 0; initMessages = true; tokenGenerator = new EventGenerator(); actionSequence = new LinkedList(); } /** *

* Called by the {@link MFCLogParser} every time a message is parsed. *

* * @param msg * message to be added */ public void addMessage(WindowsMessage msg) { if (startOfSequence(msg)) { if (!initMessages) { WindowsEvent currentAction = tokenGenerator .generateEvent(currentSequence); if (currentAction != null) { actionSequence.add(currentAction); } if (isKeyMessage(msg.getType()) && openDowns > 0) { Console.traceln("Key message found with open down mouse messages - will probabably result in a faulty sequence."); } } else { initMessages = false; } currentSequence = new LinkedList(); } if (isUpMessage(msg.getType())) { if (openDowns > 0) { openDowns--; } } currentSequence.add(msg); } /** *

* Returns the event sequence generated from the message that have been * added. *

* * @return generated event sequence */ public List getSequence() { return actionSequence; } /** *

* Called when a session in the log file is finished, i.e., a closing * session-node is found. *

*/ public void endSession() { WindowsEvent currentAction = tokenGenerator .generateEvent(currentSequence); if (currentAction != null) { actionSequence.add(currentAction); } } /** *

* Checks if the message starts a new subsequence and returns the result. *

* * @param msg * message that is checked * @return true, if a new subsequence begins */ private boolean startOfSequence(WindowsMessage msg) { boolean isStart = false; int msgType = msg.getType(); if (isKeyMessage(msgType)) { isStart = true; } if (isDownMessage(msgType)) { openDowns++; if (openDowns == 1) { isStart = true; } } if (isDblclkMessage(msgType)) { openDowns++; } return isStart; } /** *

* Checks if the type of a message is generated is a keyboard interaction. *

* * @param msgType * type of the message * @return true if it is a keyboard interaction; false otherwise */ private boolean isKeyMessage(int msgType) { boolean isKeyMsg = false; switch (msgType) { case MessageDefs.WM_KEYDOWN: case MessageDefs.WM_KEYUP: case MessageDefs.WM_SYSKEYDOWN: case MessageDefs.WM_SYSKEYUP: isKeyMsg = true; break; default: break; } return isKeyMsg; } /** *

* Checks if the type of a message indicates that the mouse has been pressed * down. *

* * @param msgType * type of the message * @return true if it is mouse-down message; false otherwise */ private boolean isDownMessage(int msgType) { boolean isDownMsg = false; switch (msgType) { case MessageDefs.WM_LBUTTONDOWN: case MessageDefs.WM_RBUTTONDOWN: case MessageDefs.WM_MBUTTONDOWN: case MessageDefs.WM_XBUTTONDOWN: case MessageDefs.WM_NCLBUTTONDOWN: case MessageDefs.WM_NCRBUTTONDOWN: case MessageDefs.WM_NCMBUTTONDOWN: case MessageDefs.WM_NCXBUTTONDOWN: isDownMsg = true; break; default: break; } return isDownMsg; } /** *

* Checks if the type of a message indicates that a double click has been * performed. *

* * @param msgType * type of the message * @return true if it is a double click message; false otherwise */ private boolean isDblclkMessage(int msgType) { boolean isDblclkMsg = false; switch (msgType) { case MessageDefs.WM_LBUTTONDBLCLK: case MessageDefs.WM_RBUTTONDBLCLK: case MessageDefs.WM_MBUTTONDBLCLK: case MessageDefs.WM_XBUTTONDBLCLK: case MessageDefs.WM_NCLBUTTONDBLCLK: case MessageDefs.WM_NCRBUTTONDBLCLK: case MessageDefs.WM_NCMBUTTONDBLCLK: case MessageDefs.WM_NCXBUTTONDBLCLK: isDblclkMsg = true; break; default: break; } return isDblclkMsg; } /** *

* Checks if the type of a message indicates that the mouse has been * released. *

* * @param msgType * type of the message * @return true if it is mouse-up message; false otherwise */ private boolean isUpMessage(int msgType) { boolean isUpMsg = false; switch (msgType) { case MessageDefs.WM_LBUTTONUP: case MessageDefs.WM_RBUTTONUP: case MessageDefs.WM_MBUTTONUP: case MessageDefs.WM_XBUTTONUP: case MessageDefs.WM_NCLBUTTONUP: case MessageDefs.WM_NCRBUTTONUP: case MessageDefs.WM_NCMBUTTONUP: case MessageDefs.WM_NCXBUTTONUP: isUpMsg = true; break; default: break; } return isUpMsg; } }