/*******************************************************************************
* Copyright (c) 2015, 2015 IBM Corporation and others.
* 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:
* Bruno Medeiros - initial API and implementation
*******************************************************************************/
package mmrnmhrm.core.engine;
import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
import melnorme.lang.ide.core.utils.CoreExecutors;
import melnorme.lang.ide.core.utils.operation.EclipseJobExecutor;
import melnorme.lang.tooling.common.ops.IOperationMonitor;
import melnorme.utilbox.concurrency.ExecutorTaskAgent;
import melnorme.utilbox.concurrency.OperationCancellation;
import melnorme.utilbox.core.CommonException;
import melnorme.utilbox.core.fntypes.OperationCallable;
import melnorme.utilbox.core.fntypes.OperationResult;
import melnorme.utilbox.misc.Location;
public abstract class DeeEngineOperation<RET> {
protected final DeeLanguageEngine languageEngine;
protected final Location location;
protected final int offset;
protected final int timeoutMillis;
protected final String opName;
public DeeEngineOperation(DeeLanguageEngine languageEngine, Location location, int offset, int timeoutMillis,
String opName) {
this.languageEngine = languageEngine;
this.location = assertNotNull(location);
this.offset = offset;
this.timeoutMillis = timeoutMillis;
this.opName = assertNotNull(opName);
}
public RET runEngineOperation(final IOperationMonitor om)
throws CommonException, OperationCancellation {
if(timeoutMillis <= 0 ) {
// Run directly
return doRunEngineOperation(om);
}
// Use a one-time executor
ExecutorTaskAgent completionExecutor = CoreExecutors.newExecutorTaskAgent(opName + " - Task Executor");
try {
return runEngineOperationWithExecutor(om, completionExecutor);
} finally {
completionExecutor.shutdownNow();
}
}
protected RET runEngineOperationWithExecutor(final IOperationMonitor om, ExecutorTaskAgent completionExecutor)
throws CommonException, OperationCancellation {
Future<RET> future = completionExecutor.submit(new Callable<RET>() {
@Override
public RET call() throws CommonException, OperationCancellation {
OperationCallable<RET> opCallable = () -> doRunEngineOperation(om);
Function<IOperationMonitor, OperationResult<RET>> op = (_om) -> {
return OperationResult.callToOpResult(opCallable);
};
return new EclipseJobExecutor().startOpFunction("Engine analysis", true, op).awaitResult2().get();
}
});
try {
return future.get(timeoutMillis, TimeUnit.MILLISECONDS);
} catch(ExecutionException e) {
if(e.getCause() instanceof OperationCancellation) {
throw (OperationCancellation) e.getCause();
}
if(e.getCause() instanceof CommonException) {
throw (CommonException) e.getCause();
}
throw new CommonException("Error performing " + opName + ".", e.getCause());
} catch (TimeoutException e) {
throw new CommonException("Timeout performing " + opName + ".", null);
} catch (InterruptedException e) {
throw new CommonException("Interrupted.", e);
}
}
protected RET doRunEngineOperation(final IOperationMonitor om)
throws CommonException, OperationCancellation {
// TODO: ensure working copy at location is updated.
return doRunOperationWithWorkingCopy(om);
}
protected abstract RET doRunOperationWithWorkingCopy(IOperationMonitor om)
throws CommonException, OperationCancellation;
}