/*******************************************************************************
* Copyright (c) 2009-2011 CWI
* 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
*
* Contributors:
* * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI
* * Anya Helene Bagge - A.H.S.Bagge@cwi.nl (Univ. Bergen)
* * Mark Hills - Mark.Hills@cwi.nl (CWI)
*******************************************************************************/
package org.rascalmpl.eclipse.nature;
import java.io.PrintWriter;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubMonitor;
import org.rascalmpl.debug.IRascalMonitor;
import org.rascalmpl.interpreter.asserts.ImplementationError;
import io.usethesource.vallang.ISourceLocation;
public class RascalMonitor implements IRascalMonitor {
private SubRascalMonitor subMon = null;
private final IProgressMonitor monitor;
private String topName;
private final IWarningHandler handler;
public RascalMonitor(IProgressMonitor monitor, IWarningHandler handler) {
this.monitor = monitor;
this.handler = handler == null ? new WarningsToPrintWriter(new PrintWriter(System.err)) : handler;
}
@Override
public int endJob(boolean succeeded) {
if (subMon == null) {
throw new UnsupportedOperationException("endJob without startJob");
}
int worked = subMon.getWorkDone();
subMon = subMon.endJob();
monitor.setTaskName(topName);
return worked;
}
@Override
public void event(String name) {
event(name, 1);
}
@Override
public void event(String name, int inc) {
if(subMon != null) {
event(inc);
subMon.setName(name);
}
else {
throw new ImplementationError("event() called before startJob()");
}
}
@Override
public void event(int inc) {
if(subMon != null)
subMon.event(inc);
else
throw new ImplementationError("event() called before startJob()");
}
@Override
public void startJob(String name) {
startJob(name, 10, 0);
}
@Override
public void startJob(String name, int totalWork) {
startJob(name, totalWork, totalWork);
}
@Override
public void startJob(String name, int workShare, int totalWork) {
if (topName == null) {
topName = name;
}
monitor.setTaskName(name);
if(subMon == null)
subMon = new SubRascalMonitor(SubMonitor.convert(monitor), name, workShare, totalWork);
else
subMon = subMon.startJob(name, workShare, totalWork);
}
@Override
public void todo(int workRemaining) {
if(subMon != null)
subMon.todo(workRemaining);
else
throw new ImplementationError("event() called before startJob()");
}
private long nextPoll = 0;
private boolean previousResult;
@Override
public boolean isCanceled() {
if (System.currentTimeMillis() < nextPoll) {
return previousResult;
}
nextPoll = System.currentTimeMillis() + 100;
previousResult = monitor.isCanceled();
return previousResult;
}
private class SubRascalMonitor {
private final SubRascalMonitor parent;
private final SubMonitor monitor;
private int workActuallyDone;
private int workRemaining;
private int nextWorkUnit;
SubRascalMonitor(SubRascalMonitor parent, String name, int workShare, int totalWork) {
this.monitor = parent.monitor.newChild(workShare);
monitor.beginTask(name, totalWork);
this.workRemaining = totalWork;
this.parent = parent;
parent.nextWorkUnit = workShare;
}
SubRascalMonitor(SubMonitor monitor, String name, int workShare, int totalWork) {
this.monitor = SubMonitor.convert(monitor, workShare);
monitor.beginTask(name, totalWork);
this.workRemaining = totalWork;
this.parent = null;
}
void event(int inc) {
monitor.worked(nextWorkUnit);
workActuallyDone += nextWorkUnit;
if(workRemaining == 0)
monitor.setWorkRemaining(200);
else
workRemaining -= nextWorkUnit;
nextWorkUnit = inc;
}
void todo(int work) {
workRemaining = work;
monitor.setWorkRemaining(work);
}
SubRascalMonitor startJob(String name, int workShare, int totalWork) {
return new SubRascalMonitor(this, name, workShare, totalWork);
}
SubRascalMonitor endJob() {
monitor.done();
workActuallyDone += nextWorkUnit;
nextWorkUnit = 0;
if (parent != null) {
parent.workActuallyDone += parent.nextWorkUnit;
if (parent.workRemaining != 0)
parent.workRemaining -= parent.nextWorkUnit;
parent.nextWorkUnit = 0;
}
return parent;
}
void setName(String name) {
monitor.subTask(name);
}
public int getWorkDone() {
return workActuallyDone;
}
}
@Override
public void warning(String msg, ISourceLocation src) {
handler.warning(msg, src);
}
}