package rtt.core.manager.data;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.Writer;
import java.util.GregorianCalendar;
import java.util.List;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
import rtt.core.archive.logging.ArchiveLog;
import rtt.core.archive.logging.Detail;
import rtt.core.archive.logging.Entry;
import rtt.core.archive.logging.EntryType;
import rtt.core.archive.logging.Failure;
import rtt.core.archive.logging.Result;
import rtt.core.archive.logging.ResultType;
import rtt.core.archive.logging.Testrun;
import rtt.core.loader.ArchiveLoader;
import rtt.core.loader.fetching.SimpleFileFetching;
import rtt.core.testing.compare.results.ITestFailure;
import rtt.core.testing.compare.results.TestResult;
import rtt.core.utils.RTTLogging;
/**
* This manager provides all operations on the {@link ArchiveLog}.
*
* @author Christian Oelsner <C.Oelsner@gmail.com>
* @see AbstractDataManager
* @see ArchiveLog
*
*/
public class LogManager extends AbstractDataManager<ArchiveLog> {
/**
* Creates a new log manager for the given {@link ArchiveLoader}.
*
* @param loader
* the {@link ArchiveLoader}
*/
public LogManager(ArchiveLoader loader) {
super(loader, new SimpleFileFetching("log.xml", ""));
}
@Override
protected ArchiveLog doLoad() throws Exception {
return unmarshall(ArchiveLog.class);
}
@Override
protected void doSave(ArchiveLog data) {
marshall(ArchiveLog.class, data);
}
@Override
protected ArchiveLog getEmptyData() {
return new ArchiveLog();
}
private Entry createEntry(String message, String suffix, EntryType type) {
Entry entry = new Entry();
entry.setDate(getNow());
entry.setMsg(message);
entry.setSuffix(suffix);
entry.setType(type);
return entry;
}
private XMLGregorianCalendar getNow() {
try {
XMLGregorianCalendar cal = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(new GregorianCalendar());
cal.normalize();
return cal;
} catch (DatatypeConfigurationException e) {
RTTLogging.trace("Could not retrieve gregorian calendar", e);
return null;
}
}
/**
* Returns the {@link Entry} found from the given data.
* @param type an {@link EntryType} object
* @param date a {@link XMLGregorianCalendar} date object
* @return an {@linkplain Entry} object
*/
public Entry getEntry(EntryType type, XMLGregorianCalendar date) {
if (type == null || date == null) {
throw new IllegalArgumentException("EntryType or date was null.");
}
for (Entry entry : getData().getEntry()) {
if (entry.getType().equals(type) && entry.getDate().equals(date)) {
return entry;
}
}
return null;
}
/**
* Returns a {@link Testrun} from the log.
* <p>
* Calls {@link #getEntry(EntryType, XMLGregorianCalendar)} with
* preset {@link EntryType#TESTRUN}.
*
* @param date a {@link XMLGregorianCalendar} object
* @return a {@link Testrun} object
* @see #getEntry(EntryType, XMLGregorianCalendar)
*/
public Testrun getTestrun(XMLGregorianCalendar date) {
return (Testrun) getEntry(EntryType.TESTRUN, date);
}
/**
* Returns the corresponding {@link Result} from the given data.
* @param testrun
* @param type
* @param suiteName
* @param caseName
* @return
*/
public Result getResultFromTestrun(Testrun testrun, ResultType type, String suiteName, String caseName) {
if (testrun == null) {
throw new IllegalArgumentException("Testrun was null.");
}
for (Result result : testrun.getResult()) {
if (result.getType() == type &&
result.getTestsuite().equals(suiteName) &&
result.getTestcase().equals(caseName)) {
return result;
}
}
return null;
}
public List<Entry> getLogEntries() {
return getData().getEntry();
}
/**
* Adds an {@link Entry} to the {@link ArchiveLog}, with a list of
* {@link Detail}s.
*
* @param type
* the {@link EntryType}
* @param message
* the message of the new entry
* @param suffix
* the suffix of the new entry
* @param details
* a list of {@link Detail}s
* @see #addEntry(EntryType, String, String)
* @see ArchiveLog
* @see Entry
* @see EntryType
* @see Detail
*/
public void addEntry(EntryType type, String message, String suffix,
List<Detail> details) {
Entry entry = createEntry(message, suffix, type);
if (details != null) {
entry.getDetail().addAll(details);
}
data.getEntry().add(entry);
}
/**
* Adds an {@link Entry} to the {@link ArchiveLog}, without details.
*
* @param type
* the {@link EntryType}
* @param message
* the message of the new entry
* @param suffix
* the suffix of the new entry
* @see #addEntry(EntryType, String, String, List)
* @see ArchiveLog
* @see Entry
* @see EntryType
* @see Detail
*/
public void addEntry(EntryType type, String message, String suffix) {
addEntry(type, message, suffix, null);
}
public void addTestrunResult(List<TestResult> testResults,
String configName, String suiteName) {
Testrun tr = new Testrun();
tr.setDate(getNow());
tr.setConfiguration(configName);
tr.setType(EntryType.TESTRUN);
String message = "Test run for test suite [" + suiteName + "] ";
if (testResults.isEmpty()) {
message += "was empty. Configuration used: ";
} else {
message += "executed with configuration: ";
}
tr.setMsg(message);
tr.setSuffix(configName);
tr.setTestsuite(suiteName);
for (TestResult result : testResults) {
Result resultEntry = new Result();
resultEntry.setTestcase(result.getCaseName());
resultEntry.setTestsuite(result.getSuiteName());
resultEntry.setRefVersion(result.getRefVersion());
resultEntry.setTestVersion(result.getTestVersion());
switch (result.getType()) {
case FAILURE:
List<ITestFailure> failures = result.getFailures();
for (ITestFailure failure : failures) {
Failure failureEntry = new Failure();
failureEntry.setMsg(failure.getShortMessage());
resultEntry.getFailure().add(failureEntry);
}
resultEntry.setType(ResultType.FAILED);
break;
case SUCCESS:
resultEntry.setType(ResultType.PASSED);
break;
case SKIPPED:
resultEntry.setType(ResultType.SKIPPED);
break;
}
tr.getResult().add(resultEntry);
}
data.getEntry().add(tr);
}
/**
* Exports the complete {@link ArchiveLog} to a given location.
*
* @param location
* the location, where the log should be exported
* @throws Exception
* thrown, if any error occur during export
*/
public void export(File location) throws Exception {
String fileName = "log";
if (!location.isDirectory()) {
fileName = location.getName();
fileName = fileName.substring(0, fileName.lastIndexOf('.'));
location = location.getParentFile();
if (fileName.equals("") || location == null) {
throw new RuntimeException("The location of export couldn't be found. (was: " + location + ")");
}
}
File resultFile = new File(location.getAbsolutePath() + File.separatorChar + fileName + ".htm");
doSave(data);
InputStream logStream = getInputStream();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder db = factory.newDocumentBuilder();
Document document = db.parse(logStream);
StreamSource styleSource = new StreamSource(getClass().getResourceAsStream("/log.xslt"));
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer(styleSource);
Writer out = new FileWriter(resultFile);
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(out);
transformer.transform(source, result);
RTTLogging.info("Logging File exported to: " + resultFile.getCanonicalPath());
}
}