Changeset 1496 for trunk


Ignore:
Timestamp:
04/11/14 12:12:52 (10 years ago)
Author:
pharms
Message:
  • adapted parsing of HTML files to have more power in specifying replacements
Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/autoquest-htmlmonitor-test/src/test/java/de/ugoe/cs/autoquest/htmlmonitor/HtmlMonitorTest.java

    r1429 r1496  
    1919import java.io.File; 
    2020import java.util.Collection; 
    21 import java.util.HashMap; 
    2221import java.util.Iterator; 
    2322import java.util.List; 
     
    152151        assertTrue(logFile.exists()); 
    153152         
    154         HTMLLogParser parser = new HTMLLogParser(new HashMap<String, List<String>>()); 
     153        HTMLLogParser parser = new HTMLLogParser(null); 
    155154         
    156155        parser.parseFile(logFile); 
     
    368367        assertTrue(logFile.exists()); 
    369368         
    370         HTMLLogParser parser = new HTMLLogParser(new HashMap<String, List<String>>()); 
     369        HTMLLogParser parser = new HTMLLogParser(null); 
    371370         
    372371        parser.parseFile(logFile); 
     
    526525        htmlMonitor = null; 
    527526         
    528         HTMLLogParser parser = new HTMLLogParser(new HashMap<String, List<String>>()); 
     527        HTMLLogParser parser = new HTMLLogParser(null); 
    529528         
    530529        // assert 9 already rotated log files 
     
    685684        assertTrue(logFile2.exists()); 
    686685          
    687         HTMLLogParser parser = new HTMLLogParser(new HashMap<String, List<String>>()); 
     686        HTMLLogParser parser = new HTMLLogParser(null); 
    688687         
    689688        parser.parseFile(logFile1); 
  • trunk/autoquest-plugin-html-test/src/test/java/de/ugoe/cs/autoquest/plugin/html/HTMLLogParserTest.java

    r1340 r1496  
    1818 
    1919import java.io.File; 
     20import java.io.FileOutputStream; 
     21import java.io.PrintWriter; 
    2022import java.util.Collection; 
    21 import java.util.HashMap; 
    2223import java.util.Iterator; 
    23 import java.util.LinkedList; 
    2424import java.util.List; 
    25 import java.util.Map; 
    2625import java.util.logging.Level; 
    2726 
     27import org.junit.After; 
    2828import org.junit.Before; 
    2929import org.junit.Test; 
     
    4242public class HTMLLogParserTest { 
    4343 
    44     /** 
    45     * 
    46     */ 
    47    @Before 
    48    public void setUp() { 
    49        new TextConsole(Level.FINEST); 
    50    } 
    51  
    52    /** 
    53     * Tests the parseFile method with a given trace file. 
    54     * @throws Exception 
    55     */ 
    56    @Test 
    57    public void testParseFile_1() throws Exception { 
    58        HTMLLogParser parser = new HTMLLogParser(new HashMap<String, List<String>>()); 
    59        parser.parseFile 
    60            (new File(ClassLoader.getSystemResource("htmlmonitor_testtrace_1.xml").getFile())); 
    61        Collection<List<Event>> events = parser.getSequences(); 
    62  
    63        assertNotNull(events); 
    64        assertEquals(1, events.size()); 
    65         
    66        Iterator<List<Event>> iterator = events.iterator(); 
    67        assertNotNull(iterator); 
    68        assertEquals(1, iterator.next().size()); 
    69        assertFalse(iterator.hasNext()); 
    70  
    71        System.err.println("{"); 
    72        for (List<Event> session : events) { 
    73            System.err.println("  {"); 
    74            for (Event event : session) { 
    75                System.err.print("    "); 
    76                System.err.print(event); 
    77                System.err.println(","); 
    78            } 
    79            System.err.println("  }"); 
    80        } 
    81        System.err.println("}"); 
    82        System.err.println("\n\n"); 
    83  
    84        GUIModel guiModel = parser.getGuiModel(); 
    85        assertNotNull(guiModel); 
    86  
    87        for (IGUIElement root : guiModel.getRootElements()) { 
    88            dumpGUIElement(root, guiModel, ""); 
    89        } 
    90    } 
    91  
    92    /** 
    93     * Tests the parseFile method with a given trace file. 
    94     * @throws Exception 
    95     */ 
    96    @Test 
    97    public void testParseFile_2() throws Exception { 
    98        HTMLLogParser parser = new HTMLLogParser(new HashMap<String, List<String>>()); 
    99        parser.parseFile 
    100            (new File(ClassLoader.getSystemResource("htmlmonitor_testtrace_2.xml").getFile())); 
    101        Collection<List<Event>> events = parser.getSequences(); 
    102  
    103        assertNotNull(events); 
    104        assertEquals(1, events.size()); 
    105         
    106        Iterator<List<Event>> iterator = events.iterator(); 
    107        assertNotNull(iterator); 
    108        assertEquals(2, iterator.next().size()); 
    109        assertFalse(iterator.hasNext()); 
    110  
    111        System.err.println("{"); 
    112        for (List<Event> session : events) { 
    113            System.err.println("  {"); 
    114            for (Event event : session) { 
    115                System.err.print("    "); 
    116                System.err.print(event); 
    117                System.err.println(","); 
    118            } 
    119            System.err.println("  }"); 
    120        } 
    121        System.err.println("}"); 
    122        System.err.println("\n\n"); 
    123  
    124        GUIModel guiModel = parser.getGuiModel(); 
    125        assertNotNull(guiModel); 
    126  
    127        for (IGUIElement root : guiModel.getRootElements()) { 
    128            dumpGUIElement(root, guiModel, ""); 
    129        } 
    130    } 
    131  
    132    /** 
    133     * Tests the parseFile method with a given trace file. 
    134     * @throws Exception 
    135     */ 
    136    @Test 
    137    public void testParseFile_3() throws Exception { 
    138        Map<String, List<String>> params = new HashMap<String, List<String>>(); 
    139        List<String> list = new LinkedList<String>(); 
    140        list.add("td[2]"); 
    141        list.add("th"); 
    142        params.put("clearIndex", list); 
    143        HTMLLogParser parser = new HTMLLogParser(params); 
    144         
    145        parser.parseFile 
    146            (new File(ClassLoader.getSystemResource("htmlmonitor_testtrace_3.xml").getFile())); 
    147        Collection<List<Event>> events = parser.getSequences(); 
    148  
    149        assertNotNull(events); 
    150        assertEquals(1, events.size()); 
    151         
    152        Iterator<List<Event>> iterator = events.iterator(); 
    153        assertNotNull(iterator); 
    154        assertEquals(2, iterator.next().size()); 
    155        assertFalse(iterator.hasNext()); 
    156  
    157        System.err.println("{"); 
    158        for (List<Event> session : events) { 
    159            System.err.println("  {"); 
    160            for (Event event : session) { 
    161                System.err.print("    "); 
    162                System.err.print(event); 
    163                System.err.println(","); 
    164            } 
    165            System.err.println("  }"); 
    166        } 
    167        System.err.println("}"); 
    168        System.err.println("\n\n"); 
    169  
    170        GUIModel guiModel = parser.getGuiModel(); 
    171        assertNotNull(guiModel); 
    172  
    173        for (IGUIElement root : guiModel.getRootElements()) { 
    174            dumpGUIElement(root, guiModel, ""); 
    175        } 
    176    } 
    177  
    178    /** 
    179     * Tests the parseFile method with a given trace file. 
    180     * @throws Exception 
    181     */ 
    182    @Test 
    183    public void testParseFile_4() throws Exception { 
    184        Map<String, List<String>> params = new HashMap<String, List<String>>(); 
    185        List<String> list = new LinkedList<String>(); 
    186        list.add("html/body[1]/h1"); 
    187        params.put("clearId", list); 
    188        HTMLLogParser parser = new HTMLLogParser(params); 
    189         
    190        parser.parseFile 
    191            (new File(ClassLoader.getSystemResource("htmlmonitor_testtrace_4.xml").getFile())); 
    192        Collection<List<Event>> events = parser.getSequences(); 
    193  
    194        assertNotNull(events); 
    195        assertEquals(1, events.size()); 
    196         
    197        Iterator<List<Event>> iterator = events.iterator(); 
    198        assertNotNull(iterator); 
    199        assertEquals(2, iterator.next().size()); 
    200        assertFalse(iterator.hasNext()); 
    201  
    202        System.err.println("{"); 
    203        for (List<Event> session : events) { 
    204            System.err.println("  {"); 
    205            for (Event event : session) { 
    206                System.err.print("    "); 
    207                System.err.print(event); 
    208                System.err.println(","); 
    209            } 
    210            System.err.println("  }"); 
    211        } 
    212        System.err.println("}"); 
    213        System.err.println("\n\n"); 
    214  
    215        GUIModel guiModel = parser.getGuiModel(); 
    216        assertNotNull(guiModel); 
    217  
    218        for (IGUIElement root : guiModel.getRootElements()) { 
    219            dumpGUIElement(root, guiModel, ""); 
    220        } 
    221    } 
    222  
    223    /** 
    224     * Tests the parseFile method with a given trace file. 
    225     * @throws Exception 
    226     */ 
    227    @Test 
    228    public void testParseFile_5() throws Exception { 
    229        Map<String, List<String>> params = new HashMap<String, List<String>>(); 
    230        List<String> list = new LinkedList<String>(); 
    231        list.add("html/body[1]/h1(htmlId=id_h1)"); 
    232        params.put("clearId", list); 
    233        HTMLLogParser parser = new HTMLLogParser(params); 
    234         
    235        parser.parseFile 
    236            (new File(ClassLoader.getSystemResource("htmlmonitor_testtrace_4.xml").getFile())); 
    237        Collection<List<Event>> events = parser.getSequences(); 
    238  
    239        assertNotNull(events); 
    240        assertEquals(1, events.size()); 
    241         
    242        Iterator<List<Event>> iterator = events.iterator(); 
    243        assertNotNull(iterator); 
    244        assertEquals(2, iterator.next().size()); 
    245        assertFalse(iterator.hasNext()); 
    246  
    247        System.err.println("{"); 
    248        for (List<Event> session : events) { 
    249            System.err.println("  {"); 
    250            for (Event event : session) { 
    251                System.err.print("    "); 
    252                System.err.print(event); 
    253                System.err.println(","); 
    254            } 
    255            System.err.println("  }"); 
    256        } 
    257        System.err.println("}"); 
    258        System.err.println("\n\n"); 
    259  
    260        GUIModel guiModel = parser.getGuiModel(); 
    261        assertNotNull(guiModel); 
    262  
    263        for (IGUIElement root : guiModel.getRootElements()) { 
    264            dumpGUIElement(root, guiModel, ""); 
    265        } 
    266    } 
    267  
    268    /** 
    269     * Helper method to print out GUIElements 
    270     * @param guiElement 
    271     * @param guiModel 
    272     * @param indent 
    273     */ 
    274    private void dumpGUIElement(IGUIElement guiElement, GUIModel guiModel, String indent) { 
    275        assertTrue(guiElement instanceof HTMLGUIElement); 
    276  
    277        System.err.print(indent); 
    278        System.err.print(guiElement); 
    279  
    280        List<IGUIElement> children = guiModel.getChildren(guiElement); 
    281  
    282        if ((children != null) && (children.size() > 0)) { 
    283            System.err.println(" {"); 
    284  
    285            for (IGUIElement child : children) { 
    286                dumpGUIElement(child, guiModel, indent + "  "); 
    287            } 
    288  
    289            System.err.print(indent); 
    290            System.err.print("}"); 
    291        } 
    292  
    293        System.err.println(); 
    294    } 
     44    /** */ 
     45    private static final String PARSE_PARAM_FILE = "tmpParseParamFile"; 
     46     
     47    /** 
     48     * 
     49     */ 
     50    @Before 
     51    public void setUp() { 
     52        new TextConsole(Level.FINEST); 
     53    } 
     54 
     55    /** 
     56     * 
     57     */ 
     58    @After 
     59    public void tearDown() { 
     60        new File(PARSE_PARAM_FILE).delete(); 
     61    } 
     62 
     63    /** 
     64     * Tests the parseFile method with a given trace file. 
     65     * @throws Exception 
     66     */ 
     67    @Test 
     68    public void testParseFile_1() throws Exception { 
     69        HTMLLogParser parser = new HTMLLogParser(null); 
     70        parser.parseFile 
     71        (new File(ClassLoader.getSystemResource("htmlmonitor_testtrace_1.xml").getFile())); 
     72        Collection<List<Event>> events = parser.getSequences(); 
     73 
     74        assertNotNull(events); 
     75        assertEquals(1, events.size()); 
     76 
     77        Iterator<List<Event>> iterator = events.iterator(); 
     78        assertNotNull(iterator); 
     79        assertEquals(1, iterator.next().size()); 
     80        assertFalse(iterator.hasNext()); 
     81 
     82        System.err.println("{"); 
     83        for (List<Event> session : events) { 
     84            System.err.println("  {"); 
     85            for (Event event : session) { 
     86                System.err.print("    "); 
     87                System.err.print(event); 
     88                System.err.println(","); 
     89            } 
     90            System.err.println("  }"); 
     91        } 
     92        System.err.println("}"); 
     93        System.err.println("\n\n"); 
     94 
     95        GUIModel guiModel = parser.getGuiModel(); 
     96        assertNotNull(guiModel); 
     97 
     98        for (IGUIElement root : guiModel.getRootElements()) { 
     99            dumpGUIElement(root, guiModel, ""); 
     100        } 
     101    } 
     102 
     103    /** 
     104     * Tests the parseFile method with a given trace file. 
     105     * @throws Exception 
     106     */ 
     107    @Test 
     108    public void testParseFile_2() throws Exception { 
     109        HTMLLogParser parser = new HTMLLogParser(null); 
     110        parser.parseFile 
     111        (new File(ClassLoader.getSystemResource("htmlmonitor_testtrace_2.xml").getFile())); 
     112        Collection<List<Event>> events = parser.getSequences(); 
     113 
     114        assertNotNull(events); 
     115        assertEquals(1, events.size()); 
     116 
     117        Iterator<List<Event>> iterator = events.iterator(); 
     118        assertNotNull(iterator); 
     119        assertEquals(2, iterator.next().size()); 
     120        assertFalse(iterator.hasNext()); 
     121 
     122        System.err.println("{"); 
     123        for (List<Event> session : events) { 
     124            System.err.println("  {"); 
     125            for (Event event : session) { 
     126                System.err.print("    "); 
     127                System.err.print(event); 
     128                System.err.println(","); 
     129            } 
     130            System.err.println("  }"); 
     131        } 
     132        System.err.println("}"); 
     133        System.err.println("\n\n"); 
     134 
     135        GUIModel guiModel = parser.getGuiModel(); 
     136        assertNotNull(guiModel); 
     137 
     138        for (IGUIElement root : guiModel.getRootElements()) { 
     139            dumpGUIElement(root, guiModel, ""); 
     140        } 
     141    } 
     142 
     143    /** 
     144     * Tests the parseFile method with a given trace file. 
     145     * @throws Exception 
     146     */ 
     147    @Test 
     148    public void testParseFile_3() throws Exception { 
     149        PrintWriter out = new PrintWriter(new FileOutputStream(new File(PARSE_PARAM_FILE))); 
     150        out.println("td[2]=CLEAR_INDEX"); 
     151        out.println("th=CLEAR_INDEX"); 
     152        out.close(); 
     153 
     154        HTMLLogParser parser = new HTMLLogParser(PARSE_PARAM_FILE); 
     155 
     156        parser.parseFile 
     157        (new File(ClassLoader.getSystemResource("htmlmonitor_testtrace_3.xml").getFile())); 
     158        Collection<List<Event>> events = parser.getSequences(); 
     159 
     160        assertNotNull(events); 
     161        assertEquals(1, events.size()); 
     162 
     163        Iterator<List<Event>> iterator = events.iterator(); 
     164        assertNotNull(iterator); 
     165        assertEquals(2, iterator.next().size()); 
     166        assertFalse(iterator.hasNext()); 
     167 
     168        System.err.println("{"); 
     169        for (List<Event> session : events) { 
     170            System.err.println("  {"); 
     171            for (Event event : session) { 
     172                System.err.print("    "); 
     173                System.err.print(event); 
     174                System.err.println(","); 
     175            } 
     176            System.err.println("  }"); 
     177        } 
     178        System.err.println("}"); 
     179        System.err.println("\n\n"); 
     180 
     181        GUIModel guiModel = parser.getGuiModel(); 
     182        assertNotNull(guiModel); 
     183 
     184        for (IGUIElement root : guiModel.getRootElements()) { 
     185            dumpGUIElement(root, guiModel, ""); 
     186        } 
     187    } 
     188 
     189    /** 
     190     * Tests the parseFile method with a given trace file. 
     191     * @throws Exception 
     192     */ 
     193    @Test 
     194    public void testParseFile_4() throws Exception { 
     195        PrintWriter out = new PrintWriter(new FileOutputStream(new File(PARSE_PARAM_FILE))); 
     196        out.println("html/body[1]/h1="); 
     197        out.close(); 
     198 
     199        HTMLLogParser parser = new HTMLLogParser(PARSE_PARAM_FILE); 
     200 
     201        parser.parseFile 
     202        (new File(ClassLoader.getSystemResource("htmlmonitor_testtrace_4.xml").getFile())); 
     203        Collection<List<Event>> events = parser.getSequences(); 
     204 
     205        assertNotNull(events); 
     206        assertEquals(1, events.size()); 
     207 
     208        Iterator<List<Event>> iterator = events.iterator(); 
     209        assertNotNull(iterator); 
     210        assertEquals(2, iterator.next().size()); 
     211        assertFalse(iterator.hasNext()); 
     212 
     213        System.err.println("{"); 
     214        for (List<Event> session : events) { 
     215            System.err.println("  {"); 
     216            for (Event event : session) { 
     217                System.err.print("    "); 
     218                System.err.print(event); 
     219                System.err.println(","); 
     220            } 
     221            System.err.println("  }"); 
     222        } 
     223        System.err.println("}"); 
     224        System.err.println("\n\n"); 
     225 
     226        GUIModel guiModel = parser.getGuiModel(); 
     227        assertNotNull(guiModel); 
     228 
     229        for (IGUIElement root : guiModel.getRootElements()) { 
     230            dumpGUIElement(root, guiModel, ""); 
     231        } 
     232    } 
     233 
     234    /** 
     235     * Tests the parseFile method with a given trace file. 
     236     * @throws Exception 
     237     */ 
     238    @Test 
     239    public void testParseFile_5() throws Exception { 
     240        PrintWriter out = new PrintWriter(new FileOutputStream(new File(PARSE_PARAM_FILE))); 
     241        out.println("html/body[1]/h1(htmlId\\=id_h1)="); 
     242        out.close(); 
     243         
     244        HTMLLogParser parser = new HTMLLogParser(PARSE_PARAM_FILE); 
     245 
     246        parser.parseFile 
     247        (new File(ClassLoader.getSystemResource("htmlmonitor_testtrace_4.xml").getFile())); 
     248        Collection<List<Event>> events = parser.getSequences(); 
     249 
     250        assertNotNull(events); 
     251        assertEquals(1, events.size()); 
     252 
     253        Iterator<List<Event>> iterator = events.iterator(); 
     254        assertNotNull(iterator); 
     255        assertEquals(2, iterator.next().size()); 
     256        assertFalse(iterator.hasNext()); 
     257 
     258        System.err.println("{"); 
     259        for (List<Event> session : events) { 
     260            System.err.println("  {"); 
     261            for (Event event : session) { 
     262                System.err.print("    "); 
     263                System.err.print(event); 
     264                System.err.println(","); 
     265            } 
     266            System.err.println("  }"); 
     267        } 
     268        System.err.println("}"); 
     269        System.err.println("\n\n"); 
     270 
     271        GUIModel guiModel = parser.getGuiModel(); 
     272        assertNotNull(guiModel); 
     273 
     274        for (IGUIElement root : guiModel.getRootElements()) { 
     275            dumpGUIElement(root, guiModel, ""); 
     276        } 
     277    } 
     278 
     279    /** 
     280     * Helper method to print out GUIElements 
     281     * @param guiElement 
     282     * @param guiModel 
     283     * @param indent 
     284     */ 
     285    private void dumpGUIElement(IGUIElement guiElement, GUIModel guiModel, String indent) { 
     286        assertTrue(guiElement instanceof HTMLGUIElement); 
     287 
     288        System.err.print(indent); 
     289        System.err.print(guiElement); 
     290 
     291        List<IGUIElement> children = guiModel.getChildren(guiElement); 
     292 
     293        if ((children != null) && (children.size() > 0)) { 
     294            System.err.println(" {"); 
     295 
     296            for (IGUIElement child : children) { 
     297                dumpGUIElement(child, guiModel, indent + "  "); 
     298            } 
     299 
     300            System.err.print(indent); 
     301            System.err.print("}"); 
     302        } 
     303 
     304        System.err.println(); 
     305    } 
    295306 
    296307} 
  • trunk/autoquest-plugin-html/src/main/java/de/ugoe/cs/autoquest/plugin/html/HTMLLogParser.java

    r1435 r1496  
    1919import java.io.FileNotFoundException; 
    2020import java.io.IOException; 
    21 import java.util.Arrays; 
    2221import java.util.HashMap; 
     22import java.util.LinkedList; 
    2323import java.util.List; 
    2424import java.util.Map; 
     
    3535import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement; 
    3636import de.ugoe.cs.autoquest.plugin.html.eventcore.HTMLEventTypeFactory; 
     37import de.ugoe.cs.autoquest.plugin.html.guimodel.HTMLDocument; 
    3738import de.ugoe.cs.autoquest.plugin.html.guimodel.HTMLDocumentSpec; 
    3839import de.ugoe.cs.autoquest.plugin.html.guimodel.HTMLGUIElement; 
     
    4849 * </p> 
    4950 * <p> 
    50  * The parser can be configured with parsing parameters to ignore, e.g., ids or indexes of 
     51 * The parser can be configured with parsing parameters to adapt, e.g., ids or or ignore indexes of 
    5152 * parsed GUI elements. Details can be found in the manual pages of the respective parsing commands. 
    5253 * </p> 
     
    6869    /** 
    6970     * <p> 
    70      * the pattern used for parsing parsing parameters 
    71      * </p> 
    72      */ 
    73     private Pattern htmlElementSpecPattern = 
    74         Pattern.compile("(\\w+)(\\[(\\d+)\\]|\\(htmlId=([\\w-#]+)\\))?"); 
    75      
    76     /** 
    77      * <p> 
    78      * parameters to influence parsing 
    79      * </p> 
    80      */ 
    81     private Map<String, List<String>> parseParams; 
     71     * file containing parameters to influence parsing 
     72     * </p> 
     73     */ 
     74    private String parseParamFile; 
    8275 
    8376    /** 
     
    8679     * </p> 
    8780     */ 
    88     private Map<String, String> idReplacements; 
    89  
    90     /** 
    91      * <p> 
    92      * initializes the parser with the parsing parameters to be considered 
     81    private Map<String, List<ReplacementSpecification>> replacementSpecifications; 
     82 
     83    /** 
     84     * <p> 
     85     * initializes the parser with the file containing parsing parameters to be considered 
    9386     * </p> 
    9487     * 
    95      * @param parseParams the parsing parameters to be considered 
    96      */ 
    97     public HTMLLogParser(Map<String, List<String>> parseParams) { 
    98         this.parseParams = parseParams; 
    99          
    100         for (String paramKey : parseParams.keySet()) { 
    101             if (!"clearId".equals(paramKey) && !"clearIndex".equals(paramKey) && 
    102                 !"idReplacements".equals(paramKey)) 
    103             { 
    104                 throw new IllegalArgumentException("unknown parse parameter key " + paramKey); 
    105             } 
    106         } 
     88     * @param parseParamFile the parsing parameters to be considered 
     89     */ 
     90    public HTMLLogParser(String parseParamFile) { 
     91        this.parseParamFile = parseParamFile; 
    10792    } 
    10893 
     
    11499        throws SAXException 
    115100    { 
     101        ensureParsingParameters(); 
     102         
    116103        HTMLGUIElementSpec specification = null; 
    117104         
     
    182169                String htmlId = parameters.get("htmlid"); 
    183170                 
    184                 if (clearIndex(tagName, index, htmlId, parent)) { 
    185                     index = -1; 
    186                 } 
    187                  
    188                 String idReplacement = replaceHTMLId(tagName, index, htmlId, parent); 
    189                 if (idReplacement != null) { 
    190                     htmlId = idReplacement; 
    191                 } 
    192                 else if (clearHTMLId(tagName, index, htmlId, parent)) { 
    193                     htmlId = null; 
     171                String replacement = getReplacementMapping(tagName, index, htmlId, parent); 
     172                 
     173                if (replacement != null) { 
     174                    if (replacement.startsWith("CLEAR_INDEX,")) { 
     175                        index = -1; 
     176                        replacement = replacement.substring("CLEAR_INDEX,".length()); 
     177                    } 
     178                    else if ("CLEAR_INDEX".equals(replacement)) { 
     179                        index = -1; 
     180                        replacement = htmlId; 
     181                    } 
     182                     
     183                    if ("".equals(replacement)) { 
     184                        htmlId = null; 
     185                    } 
     186                    else { 
     187                        htmlId = replacement; 
     188                    } 
    194189                } 
    195190                 
     
    226221        } 
    227222    } 
    228  
    229     /** 
    230      * <p> 
    231      * checks if for a specific GUI element the index shall be ignored or not by considering the 
    232      * parsing parameters. 
     223     
     224    /** 
     225     * <p> 
     226     * returns the replacement mapping for the tag specified by the parameters, if a mapping exists. 
    233227     * </p> 
    234228     * 
    235      * @param tagName the tag of the considered GUI element 
    236      * @param index   the index of the GUI element 
    237      * @param id      the id of the GUI element 
    238      * @param parent  the parent GUI element of the considered GUI element 
     229     * @param tagName      the tag of the considered GUI element 
     230     * @param index        the index of the GUI element 
     231     * @param id           the id of the GUI element 
     232     * @param parent       the parent GUI element of the considered GUI element 
    239233     *  
    240      * @return true if the index shall be ignored, false else. 
    241      */ 
    242     private boolean clearIndex(String tagName, int index, String id, HTMLGUIElement parent) { 
    243         return clearSomething("clearIndex", tagName, index, id, parent); 
    244     } 
    245  
    246     /** 
    247      * <p> 
    248      * checks if the parsing parameters define a replacement for the id of the given GUI element 
    249      * and if so returns this replacement 
    250      * </p> 
    251      * 
    252      * @param tagName the tag of the considered GUI element 
    253      * @param index   the index of the GUI element 
    254      * @param id      the id of the GUI element 
    255      * @param parent  the parent GUI element of the considered GUI element 
    256      *  
    257      * @return the identified replacement 
    258      */ 
    259     private String replaceHTMLId(String tagName, int index, String htmlId, HTMLGUIElement parent) 
    260         throws SAXException 
     234     * @return the replacement mapping, if any is configured; null else 
     235     */ 
     236    private String getReplacementMapping(String         tagName, 
     237                                         int            index, 
     238                                         String         htmlId, 
     239                                         HTMLGUIElement parent) 
    261240    { 
    262         if ((idReplacements == null) && (parseParams.containsKey("idReplacements"))) { 
    263             idReplacements = new HashMap<String, String>(); 
    264             for (String fileName : parseParams.get("idReplacements")) { 
     241        List<ReplacementSpecification> mappingCandidates = replacementSpecifications.get(tagName); 
     242         
     243        if (mappingCandidates != null) { 
     244            for (ReplacementSpecification replacementSpec : mappingCandidates) { 
     245                if (replacementSpec.matches(tagName, index, htmlId, parent)) { 
     246                    return replacementSpec.getReplacement(); 
     247                } 
     248            } 
     249        } 
     250         
     251        return null; 
     252    } 
     253 
     254    /* (non-Javadoc) 
     255     * @see de.ugoe.cs.autoquest.plugin.html.AbstractDefaultLogParser#handleEvent(String, Map) 
     256     */ 
     257    @Override 
     258    protected boolean handleEvent(String type, Map<String, String> parameters) throws SAXException { 
     259        String targetId = parameters.get("target"); 
     260         
     261        if (targetId == null) { 
     262            if (replacementSpecifications.size() != 0) { 
     263                throw new SAXException 
     264                    ("old log file versions can not be parsed with parse parameters"); 
     265            } 
     266             
     267            String targetDocument = parameters.get("targetDocument"); 
     268            String targetDOMPath = parameters.get("targetDOMPath"); 
     269             
     270            if ((targetDocument == null) || (targetDOMPath == null)) { 
     271                throw new SAXException("event has no target defined"); 
     272            } 
     273             
     274            targetId = determineTargetId(targetDocument, targetDOMPath); 
     275             
     276            if (targetId == null) { 
     277                // the target id can not be determined yet 
     278                return false; 
     279            } 
     280        } 
     281         
     282        IGUIElement target = super.getGUIElementTree().find(targetId); 
     283         
     284        if (target == null) { 
     285            // event not processible yet 
     286            return false; 
     287        } 
     288 
     289        IEventType eventType = 
     290            HTMLEventTypeFactory.getInstance().getEventType(type, parameters, target); 
     291         
     292        if (eventType != null) { 
     293            Event event = new Event(eventType, target); 
     294 
     295            String timestampStr = parameters.get("timestamp"); 
     296         
     297            if (timestampStr != null) { 
     298                event.setTimestamp(Long.parseLong(timestampStr)); 
     299            } 
     300 
     301            ((HTMLGUIElement) event.getTarget()).markUsed(); 
     302         
     303            super.addToSequence(event); 
     304        } 
     305        // else ignore unknown event type 
     306 
     307        return true; 
     308    } 
     309 
     310    /** 
     311     * <p> 
     312     * reads parsing parameters from the config file and makes them available for the parsing 
     313     * process 
     314     * </p> 
     315     */ 
     316    private void ensureParsingParameters() throws SAXException { 
     317        if (replacementSpecifications == null) { 
     318            replacementSpecifications = new HashMap<String, List<ReplacementSpecification>>(); 
     319             
     320            if (parseParamFile != null) { 
    265321                Properties props = new Properties(); 
    266322                FileInputStream stream = null; 
    267323                try { 
    268                     stream = new FileInputStream(new File(fileName)); 
     324                    stream = new FileInputStream(new File(parseParamFile)); 
    269325                    props.load(stream); 
    270326                } 
    271327                catch (FileNotFoundException e) { 
    272                     throw new SAXException("could not find file " + fileName, e); 
     328                    throw new SAXException("could not find file " + parseParamFile, e); 
    273329                } 
    274330                catch (IOException e) { 
    275                     throw new SAXException("error reading file " + fileName, e); 
     331                    throw new SAXException("error reading file " + parseParamFile, e); 
    276332                } 
    277333                finally { 
     
    285341                    } 
    286342                } 
    287                  
     343 
    288344                for (Map.Entry<Object, Object> entry : props.entrySet()) { 
    289                     idReplacements.put((String) entry.getKey(), (String) entry.getValue()); 
    290                 } 
    291             } 
    292         } 
    293          
    294         if (idReplacements != null) { 
    295             for (Map.Entry<String, String> replacementSpec : idReplacements.entrySet()) { 
    296                 String tagSpec = replacementSpec.getKey(); 
    297  
    298                 if (tagSpec.startsWith("/")) { 
    299                     throw new IllegalArgumentException("can not handle absolute specifications"); 
    300                 } 
    301                 else if (tagSpec.endsWith("/")) { 
    302                     throw new IllegalArgumentException("specifications may not end with a /"); 
    303                 } 
    304  
    305                 String[] tagSpecs = tagSpec.split("/"); 
    306  
    307                 if (tagMatchesTagSpec(tagName, index, htmlId, parent, tagSpecs)) { 
    308                     return replacementSpec.getValue(); 
    309                 } 
    310             } 
    311         } 
    312          
    313         return null; 
    314     } 
    315  
    316     /** 
    317      * <p> 
    318      * checks if for a specific GUI element the id shall be ignored or not by considering the 
    319      * parsing parameters. 
    320      * </p> 
    321      * 
    322      * @param tagName the tag of the considered GUI element 
    323      * @param index   the index of the GUI element 
    324      * @param id      the id of the GUI element 
    325      * @param parent  the parent GUI element of the considered GUI element 
    326      *  
    327      * @return true if the id shall be ignored, false else. 
    328      */ 
    329     private boolean clearHTMLId(String tagName, int index, String id, HTMLGUIElement parent) { 
    330         return clearSomething("clearId", tagName, index, id, parent); 
     345                    ReplacementSpecification replSpec = new ReplacementSpecification 
     346                        ((String) entry.getKey(), (String) entry.getValue()); 
     347                     
     348                    List<ReplacementSpecification> similarReplSpecs = 
     349                        replacementSpecifications.get(replSpec.getLastTagName()); 
     350                     
     351                    if (similarReplSpecs == null) { 
     352                        similarReplSpecs = new LinkedList<ReplacementSpecification>(); 
     353                        replacementSpecifications.put(replSpec.getLastTagName(), similarReplSpecs); 
     354                    } 
     355                     
     356                    similarReplSpecs.add(replSpec); 
     357                } 
     358            } 
     359        } 
    331360    } 
    332361     
    333     /** 
    334      * <p> 
    335      * convenience method to check for the existence for specific parsing parameters for clearing 
    336      * ids or indexes of GUI elements. 
    337      * </p> 
    338      * 
    339      * @param parseParamId the id of the parsing parameter to be checked for the GUI element 
    340      * @param tagName      the tag of the considered GUI element 
    341      * @param index        the index of the GUI element 
    342      * @param id           the id of the GUI element 
    343      * @param parent       the parent GUI element of the considered GUI element 
    344      *  
    345      * @return true if the denoted parse parameter is set to ignore, false else. 
    346      */ 
    347     private boolean clearSomething(String         parseParamId, 
    348                                    String         tagName, 
    349                                    int            index, 
    350                                    String         id, 
    351                                    HTMLGUIElement parent) 
    352     { 
    353         if (parseParams.containsKey(parseParamId)) { 
    354             for (String spec : parseParams.get(parseParamId)) { 
    355                 // determine the specification parts 
    356                 if (spec.startsWith("/")) { 
    357                     throw new IllegalArgumentException("can not handle absolute specifications"); 
    358                 } 
    359                 else if (spec.endsWith("/")) { 
    360                     throw new IllegalArgumentException("specifications may not end with a /"); 
    361                 } 
    362                  
    363                 String[] tagSpecs = spec.split("/"); 
    364                  
    365                 if (tagMatchesTagSpec(tagName, index, id, parent, tagSpecs)) { 
    366                     return true; 
    367                 } 
    368             } 
    369         } 
    370          
    371         return false; 
    372     } 
    373  
    374     /** 
    375      * <p> 
    376      * convenience method to check if a given GUI element matches a specification tags provided 
    377      * through the parsing parameters. 
    378      * </p> 
    379      * 
    380      * @param tagName  the tag of the considered GUI element 
    381      * @param index    the index of the GUI element 
    382      * @param id       the id of the GUI element 
    383      * @param parent   the parent GUI element of the considered GUI element 
    384      * @param tagSpecs the specification of a GUI element to match against the given GUI element 
    385      *  
    386      * @return true if the denoted parse parameter is set to ignore, false else. 
    387      */ 
    388     private boolean tagMatchesTagSpec(String         tagName, 
    389                                       int            index, 
    390                                       String         id, 
    391                                       HTMLGUIElement parent, 
    392                                       String[]       tagSpecs) 
    393     { 
    394          
    395         if (tagSpecs.length > 0) { 
    396             Matcher matcher = htmlElementSpecPattern.matcher(tagSpecs[tagSpecs.length - 1]); 
    397              
    398             if (!matcher.matches()) { 
    399                 throw new IllegalArgumentException 
    400                     ("illegal tag specification " + tagSpecs[tagSpecs.length - 1]); 
    401             } 
    402              
    403             if (!tagName.equals(matcher.group(1))) { 
    404                 return false; 
    405             } 
    406              
    407             String idCondition = matcher.group(4); 
    408              
    409             if (idCondition != null) { 
    410                 if (!idCondition.equals(id)) { 
    411                     // check if the id condition would match with ignoring specific characters 
    412                     if ((id != null) && (idCondition.indexOf('#') > -1)) { 
    413                         // first of all, the length must match 
    414                         if (idCondition.length() != id.length()) { 
    415                             return false; 
    416                         } 
    417                          
    418                         for (int i = 0; i < idCondition.length(); i++) { 
    419                             if ((idCondition.charAt(i) != '#') && 
    420                                 (idCondition.charAt(i) != id.charAt(i))) 
    421                             { 
    422                                 // if there is a character that is neither ignored not matches 
    423                                 // the condition at a specific position, return "no match" 
    424                                 return false; 
    425                             } 
    426                         } 
    427                          
    428                     } 
    429                     else { 
    430                         // no condition ignoring specific characters 
    431                         return false; 
    432                     } 
    433                 } 
    434             } 
    435              
    436             String indexCondition = matcher.group(3); 
    437              
    438             if (indexCondition != null) { 
    439                 try { 
    440                     if (index != Integer.parseInt(indexCondition)) { 
    441                         return false; 
    442                     } 
    443                 } 
    444                 catch (NumberFormatException e) { 
    445                     throw new IllegalArgumentException 
    446                         ("illegal tag index specification " + indexCondition, e); 
    447                 } 
    448             } 
    449              
    450             if (tagSpecs.length > 1) { 
    451                 if (parent instanceof HTMLPageElement) { 
    452                     return tagMatchesTagSpec(((HTMLPageElement) parent).getTagName(), 
    453                                              ((HTMLPageElement) parent).getIndex(), 
    454                                              ((HTMLPageElement) parent).getHtmlId(), 
    455                                              (HTMLGUIElement) parent.getParent(), 
    456                                              Arrays.copyOfRange(tagSpecs, 0, tagSpecs.length - 1)); 
    457                 } 
    458                 else { 
    459                     throw new IllegalArgumentException 
    460                         ("specification matches documents or servers. This is not supported yet."); 
    461                 } 
    462             } 
    463             else { 
    464                 return true; 
    465             } 
    466         } 
    467         else { 
    468             return true; 
    469         } 
    470     } 
    471  
    472     /* (non-Javadoc) 
    473      * @see de.ugoe.cs.autoquest.plugin.html.AbstractDefaultLogParser#handleEvent(String, Map) 
    474      */ 
    475     @Override 
    476     protected boolean handleEvent(String type, Map<String, String> parameters) throws SAXException { 
    477         String targetId = parameters.get("target"); 
    478          
    479         if (targetId == null) { 
    480             if (parseParams.size() != 0) { 
    481                 throw new SAXException 
    482                     ("old log file versions can not be parsed with parse parameters"); 
    483             } 
    484              
    485             String targetDocument = parameters.get("targetDocument"); 
    486             String targetDOMPath = parameters.get("targetDOMPath"); 
    487              
    488             if ((targetDocument == null) || (targetDOMPath == null)) { 
    489                 throw new SAXException("event has no target defined"); 
    490             } 
    491              
    492             targetId = determineTargetId(targetDocument, targetDOMPath); 
    493              
    494             if (targetId == null) { 
    495                 // the target id can not be determined yet 
    496                 return false; 
    497             } 
    498         } 
    499          
    500         IGUIElement target = super.getGUIElementTree().find(targetId); 
    501          
    502         if (target == null) { 
    503             // event not processible yet 
    504             return false; 
    505         } 
    506  
    507         IEventType eventType = 
    508             HTMLEventTypeFactory.getInstance().getEventType(type, parameters, target); 
    509          
    510         if (eventType != null) { 
    511             Event event = new Event(eventType, target); 
    512  
    513             String timestampStr = parameters.get("timestamp"); 
    514          
    515             if (timestampStr != null) { 
    516                 event.setTimestamp(Long.parseLong(timestampStr)); 
    517             } 
    518  
    519             ((HTMLGUIElement) event.getTarget()).markUsed(); 
    520          
    521             super.addToSequence(event); 
    522         } 
    523         // else ignore unknown event type 
    524  
    525         return true; 
    526     } 
    527  
    528362    /** 
    529363     * <p> 
     
    647481    } 
    648482 
     483    /** 
     484     * <p>specification for a replacement consisting of path of tag or document specifications 
     485     * and the appropriate replacement.</p> 
     486     */ 
     487    private static class ReplacementSpecification { 
     488         
     489        /** 
     490         * <p> 
     491         * the pattern used for parsing parsing parameters 
     492         * </p> 
     493         */ 
     494        private Pattern htmlElementSpecPattern = Pattern.compile 
     495            ("(document\\(path=([\\w/-]+)\\))|((\\w+)(\\[(\\d+)\\]|\\(htmlId=([\\w-_#]+)\\))?)"); 
     496         
     497        /** 
     498         * <p> 
     499         * the path of specifications (tags and document) specifying the tag for which this 
     500         * replacement is specified 
     501         * </p> 
     502         */ 
     503        private List<Spec> specs = new LinkedList<Spec>(); 
     504         
     505        /** 
     506         * <p> 
     507         * the name of the last tag in the specification path (used for indexing purposes) 
     508         * </p> 
     509         */ 
     510        private String lastTagName; 
     511         
     512        /** 
     513         * <p> 
     514         * the configured replacement 
     515         * </p> 
     516         */ 
     517        private String replacement; 
     518 
     519        /** 
     520         * <p> 
     521         * initializes the specification with the key/value strings from the config file. Parses 
     522         * the key to get the specification path consisting of, optionally, a document 
     523         * specification and one or more tag specification. 
     524         * </p> 
     525         */ 
     526        public ReplacementSpecification(String tagSpec, String replacement) { 
     527            List<String> tagSpecs = split(tagSpec); 
     528             
     529            for (int i = 0; i < tagSpecs.size(); i++) { 
     530                Matcher matcher = htmlElementSpecPattern.matcher(tagSpecs.get(i)); 
     531                 
     532                if (!matcher.matches()) { 
     533                    throw new IllegalArgumentException 
     534                        ("illegal tag specification " + tagSpecs.get(i)); 
     535                } 
     536                 
     537                if (matcher.group(1) != null) { 
     538                    this.specs.add(new DocumentSpec(matcher.group(2))); 
     539                } 
     540                else if (matcher.group(4) != null) { 
     541                    String indexConditionStr = matcher.group(6); 
     542                    Integer indexCondition = null; 
     543                 
     544                    if (indexConditionStr != null) { 
     545                        try { 
     546                            indexCondition = Integer.parseInt(indexConditionStr); 
     547                        } 
     548                        catch (NumberFormatException e) { 
     549                            throw new IllegalArgumentException 
     550                                ("illegal tag index specification " + indexConditionStr, e); 
     551                        } 
     552                    } 
     553                 
     554                    this.specs.add 
     555                        (new TagSpec(matcher.group(4), indexCondition, matcher.group(7))); 
     556                } 
     557            } 
     558             
     559            this.lastTagName = ((TagSpec) this.specs.get(this.specs.size() - 1)).getTagName(); 
     560             
     561            this.replacement = replacement; 
     562        } 
     563 
     564        /** 
     565         * <p> 
     566         * convenience method to split the key of a key/value pair from the config file into its 
     567         * parts 
     568         * </p> 
     569         */ 
     570        private List<String> split(String tagSpec) { 
     571            List<String> specs = new LinkedList<String>(); 
     572             
     573            StringBuffer currentSpec = new StringBuffer(); 
     574            int openBraces = 0; 
     575             
     576            for (int i = 0; i < tagSpec.length(); i++) { 
     577                char curChar = tagSpec.charAt(i); 
     578                if ((openBraces == 0) && ('/' == curChar) && (currentSpec.length() > 0)) { 
     579                    specs.add(currentSpec.toString()); 
     580                    currentSpec.setLength(0); 
     581                } 
     582                else { 
     583                    if ('(' == curChar) { 
     584                        openBraces++; 
     585                    } 
     586                    else if (')' == curChar) { 
     587                        openBraces--; 
     588                    } 
     589                    currentSpec.append(curChar); 
     590                } 
     591            } 
     592             
     593            if (currentSpec.length() > 0) { 
     594                specs.add(currentSpec.toString()); 
     595            } 
     596             
     597            return specs; 
     598        } 
     599 
     600        /** 
     601         * <p> 
     602         * checks, if the tag identified by the parameters matches this specificaiton. 
     603         * </p> 
     604         */ 
     605        private boolean matches(String tagName, int index, String htmlId, HTMLGUIElement parent) { 
     606            String currentTagName = tagName; 
     607            int currentIndex = index; 
     608            String currentHtmlId = htmlId; 
     609            String currentPath = null; 
     610            HTMLGUIElement currentParent = parent; 
     611             
     612            int i = specs.size() - 1; 
     613             
     614            while (i >= 0) { 
     615                if ((specs.get(i) instanceof TagSpec) && 
     616                    (!((TagSpec) specs.get(i)).matches(currentTagName, currentIndex, currentHtmlId))) 
     617                { 
     618                    return false; 
     619                } 
     620                else if ((specs.get(i) instanceof DocumentSpec) && 
     621                         (!((DocumentSpec) specs.get(i)).matches(currentPath))) 
     622                { 
     623                    return false; 
     624                } 
     625                 
     626                i--; 
     627                 
     628                if (i >= 0) { 
     629                    if (currentParent instanceof HTMLPageElement) { 
     630                        currentTagName = ((HTMLPageElement) currentParent).getTagName(); 
     631                        currentIndex = ((HTMLPageElement) currentParent).getIndex(); 
     632                        currentHtmlId = ((HTMLPageElement) currentParent).getHtmlId(); 
     633                        currentPath = null; 
     634                        currentParent = (HTMLGUIElement) currentParent.getParent(); 
     635                     } 
     636                    else if (currentParent instanceof HTMLDocument) { 
     637                        currentTagName = null; 
     638                        currentIndex = Integer.MIN_VALUE; 
     639                        currentHtmlId = null; 
     640                        currentPath = ((HTMLDocument) currentParent).getPath(); 
     641                        currentParent = (HTMLGUIElement) currentParent.getParent(); 
     642                    } 
     643                    else { 
     644                        throw new IllegalArgumentException 
     645                            ("specification matches documents or servers. This is not supported yet."); 
     646                    } 
     647                } 
     648            } 
     649             
     650            return true; 
     651        } 
     652 
     653        /** 
     654         * <p> 
     655         * returns the specified replacement 
     656         * </p> 
     657         */ 
     658        private String getReplacement() { 
     659            return replacement; 
     660        } 
     661 
     662        /** 
     663         * <p> 
     664         * returns the name of the last tag specified in the specification path 
     665         * </p> 
     666         */ 
     667        private String getLastTagName() { 
     668            return lastTagName; 
     669        } 
     670 
     671        /* (non-Javadoc) 
     672         * @see java.lang.Object#toString() 
     673         */ 
     674        @Override 
     675        public String toString() { 
     676            StringBuffer result = new StringBuffer(); 
     677            for (Spec spec : specs) { 
     678                if (result.length() > 0) { 
     679                    result.append("/"); 
     680                } 
     681                result.append(spec); 
     682            } 
     683             
     684            result.append('='); 
     685            result.append(replacement); 
     686             
     687            return result.toString(); 
     688        } 
     689         
     690    } 
     691 
     692    /** 
     693     * <p> 
     694     * parent type for document and tag specifications 
     695     * </p> 
     696     */ 
     697    private static interface Spec { } 
     698 
     699    /** 
     700     * <p> 
     701     * specification of a document 
     702     * </p> 
     703     */ 
     704    private static class DocumentSpec implements Spec { 
     705         
     706        /** 
     707         * <p> 
     708         * the part of the path the document path must have to match this specification 
     709         * </p> 
     710         */ 
     711        private String pathPart; 
     712 
     713        /** 
     714         * <p> 
     715         * initializes the document specification with the path part 
     716         * </p> 
     717         */ 
     718        private DocumentSpec(String pathPart) { 
     719            this.pathPart = pathPart; 
     720        } 
     721 
     722        /** 
     723         * <p> 
     724         * returns true if the provided path contains the path part provided to the parameter 
     725         * </p> 
     726         */ 
     727        private boolean matches(String path) { 
     728            return path.contains(pathPart); 
     729        } 
     730 
     731        /* (non-Javadoc) 
     732         * @see java.lang.Object#toString() 
     733         */ 
     734        @Override 
     735        public String toString() { 
     736            return "document(path=" + pathPart + ")"; 
     737        } 
     738    } 
     739 
     740    /** 
     741     * <p> 
     742     * specification for a tag containing a tag name and either an index or id condition. 
     743     * </p> 
     744     */ 
     745    private static class TagSpec implements Spec { 
     746 
     747        /** 
     748         * <p> 
     749         * the name of the tag to match 
     750         * </p> 
     751         */ 
     752        private String tagName; 
     753         
     754        /** 
     755         * <p> 
     756         * the index of the tag to match 
     757         * </p> 
     758         */ 
     759        private Integer indexCondition; 
     760         
     761        /** 
     762         * <p> 
     763         * the id of the tag to match 
     764         * </p> 
     765         */ 
     766        private String idCondition; 
     767 
     768        /** 
     769         * <p> 
     770         * initializes the specification with all required parameters 
     771         * </p> 
     772         */ 
     773        private TagSpec(String tagName, Integer indexCondition, String idCondition) { 
     774            this.tagName = tagName; 
     775            this.indexCondition = indexCondition; 
     776            this.idCondition = idCondition; 
     777        } 
     778 
     779        /** 
     780         * <p> 
     781         * returns true if the provided tag information matches this specification. The id is 
     782         * checked first. If the id condition has a # at some position, the respective element 
     783         * of the provided id is ignored. 
     784         * </p> 
     785         */ 
     786        private boolean matches(String tagName, int index, String htmlId) { 
     787            if (!this.tagName.equals(tagName)) { 
     788                return false; 
     789            } 
     790             
     791            if (idCondition != null) { 
     792                if (!idCondition.equals(htmlId)) { 
     793                    // check if the id condition would match with ignoring specific characters 
     794                    if ((htmlId != null) && (idCondition.indexOf('#') > -1)) { 
     795                        // first of all, the length must match 
     796                        if (idCondition.length() != htmlId.length()) { 
     797                            return false; 
     798                        } 
     799                         
     800                        for (int i = 0; i < idCondition.length(); i++) { 
     801                            if ((idCondition.charAt(i) != '#') && 
     802                                (idCondition.charAt(i) != htmlId.charAt(i))) 
     803                            { 
     804                                // if there is a character that is neither ignored nor matches 
     805                                // the condition at a specific position, return "no match" 
     806                                return false; 
     807                            } 
     808                        } 
     809                         
     810                    } 
     811                    else { 
     812                        // no condition ignoring specific characters 
     813                        return false; 
     814                    } 
     815                } 
     816            } 
     817             
     818            if ((indexCondition != null) && (index != indexCondition)) { 
     819                return false; 
     820            } 
     821             
     822            return true; 
     823        } 
     824 
     825        /** 
     826         * <p> 
     827         * returns the name of the tags matched by this specification 
     828         * </p> 
     829         */ 
     830        private String getTagName() { 
     831            return tagName; 
     832        } 
     833 
     834        /* (non-Javadoc) 
     835         * @see java.lang.Object#toString() 
     836         */ 
     837        @Override 
     838        public String toString() { 
     839            StringBuffer result = new StringBuffer(tagName); 
     840             
     841            if (idCondition != null) { 
     842                result.append("(htmlId="); 
     843                result.append(idCondition); 
     844                result.append(')'); 
     845            } 
     846            else if (indexCondition != null) { 
     847                result.append('['); 
     848                result.append(indexCondition); 
     849                result.append(']'); 
     850            } 
     851             
     852            return result.toString(); 
     853        } 
     854         
     855    } 
    649856} 
  • trunk/autoquest-plugin-html/src/main/java/de/ugoe/cs/autoquest/plugin/html/commands/CMDcorrectHTMLLogDirs.java

    r1339 r1496  
    1717import java.io.File; 
    1818import java.util.Arrays; 
    19 import java.util.HashMap; 
    2019import java.util.List; 
    2120import java.util.logging.Level; 
     
    9190            String serverName = null; 
    9291             
    93             HTMLLogParser parser = new HTMLLogParser(new HashMap<String, List<String>>()); 
     92            HTMLLogParser parser = new HTMLLogParser(null); 
    9493            try { 
    9594                parser.parseFile(file); 
  • trunk/autoquest-plugin-html/src/main/java/de/ugoe/cs/autoquest/plugin/html/commands/CMDparseDirHTML.java

    r1435 r1496  
    1818import java.util.Arrays; 
    1919import java.util.Collection; 
    20 import java.util.HashMap; 
    21 import java.util.LinkedList; 
    2220import java.util.List; 
    23 import java.util.Map; 
    2421import java.util.logging.Level; 
    2522import java.util.regex.Matcher; 
     
    5552        String path = null; 
    5653        String sequencesName = null; 
    57         Map<String, List<String>> parseParams = new HashMap<String, List<String>>(); 
     54        String parseParamFile = null; 
    5855 
    5956        try { 
     
    6966                } 
    7067                else { 
    71                     Pattern parseParamPattern = Pattern.compile("-(\\w*)=([\\w=\\[\\]\\(\\)/\\.-]*)"); 
     68                    Pattern parseParamPattern = Pattern.compile("-(\\w*)=([\\w/\\.-]*)"); 
    7269                    Matcher matcher = parseParamPattern.matcher(param); 
    7370                     
    7471                    if (matcher.matches()) { 
    7572                        String key = matcher.group(1); 
    76                         List<String> values = parseParams.get(key); 
    77                          
    78                         if (values == null) { 
    79                             values = new LinkedList<String>(); 
    80                             parseParams.put(key, values); 
     73                        if (!"parseParamFile".equals(key)) { 
     74                            String message = "unknown parameter: " + key; 
     75                            Console.printerrln(message); 
     76                            throw new IllegalArgumentException(message); 
    8177                        } 
    8278                         
    83                         values.add(matcher.group(2)); 
     79                        parseParamFile = matcher.group(2); 
    8480                    } 
    8581                    else { 
    86                         String message = "parse parameter does not follow format: -<key>=<value>"; 
     82                        String message = "parameter does not follow format: -<key>=<value>"; 
    8783                        Console.printerrln(message); 
    8884                        throw new IllegalArgumentException(message); 
     
    105101        } 
    106102 
    107         HTMLLogParser parser = new HTMLLogParser(parseParams); 
     103        HTMLLogParser parser = new HTMLLogParser(parseParamFile); 
    108104 
    109105        parseFile(folder, parser); 
     
    161157    @Override 
    162158    public String help() { 
    163         return "parseDirHTML <directory> [<sequencesName>] " + 
    164             "{-idReplacements=path/to/replacementfile} {-clearId=path/to[0]/gui(htmlId=element)} " + 
    165             "{-clearIndex=path/to[0]/gui(htmlId=element)}"; 
     159        return "parseDirHTML <directory> [<sequencesName>] {-parseParams=path/to/parseParamsFile}"; 
    166160    } 
    167161 
  • trunk/autoquest-plugin-html/src/main/java/de/ugoe/cs/autoquest/plugin/html/commands/CMDparseHTML.java

    r1435 r1496  
    1616 
    1717import java.util.Collection; 
    18 import java.util.HashMap; 
    19 import java.util.LinkedList; 
    2018import java.util.List; 
    21 import java.util.Map; 
    2219import java.util.regex.Matcher; 
    2320import java.util.regex.Pattern; 
     
    5047        String filename = null; 
    5148        String sequencesName = null; 
    52         Map<String, List<String>> parseParams = new HashMap<String, List<String>>(); 
     49        String parseParamFile = null; 
    5350 
    5451        try { 
     
    6461                } 
    6562                else { 
    66                     Pattern parseParamPattern = Pattern.compile("-(\\w*)=([\\w=\\[\\]\\(\\)/\\.-]*)"); 
     63                    Pattern parseParamPattern = Pattern.compile("-(\\w*)=([\\w/\\.-]*)"); 
    6764                    Matcher matcher = parseParamPattern.matcher(param); 
    6865                     
    6966                    if (matcher.matches()) { 
    7067                        String key = matcher.group(1); 
    71                         List<String> values = parseParams.get(key); 
    72                          
    73                         if (values == null) { 
    74                             values = new LinkedList<String>(); 
    75                             parseParams.put(key, values); 
     68                        if (!"parseParamFile".equals(key)) { 
     69                            String message = "unknown parameter: " + key; 
     70                            Console.printerrln(message); 
     71                            throw new IllegalArgumentException(message); 
    7672                        } 
    7773                         
    78                         values.add(matcher.group(2)); 
     74                        parseParamFile = matcher.group(2); 
    7975                    } 
    8076                    else { 
    81                         String message = "parse parameter does not follow format: -<key>=<value>"; 
     77                        String message = "parameter does not follow format: -<key>=<value>"; 
    8278                        Console.printerrln(message); 
    8379                        throw new IllegalArgumentException(message); 
     
    9490        } 
    9591 
    96         HTMLLogParser parser = new HTMLLogParser(parseParams); 
     92        HTMLLogParser parser = new HTMLLogParser(parseParamFile); 
    9793 
    9894        try { 
     
    124120    @Override 
    125121    public String help() { 
    126         return "parseHTML <filename> [<sequencesName>] " + 
    127             "{-idReplacements=path/to/replacementfile} {-clearId=path/to[0]/gui(htmlId=element)} " + 
    128             "{-clearIndex=path/to[0]/gui(htmlId=element)}"; 
     122        return "parseHTML <filename> [<sequencesName>] {-parseParams=path/to/parseParamsFile}"; 
    129123    } 
    130124 
  • trunk/autoquest-plugin-html/src/main/java/de/ugoe/cs/autoquest/plugin/html/guimodel/HTMLPageElement.java

    r1490 r1496  
    9090        } 
    9191        else if (otherElement instanceof HTMLPageElement) { 
    92             if (this == otherElement) { 
     92            if (equals(otherElement)) { 
    9393                return DISTANCE_NONE; 
    9494            } 
  • trunk/autoquest-plugin-html/src/main/resources/manuals/parseDirHTML

    r1354 r1496  
    11Treats all files in a directory structure as HTML log files and parses them into event sequences and a GUI model. Also sub directories are parsed. 
    22 
    3 The parsing process can be parameterized. This allows to replace or ignore ids or indexes of GUI elements in the log files. If they are replaced or ignored, the GUI model is more harmonized and GUI elements are considered equal although they are not. This may be helpful, e.g., if you have a table where each row is semantically the same. Without replacing or ignoring indexes or ids of the rows, each row is treated separately. But with replaced or ignored indexes or ids, all rows are considered the same. 
     3The parsing process can be parameterized. This allows to replace ids or ignore indexes of GUI elements in the log files. If they are replaced or ignored, the GUI model is more harmonized and GUI elements are considered equal although they are not. This may be helpful, e.g., if you have a table where each row is semantically the same. Without ignoring indexes or ids of the rows, each row is treated separately. But with ignored or replaced indexes or ids, all rows are considered the same. 
    44 
    5 To ignore the indexes, add -clearIndex=<path to GUI element> as parameter to the command call. To ignore ids, add -clearId=<path to GUI element> to the command call. The path to the GUI element is written using the HTML tag names and either their index or their id as identification. E.g., to denote all rows in a table where the table has the id "table_1" you can specify "table(htmlId=table_1)/tbody/tr". To denote e.g. all divs being the child of a div with an index 1, you specify "div[1]/div".   
     5The parameterization is done in a separate properties file. The keys in the file specify the tags for which either the id shall be replaced or the index shall be ignored. A specification for a simple tag either simply by its name, by its name and index or by its name and id looks as follows: 
    66 
    7 To replace ids, a separate files with mappings must be created. The path to this file must be provided using the idReplacements parameter. The file follows a typical properties format. The key is the path denoting the GUI element of which the id shall be set. The value is the actual id. The key may contain the # character to denote a wildcard in html ids. This allows matching several GUI elements with similar ids at once and to give them the same id. An example entry of this file is: 
     7tagName 
     8tagName[index] 
     9tagName(htmlId\=id) 
    810 
    9 div(htmlId\=id_number_#)=div_number_X 
     11Furthermore, tags can be specified as paths through the DOM in that several tags specifications are given and concatenated using /. An example with three specified tag (tag1 with index 5, tag 2, and tag 3 with id "id") is the following: 
    1012 
    11 This line would give all divs with an id "id_number_#" where # denotes any character the new id "div_number_X". Please note that for specifying the keys, it is required to escape any = sign in the key specification. This is usually required if the path to the denoted GUI elements denotes elements by their id as shown in the example. 
     13tag1[5]/tag2/tag3(htmlId\=id) 
    1214 
     15The specification of a tag id may contain the # character to denote a wildcard. This allows matching several GUI elements with similar ids at once and to give them the same id. An example entry of this is: 
     16 
     17div(htmlId\=id_number_#) 
     18 
     19This line would match all divs with an id starting with "id_number_" where # denotes any character. 
     20 
     21It is also possible to specify the document in which the tag path should match. A document is specified by giving a part of the documents path in the URL. After the document specification, the full path to the specified tag must be given. An example is the following: 
     22 
     23document(path\=accounts)/html/body/div[0]/ul/li(htmlId\=breadcrumb1)/a 
     24 
     25Please note that for specifying the keys, it is required to escape any = sign in the key specification. This is usually required if the path to the denoted GUI elements denotes elements by their id as shown in the example. 
     26 
     27To remove the id of a specified tag, the value must be empty. To set the id, the value must the id the tag shall have. To clear the index of the specified tag, that value must be CLEAR_INDEX. Here are some further example entries: 
     28 
     29body/div/div/div/form= 
     30body/p/small/a=imprint-link 
     31document(path\=accounts/login)/html/body/div[0]/div[1]/div[0]/form/p/a=password-reset-link 
     32document(path\=accounts/login)/html/body/div[0]/div[1]/div[0]/form/div/button=CLEAR_INDEX 
     33body/div[5]=date-chooser 
     34div(htmlId\=date-chooser)/div[0]=date-chooser_day 
    1335 
    1436 
     
    1941[<sequenceNames>] 
    2042    array of sequences into which the parsed events shall be stored 
    21 {-idReplacements=path/to/replacementfile} 
     43{-parseParams=path/to/replacementfile} 
    2244    used to define id replacements as described in a separate file 
    23 {-clearId=path/to[0]/gui(htmlId=element)} 
    24     used to define GUI elements of which the ids shall be ignored 
    25 {-clearIndex=path/to[0]/gui(htmlId=element)} 
    26     used to define GUI elements of which the indexes shall be ignored 
    2745 
    2846Example(s): 
    2947parseDirHTML /path/to/directory 
    30 parseDirHTML /path/to/directory sequences -clearId=table(htmlId=overview)/tbody[0]/tr 
    31 parseDirHTML /path/to/directory sequences -idReplacements=idReplacements.txt -clearId=body 
     48parseDirHTML /path/to/directory sequences -parseParams=idReplacements.txt 
  • trunk/autoquest-plugin-html/src/main/resources/manuals/parseHTML

    r1354 r1496  
    11Parses an HTML log file them into an event sequence and a GUI model. 
    22 
    3 The parsing process can be parameterized. This allows to replace or ignore ids or indexes of GUI elements in the log files. If they are replaced or ignored, the GUI model is more harmonized and GUI elements are considered equal although they are not. This may be helpful, e.g., if you have a table where each row is semantically the same. Without ignoring indexes or ids of the rows, each row is treated separately. But with ignored or replaced indexes or ids, all rows are considered the same. 
     3The parsing process can be parameterized. This allows to replace ids or ignore indexes of GUI elements in the log files. If they are replaced or ignored, the GUI model is more harmonized and GUI elements are considered equal although they are not. This may be helpful, e.g., if you have a table where each row is semantically the same. Without ignoring indexes or ids of the rows, each row is treated separately. But with ignored or replaced indexes or ids, all rows are considered the same. 
    44 
    5 To ignore the indexes, add -clearIndex=<path to GUI element> as parameter to the command call. To ignore ids, add -clearId=<path to GUI element> to the command call. The path to the GUI element is written using the HTML tag names and either their index or their id as identification. E.g., to denote all rows in a table where the table has the id "table_1" you can specify "table(htmlId=table_1)/tbody/tr". To denote e.g. all divs being the child of a div with an index 1, you specify "div[1]/div".   
     5The parameterization is done in a separate properties file. The keys in the file specify the tags for which either the id shall be replaced or the index shall be ignored. A specification for a simple tag either simply by its name, by its name and index or by its name and id looks as follows: 
    66 
    7 To replace ids, a separate files with mappings must be created. The path to this file must be provided using the idReplacements parameter. The file follows a typical properties format. The key is the path denoting the GUI element of which the id shall be set. The value is the actual id. The key may contain the # character to denote a wildcard in html ids. This allows matching several GUI elements with similar ids at once and to give them the same id. An example entry of this file is: 
     7tagName 
     8tagName[index] 
     9tagName(htmlId\=id) 
    810 
    9 div(htmlId\=id_number_#)=div_number_X 
     11Furthermore, tags can be specified as paths through the DOM in that several tags specifications are given and concatenated using /. An example with three specified tag (tag1 with index 5, tag 2, and tag 3 with id "id") is the following: 
    1012 
    11 This line would give all divs with an id "id_number_#" where # denotes any character the new id "div_number_X". Please note that for specifying the keys, it is required to escape any = sign in the key specification. This is usually required if the path to the denoted GUI elements denotes elements by their id as shown in the example. 
     13tag1[5]/tag2/tag3(htmlId\=id) 
    1214 
     15The specification of a tag id may contain the # character to denote a wildcard. This allows matching several GUI elements with similar ids at once and to give them the same id. An example entry of this is: 
    1316 
     17div(htmlId\=id_number_#) 
     18 
     19This line would match all divs with an id starting with "id_number_" where # denotes any character. 
     20 
     21It is also possible to specify the document in which the tag path should match. A document is specified by giving a part of the documents path in the URL. After the document specification, the full path to the specified tag must be given. An example is the following: 
     22 
     23document(path\=accounts)/html/body/div[0]/ul/li(htmlId\=breadcrumb1)/a 
     24 
     25Please note that for specifying the keys, it is required to escape any = sign in the key specification. This is usually required if the path to the denoted GUI elements denotes elements by their id as shown in the example. 
     26 
     27To remove the id of a specified tag, the value must be empty. To set the id, the value must the id the tag shall have. To clear the index of the specified tag, that value must be CLEAR_INDEX. Here are some further example entries: 
     28 
     29body/div/div/div/form= 
     30body/p/small/a=imprint-link 
     31document(path\=accounts/login)/html/body/div[0]/div[1]/div[0]/form/p/a=password-reset-link 
     32document(path\=accounts/login)/html/body/div[0]/div[1]/div[0]/form/div/button=CLEAR_INDEX 
     33body/div[5]=date-chooser 
     34div(htmlId\=date-chooser)/div[0]=date-chooser_day 
    1435 
    1536$USAGE$ 
     
    1940[<sequenceNames>] 
    2041    array of sequences into which the parsed events shall be stored 
    21 {-idReplacements=path/to/replacementfile} 
     42{-parseParams=path/to/replacementfile} 
    2243    used to define id replacements as described in a separate file 
    23 {-clearId=path/to[0]/gui(htmlId=element)} 
    24     used to define GUI elements of which the ids shall be ignored 
    25 {-clearIndex=path/to[0]/gui(htmlId=element)} 
    26     used to define GUI elements of which the indexes shall be ignored 
    2744 
    2845Example(s): 
    2946parseDirHTML /path/to/file.log 
    30 parseDirHTML /path/to/file.log sequences -clearId=table(htmlId=overview)/tbody[0]/tr 
    31 parseDirHTML /path/to/directory sequences -idReplacements=idReplacements.txt -clearId=body 
     47parseDirHTML /path/to/file.log sequences -parseParams=idReplacements.txt 
Note: See TracChangeset for help on using the changeset viewer.