/**
* <copyright>
* Copyright (c) 2010-2014 Henshin developers. All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
* </copyright>
*/
package org.eclipse.emf.henshin.interpreter.impl;
import java.io.IOException;
import java.io.PrintStream;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.xmi.XMIResource;
import org.eclipse.emf.henshin.interpreter.ApplicationMonitor;
import org.eclipse.emf.henshin.interpreter.Assignment;
import org.eclipse.emf.henshin.interpreter.EGraph;
import org.eclipse.emf.henshin.interpreter.Match;
import org.eclipse.emf.henshin.interpreter.RuleApplication;
import org.eclipse.emf.henshin.interpreter.UnitApplication;
import org.eclipse.emf.henshin.interpreter.util.InterpreterUtil;
import org.eclipse.emf.henshin.model.resource.HenshinResourceSet;
/**
* {@link ApplicationMonitor} implementation with logging capabilities.
* @author Christian Krause
*
*/
public class LoggingApplicationMonitor extends BasicApplicationMonitor {
// Print stream to be used for logging:
protected PrintStream logStream = System.out;
// Whether to print logs only for rule applications:
protected boolean onlyRuleApplications = false;
// Whether to print logs only for unit (not rule) applications:
protected boolean onlyUnitApplications = false;
// Whether to print logs only for successful unit applications:
protected boolean onlySuccesses = false;
// Whether to print logs only for failed unit applications:
protected boolean onlyFailures = false;
// URI for saving intermediate models:
protected URI autoSaveURI;
// Execution step:
protected int step = 0;
// Maximum number of execution steps:
protected int maxSteps = -1;
/*
* (non-Javadoc)
* @see org.eclipse.emf.henshin.interpreter.impl.ApplicationMonitorImpl#cancel()
*/
@Override
public void cancel() {
super.cancel();
if (logStream!=null) {
logStream.println("=== CANCEL REQUESTED ===\n");
}
}
/*
* (non-Javadoc)
* @see org.eclipse.emf.henshin.interpreter.impl.ApplicationMonitorImpl#cancelAndUndo()
*/
@Override
public void cancelAndUndo() {
super.cancelAndUndo();
if (logStream!=null) {
logStream.println("=== CANCEL AND UNDO REQUESTED ===\n");
}
}
/*
* (non-Javadoc)
* @see org.eclipse.emf.henshin.interpreter.impl.ApplicationMonitorImpl#notifyExecute(org.eclipse.emf.henshin.interpreter.UnitApplication, boolean)
*/
@Override
public void notifyExecute(UnitApplication application, boolean success) {
super.notifyExecute(application, success);
logStep(application, success, "EXECUTED");
}
/*
* (non-Javadoc)
* @see org.eclipse.emf.henshin.interpreter.impl.ApplicationMonitorImpl#notifyUndo(org.eclipse.emf.henshin.interpreter.UnitApplication, boolean)
*/
@Override
public void notifyUndo(UnitApplication application, boolean success) {
super.notifyUndo(application, success);
logStep(application, success, "UNDONE");
}
/*
* (non-Javadoc)
* @see org.eclipse.emf.henshin.interpreter.impl.ApplicationMonitorImpl#notifyRedo(org.eclipse.emf.henshin.interpreter.UnitApplication, boolean)
*/
@Override
public void notifyRedo(UnitApplication application, boolean success) {
super.notifyExecute(application, success);
logStep(application, success, "REDONE");
}
/*
* Print log info about an execution step.
*/
protected void logStep(UnitApplication application, boolean success, String stepKind) {
if (logStream==null) {
return;
}
if (onlyRuleApplications && !(application instanceof RuleApplication)) {
return;
}
if (onlyUnitApplications && (application instanceof RuleApplication)) {
return;
}
if (onlySuccesses && !success) {
return;
}
if (onlyFailures && success) {
return;
}
step++;
EGraph graph = application.getEGraph();
logStream.println("=== (" + step + ") " + stepKind +
((application instanceof RuleApplication) ? " RULE " : " UNIT ") +
"'" + application.getUnit().getName() + "' [" + String.valueOf(success).toUpperCase() + "] ===\n");
String edges = "?";
try {
edges = String.valueOf(InterpreterUtil.countEdges(graph));
} catch (Throwable t) {}
logStream.println("Graph size: " + graph.size() + " nodes, " + edges + " edges\n");
if (application instanceof RuleApplication) {
RuleApplication ruleApp = (RuleApplication) application;
if (success) {
logStream.println(ruleApp.getCompleteMatch());
logStream.println(ruleApp.getResultMatch());
} else {
Match match = ruleApp.getPartialMatch();
if (match!=null && !match.isEmpty()) {
logStream.println("Partial " + ruleApp.getPartialMatch().toString().replaceFirst("Match", "match"));
}
}
} else {
Assignment assignment = application.getAssignment();
Assignment resultAssignment = application.getResultAssignment();
if (assignment!=null && !assignment.isEmpty()) {
logStream.println(assignment);
}
if (success && resultAssignment!=null && !resultAssignment.isEmpty()) {
logStream.println(resultAssignment);
}
}
// Save intermediate result?
if (autoSaveURI!=null) {
String basename = autoSaveURI.lastSegment();
String realname = autoSaveURI.trimFileExtension().lastSegment() +
"-" + new DecimalFormat("0000").format(step) + "." + autoSaveURI.fileExtension();
URI uri = URI.createURI(autoSaveURI.toString().replaceFirst(basename, realname));
ResourceSet resourceSet = null;
for (EObject root : graph.getRoots()) {
if (root.eResource()!=null && root.eResource().getResourceSet()!=null) {
resourceSet = root.eResource().getResourceSet();
break;
}
}
if (resourceSet==null) {
resourceSet = new HenshinResourceSet();
}
EGraph copy = graph.copy(null);
Resource resource = resourceSet.createResource(uri);
resource.getContents().addAll(copy.getRoots());
Map<Object,Object> options = new HashMap<Object,Object>();
options.put(XMIResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE);
try {
System.out.println("Saving intermediate result to " + uri + "\n");
resource.save(options);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (maxSteps>=0 && step>=maxSteps) {
System.out.println("Terminated after " + step + " steps by logging application monitor.");
System.exit(1);
}
}
public void setLogStream(PrintStream logStream) {
this.logStream = logStream;
}
public void setOnlyRuleApplications(boolean onlyRuleApplications) {
this.onlyRuleApplications = onlyRuleApplications;
}
public void setOnlyUnitApplications(boolean onlyUnitApplications) {
this.onlyUnitApplications = onlyUnitApplications;
}
public void setOnlySuccesses(boolean onlySuccesses) {
this.onlySuccesses = onlySuccesses;
}
public void setOnlyFailures(boolean onlyFailures) {
this.onlyFailures = onlyFailures;
}
public void setAutoSaveURI(URI autoSaveURI) {
this.autoSaveURI = autoSaveURI;
}
public void setMaxSteps(int maxSteps) {
this.maxSteps = maxSteps;
}
}