001: package abbot.editor.recorder;
002:
003: import java.awt.*;
004: import java.awt.event.*;
005:
006: import abbot.*;
007: import abbot.i18n.Strings;
008: import abbot.script.*;
009: import abbot.script.Resolver;
010: import abbot.tester.Robot;
011:
012: /**
013: * The <code>Recorder</code> provides a mechanism for recording an event stream and
014: * generating a sequence of script steps from that stream.
015: * <p>
016: * NOTE: when writing a recorder, be very careful not to test for
017: * platform-specific behavior, and avoid being susceptible to
018: * platform-specific bugs. Please make sure the recorder works on both
019: * pointer-focus and click-to-focus window managers, as well as on at least
020: * two platforms.<p>
021: */
022: public abstract class Recorder {
023: private ActionListener al;
024: private Resolver resolver;
025: private long lastEventTime = 0;
026:
027: /** Create a Recorder for use in converting events into script steps. */
028: public Recorder(Resolver resolver) {
029: this .resolver = resolver;
030: }
031:
032: /** The recorder supports zero or one listeners. */
033: public void addActionListener(ActionListener al) {
034: this .al = al;
035: }
036:
037: protected ActionListener getListener() {
038: return al;
039: }
040:
041: /** Start recording a new event stream. */
042: public void start() {
043: lastEventTime = System.currentTimeMillis();
044: }
045:
046: /** Indicate the end of the current event input stream. */
047: public abstract void terminate() throws RecordingFailedException;
048:
049: public long getLastEventTime() {
050: return lastEventTime;
051: }
052:
053: /** Create a step or sequence of steps based on the event stream so far. */
054: protected abstract Step createStep();
055:
056: /** Return a step or sequence of steps representing the steps created thus
057: far, or null if none.
058: */
059: public Step getStep() {
060: return createStep();
061: }
062:
063: /** Insert an arbitrary step into the recording stream. */
064: public void insertStep(Step step) {
065: // Default does nothing
066: }
067:
068: /** Process the given event.
069: @throws RecordingFailedException if an error was encountered and
070: recording should discontinue.
071: */
072: public void record(java.awt.AWTEvent event)
073: throws RecordingFailedException {
074: if (Log.isClassDebugEnabled(getClass()))
075: Log.debug("REC: " + Robot.toString(event));
076: lastEventTime = System.currentTimeMillis();
077: try {
078: recordEvent(event);
079: } catch (RecordingFailedException e) {
080: throw e;
081: } catch (Throwable thrown) {
082: Log.log("REC: Unexpected failure: " + thrown);
083: String msg = Strings.get("editor.recording.exception");
084: throw new RecordingFailedException(new BugReport(msg,
085: thrown));
086: }
087: }
088:
089: /** Implement this to actually handle the event.
090: @throws RecordingFailedException if an error was encountered and
091: recording should be discontinued.
092: */
093: protected abstract void recordEvent(AWTEvent event)
094: throws RecordingFailedException;
095:
096: /** Return the events of interest to this Recorder. */
097: public long getEventMask() {
098: return -1;
099: }
100:
101: /** @return the {@link Resolver} to be used by this <code>Recorder</code>. */
102: protected Resolver getResolver() {
103: return resolver;
104: }
105:
106: /** Indicate the current recording state, so that the status may be
107: * displayed elsewhere.
108: */
109: protected void setStatus(String msg) {
110: if (al != null) {
111: ActionEvent event = new ActionEvent(this,
112: ActionEvent.ACTION_PERFORMED, msg);
113: al.actionPerformed(event);
114: }
115: }
116: }
|