Clover coverage report - JFCUnit Test Coverage
Coverage timestamp: Mon Dec 20 2004 23:38:10 MST
file stats: LOC: 580   Methods: 16
NCLOC: 374   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
XMLRecorder.java 0% 0% 0% 0%
coverage
 1   
 package junit.extensions.jfcunit.xml;
 2   
 
 3   
 import junit.extensions.jfcunit.TestHelper;
 4   
 import junit.extensions.jfcunit.eventdata.AbstractEventData;
 5   
 import junit.extensions.jfcunit.eventdata.AbstractKeyEventData;
 6   
 import junit.extensions.jfcunit.eventdata.DragEventData;
 7   
 import junit.extensions.jfcunit.eventdata.JFCEventDataListener;
 8   
 import junit.extensions.jfcunit.eventdata.JFCEventManager;
 9   
 import junit.extensions.jfcunit.eventdata.KeyEventData;
 10   
 import junit.extensions.jfcunit.eventdata.MouseEventData;
 11   
 import junit.extensions.jfcunit.eventdata.MouseWheelEventData;
 12   
 import junit.extensions.jfcunit.finder.AbstractButtonFinder;
 13   
 import junit.extensions.jfcunit.finder.ComponentFinder;
 14   
 import junit.extensions.jfcunit.finder.Finder;
 15   
 import junit.extensions.jfcunit.finder.JMenuItemFinder;
 16   
 import junit.extensions.jfcunit.finder.NamedComponentFinder;
 17   
 import junit.extensions.jfcunit.keyboard.JFCKeyStroke;
 18   
 import junit.extensions.jfcunit.tools.Operator;
 19   
 
 20   
 import junit.extensions.xml.IXMLTestCase;
 21   
 import junit.extensions.xml.XMLException;
 22   
 import junit.extensions.xml.elements.SaveTagHandler;
 23   
 
 24   
 import org.w3c.dom.Document;
 25   
 import org.w3c.dom.Element;
 26   
 import org.w3c.dom.Node;
 27   
 
 28   
 import java.awt.Component;
 29   
 import java.awt.Container;
 30   
 import java.awt.Point;
 31   
 import java.awt.Window;
 32   
 
 33   
 import javax.swing.AbstractButton;
 34   
 import javax.swing.JDialog;
 35   
 import javax.swing.JFrame;
 36   
 import javax.swing.JMenu;
 37   
 import javax.swing.JMenuItem;
 38   
 import javax.swing.JPopupMenu;
 39   
 
 40   
 
 41   
 /**
 42   
  * <p>Title: class XMLRecorder.</p>
 43   
  * <p>Description: </p>
 44   
  * <p>Copyright: Copyright (c) 2002</p>
 45   
  * <p>Company: Hewlett-Packard Company</p>
 46   
  * @author Kevin Wilson
 47   
  * @version 1.0
 48   
  *
 49   
  * Attributes:
 50   
  *    terminator=8 sets the terminator to ctrl-h
 51   
  *       improved parsing to be added later.
 52   
  */
 53   
 public class XMLRecorder extends SaveTagHandler implements JFCEventDataListener,
 54   
     JFCXMLConstants {
 55   
     /**
 56   
      * Replay mode.
 57   
      */
 58   
     private static boolean s_replay = false;
 59   
 
 60   
     /**
 61   
      * Document of the recording.
 62   
      */
 63   
     private Document m_doc = null;
 64   
 
 65   
     /**
 66   
      * Root element of the recording.
 67   
      */
 68   
     private Element m_root = null;
 69   
 
 70   
     /**
 71   
      * Indent string for each node.
 72   
      */
 73   
     private String m_indent = null;
 74   
 
 75   
     /**
 76   
      * Terminator keystroke.
 77   
      */
 78   
     private JFCKeyStroke[] m_terminator = null;
 79   
 
 80   
     /**
 81   
      * Paused State.
 82   
      */
 83   
     private volatile boolean m_paused = false;
 84   
 
 85   
     /**
 86   
      * Index of next generated component.
 87   
      */
 88   
     private int m_compIndex = -1;
 89   
 
 90   
     /**
 91   
      * Constructor for the XML Recorder.
 92   
      * @param element element to be recorded.
 93   
      * @param testCase Test Case for the recording.
 94   
      */
 95  0
     public XMLRecorder(final Element element, final IXMLTestCase testCase) {
 96  0
         super(element, testCase);
 97  0
         m_root     = (Element) element.getParentNode();
 98  0
         m_doc      = element.getOwnerDocument();
 99   
 
 100  0
         Node previousSibling = element.getPreviousSibling();
 101  0
         int keyCode = super.getInt(element, TERMINATOR, 4);
 102  0
         JFCKeyStroke[] ks = TestHelper.getKeyMapping().getKeyStrokes(keyCode);
 103  0
         setTerminator(ks);
 104   
 
 105  0
         if (previousSibling.getNodeType() == Node.TEXT_NODE) {
 106  0
             m_indent = previousSibling.getNodeValue();
 107   
         }
 108   
     }
 109   
 
 110   
     /**
 111   
      * If the replay mode is set then the record elements are ignored.
 112   
      * @param value true if the record elements are to be ignored.
 113   
      */
 114  0
     public static void setReplay(final boolean value) {
 115  0
         s_replay = value;
 116   
     }
 117   
 
 118   
     /**
 119   
      * Set the terminator to be used to end the
 120   
      * recording session.
 121   
      * @param stroke Stroke to end the recording.
 122   
      */
 123  0
     public void setTerminator(final JFCKeyStroke[] stroke) {
 124  0
         m_terminator = stroke;
 125   
     }
 126   
 
 127   
     /**
 128   
      * Get the current record Terminator.
 129   
      * @return JFCKeyStroke which terminates the session.
 130   
      */
 131  0
     public JFCKeyStroke[] getTerminator() {
 132  0
         if (m_terminator == null) {
 133  0
             m_terminator = getDefaultTerminator();
 134   
         }
 135   
 
 136  0
         return m_terminator;
 137   
     }
 138   
 
 139   
     /**
 140   
      * Generate the finder node(s) to find the component.
 141   
      * @param comp Component to be found.
 142   
      * @return Name of the component.
 143   
      */
 144  0
     public String generateFind(final Component comp) {
 145  0
         String name = getXMLTestCase().getPropertyName(comp);
 146   
 
 147  0
         if ((name != null) && (name.length() != 0)) {
 148  0
             return name;
 149   
         }
 150   
 
 151  0
         if (comp instanceof JMenuItem) {
 152  0
             return generateMenuFind(comp);
 153   
         }
 154   
 
 155  0
         Window w = null;
 156   
 
 157  0
         if (!(comp instanceof Window)) {
 158  0
             w = javax.swing.SwingUtilities.getWindowAncestor(comp);
 159   
         }
 160   
 
 161  0
         String windowName = generateWindowFind(w);
 162  0
         name = "Component" + getComponentIndex();
 163   
 
 164  0
         String className  = comp.getClass().getName();
 165  0
         String named      = comp.getName();
 166  0
         String finderName = null;
 167  0
         Finder finder     = null;
 168  0
         String label      = null;
 169   
 
 170  0
         if (named != null) {
 171  0
             finderName     = "NamedComponentFinder";
 172  0
             finder         = new NamedComponentFinder(
 173   
                     comp.getClass(),
 174   
                     named);
 175  0
         } else if (comp instanceof AbstractButton
 176   
                 && (((AbstractButton) comp).getText() != null)) {
 177  0
             finderName     = "AbstractButtonFinder";
 178  0
             label          = ((AbstractButton) comp).getText();
 179  0
             finder         = new AbstractButtonFinder(label);
 180   
         } else {
 181  0
             finderName     = "ComponentFinder";
 182  0
             finder         = new ComponentFinder(comp.getClass());
 183   
         }
 184   
 
 185  0
         int index = TestHelper.indexOf(finder, w, comp);
 186   
 
 187  0
         if (index == -1) {
 188  0
             windowName     = null;
 189  0
             index          = TestHelper.indexOf(finder, null, comp);
 190   
         }
 191   
 
 192  0
         if (index == -1) {
 193  0
             Node comment = m_doc.createComment(
 194   
                     "Assuming zero index. Could not find index of: "
 195   
                     + comp.getClass());
 196  0
             insertNode(comment);
 197  0
             index = 0;
 198   
         }
 199   
 
 200  0
         Element e = m_doc.createElement(FIND);
 201  0
         e.setAttribute(FINDER, finderName);
 202  0
         e.setAttribute(ID, name);
 203   
 
 204  0
         if (label != null) {
 205  0
             e.setAttribute(LABEL, label);
 206   
         }
 207   
 
 208  0
         e.setAttribute(CLASS, className);
 209   
 
 210  0
         if (named != null) {
 211  0
             e.setAttribute(NAME, named);
 212   
         }
 213   
 
 214  0
         e.setAttribute(
 215   
             INDEX,
 216   
             Integer.toString(index));
 217  0
         e.setAttribute(
 218   
             OPERATION,
 219   
             Operator.Operation.toString(Operator.Operation.EQUALS));
 220   
 
 221  0
         if (windowName != null) {
 222  0
             e.setAttribute(CONTAINER, windowName);
 223   
         }
 224   
 
 225  0
         insertNode(e);
 226  0
         getXMLTestCase().addProperty(name, comp);
 227   
 
 228  0
         return name;
 229   
     }
 230   
 
 231   
     /**
 232   
      * Handle the event data by generating XML.
 233   
      * @param evtData event date generated.
 234   
      */
 235  0
     public void handleEvent(final AbstractEventData evtData) {
 236  0
         if (evtData.getComponent() == null) {
 237  0
             return;
 238   
         }
 239   
 
 240  0
         if (evtData instanceof KeyEventData) {
 241  0
             JFCKeyStroke[] terminator = getTerminator();
 242  0
             JFCKeyStroke[] strokes = ((KeyEventData) evtData).getKeyStrokes();
 243   
 
 244  0
             if (java.util.Arrays.equals(terminator, strokes)) {
 245  0
                 stop();
 246  0
                 System.err.println("Stop recording for test: "
 247   
                     + this.getTestCase().getName());
 248   
 
 249  0
                 return;
 250   
             }
 251   
         }
 252   
 
 253  0
         if (evtData instanceof DragEventData) {
 254  0
             DragEventData ded      = (DragEventData) evtData;
 255  0
             Component     comp     = ded.getSource().getComponent();
 256  0
             String        sourceId = generateFind(comp);
 257  0
             Element       src      = m_doc.createElement(SOURCE);
 258  0
             ded.getSource().populate(src);
 259  0
             src.setAttribute(REFID, sourceId);
 260   
 
 261  0
             Element e = m_doc.createElement(DRAG);
 262  0
             e.appendChild(src);
 263   
 
 264  0
             if (ded.getDest() != null) {
 265  0
                 Element dst    = m_doc.createElement(DESTINATION);
 266  0
                 String  destId = generateFind(ded.getDest().getComponent());
 267  0
                 ded.getDest().populate(dst);
 268  0
                 dst.setAttribute(REFID, destId);
 269  0
                 e.appendChild(dst);
 270   
             }
 271   
 
 272  0
             if (ded.getPoints() != null) {
 273  0
                 java.awt.Point[] p = ded.getPoints();
 274   
 
 275  0
                 for (int i = 0; i < p.length; i++) {
 276  0
                     Element pnt = m_doc.createElement(POINT);
 277  0
                     String  ref = "" + p[i].x + "," + p[i].y;
 278  0
                     pnt.setAttribute(REFERENCE, ref);
 279  0
                     e.appendChild(pnt);
 280   
                 }
 281   
             }
 282   
 
 283  0
             insertNode(e);
 284  0
         } else if (evtData instanceof MouseWheelEventData) {
 285  0
             Element e      = m_doc.createElement("wheel");
 286  0
             String  source = generateFind(evtData.getComponent());
 287  0
             e.setAttribute(REFID, source);
 288  0
             evtData.populate(e);
 289  0
             insertNode(e);
 290  0
         } else if (evtData instanceof AbstractKeyEventData) {
 291  0
             String  source = generateFind(evtData.getComponent());
 292  0
             Element e = m_doc.createElement(KEY);
 293  0
             e.setAttribute(REFID, source);
 294  0
             evtData.populate(e);
 295  0
             insertNode(e);
 296  0
         } else if (evtData instanceof AbstractEventData) {
 297  0
             String  source = generateFind(evtData.getComponent());
 298  0
             Element e = m_doc.createElement(CLICK);
 299  0
             e.setAttribute(REFID, source);
 300  0
             evtData.populate(e);
 301  0
             insertNode(e);
 302   
         }
 303   
     }
 304   
 
 305   
     /**
 306   
      * @see junit.extensions.xml.elements.AbstractTagHandler#processElement().
 307   
      * @throws XMLException is thrown if the element cannot be understood.
 308   
      */
 309  0
     public void processElement() throws XMLException {
 310  0
         validateElement();
 311   
 
 312  0
         if (s_replay) {
 313  0
             return;
 314   
         }
 315   
 
 316  0
         String term = getString(TERMINATOR);
 317  0
         if (term != null && term.length() > 0) {
 318  0
             setTerminator(new JFCKeyStroke[] {
 319   
                 new JFCKeyStroke(term)
 320   
             });
 321   
         }
 322  0
         record();
 323  0
         pause();
 324  0
         super.processElement();
 325   
     }
 326   
 
 327   
     /**
 328   
      * @see junit.extensions.xml.elements.AbstractTagHandler#validateElement().
 329   
      * @throws XMLException if the required elements are not present.
 330   
      */
 331  0
     public void validateElement() throws XMLException {
 332   
         // do the default validations from the super class
 333  0
         super.validateElement();
 334   
 
 335   
         // check the element tag name
 336  0
         checkElementTagName("record");
 337   
     }
 338   
 
 339   
     /**
 340   
      * Get the default terminator.
 341   
      * @return JFCKeyStroke used to terminate the record session.
 342   
      */
 343  0
     protected JFCKeyStroke[] getDefaultTerminator() {
 344   
         // Control D
 345  0
         return TestHelper.getKeyMapping().getKeyStrokes(4);
 346   
     }
 347   
 
 348   
     /**
 349   
      * Get the component index.
 350   
      * @return int index of component.
 351   
      */
 352  0
     private int getComponentIndex() {
 353  0
         if (m_compIndex == -1) {
 354  0
             int      max   = 0;
 355  0
             String[] names = getXMLTestCase().getPropertyNames();
 356   
 
 357  0
             for (int i = 0; i < names.length; i++) {
 358  0
                 int j;
 359   
 
 360  0
                 for (j = names[i].length() - 1;
 361  0
                         Character.isDigit(names[i].charAt(j)) && (j > 0);
 362   
                         j--) {
 363   
                     // Nothing to do.
 364   
                 }
 365   
 
 366   
                 ;
 367   
 
 368  0
                 if (j < (names[i].length() - 1)) {
 369  0
                     int number = Integer.parseInt(names[i].substring(j + 1));
 370  0
                     max = Math.max(max, number);
 371   
                 }
 372   
             }
 373   
 
 374  0
             m_compIndex = max + 1;
 375   
         }
 376   
 
 377  0
         return m_compIndex++;
 378   
     }
 379   
 
 380   
     /**
 381   
      * Generate the XML elements to locate a menu item.
 382   
      * @param comp Component to be located.
 383   
      * @return Name of the component.
 384   
      */
 385  0
     private String generateMenuFind(final Component comp) {
 386  0
         JMenuItem mi          = (JMenuItem) comp;
 387  0
         String    label       = mi.getText();
 388  0
         String    containerID = null;
 389  0
         Container parent      = mi.getParent();
 390   
 
 391  0
         if (parent instanceof JPopupMenu) {
 392  0
             JPopupMenu menu    = (JPopupMenu) mi.getParent();
 393  0
             Component  invoker = menu.getInvoker();
 394   
 
 395  0
             if (invoker instanceof JMenuItem) {
 396  0
                 containerID = generateFind(invoker);
 397   
 
 398  0
                 MouseEventData data = new MouseEventData(null, invoker, 0);
 399  0
                 data.setNumberOfClicks(0);
 400  0
                 data.setModifiers(0);
 401   
 
 402  0
                 Element e = m_doc.createElement(CLICK);
 403  0
                 e.setAttribute(REFID, containerID);
 404  0
                 data.populate(e);
 405  0
                 insertNode(e);
 406   
 
 407  0
                 if (invoker instanceof JMenu) {
 408   
                     // Get the direction of the child menu.
 409  0
                     Point popupLoc = ((JMenu) invoker).getPopupMenu()
 410   
                                       .getLocation();
 411  0
                     Point invokerLoc = invoker.getLocation();
 412  0
                     int   xPercent   = 110;
 413   
 
 414  0
                     if (popupLoc.x < invokerLoc.x) {
 415  0
                         xPercent = -10;
 416   
                     }
 417   
 
 418  0
                     data.setPosition(AbstractEventData.PERCENT);
 419  0
                     data.setReferencePoint(new Point(xPercent, 50));
 420   
 
 421  0
                     Element moveRight = m_doc.createElement(CLICK);
 422  0
                     moveRight.setAttribute(REFID, containerID);
 423  0
                     data.populate(moveRight);
 424  0
                     insertNode(moveRight);
 425   
                 }
 426   
 
 427  0
                 Element sleep = m_doc.createElement("sleep");
 428  0
                 sleep.setAttribute(DURATION, "500");
 429  0
                 insertNode(sleep);
 430   
             }
 431   
         } else {
 432  0
             Window w = javax.swing.SwingUtilities.getWindowAncestor(comp);
 433  0
             containerID = generateWindowFind(w);
 434   
         }
 435   
 
 436  0
         String name = "MenuItem" + getComponentIndex();
 437   
 
 438  0
         String className  = comp.getClass().getName();
 439  0
         String named      = comp.getName();
 440  0
         String finderName = "JMenuItemFinder";
 441  0
         Finder finder     = new JMenuItemFinder(label);
 442  0
         finder.setOperation(Operator.Operation.EQUALS);
 443   
 
 444  0
         int index = TestHelper.indexOf(finder, null, comp);
 445   
 
 446   
         // Kluge component may not be visible
 447  0
         if (index == -1) {
 448  0
             index = 0;
 449   
         }
 450   
 
 451  0
         Element e = m_doc.createElement(FIND);
 452   
 
 453  0
         if (containerID != null) {
 454  0
             e.setAttribute(CONTAINER, containerID);
 455   
         }
 456   
 
 457  0
         e.setAttribute(FINDER, finderName);
 458  0
         e.setAttribute(ID, name);
 459  0
         e.setAttribute(LABEL, label);
 460  0
         e.setAttribute(
 461   
             INDEX,
 462   
             Integer.toString(index));
 463  0
         e.setAttribute(
 464   
             OPERATION,
 465   
             Operator.Operation.toString(Operator.Operation.EQUALS));
 466   
 
 467  0
         insertNode(e);
 468  0
         getXMLTestCase().addProperty(name, comp);
 469   
 
 470  0
         return name;
 471   
     }
 472   
 
 473   
     /**
 474   
      * Generate the XML Nodes to find the window given.
 475   
      * @param w Window to be located.
 476   
      * @return Name of the window.
 477   
      */
 478  0
     private String generateWindowFind(final Component w) {
 479  0
         String name   = getXMLTestCase().getPropertyName(w);
 480  0
         String finder = null;
 481  0
         String title  = null;
 482   
 
 483  0
         if (name != null) {
 484  0
             return name;
 485   
         }
 486   
 
 487   
         // The window was not previously found,
 488   
         // so lets generate the find.
 489  0
         if (w instanceof JFrame) {
 490  0
             name       = "JFrame" + getComponentIndex();
 491  0
             title      = ((javax.swing.JFrame) w).getTitle();
 492  0
             finder     = "FrameFinder";
 493  0
         } else if (w instanceof JDialog) {
 494  0
             name       = "JDialog" + getComponentIndex();
 495  0
             title      = ((javax.swing.JDialog) w).getTitle();
 496  0
             finder     = "DialogFinder";
 497   
         }
 498   
 
 499  0
         if (title == null) {
 500  0
             title = "";
 501   
         }
 502   
 
 503  0
         if (name != null) {
 504  0
             getXMLTestCase().addProperty(name, w);
 505   
 
 506  0
             Element find = m_doc.createElement(FIND);
 507  0
             find.setAttribute(FINDER, finder);
 508  0
             find.setAttribute(TITLE, title);
 509   
 
 510  0
             String operation = Operator.Operation.toString(Operator.Operation.EQUALS);
 511  0
             find.setAttribute(OPERATION, operation);
 512  0
             find.setAttribute(ID, name);
 513  0
             find.setAttribute(INDEX, "0");
 514  0
             insertNode(find);
 515   
         }
 516   
 
 517  0
         return name;
 518   
     }
 519   
 
 520   
     /**
 521   
      * Insert the node into the tree.
 522   
      * @param e The node to be inserted.
 523   
      */
 524  0
     private void insertNode(final Node e) {
 525  0
         Node parent = getElement().getParentNode();
 526  0
         parent.insertBefore(
 527   
             e,
 528   
             getElement());
 529   
 
 530  0
         Node text = m_doc.createTextNode(m_indent);
 531  0
         parent.insertBefore(
 532   
             text,
 533   
             getElement());
 534   
     }
 535   
 
 536   
     /**
 537   
      * Pause the recording.
 538   
      */
 539  0
     private void pause() {
 540  0
         m_paused = true;
 541   
 
 542   
         // stop the test case to allow the recording.
 543  0
         while (m_paused) {
 544  0
             try {
 545  0
                 Thread.yield();
 546  0
                 Thread.currentThread().sleep(500);
 547   
             } catch (java.lang.InterruptedException ie) {
 548   
                 // Ignore
 549   
             }
 550   
         }
 551   
     }
 552   
 
 553   
     /**
 554   
      * Start the recording.
 555   
      */
 556  0
     private void record() {
 557  0
         JFCKeyStroke[] strokes = getTerminator();
 558  0
         System.err.println("Start recording for test: "
 559   
             + this.getTestCase().getName());
 560  0
         System.err.println("Press " + strokes[0].toString()
 561   
             + " to complete the recording.");
 562   
 
 563  0
         Node comment = m_doc.createComment("started recording "
 564   
                 + new java.util.Date().toString());
 565  0
         this.insertNode(comment);
 566  0
         JFCEventManager.setRecording(true);
 567  0
         JFCEventManager.getEventManager().addJFCEventDataListener(this);
 568  0
         ((JFCXMLTestCase) getTestCase()).flushAWT();
 569   
     }
 570   
 
 571   
     /**
 572   
      * Stop the recording.
 573   
      */
 574  0
     private void stop() {
 575  0
         JFCEventManager.getEventManager().removeJFCEventDataListener(this);
 576  0
         JFCEventManager.setRecording(false);
 577  0
         m_paused = false;
 578   
     }
 579   
 }
 580