Source Code Cross Referenced for EventRecorder.java in  » Testing » abbot-1.0.1 » abbot » editor » recorder » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Testing » abbot 1.0.1 » abbot.editor.recorder 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package abbot.editor.recorder;
002:
003:        import java.awt.*;
004:        import java.awt.event.*;
005:        import java.lang.reflect.*;
006:        import java.text.MessageFormat;
007:        import java.util.*;
008:
009:        import javax.swing.*;
010:
011:        import abbot.*;
012:        import abbot.i18n.Strings;
013:        import abbot.script.*;
014:        import abbot.script.Action;
015:        import abbot.script.Event;
016:        import abbot.script.Resolver;
017:        import abbot.tester.Robot;
018:        import abbot.util.AWT;
019:
020:        /** 
021:         * Provides recording of raw AWT events and high-level semantic events.
022:         * This is the main controller for any SemanticRecorder objects.
023:         */
024:
025:        // TODO: Are there other instances (cf JInternalFrame) where we'd like this
026:        // recorder to be the listener to other events?
027:        // TODO: add internal frame listener, re-post events when heard
028:        // TODO: discard events on LAF pieces of internal frames
029:        // TODO: extract filters as plugins
030:        // TODO: run all semantic recorder tests through this class, using canned
031:        // event streams instead of robot-generated events; keep the robot-generated
032:        // event streams, though, to test whether the stream has changed
033:        public class EventRecorder extends Recorder implements  SemanticEvents {
034:
035:            private static final String ANY_KEY = null;
036:            private static final int EITHER = 0;
037:            private static final int PRESS = 1;
038:            private static final int RELEASE = 2;
039:            private boolean captureMotion;
040:            private long lastStepTime;
041:            ArrayList steps = new ArrayList();
042:
043:            /** Put all built-in recorder classes here.  Don't worry though, 'cause if
044:             * it doesn't get added here it'll get found dynamically.
045:             */
046:            private static final Class[] recorderClasses = {
047:                    AbstractButton.class, Component.class, Container.class,
048:                    Dialog.class, Frame.class, JComboBox.class,
049:                    JComponent.class, JInternalFrame.class, JList.class,
050:                    JMenuItem.class, JTabbedPane.class, JTable.class,
051:                    JTree.class, Window.class, };
052:
053:            /** Create a Recorder for use in capturing raw AWTEvents.  Indicate
054:             * whether mouse motion should be captured, and what semantic event type
055:             * to capture.
056:             */
057:            public EventRecorder(Resolver resolver, boolean captureMotion) {
058:                super (resolver);
059:                this .captureMotion = captureMotion;
060:                // Install existing semantic recorders
061:                for (int i = 0; i < recorderClasses.length; i++) {
062:                    getSemanticRecorder(recorderClasses[i]);
063:                }
064:            }
065:
066:            /** Return the name of the type of GUI action to be recorded. */
067:            public String toString() {
068:                return captureMotion ? Strings.get("actions.capture-all")
069:                        : Strings.get("actions.capture");
070:            }
071:
072:            public void start() {
073:                super .start();
074:                steps.clear();
075:                MessageFormat mf = new MessageFormat(Strings.get("RecordingX"));
076:                setStatus(mf.format(new Object[] { toString() }));
077:                lastStepTime = getLastEventTime();
078:            }
079:
080:            private boolean isKey(Step step, String code, int type) {
081:                boolean match = false;
082:                if (step instanceof  Event) {
083:                    Event se = (Event) step;
084:                    match = "KeyEvent".equals(se.getType())
085:                            && (type == EITHER
086:                                    || (type == PRESS && "KEY_PRESSED"
087:                                            .equals(se.getKind())) || (type == RELEASE && "KEY_RELEASED"
088:                                    .equals(se.getKind())))
089:                            && (code == ANY_KEY || code.equals(se
090:                                    .getAttribute(XMLConstants.TAG_KEYCODE)));
091:                }
092:                return match;
093:            }
094:
095:            private boolean isKeyString(Step step) {
096:                return (step instanceof  Action)
097:                        && ((Action) step).getMethodName().equals(
098:                                "actionKeyString");
099:            }
100:
101:            private boolean isKeyStroke(Step step, String keycode) {
102:                if (step instanceof  Action) {
103:                    Action action = (Action) step;
104:                    if (action.getMethodName().equals("actionKeyStroke")) {
105:                        String[] args = action.getArguments();
106:                        return (keycode == ANY_KEY
107:                                || (args.length > 1 && args[1].equals(keycode)) || (keycode
108:                                .startsWith("VK_NUMPAD") && args[1]
109:                                .equals("VK_" + keycode.substring(9))));
110:                    }
111:                }
112:                return false;
113:            }
114:
115:            private void removeTerminalShift() {
116:                // Remove the terminal SHIFT keypress
117:                if (steps.size() > 0) {
118:                    Step step = (Step) steps.get(steps.size() - 1);
119:                    while (isKey(step, "VK_SHIFT", PRESS)) {
120:                        steps.remove(step);
121:                        if (steps.size() == 0)
122:                            break;
123:                        step = (Step) steps.get(steps.size() - 1);
124:                    }
125:                }
126:            }
127:
128:            /** Eliminate redundant modifier keys surrounding keystrokes or
129:             * keystrings.
130:             */
131:            private void removeExtraModifiers() {
132:                setStatus("Removing extra modifiers");
133:                for (int i = 0; i < steps.size(); i++) {
134:                    Step step = (Step) steps.get(i);
135:                    if (isKey(step, ANY_KEY, PRESS)) {
136:                        Event se = (Event) step;
137:                        String cs = se.getAttribute(XMLConstants.TAG_KEYCODE);
138:                        int code = AWT.getKeyCode(cs);
139:                        boolean remove = false;
140:                        boolean foundKeyStroke = false;
141:                        if (AWT.isModifier(code)) {
142:                            for (int j = i + 1; j < steps.size(); j++) {
143:                                Step next = (Step) steps.get(j);
144:                                if (isKey(next, cs, RELEASE)) {
145:                                    if (foundKeyStroke) {
146:                                        steps.remove(j);
147:                                        remove = true;
148:                                    }
149:                                    break;
150:                                } else if (isKeyStroke(next, ANY_KEY)
151:                                        || isKeyString(next)) {
152:                                    foundKeyStroke = true;
153:                                    remove = true;
154:                                } else if (!isKey(next, ANY_KEY, EITHER)) {
155:                                    break;
156:                                }
157:                            }
158:                        }
159:                        if (remove) {
160:                            steps.remove(i--);
161:                        }
162:                    }
163:                }
164:            }
165:
166:            /** Combine multiple keystroke actions into keystring actions. */
167:            private void coalesceKeyStrings() {
168:                setStatus("Coalescing key strings");
169:                for (int i = 0; i < steps.size(); i++) {
170:                    Step step = (Step) steps.get(i);
171:                    if (isKeyString(step)) {
172:                        int j = i;
173:                        while (++j < steps.size()) {
174:                            Step next = (Step) steps.get(j);
175:                            if (isKeyString(next)) {
176:                                Action action = (Action) step;
177:                                String[] args1 = action.getArguments();
178:                                String[] args2 = ((Action) next).getArguments();
179:                                action.setArguments(new String[] { args1[0],
180:                                        args1[1] + args2[1] });
181:                                setStatus("Joining '" + args1[1] + "' and '"
182:                                        + args2[1] + "'");
183:                                steps.remove(j--);
184:                            } else {
185:                                setStatus("Next step is not a key string: "
186:                                        + next);
187:                                break;
188:                            }
189:                        }
190:                    }
191:                }
192:            }
193:
194:            /** Eliminate redundant key press/release events surrounding a keytyped
195:             * event.  
196:             */
197:            private void coalesceKeyEvents() {
198:                setStatus("Coalescing key events");
199:                for (int i = 0; i < steps.size(); i++) {
200:                    Step step = (Step) steps.get(i);
201:                    if (isKey(step, ANY_KEY, PRESS)) {
202:                        // In the case of modifiers, remove only if the presence of
203:                        // the key down/up is redundant.
204:                        Event se = (Event) step;
205:                        String cs = se.getAttribute(XMLConstants.TAG_KEYCODE);
206:                        int code = AWT.getKeyCode(cs);
207:                        // OSX option modifier should be ignored, since it is used to
208:                        // generate input method events.
209:                        boolean isOSXOption = Platform.isOSX()
210:                                && code == KeyEvent.VK_ALT;
211:                        if (AWT.isModifier(code) && !isOSXOption)
212:                            continue;
213:
214:                        // In the case of non-modifier keys, walk the steps until we
215:                        // find the key release, then optionally replace the key press
216:                        // with a keystroke, or remove it if the keystroke was already
217:                        // recorded.  This sorts out jumbled key press/release events.
218:                        boolean foundKeyStroke = false;
219:                        boolean foundRelease = false;
220:                        for (int j = i + 1; j < steps.size(); j++) {
221:                            Step next = (Step) steps.get(j);
222:                            // If we find the release, remove it and this
223:                            if (isKey(next, cs, RELEASE)) {
224:                                foundRelease = true;
225:                                String target = ((Event) next).getComponentID();
226:                                steps.remove(j);
227:                                steps.remove(i);
228:                                // Add a keystroke only if we didn't find any key
229:                                // input between press and release (except on OSX,
230:                                // where the option key generates input method events
231:                                // which aren't recorded). 
232:                                if (!foundKeyStroke && !isOSXOption) {
233:                                    String mods = se
234:                                            .getAttribute(XMLConstants.TAG_MODIFIERS);
235:                                    String[] args = (mods == null
236:                                            || "0".equals(mods) ? new String[] {
237:                                            target, cs } : new String[] {
238:                                            target, cs, mods });
239:                                    Step typed = new Action(getResolver(),
240:                                            null, "actionKeyStroke", args);
241:                                    steps.add(i, typed);
242:                                    setStatus("Insert artifical " + typed);
243:                                } else {
244:                                    setStatus("Removed redundant key events ("
245:                                            + cs + ")");
246:                                    --i;
247:                                }
248:                                break;
249:                            } else if (isKeyStroke(next, ANY_KEY)
250:                                    || isKeyString(next)) {
251:                                foundKeyStroke = true;
252:                                // If it's a numpad keycode, use the numpad
253:                                // keycode instead of the resulting numeric character
254:                                // keystroke. 
255:                                if (cs.startsWith("VK_NUMPAD")) {
256:                                    foundKeyStroke = false;
257:                                    steps.remove(j--);
258:                                }
259:                            }
260:                        }
261:                        // We don't like standalone key presses
262:                        if (!foundRelease) {
263:                            setStatus("Removed extraneous key press (" + cs
264:                                    + ")");
265:                            steps.remove(i--);
266:                        }
267:                    }
268:                }
269:            }
270:
271:            // Required for OS X, remove modifier keys when they're only used to
272:            // invoke MB2/3
273:            private boolean pruneButtonModifier = false;
274:            private int lastButton = 0;
275:
276:            /** Used only on Mac OS, to remove key modifiers that are used to simulate
277:             * mouse buttons 2 and 3.  Returns whether the event should be ignored.
278:             */
279:            private boolean pruneClickModifiers(AWTEvent event) {
280:                lastButton = 0;
281:                boolean ignoreEvent = false;
282:                if (event.getID() == MouseEvent.MOUSE_PRESSED) {
283:                    MouseEvent me = (MouseEvent) event;
284:                    int buttons = me.getModifiers()
285:                            & (MouseEvent.BUTTON2_MASK | MouseEvent.BUTTON3_MASK);
286:                    pruneButtonModifier = buttons != 0;
287:                    lastButton = buttons;
288:                } else if (event.getID() == KeyEvent.KEY_RELEASED
289:                        && pruneButtonModifier) {
290:                    pruneButtonModifier = false;
291:                    KeyEvent ke = (KeyEvent) event;
292:                    int code = ke.getKeyCode();
293:                    if ((code == KeyEvent.VK_CONTROL || code == KeyEvent.VK_ALT
294:                            && (lastButton & MouseEvent.BUTTON2_MASK) != 0)
295:                            || (code == KeyEvent.VK_META && (lastButton & MouseEvent.BUTTON3_MASK) != 0)) {
296:                        if (steps.size() > 1) {
297:                            Step step = (Step) steps.get(steps.size() - 2);
298:                            if ((code == KeyEvent.VK_CONTROL
299:                                    && isKey(step, "VK_CONTROL", PRESS) || (code == KeyEvent.VK_ALT && isKey(
300:                                    step, "VK_ALT", PRESS)))
301:                                    || (code == KeyEvent.VK_META && isKey(step,
302:                                            "VK_META", PRESS))) {
303:                                // might be another one
304:                                steps.remove(steps.size() - 2);
305:                                pruneButtonModifier = true;
306:                                ignoreEvent = true;
307:                            }
308:                        }
309:                    }
310:                }
311:                return ignoreEvent;
312:            }
313:
314:            /** Ignore any key presses at the end of the recording. */
315:            private void removeTrailingKeyPresses() {
316:                while (steps.size() > 0
317:                        && isKey((Step) steps.get(steps.size() - 1), ANY_KEY,
318:                                PRESS)) {
319:                    steps.remove(steps.size() - 1);
320:                }
321:            }
322:
323:            /** Remove keypress events preceding and following ActionMap actions. */
324:            private void removeShortcutModifierKeyPresses() {
325:                int current = 0;
326:                int mask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
327:                String modifier = AWT.getKeyCode(AWT.maskToKeyCode(mask));
328:                while (current < steps.size()) {
329:                    Step step = (Step) steps.get(current);
330:                    if (isKey(step, modifier, PRESS)) {
331:                        Log.debug("Found possible extraneous modifier");
332:                        int keyDown = current;
333:                        Action action = null;
334:                        while (++current < steps.size()) {
335:                            step = (Step) steps.get(current);
336:                            if (step instanceof  Action) {
337:                                if ("actionActionMap".equals(((Action) step)
338:                                        .getMethodName())) {
339:                                    action = (Action) step;
340:                                    continue;
341:                                }
342:                            } else if (isKey(step, modifier, RELEASE)) {
343:                                if (action != null) {
344:                                    Log
345:                                            .debug("Removing extraneous shortcut modifier");
346:                                    steps.remove(current);
347:                                    steps.remove(keyDown);
348:                                    current = keyDown - 1;
349:                                }
350:                            }
351:                            break;
352:                        }
353:                    }
354:                    ++current;
355:                }
356:            }
357:
358:            /** Insert an arbitrary script step into the currently recorded stream. */
359:            public void insertStep(Step step) {
360:                steps.add(step);
361:                if ((step instanceof  Assert)
362:                        && ((Assert) step).getMethodName().equals(
363:                                "assertFrameShowing")) {
364:                    long timeout = ((Assert) step).getTimeout();
365:                    long delta = System.currentTimeMillis() - lastStepTime;
366:                    if (delta > timeout)
367:                        timeout += delta;
368:                    ((Assert) step).setTimeout(timeout);
369:                }
370:                lastStepTime = getLastEventTime();
371:            }
372:
373:            /**
374:             * Return a sequence containing all the semantic and basic events captured
375:             * thus far.
376:             */
377:            protected Step createStep() {
378:                removeTerminalShift();
379:                coalesceKeyEvents();
380:                removeExtraModifiers();
381:                coalesceKeyStrings();
382:                removeShortcutModifierKeyPresses();
383:                removeTrailingKeyPresses();
384:
385:                return new Sequence(getResolver(), null, steps);
386:            }
387:
388:            /** The current semantic recorder, if any. */
389:            private SemanticRecorder semanticRecorder = null;
390:
391:            /** Return whether an event was generated.  Assumes a SemanticRecorder is
392:                active.
393:                @throws RecordingFailedException if an error was encountered.
394:             */
395:            private boolean saveSemanticEvent() throws RecordingFailedException {
396:                Log.log("Storing event from current semantic recorder");
397:                try {
398:                    Step step = semanticRecorder.getStep();
399:                    if (step != null) {
400:                        insertStep(step);
401:                        setStatus("Added " + step);
402:                    } else {
403:                        setStatus("No semantic event found, events skipped");
404:                    }
405:                    semanticRecorder = null;
406:                    return step != null;
407:                } catch (BugReport bug) {
408:                    throw new RecordingFailedException(bug);
409:                } catch (Exception e) {
410:                    Log.log("Recording failed when saving action: " + e);
411:                    String msg = Strings.get("editor.recording.exception");
412:                    throw new RecordingFailedException(new BugReport(msg, e));
413:                }
414:            }
415:
416:            public void terminate() throws RecordingFailedException {
417:                Log.log("EventRecorder terminated");
418:                if (semanticRecorder != null) {
419:                    saveSemanticEvent();
420:                }
421:            }
422:
423:            /** Handle an event.  This can either be ignored or contribute to the
424:             * recording.
425:             * For a given event, if no current semantic recorder is active,
426:             * select one based on the event's component.  If the semantic recorder
427:             * accepts the event, then it is used to consume each subsequent event,
428:             * until its recordEvent method returns true, indicating that the semantic
429:             * event has completed.
430:             */
431:            protected void recordEvent(AWTEvent event)
432:                    throws RecordingFailedException {
433:
434:                // Discard any key/button release events at the start of the recording.
435:                if (steps.size() == 0 && event.getID() == KeyEvent.KEY_RELEASED) {
436:                    Log.log("Ignoring initial release event");
437:                    return;
438:                }
439:
440:                SemanticRecorder newRecorder = null;
441:
442:                // Process extraneous key modifiers used to simulate mouse buttons
443:                // Only check events while we have no semantic recorder, though,
444:                // because we wish to ignore everything between the modifiers
445:                if (Platform.isMacintosh() && semanticRecorder == null) {
446:                    if (pruneClickModifiers(event))
447:                        return;
448:                }
449:
450:                if (semanticRecorder == null) {
451:                    SemanticRecorder sr = (event.getSource() instanceof  Component) ? getSemanticRecorder((Component) event
452:                            .getSource())
453:                            // Use ComponentRecorder for MenuComponents
454:                            : getSemanticRecorder(Component.class);
455:                    if (sr.accept(event)) {
456:                        semanticRecorder = newRecorder = sr;
457:                        setStatus("Recording semantic event with " + sr);
458:                        if (event.getSource() instanceof  JInternalFrame) {
459:                            // Ideally, adding an extra listener would be done by the
460:                            // JInternalFrameRecorder, but the object needs more state
461:                            // than is available to the recorder (notably to be able
462:                            // to send events to the primary recorder).  If something
463:                            // else turns up similar to this, then the EventRecorder
464:                            // should be made available to the semantic recorders.
465:                            //
466:                            // Must add a listener, since COMPONENT_HIDDEN is not sent
467:                            // on JInternalFrame close (1.4.1).
468:                            JInternalFrame f = (JInternalFrame) event
469:                                    .getSource();
470:                            new InternalFrameWatcher(f);
471:                        }
472:                    }
473:                }
474:
475:                // If we're currently recording a semantic event, continue to do so
476:                if (semanticRecorder != null) {
477:                    boolean consumed = semanticRecorder.record(event);
478:                    boolean finished = semanticRecorder.isFinished();
479:                    if (finished) {
480:                        Log.debug("Semantic recorder is finished");
481:                        saveSemanticEvent();
482:                    }
483:                    // If not consumed, need to check for semantic recorder (again)
484:                    // (but avoid recursing indefinitely)
485:                    if (!consumed && newRecorder == null) {
486:                        Log.debug("Event was not consumed, parse it again");
487:                        recordEvent(event);
488:                    }
489:                } else {
490:                    captureRawEvent(event);
491:                }
492:            }
493:
494:            /** Capture the given event as a raw event. */
495:            private void captureRawEvent(AWTEvent event) {
496:
497:                // FIXME maybe measure time delay between events and insert delay
498:                // events? 
499:                int id = event.getID();
500:                boolean capture = false;
501:                switch (id) {
502:                case MouseEvent.MOUSE_PRESSED:
503:                case MouseEvent.MOUSE_RELEASED:
504:                    capture = true;
505:                    break;
506:                case KeyEvent.KEY_PRESSED:
507:                case KeyEvent.KEY_RELEASED:
508:                    KeyEvent e = (KeyEvent) event;
509:                    capture = e.getKeyCode() != KeyEvent.VK_UNDEFINED;
510:                    if (!capture) {
511:                        Log.warn("VM bug: no valid keycode on key "
512:                                + (id == KeyEvent.KEY_PRESSED ? "press"
513:                                        : "release"));
514:                    }
515:                    break;
516:                case MouseEvent.MOUSE_ENTERED:
517:                case MouseEvent.MOUSE_EXITED:
518:                case MouseEvent.MOUSE_MOVED:
519:                case MouseEvent.MOUSE_DRAGGED:
520:                    capture = captureMotion;
521:                    break;
522:                default:
523:                    break;
524:                }
525:                if (capture) {
526:                    Event step = new Event(getResolver(), null, event);
527:                    insertStep(step);
528:                    setStatus("Added event " + step);
529:                }
530:            }
531:
532:            /** Events of interest when recording all actions. */
533:            public static final long RECORDING_EVENT_MASK = AWTEvent.MOUSE_EVENT_MASK
534:                    | AWTEvent.MOUSE_MOTION_EVENT_MASK
535:                    | AWTEvent.KEY_EVENT_MASK | AWTEvent.WINDOW_EVENT_MASK
536:                    /*| AWTEvent.PAINT_EVENT_MASK*/
537:                    /*| AWTEvent.HIERARCHY_EVENT_MASK
538:                      | AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK*/
539:                    | AWTEvent.COMPONENT_EVENT_MASK | AWTEvent.FOCUS_EVENT_MASK
540:                    // required for non-standard input 
541:                    | AWTEvent.INPUT_METHOD_EVENT_MASK
542:                    // For java.awt.Choice selections
543:                    | AWTEvent.ITEM_EVENT_MASK
544:                    // required to capture MenuItem actions
545:                    | AWTEvent.ACTION_EVENT_MASK;
546:
547:            /** Return the events of interest to this Recorder.  */
548:            public long getEventMask() {
549:                return RECORDING_EVENT_MASK;
550:            }
551:
552:            /** Maps component classes to corresponding semantic recorders. */
553:            private HashMap semanticRecorders = new HashMap();
554:
555:            /** Return the semantic recorder for the given component. */
556:            private SemanticRecorder getSemanticRecorder(Component comp) {
557:                // FIXME extract into AWT.getLAFParent?
558:                // Account for LAF implementations that use a JButton on top
559:                // of the combo box
560:                if ((comp instanceof  JButton)
561:                        && (comp.getParent() instanceof  JComboBox)) {
562:                    comp = comp.getParent();
563:                }
564:                // Account for LAF components of JInternalFrame
565:                else if (AWT.isInternalFrameDecoration(comp)) {
566:                    while (!(comp instanceof  JInternalFrame))
567:                        comp = comp.getParent();
568:                }
569:                return getSemanticRecorder(comp.getClass());
570:            }
571:
572:            /** Return the semantic recorder for the given component class. */
573:            private SemanticRecorder getSemanticRecorder(Class cls) {
574:                if (!(Component.class.isAssignableFrom(cls))) {
575:                    throw new IllegalArgumentException(
576:                            "Class must derive from " + "Component");
577:                }
578:                SemanticRecorder sr = (SemanticRecorder) semanticRecorders
579:                        .get(cls);
580:                if (sr == null) {
581:                    Class ccls = Robot.getCanonicalClass(cls);
582:                    if (ccls != cls) {
583:                        sr = getSemanticRecorder(ccls);
584:                        // Additionally cache the mapping from the non-canonical class
585:                        semanticRecorders.put(cls, sr);
586:                        return sr;
587:                    }
588:                    String cname = Robot.simpleClassName(cls);
589:                    try {
590:                        cname = "abbot.editor.recorder." + cname + "Recorder";
591:                        Class recorderClass = Class.forName(cname);
592:                        Constructor ctor = recorderClass
593:                                .getConstructor(new Class[] { Resolver.class, });
594:                        sr = (SemanticRecorder) ctor
595:                                .newInstance(new Object[] { getResolver() });
596:                        sr.addActionListener(getListener());
597:                    } catch (InvocationTargetException e) {
598:                        Log.warn(e);
599:                    } catch (NoSuchMethodException e) {
600:                        sr = getSemanticRecorder(cls.getSuperclass());
601:                    } catch (InstantiationException e) {
602:                        sr = getSemanticRecorder(cls.getSuperclass());
603:                    } catch (IllegalAccessException iae) {
604:                        sr = getSemanticRecorder(cls.getSuperclass());
605:                    } catch (ClassNotFoundException cnf) {
606:                        sr = getSemanticRecorder(cls.getSuperclass());
607:                    }
608:                    // Cache the results for future reference
609:                    semanticRecorders.put(cls, sr);
610:                }
611:                return sr;
612:            }
613:
614:            /** Special adapter to catch events on JInternalFrame instances. */
615:            private class InternalFrameWatcher extends
616:                    AbstractInternalFrameWatcher {
617:                public InternalFrameWatcher(JInternalFrame f) {
618:                    super (f);
619:                }
620:
621:                protected void dispatch(AWTEvent e) {
622:                    record(e);
623:                }
624:            }
625:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.