// Copyright 2012 Georg-August-Universität Göttingen, Germany
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package de.ugoe.cs.autoquest.commands.sequences;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import de.ugoe.cs.autoquest.CommandHelpers;
import de.ugoe.cs.autoquest.IReplayDecorator;
import de.ugoe.cs.autoquest.SequenceInstanceOf;
import de.ugoe.cs.autoquest.eventcore.Event;
import de.ugoe.cs.autoquest.eventcore.IReplayable;
import de.ugoe.cs.util.StringTools;
import de.ugoe.cs.util.console.Command;
import de.ugoe.cs.util.console.Console;
import de.ugoe.cs.util.console.GlobalDataContainer;
/**
*
* Command to create a replay file from stored sessions.
*
*
* TODO: Add appropriate checks if Events are replayable
*
* @author Steffen Herbold
* @version 1.0
*/
public class CMDgenerateReplayfile implements Command {
/*
* (non-Javadoc)
*
* @see de.ugoe.cs.util.console.Command#help()
*/
@Override
public String help() {
return "generateReplayfile ";
}
/*
* (non-Javadoc)
*
* @see de.ugoe.cs.util.console.Command#run(java.util.List)
*/
@SuppressWarnings("unchecked")
@Override
public void run(List parameters) {
String filename;
String sequencesName;
try {
filename = (String) parameters.get(0);
sequencesName = (String) parameters.get(1);
}
catch (Exception e) {
throw new IllegalArgumentException();
}
Collection> sequences = null;
Object dataObject = GlobalDataContainer.getInstance().getData(sequencesName);
if (dataObject == null) {
CommandHelpers.objectNotFoundMessage(sequencesName);
return;
}
if (!SequenceInstanceOf.isCollectionOfSequences(dataObject)) {
CommandHelpers.objectNotType(sequencesName, "Collection>>");
return;
}
sequences = (Collection>) dataObject;
createLogfileMultipleSessions(sequences, filename);
writeJacaretoXML(sequences, filename);
}
private void writeLine(BufferedWriter writer, String line) throws IOException {
writer.write(line);
writer.newLine();
}
private void writeJacaretoHead(BufferedWriter writer) throws IOException {
writeLine(writer, "");
writeLine(writer, "");
writeLine(writer, "");
// TODO: This header content is basically copy+paste from a
// specific jacareto replay file right now.
// Some things such as screen resolution and especially the
// application starter details need to be changed for general cases.
writeLine(writer,
" ");
writeLine(writer,
" ");
writeLine(writer,
" ");
writeLine(writer, "ComponentMode numberPopupMenues=\"true\" />");
writeLine(writer,
" ");
}
private void writeJacaretoEvents(BufferedWriter writer, Collection> sequences)
throws IOException
{
for (List sequence : sequences) {
for (Iterator eventIter = sequence.iterator(); eventIter.hasNext();) {
Event event = eventIter.next();
// TODO
}
}
}
private void writeJacaretoTail(BufferedWriter writer) throws IOException {
writeLine(writer, "
");
// TODO: There is a really big part in jacareto's replay
// files but they make no sense to me right now - skip this until later
// or until jacareto complains. =)
writeLine(writer, "");
writeLine(writer, " ");
writeLine(writer, "");
}
private void writeJacaretoXML(Collection> sequences, String filename) {
BufferedWriter writer = new BufferedWriter(openReplayFile(filename + ".xml"));
try {
writeJacaretoHead(writer);
writeJacaretoEvents(writer, sequences);
writeJacaretoTail(writer);
writer.flush();
writer.close();
}
catch (IOException e) {
Console.printerrln("Unable to write Jacareto replay file " + filename);
}
}
/**
*
* {@link IReplayDecorator} to be used. If this field is {@code null}, no decorator is used.
* Default: {@code null}
*
*/
private IReplayDecorator decorator = null;
/**
*
* Id of the current session. The starting id is 1.
*
*/
int sessionId = 1;
/**
*
* Creates a replay file that contains multiple event sequences.
*
*
* @param sequences
* collection of event sequences from which the sessions are generated
* @param filename
* name and path of the replay file
*/
private void createLogfileMultipleSessions(Collection> sequences, String filename) {
OutputStreamWriter writer = openReplayFile(filename);
if (writer != null) {
try {
try {
decorator =
sequences.iterator().next().get(0).getReplayables().get(0).getDecorator();
}
catch (Exception e) {
// in the above line, many things can go wrong: emtpy sequences, null
// references, etc. However, all failures just indicate that no replay decorator
// should be used, hence, we ignore the exception
Console.traceln(Level.FINEST, "no decorator used for " + filename);
}
if (decorator != null) {
writer.write(decorator.getHeader());
}
for (List actions : sequences) {
writeSession(actions, writer);
}
if (decorator != null) {
writer.write(decorator.getFooter());
}
decorator = null;
writer.close();
}
catch (IOException e) {
Console.printerrln("Unable to write replay file " + filename);
}
}
}
/**
*
* Helper function that opens the replay file for writing.
*
*
* @param filename
* name and path of the replay file
* @param encoding
* file encoding, empty string for platform default
* @return {@link OutputStreamWriter} that writes to the replay file
*/
private OutputStreamWriter openReplayFile(String filename, String encoding) {
File file = new File(filename);
boolean fileCreated;
try {
fileCreated = file.createNewFile();
if (!fileCreated) {
Console.traceln(Level.INFO, "Created logfile " + filename);
}
else {
Console.traceln(Level.INFO, "Overwrote existing logfile " + filename);
}
}
catch (IOException e) {
Console.printerrln("Unable to create file " + filename);
Console.logException(e);
}
OutputStreamWriter writer = null;
try {
if (encoding.isEmpty()) {
writer = new OutputStreamWriter(new FileOutputStream(file));
}
else {
writer = new OutputStreamWriter(new FileOutputStream(file), encoding);
}
}
catch (IOException e) {
Console.printerrln("Unable to open file for writing (read-only file):" + filename);
Console.logException(e);
}
return writer;
}
private OutputStreamWriter openReplayFile(String filename) {
return openReplayFile(filename, "");
}
/**
*
* Helper function that adds an event sequence to the replay.
*
*
* @param actions
* event sequences to be added
* @param writer
* {@link OutputStreamWriter} to which the replay is added
* @throws IOException
* thrown if there is a problem writing to writer
*/
private void writeSession(List actions, OutputStreamWriter writer) throws IOException {
if (decorator != null) {
writer.write(decorator.getSessionHeader(sessionId));
}
for (Event currentAction : actions) {
List extends IReplayable> replayables = currentAction.getReplayables();
for (IReplayable replayble : replayables) {
writer.write(replayble.getReplay() + StringTools.ENDLINE);
writer.flush();
}
}
if (decorator != null) {
writer.write(decorator.getSessionFooter(sessionId));
}
sessionId++;
}
}