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

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

some refactorings

  • Property svn:mime-type set to text/plain
File size: 11.8 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                switch (event.getType().getName())
138                {
139                    case "LeftMouseButtonDown":
140                        structure.add("<StructureElement class=\"jacareto.struct.MouseClick\">");
141                        writeMouseClickEvent(writer, structure, event.getTimestamp(), target, 501);
142                        break;
143                    case "LeftMouseButtonUp":
144                        writeMouseClickEvent(writer, structure, event.getTimestamp(), target, 502);
145                        break;
146                    case "LeftMouseClick":
147                        writeMouseClickEvent(writer, structure, event.getTimestamp(), target, 500);
148                        structure.add("</StructureElement>");
149                        // FIXME: don't always write an item action
150                        writeItemActionEvent(writer, structure, target);
151                        break;
152                }
153
154            }
155        }
156
157        return structure;
158    }
159
160    private void writeJacaretoTail(BufferedWriter writer, ArrayList<String> structure)
161        throws IOException
162    {
163        writeLine(writer, "</Record>");
164
165        // write the recording's structure
166        writeLine(writer, "<Structure>");
167        for (String element : structure) {
168            writeLine(writer, element);
169        }
170        // close root element
171        writeLine(writer, "</StructureElement>");
172        writeLine(writer, "</Structure>");
173    }
174
175    private void writeJacaretoXML(Collection<List<Event>> sequences, String filename) {
176        BufferedWriter writer = new BufferedWriter(openReplayFile(filename + ".xml"));
177
178        try {
179            writeJacaretoHead(writer);
180            ArrayList<String> structure = writeJacaretoEvents(writer, sequences);
181            writeJacaretoTail(writer, structure);
182            writeLine(writer, "</JacaretoStructure>");
183
184            writer.flush();
185            writer.close();
186        }
187        catch (IOException e) {
188            Console.printerrln("Unable to write Jacareto replay file " + filename);
189        }
190    }
191
192    /**
193     * <p>
194     * Helper function that opens the replay file for writing.
195     * </p>
196     *
197     * @param filename
198     *            name and path of the replay file
199     * @param encoding
200     *            file encoding, empty string for platform default
201     * @return {@link OutputStreamWriter} that writes to the replay file
202     */
203    private OutputStreamWriter openReplayFile(String filename) {
204        File file = new File(filename);
205        boolean fileCreated;
206        try {
207            fileCreated = file.createNewFile();
208            if (!fileCreated) {
209                Console.traceln(Level.INFO, "Created logfile " + filename);
210            }
211            else {
212                Console.traceln(Level.INFO, "Overwrote existing logfile " + filename);
213            }
214        }
215        catch (IOException e) {
216            Console.printerrln("Unable to create file " + filename);
217            Console.logException(e);
218        }
219        OutputStreamWriter writer = null;
220        try {
221            writer = new OutputStreamWriter(new FileOutputStream(file));
222        }
223        catch (IOException e) {
224            Console.printerrln("Unable to open file for writing (read-only file):" + filename);
225            Console.logException(e);
226        }
227        return writer;
228    }
229
230    private void writeItemActionEvent(BufferedWriter writer,
231                                      ArrayList<String> structure,
232                                      JFCGUIElement target) throws IOException
233    {
234        //@formatter:off
235        writeLine(writer,
236            "<ItemEvent "
237            + "procTime=\"0\" "
238            + "duration=\"0\" "
239            + "source=\"" + target.getJacaretoHierarchy() + "\" "
240            + "class=\"" + target.getSpecification().getType() + "\" "
241            + "uuid=\"" + UUID.randomUUID() + "\" "
242            + "ID=\"701\" "
243            + "item=\"\" "
244            + "stateChange=\"1\" />"
245        );
246        writeLine(writer,
247            "<ActionEvent "
248            + "procTime=\"0\" "
249            + "duration=\"0\" "
250            + "source=\"" + target.getJacaretoHierarchy() + "\" "
251            + "class=\"" + target.getSpecification().getType() + "\" "
252            + "uuid=\"" + UUID.randomUUID() + "\" "
253            + "ID=\"1001\" "
254            + "command=" + target.getName() + " "
255            + "modifiers=\"16\" />"
256        );
257        //@formatter:on
258        structure.add("<StructureElement class=\"jacareto.struct.ItemStateChange\">");
259        structure.add("<Recordable ref=\"" + (nextRef++) + "\" />");
260        structure.add("<Recordable ref=\"" + (nextRef++) + "\" />");
261        structure.add("</StructureElement>");
262    }
263
264    private void writeMouseClickEvent(BufferedWriter writer,
265                                      ArrayList<String> structure,
266                                      long timestamp,
267                                      JFCGUIElement target,
268                                      int jacId) throws IOException
269    {
270        // Note, that all position related attributes appear to be meaningless
271        // for our purposes.
272        // TODO: change procTime and duration to adequate values
273        //@formatter:off
274        writeLine(writer,
275            "<MouseEvent "
276            + "procTime=\"0\" "
277            + "duration=\"150\" "
278            + "source=\"" + target.getJacaretoHierarchy() + "\" "
279            + "class=\"" + target.getSpecification().getType() + "\" "
280            + "uuid=\"" + UUID.randomUUID() + "\" "
281            + "ID=\"" + jacId + "\" "
282            + "component=\"null\" "
283            + "root=\"" + target.getJacaretoRoot() + "\" "
284            + "xPos=\"0\" "
285            + "yPos=\"0\" "
286            + "width=\"0\" "
287            + "height=\"0\" "
288            + "when=\"" + timestamp + "\" "
289            + "isConsumed=\"false\">"
290        );
291        writeLine(writer,
292            "<MouseInfo "
293            + "xPosition=\"0\" "
294            + "yPosition=\"0\" "
295            + "rootX=\"0\" "
296            + "rootY=\"0\" "
297            + "clickCount=\"1\" "
298            + "modifiers=\"16\" "
299            + "isPopupTrigger=\"false\" />"
300        );
301        writeLine(writer, "</MouseEvent>");
302        //@formatter:on
303
304        structure.add("<Recordable ref=\"" + (nextRef++) + "\" />");
305    }
306}
Note: See TracBrowser for help on using the repository browser.