source: trunk/autoquest-plugin-jfc/src/main/java/de/ugoe/cs/autoquest/plugin/jfc/commands/CMDgenerateJacaretoReplay.java @ 1683

Last change on this file since 1683 was 1683, checked in by dmay, 10 years ago

more progress for mouse clicks, also start introducing timing

  • Property svn:mime-type set to text/plain
File size: 11.9 KB
Line 
1//   Copyright 2012 Georg-August-Universität Göttingen, Germany
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15package de.ugoe.cs.autoquest.plugin.jfc.commands;
16
17import java.io.BufferedWriter;
18import java.io.File;
19import java.io.FileOutputStream;
20import java.io.IOException;
21import java.io.OutputStreamWriter;
22import java.util.ArrayList;
23import java.util.Collection;
24import java.util.Iterator;
25import java.util.List;
26import java.util.UUID;
27import java.util.logging.Level;
28
29import de.ugoe.cs.autoquest.CommandHelpers;
30import de.ugoe.cs.autoquest.SequenceInstanceOf;
31import de.ugoe.cs.util.console.Command;
32import de.ugoe.cs.autoquest.eventcore.Event;
33import de.ugoe.cs.autoquest.plugin.jfc.guimodel.JFCGUIElement;
34import de.ugoe.cs.util.console.Console;
35import de.ugoe.cs.util.console.GlobalDataContainer;
36
37/**
38 * <p>
39 * Command to create a Jacareto xml replay file from stored sessions.
40 * </p>
41 *
42 * @author Daniel May
43 * @version 1.0
44 */
45public class CMDgenerateJacaretoReplay implements Command {
46
47    private int nextRef;
48
49    /*
50     * (non-Javadoc)
51     *
52     * @see de.ugoe.cs.util.console.Command#help()
53     */
54    @Override
55    public String help() {
56        return "generateJacaretoReplay <filename> <sequences>";
57    }
58
59    /*
60     * (non-Javadoc)
61     *
62     * @see de.ugoe.cs.util.console.Command#run(java.util.List)
63     */
64    @SuppressWarnings("unchecked")
65    @Override
66    public void run(List<Object> parameters) {
67        String filename;
68        String sequencesName;
69        try {
70            filename = (String) parameters.get(0);
71            sequencesName = (String) parameters.get(1);
72        }
73        catch (Exception e) {
74            throw new IllegalArgumentException();
75        }
76
77        Collection<List<Event>> sequences = null;
78        Object dataObject = GlobalDataContainer.getInstance().getData(sequencesName);
79        if (dataObject == null) {
80            CommandHelpers.objectNotFoundMessage(sequencesName);
81            return;
82        }
83        if (!SequenceInstanceOf.isCollectionOfSequences(dataObject)) {
84            CommandHelpers.objectNotType(sequencesName, "Collection<List<Event<?>>>");
85            return;
86        }
87
88        sequences = (Collection<List<Event>>) dataObject;
89
90        writeJacaretoXML(sequences, filename);
91    }
92
93    private void writeLine(BufferedWriter writer, String line) throws IOException {
94        writer.write(line);
95        writer.newLine();
96    }
97
98    private void writeJacaretoHead(BufferedWriter writer) throws IOException {
99        writeLine(writer, "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>");
100        writeLine(writer, "<JacaretoStructure>");
101        writeLine(writer, "<Record>");
102
103        // TODO: This header content is basically copy+paste from a
104        // specific jacareto replay file right now.
105        // Some things such as screen resolution and especially the
106        // application starter details need to be changed for general cases.
107        writeLine(writer,
108                  "<Calendar procTime=\"0\" duration=\"0\" year=\"2014\" month=\"8\" date=\"11\" hour=\"14\" min=\"43\" sec=\"41\" uuid=\"06831ba1-f28a-4e05-b46e-ce9d8f9ffa0f\" />");
109        writeLine(writer,
110                  "<SystemInfo procTime=\"0\" duration=\"0\" screenWidth=\"2646\" screenHeight=\"1024\" javaVersion=\"1.7.0_65\" lookAndFeel=\"javax.swing.plaf.metal.MetalLookAndFeel\" uuid=\"720f430f-52cf-4d8b-9fbe-58434f766efe\" />");
111        writeLine(writer,
112                  "<KeyboardState procTime=\"0\" duration=\"0\" isNumLockOn=\"false\" isScrollLockOn=\"false\" isCapsLockOn=\"false\" applyIsNumLockOn=\"true\" applyIsScrollLockOn=\"true\" applyIsCapsLockOn=\"true\" uuid=\"28146f79-9fc7-49f9-b4a8-5866a7625683\" />");
113        writeLine(writer, "<ComponentMode numberPopupMenues=\"true\" />");
114        writeLine(writer,
115                  "<ApplicationStarter procTime=\"0\" duration=\"0\" name=\"HelloWorldSwing\" class=\"HelloWorldSwing\" initclass=\"\" basepath=\"/home/daniel/project/autoquest-jfcmonitor\" classpathext=\"${basepath}/helloswing.jar;${basepath}/.;\" detectDuration=\"false\" captureparams=\"\" replayparams=\"\" uuid=\"a7b7d7b9-caa9-4d6d-b052-cf74d353275e\" />");
116    }
117
118    private ArrayList<String> writeJacaretoEvents(BufferedWriter writer,
119                                                  Collection<List<Event>> sequences)
120        throws IOException
121    {
122        ArrayList<String> structure = new ArrayList<String>();
123        structure.add("<StructureElement class=\"jacareto.struct.RootElement\">");
124        // reference the elements that we included in the header
125        structure.add("<Recordable ref=\"0\" />"); // Calendar
126        structure.add("<Recordable ref=\"1\" />"); // SystemInfo
127        structure.add("<Recordable ref=\"2\" />"); // KeyboardState
128        structure.add("<Recordable ref=\"3\" />"); // ComponentMode
129        structure.add("<Recordable ref=\"4\" />"); // ApplicationStarter
130        nextRef = 5;
131
132        for (List<Event> sequence : sequences) {
133            for (Iterator<Event> eventIter = sequence.iterator(); eventIter.hasNext();) {
134                Event event = eventIter.next();
135                JFCGUIElement target = (JFCGUIElement) event.getTarget();
136
137                if (event.getType().getName().equals("LeftMouseClick")) {
138                    generateMouseClick(writer, structure, event.getTimestamp(), target);
139
140                    // FIXME: assume that the target is a checkbox for now =)
141                    // this is an item event and an action event in jacareto
142                    //@formatter:off
143                    writeLine(writer,
144                        "<ItemEvent "
145                        + "procTime=\"0\" "
146                        + "duration=\"0\" "
147                        + "source=\"" + target.getJacaretoHierarchy() + "\" "
148                        + "class=\"" + target.getSpecification().getType() + "\" "
149                        + "uuid=\"" + UUID.randomUUID() + "\" "
150                        + "ID=\"701\" "
151                        + "item=\"\" "
152                        + "stateChange=\"1\" />"
153                    );
154                    writeLine(writer,
155                        "<ActionEvent "
156                        + "procTime=\"0\" "
157                        + "duration=\"0\" "
158                        + "source=\"" + target.getJacaretoHierarchy() + "\" "
159                        + "class=\"" + target.getSpecification().getType() + "\" "
160                        + "uuid=\"" + UUID.randomUUID() + "\" "
161                        + "ID=\"1001\" "
162                        + "command=" + target.getName() + " "
163                        + "modifiers=\"16\" />"
164                    );
165                    //@formatter:on
166                    structure.add("<StructureElement class=\"jacareto.struct.ItemStateChange\">");
167                    structure.add("<Recordable ref=\"" + (nextRef++) + "\" />");
168                    structure.add("<Recordable ref=\"" + (nextRef++) + "\" />");
169                    structure.add("</StructureElement>");
170                }
171            }
172        }
173
174        return structure;
175    }
176
177    private void writeJacaretoTail(BufferedWriter writer, ArrayList<String> structure)
178        throws IOException
179    {
180        writeLine(writer, "</Record>");
181
182        // write the recording's structure
183        writeLine(writer, "<Structure>");
184        for (String element : structure) {
185            writeLine(writer, element);
186        }
187        // close root element
188        writeLine(writer, "</StructureElement>");
189        writeLine(writer, "</Structure>");
190    }
191
192    private void writeJacaretoXML(Collection<List<Event>> sequences, String filename) {
193        BufferedWriter writer = new BufferedWriter(openReplayFile(filename + ".xml"));
194
195        try {
196            writeJacaretoHead(writer);
197            ArrayList<String> structure = writeJacaretoEvents(writer, sequences);
198            writeJacaretoTail(writer, structure);
199            writeLine(writer, "</JacaretoStructure>");
200
201            writer.flush();
202            writer.close();
203        }
204        catch (IOException e) {
205            Console.printerrln("Unable to write Jacareto replay file " + filename);
206        }
207    }
208
209    /**
210     * <p>
211     * Helper function that opens the replay file for writing.
212     * </p>
213     *
214     * @param filename
215     *            name and path of the replay file
216     * @param encoding
217     *            file encoding, empty string for platform default
218     * @return {@link OutputStreamWriter} that writes to the replay file
219     */
220    private OutputStreamWriter openReplayFile(String filename) {
221        File file = new File(filename);
222        boolean fileCreated;
223        try {
224            fileCreated = file.createNewFile();
225            if (!fileCreated) {
226                Console.traceln(Level.INFO, "Created logfile " + filename);
227            }
228            else {
229                Console.traceln(Level.INFO, "Overwrote existing logfile " + filename);
230            }
231        }
232        catch (IOException e) {
233            Console.printerrln("Unable to create file " + filename);
234            Console.logException(e);
235        }
236        OutputStreamWriter writer = null;
237        try {
238            writer = new OutputStreamWriter(new FileOutputStream(file));
239        }
240        catch (IOException e) {
241            Console.printerrln("Unable to open file for writing (read-only file):" + filename);
242            Console.logException(e);
243        }
244        return writer;
245    }
246
247    private void writeMouseClickEvent(BufferedWriter writer,
248                                      ArrayList<String> structure,
249                                      long timestamp,
250                                      JFCGUIElement target,
251                                      int jacId) throws IOException
252    {
253        // Note, that all position related attributes appear to be meaningless
254        // for our purposes.
255        // TODO: change procTime and duration to adequate values
256        //@formatter:off
257        writeLine(writer,
258            "<MouseEvent "
259            + "procTime=\"0\" "
260            + "duration=\"150\" "
261            + "source=\"" + target.getJacaretoHierarchy() + "\" "
262            + "class=\"" + target.getSpecification().getType() + "\" "
263            + "uuid=\"" + UUID.randomUUID() + "\" "
264            + "ID=\"" + jacId + "\" "
265            + "component=\"null\" "
266            + "root=\"" + target.getJacaretoRoot() + "\" "
267            + "xPos=\"0\" "
268            + "yPos=\"0\" "
269            + "width=\"0\" "
270            + "height=\"0\" "
271            + "when=\"" + timestamp + "\" "
272            + "isConsumed=\"false\">"
273        );
274        writeLine(writer,
275            "<MouseInfo "
276            + "xPosition=\"0\" "
277            + "yPosition=\"0\" "
278            + "rootX=\"0\" "
279            + "rootY=\"0\" "
280            + "clickCount=\"1\" "
281            + "modifiers=\"16\" "
282            + "isPopupTrigger=\"false\" />"
283        );
284        writeLine(writer, "</MouseEvent>");
285        //@formatter:on
286
287        structure.add("<Recordable ref=\"" + (nextRef++) + "\" />");
288    }
289
290    private void generateMouseClick(BufferedWriter writer,
291                                    ArrayList<String> structure,
292                                    long timestamp,
293                                    JFCGUIElement target) throws IOException
294    {
295        structure.add("<StructureElement class=\"jacareto.struct.MouseClick\">");
296
297        writeMouseClickEvent(writer, structure, timestamp, target, 501);
298        writeMouseClickEvent(writer, structure, timestamp, target, 502);
299        writeMouseClickEvent(writer, structure, timestamp, target, 500);
300
301        structure.add("</StructureElement>");
302    }
303}
Note: See TracBrowser for help on using the repository browser.