/*******************************************************************************
* Copyright (c) 2014 Open Door Logistics (www.opendoorlogistics.com)
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v3
* which accompanies this distribution, and is available at http://www.gnu.org/licenses/lgpl.txt
******************************************************************************/
package com.opendoorlogistics.core.scripts.execution;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import com.opendoorlogistics.api.ExecutionReport;
import com.opendoorlogistics.core.utils.strings.StandardisedStringSet;
import com.opendoorlogistics.core.utils.strings.Strings;
public class ExecutionReportImpl implements ExecutionReport{
private boolean failed = false;
private ArrayList<LogEntry> logs = new ArrayList<>();
private class LogEntry{
final Throwable throwable;
final String s;
LogEntry(Throwable throwable, String s) {
this.throwable = throwable;
this.s = s;
}
}
@Override
public void log(String s) {
logs.add(new LogEntry(null, s));
}
@Override
public void setFailed(String reason) {
failed = true;
if (reason != null) {
log(reason);
}
}
@Override
public boolean isFailed() {
return failed;
}
@Override
public String toString() {
return getReportString(true,true);
}
@Override
public void setFailed(Throwable reason) {
logs.add(new LogEntry(reason, null));
setFailed((String)null);
}
@Override
public void add(ExecutionReport report, boolean copyFailedStatus) {
if(ExecutionReportImpl.class.isInstance(report)==false){
throw new RuntimeException();
}
if(copyFailedStatus && report.isFailed()){
failed = true;
}
for(LogEntry s : ((ExecutionReportImpl)report).logs){
logs.add(s);
}
}
@Override
public void add(ExecutionReport report) {
add(report,true);
}
@Override
public String getReportString(boolean includeExceptionTraces,boolean showSuccessFailureMessage) {
List<String> lines = getLines(includeExceptionTraces);
StandardisedStringSet printedLines = new StandardisedStringSet(false);
// put into single string
StringBuilder builder = new StringBuilder();
for(String line:lines){
// don't repeat lines
if(!printedLines.contains(line)){
builder.append(line);
builder.append(System.lineSeparator());
printedLines.add(line);
}
}
if(showSuccessFailureMessage){
if (failed) {
builder.append("Execution of the operation failed." + System.lineSeparator());
} else {
builder.append("Execution of the operation succeeded." + System.lineSeparator());
}
}
return builder.toString();
}
public List<String> getLines(boolean includeExceptionTraces) {
// filter list of logs
ArrayList<LogEntry> filtered = new ArrayList<>(logs);
HashSet<Throwable> throwables = new HashSet<>();
Iterator<LogEntry> it = filtered.iterator();
while(it.hasNext()){
LogEntry entry = it.next();
// add the throwable to the set
if(entry.throwable!=null){
throwables.add(entry.throwable);
}
// filter runtimeexcepptions whose cause has already been logged; these are likely just a rethrow...
if(entry.throwable!=null && Strings.isEmpty(entry.s)){
Throwable throwable = entry.throwable;
if(!RuntimeException.class.isInstance(throwable)){
continue;
}
if(!Strings.isEmpty(throwable.getMessage())){
continue;
}
if(throwable.getCause()==null){
continue;
}
if(!throwables.contains(throwable.getCause())){
continue;
}
it.remove();
}
}
// build list of lines first
ArrayList<String> lines = new ArrayList<>();
for (LogEntry line : filtered) {
if(line.s!=null){
lines.add(line.s);
}
if(line.throwable!=null){
if(includeExceptionTraces){
lines.add(Strings.getStackTrace(line.throwable));
}else{
for(String s:Strings.getExceptionMessages(line.throwable)){
lines.add(s);
}
}
}
}
return lines;
}
@Override
public void setFailed() {
failed = true;
}
@Override
public ExecutionReport deepCopy() {
ExecutionReportImpl ret = new ExecutionReportImpl();
ret.failed = failed;
// logs are immutable
ret.logs.addAll(logs);
return ret;
}
@Override
public int size() {
return logs.size();
}
}