/*
* This file is part of Goko.
*
* Goko is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Goko is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Goko. If not, see <http://www.gnu.org/licenses/>.
*/
package org.goko.core.execution.monitor.service;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.goko.core.common.exception.GkException;
import org.goko.core.common.exception.GkTechnicalException;
import org.goko.core.common.service.AbstractGokoService;
import org.goko.core.common.service.IGokoService;
import org.goko.core.common.utils.CacheByKey;
import org.goko.core.execution.monitor.event.ExecutionServiceWorkspaceEvent;
import org.goko.core.gcode.element.IGCodeProvider;
import org.goko.core.gcode.execution.ExecutionQueue;
import org.goko.core.gcode.execution.ExecutionQueueType;
import org.goko.core.gcode.execution.ExecutionState;
import org.goko.core.gcode.execution.ExecutionToken;
import org.goko.core.gcode.execution.ExecutionTokenState;
import org.goko.core.gcode.execution.IExecutor;
import org.goko.core.gcode.execution.SystemExecutionQueue;
import org.goko.core.gcode.service.IExecutionQueueListener;
import org.goko.core.gcode.service.IExecutionService;
import org.goko.core.gcode.service.IGCodeExecutionListener;
import org.goko.core.gcode.service.IGCodeProviderRepository;
import org.goko.core.gcode.service.IGCodeProviderRepositoryListener;
import org.goko.core.log.GkLog;
import org.goko.core.workspace.service.IWorkspaceService;
/**
* Default implementation of the GCode execution monitor service
*
* @author PsyKo
*
*/
public class ExecutionServiceImpl extends AbstractGokoService implements IExecutionService<ExecutionTokenState, ExecutionToken<ExecutionTokenState>>, IGokoService, IGCodeProviderRepositoryListener {
/** Service ID */
public static final String SERVICE_ID = "org.goko.core.execution.monitor.service.GCodeExecutionMonitorServiceImpl";
/** LOG */
private static final GkLog LOG = GkLog.getLogger(ExecutionServiceImpl.class);
/** The list of execution listener */
private CacheByKey<ExecutionQueueType, List<IGCodeExecutionListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>>>> listenercache;
/** The list of execution queue listener */
private List<IExecutionQueueListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>>> executionQueuelistenerList;
/** The current executor */
private IExecutor<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> executor;
/** The execution queue */
private CacheByKey<ExecutionQueueType, ExecutionQueue<ExecutionTokenState, ExecutionToken<ExecutionTokenState>>> cacheExecutionQueue;
/** The execution queue runnable */
private ExecutionQueueRunnable<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> executionQueueRunnable;
/** The executor service used to run the execution queue runnable */
private ExecutorService executorService;
/** The workspace service */
private IWorkspaceService workspaceService;
/** GCode provider repository */
private List<IGCodeProviderRepository> lstGCcodeRepository;
/**
* Constructor
* @throws GkException GkException
*/
public ExecutionServiceImpl() throws GkException {
listenercache = new CacheByKey<>();
listenercache.add(ExecutionQueueType.DEFAULT, new CopyOnWriteArrayList<IGCodeExecutionListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>>>());
listenercache.add(ExecutionQueueType.SYSTEM, new CopyOnWriteArrayList<IGCodeExecutionListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>>>());
cacheExecutionQueue = new CacheByKey<>();
// Creation of the queues
ExecutionQueue<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> defaultQueue = new ExecutionQueue<ExecutionTokenState, ExecutionToken<ExecutionTokenState>>(ExecutionQueueType.DEFAULT);
ExecutionQueue<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> systemQueue = new SystemExecutionQueue<ExecutionTokenState, ExecutionToken<ExecutionTokenState>>(this);
cacheExecutionQueue.add(ExecutionQueueType.DEFAULT, defaultQueue);
cacheExecutionQueue.add(ExecutionQueueType.SYSTEM, systemQueue);
executionQueuelistenerList = new CopyOnWriteArrayList<IExecutionQueueListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>>>();
lstGCcodeRepository = new CopyOnWriteArrayList<IGCodeProviderRepository>();
}
/** (inheritDoc)
* @see org.goko.core.common.service.IGokoService#getServiceId()
*/
@Override
public String getServiceId() throws GkException {
return SERVICE_ID;
}
/** (inheritDoc)
* @see org.goko.core.common.service.IGokoService#start()
*/
@Override
public void startService() throws GkException {
}
/** (inheritDoc)
* @see org.goko.core.common.service.IGokoService#stop()
*/
@Override
public void stopService() throws GkException {
}
public ExecutionQueue<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> getExecutionQueue(ExecutionQueueType type) throws GkException{
return cacheExecutionQueue.get(type);
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#getExecutionQueue()
*/
@Override
public List<ExecutionQueue<ExecutionTokenState, ExecutionToken<ExecutionTokenState>>> getExecutionQueue() throws GkException {
return cacheExecutionQueue.get();
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#findRunningExecutionQueue()
*/
@Override
public ExecutionQueue<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> findRunningExecutionQueue() throws GkException {
if(executionQueueRunnable != null){
return executionQueueRunnable.getExecutionQueue();
}
return null;
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#addToExecutionQueue(org.goko.core.gcode.execution.IExecutionToken)
*/
@Override
public void addToExecutionQueue(ExecutionToken<ExecutionTokenState> executionToken) throws GkException {
addToExecutionQueue(ExecutionQueueType.DEFAULT, executionToken);
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#addToExecutionQueue(org.goko.core.gcode.execution.ExecutionQueueType, org.goko.core.gcode.execution.IExecutionToken)
*/
@Override
public void addToExecutionQueue(ExecutionQueueType type, ExecutionToken<ExecutionTokenState> executionToken) throws GkException {
if(isQueueBeingExecuted(type)){
throw new GkTechnicalException("Queue "+type+" is already being executed");
}
getExecutionQueue(type).add(executionToken);
workspaceService.notifyWorkspaceEvent(ExecutionServiceWorkspaceEvent.getCreateEvent(executionToken));
notifyTokenCreate(executionToken);
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#addToExecutionQueue(org.goko.core.gcode.execution.ExecutionQueueType, org.goko.core.gcode.element.IGCodeProvider)
*/
@Override
public ExecutionToken<ExecutionTokenState> addToExecutionQueue(ExecutionQueueType type, IGCodeProvider gcodeProvider) throws GkException {
if(isQueueBeingExecuted(type)){
throw new GkTechnicalException("Queue "+type+" is already being executed");
}
if(executor == null){
throw new GkTechnicalException("ExecutionServiceImpl : cannot add provider to execution queue. Executor is not set.");
}
ExecutionToken<ExecutionTokenState> existingToken = findExecutionTokenByGCodeProvider(ExecutionQueueType.DEFAULT, gcodeProvider);
if(existingToken != null){
throw new GkTechnicalException("ExecutionServiceImpl : the given GCode provider is already in the execution queue.") ;
}
ExecutionToken<ExecutionTokenState> token = executor.createToken(gcodeProvider);
addToExecutionQueue(type, token);
return token;
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#addToExecutionQueue(org.goko.core.gcode.element.IGCodeProvider)
*/
@Override
public ExecutionToken<ExecutionTokenState> addToExecutionQueue(IGCodeProvider gcodeProvider) throws GkException {
return addToExecutionQueue(ExecutionQueueType.DEFAULT, gcodeProvider);
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#clearExecutionQueue()
*/
@Override
public void clearExecutionQueue(ExecutionQueueType queueType) throws GkException {
List<ExecutionToken<ExecutionTokenState>> lstTokens = getExecutionQueue(queueType).getExecutionToken();
if(CollectionUtils.isNotEmpty(lstTokens)){
for (ExecutionToken<ExecutionTokenState> executionToken : lstTokens) {
removeFromExecutionQueue(queueType, executionToken);
}
}
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#removeFromExecutionQueue(org.goko.core.gcode.execution.IExecutionToken)
*/
@Override
public void removeFromExecutionQueue(ExecutionQueueType queueType, ExecutionToken<ExecutionTokenState> executionToken) throws GkException {
getExecutionQueue(queueType).delete(executionToken.getId());
workspaceService.notifyWorkspaceEvent(ExecutionServiceWorkspaceEvent.getDeleteEvent(executionToken));
notifyTokenDelete(executionToken);
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#removeFromExecutionQueue(java.lang.Integer)
*/
@Override
public void removeFromExecutionQueue(ExecutionQueueType queueType, Integer idExecutionToken) throws GkException {
ExecutionQueue<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> queue = getExecutionQueue(queueType);
removeFromExecutionQueue(queueType, queue.getExecutionToken(idExecutionToken));
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#addExecutionListener(org.goko.core.gcode.service.IGCodeExecutionListener)
*/
@Override
public void addExecutionListener(ExecutionQueueType queueType, IGCodeExecutionListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> listener) throws GkException {
if(!listenercache.get(queueType).contains(listener)){
listenercache.get(queueType).add(listener);
}
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#removeExecutionListener(org.goko.core.gcode.service.IGCodeExecutionListener)
*/
@Override
public void removeExecutionListener(ExecutionQueueType queueType, IGCodeExecutionListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> listener) throws GkException {
if(listenercache.get(queueType).contains(listener)){
listenercache.get(queueType).remove(listener);
}
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#removeExecutionListener(org.goko.core.gcode.service.IGCodeExecutionListener)
*/
@Override
public void removeExecutionListener(IGCodeExecutionListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> listener) throws GkException {
removeExecutionListener(ExecutionQueueType.DEFAULT, listener);
removeExecutionListener(ExecutionQueueType.SYSTEM, listener);
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#addExecutionQueueListener(org.goko.core.gcode.service.IExecutionQueueListener)
*/
@Override
public void addExecutionQueueListener(IExecutionQueueListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> listener) throws GkException {
if(!executionQueuelistenerList.contains(listener)){
executionQueuelistenerList.add(listener);
}
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#removeExecutionQueueListener(org.goko.core.gcode.service.IExecutionQueueListener)
*/
@Override
public void removeExecutionQueueListener( IExecutionQueueListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> listener) throws GkException {
executionQueuelistenerList.remove(listener);
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#notifyExecutionStart(org.goko.core.gcode.execution.IExecutionToken.execution.IGCodeExecutionToken)
*/
@Override
public void notifyExecutionStart(ExecutionToken<ExecutionTokenState> token) throws GkException {
ExecutionQueueType queueType = executionQueueRunnable.getExecutionQueue().getType();
workspaceService.notifyWorkspaceEvent( ExecutionServiceWorkspaceEvent.getUpdateEvent(token) );
if(CollectionUtils.isNotEmpty(listenercache.get(queueType))){
for (IGCodeExecutionListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> executionListener : listenercache.get(queueType)) {
executionListener.onExecutionStart(token);
}
}
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#notifyQueueExecutionStart()
*/
@Override
public void notifyQueueExecutionStart(ExecutionQueueType queueType) throws GkException {
if(CollectionUtils.isNotEmpty(listenercache.get(queueType))){
for (IGCodeExecutionListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> executionListener : listenercache.get(queueType)) {
executionListener.onQueueExecutionStart();
}
}
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#notifyQueueExecutionComplete()
*/
@Override
public void notifyQueueExecutionComplete(ExecutionQueueType queueType) throws GkException {
if(CollectionUtils.isNotEmpty(listenercache.get(queueType))){
for (IGCodeExecutionListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> executionListener : listenercache.get(queueType)) {
executionListener.onQueueExecutionComplete();
}
}
unlockGCodeProvider(queueType);
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#notifyQueueExecutionCanceled()
*/
@Override
public void notifyQueueExecutionCanceled(ExecutionQueueType queueType) throws GkException {
if(CollectionUtils.isNotEmpty(listenercache.get(queueType))){
for (IGCodeExecutionListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> executionListener : listenercache.get(queueType)) {
executionListener.onQueueExecutionCanceled();
}
}
unlockGCodeProvider(queueType);
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#notifyCommandStateChanged(org.goko.core.gcode.execution.IExecutionToken.execution.IGCodeExecutionToken, java.lang.Integer)
*/
@Override
public void notifyCommandStateChanged(ExecutionToken<ExecutionTokenState> token, Integer idLine) throws GkException {
ExecutionQueueType queueType = executionQueueRunnable.getExecutionQueue().getType();
List<IGCodeExecutionListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>>> listenerList = listenercache.get(queueType);
LOG.info("Executed line ["+idLine+"]");
if(CollectionUtils.isNotEmpty(listenerList)){
for (IGCodeExecutionListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> executionListener : listenerList) {
executionListener.onLineStateChanged(token, idLine);
}
}
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#notifyExecutionCanceled(org.goko.core.gcode.execution.IExecutionToken.execution.IGCodeExecutionToken)
*/
@Override
public void notifyExecutionCanceled(ExecutionToken<ExecutionTokenState> token) throws GkException {
ExecutionQueueType queueType = executionQueueRunnable.getExecutionQueue().getType();
List<IGCodeExecutionListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>>> listenerList = listenercache.get(queueType);
workspaceService.notifyWorkspaceEvent( ExecutionServiceWorkspaceEvent.getUpdateEvent(token) );
if(CollectionUtils.isNotEmpty(listenerList)){
for (IGCodeExecutionListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> executionListener : listenerList) {
executionListener.onExecutionCanceled(token);
}
}
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#notifyExecutionPause(org.goko.core.gcode.execution.IExecutionToken.execution.IGCodeExecutionToken)
*/
@Override
public void notifyExecutionPause(ExecutionToken<ExecutionTokenState> token) throws GkException {
ExecutionQueueType queueType = executionQueueRunnable.getExecutionQueue().getType();
List<IGCodeExecutionListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>>> listenerList = listenercache.get(queueType);
workspaceService.notifyWorkspaceEvent( ExecutionServiceWorkspaceEvent.getUpdateEvent(token) );
if(CollectionUtils.isNotEmpty(listenerList)){
for (IGCodeExecutionListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> executionListener : listenerList) {
executionListener.onExecutionPause(token);
}
}
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#notifyExecutionResume(org.goko.core.gcode.execution.IExecutionToken)
*/
@Override
public void notifyExecutionResume(ExecutionToken<ExecutionTokenState> token) throws GkException {
ExecutionQueueType queueType = executionQueueRunnable.getExecutionQueue().getType();
List<IGCodeExecutionListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>>> listenerList = listenercache.get(queueType);
workspaceService.notifyWorkspaceEvent( ExecutionServiceWorkspaceEvent.getUpdateEvent(token) );
if(CollectionUtils.isNotEmpty(listenerList)){
for (IGCodeExecutionListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> executionListener : listenerList) {
executionListener.onExecutionResume(token);
}
}
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#notifyExecutionComplete(org.goko.core.gcode.execution.IExecutionToken.execution.IGCodeExecutionToken)
*/
@Override
public void notifyExecutionComplete(ExecutionToken<ExecutionTokenState> token) throws GkException {
ExecutionQueueType queueType = executionQueueRunnable.getExecutionQueue().getType();
List<IGCodeExecutionListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>>> listenerList = listenercache.get(queueType);
workspaceService.notifyWorkspaceEvent( ExecutionServiceWorkspaceEvent.getUpdateEvent(token) );
if(CollectionUtils.isNotEmpty(listenerList)){
for (IGCodeExecutionListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> executionListener : listenerList) {
executionListener.onExecutionComplete(token);
}
}
}
/**
* Notifies the registered listener for a token create event
* @param token the created token
*/
protected void notifyTokenCreate(ExecutionToken<ExecutionTokenState> token){
for (IExecutionQueueListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> listener : executionQueuelistenerList) {
listener.onTokenCreate(token);
}
}
/**
* Notifies the registered listener for a token delete event
* @param token the deleted token
*/
protected void notifyTokenDelete(ExecutionToken<ExecutionTokenState> token){
for (IExecutionQueueListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> listener : executionQueuelistenerList) {
listener.onTokenDelete(token);
}
}
/**
* Notifies the registered listener for a token update event
* @param token the updated token
*/
protected void notifyTokenUpdate(ExecutionToken<ExecutionTokenState> token){
for (IExecutionQueueListener<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> listener : executionQueuelistenerList) {
listener.onTokenUpdate(token);
}
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#setExecutor(org.goko.core.gcode.execution.IExecutor)
*/
@Override
public void setExecutor(IExecutor<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> executor) throws GkException {
this.executor = executor;
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#beginQueueExecution()
*/
@Override
public void beginQueueExecution(ExecutionQueueType type) throws GkException {
ExecutionQueue<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> executionQueue = getExecutionQueue(type);
if(executionQueue != null && executor.isReadyForQueueExecution()){
if(executionQueueRunnable != null &&
(executionQueueRunnable.getState() == ExecutionState.RUNNING ||
executionQueueRunnable.getState() == ExecutionState.PAUSED ||
executionQueueRunnable.getState() == ExecutionState.ERROR)){
throw new GkTechnicalException("Queue is already running");
}
lockGCodeProvider(type);
executionQueue.reset();
executionQueueRunnable = new ExecutionQueueRunnable<>(this);
executionQueueRunnable.setExecutor(executor);
executionQueueRunnable.setExecutionQueue(executionQueue);
if(executorService != null){
executorService.shutdown();
}
executorService = Executors.newSingleThreadExecutor();
executorService.execute(executionQueueRunnable);
}
}
/**
* Lock the GCode providers in queue
* @throws GkException GkException
*/
private void lockGCodeProvider(ExecutionQueueType queueType) throws GkException {
List<ExecutionToken<ExecutionTokenState>> lstToken = getExecutionQueue(queueType).getExecutionToken();
if(CollectionUtils.isNotEmpty(lstToken)){
for (ExecutionToken<ExecutionTokenState> executionToken : lstToken) {
executionToken.getGCodeProvider().lock();
}
}
}
/**
* Unlock the GCode providers in queue
* @throws GkException GkException
*/
protected void unlockGCodeProvider(ExecutionQueueType queueType) throws GkException {
List<ExecutionToken<ExecutionTokenState>> lstToken = getExecutionQueue(queueType).getExecutionToken();
if(CollectionUtils.isNotEmpty(lstToken)){
for (ExecutionToken<ExecutionTokenState> executionToken : lstToken) {
executionToken.getGCodeProvider().unlock();
}
}
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#pauseQueueExecution()
*/
@Override
public void pauseQueueExecution() throws GkException {
if(getExecutionState() != ExecutionState.PAUSED && getExecutionState() != ExecutionState.IDLE){
if(executionQueueRunnable != null){
executionQueueRunnable.pause();
}
}
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#stopQueueExecution()
*/
@Override
public void stopQueueExecution() throws GkException {
if(getExecutionState() != ExecutionState.STOPPED){
if(executionQueueRunnable != null){
executionQueueRunnable.stop();
unlockGCodeProvider(executionQueueRunnable.getExecutionQueue().getType());
}
}
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#resumeQueueExecution()
*/
@Override
public void resumeQueueExecution() throws GkException {
if(getExecutionState() == ExecutionState.PAUSED){
if(executionQueueRunnable != null){
executionQueueRunnable.resume();
}
}
}
protected boolean isQueueBeingExecuted(ExecutionQueueType type){
if(executionQueueRunnable != null && executionQueueRunnable.getExecutionQueue().getType() == type){
return executionQueueRunnable.getState() == ExecutionState.ERROR ||
executionQueueRunnable.getState() == ExecutionState.PAUSED ||
executionQueueRunnable.getState() == ExecutionState.RUNNING;
}
return false;
}
public boolean isReadyForExecution() throws GkException{
if(getExecutionState() == ExecutionState.IDLE ||
getExecutionState() == ExecutionState.COMPLETE ||
getExecutionState() == ExecutionState.FATAL_ERROR||
getExecutionState() == ExecutionState.STOPPED){
return true;
}
return false;
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#getExecutionState()
*/
@Override
public ExecutionState getExecutionState() throws GkException {
if(executionQueueRunnable == null){
return ExecutionState.IDLE;
}
return executionQueueRunnable.getState();
}
/**
* @return the workspaceService
*/
public IWorkspaceService getWorkspaceService() {
return workspaceService;
}
/**
* @param workspaceService the workspaceService to set
* @throws GkException GkException
*/
public void setWorkspaceService(IWorkspaceService workspaceService) {
this.workspaceService = workspaceService;
}
/**
* @param gcodeRepository the gcodeRepository to set
* @throws GkException GkException
*/
public void addGCodeRepository(IGCodeProviderRepository gcodeRepository) throws GkException {
this.lstGCcodeRepository.add(gcodeRepository);
gcodeRepository.addListener(this);
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IGCodeProviderRepositoryListener#onGCodeProviderCreate(org.goko.core.gcode.element.IGCodeProvider)
*/
@Override
public void onGCodeProviderCreate(IGCodeProvider provider) throws GkException {
// TODO Auto-generated method stub
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IGCodeProviderRepositoryListener#onGCodeProviderUpdate(org.goko.core.gcode.element.IGCodeProvider)
*/
@Override
public void onGCodeProviderUpdate(IGCodeProvider provider) throws GkException {
// Reset the data for the updated token
for (ExecutionQueue<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> executionQueue : cacheExecutionQueue.get()) {
ExecutionToken<ExecutionTokenState> token = findExecutionTokenByGCodeProvider(executionQueue.getType(), provider);
if(token != null){
token.reset();
notifyTokenUpdate(token);
break;
}
}
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IGCodeProviderRepositoryListener#beforeGCodeProviderDelete(org.goko.core.gcode.element.IGCodeProvider)
*/
@Override
public void beforeGCodeProviderDelete(IGCodeProvider provider) throws GkException {
ExecutionToken<ExecutionTokenState> tokenToRemove = null;
ExecutionQueueType type = null;
for (ExecutionQueue<ExecutionTokenState, ExecutionToken<ExecutionTokenState>> executionQueue : cacheExecutionQueue.get()) {
ExecutionToken<ExecutionTokenState> token = findExecutionTokenByGCodeProvider(executionQueue.getType(), provider);
if(token != null){
tokenToRemove = token;
type = executionQueue.getType();
break;
}
}
if(tokenToRemove != null){
removeFromExecutionQueue(type, tokenToRemove);
}
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IGCodeProviderRepositoryListener#afterGCodeProviderDelete(org.goko.core.gcode.element.IGCodeProvider)
*/
@Override
public void afterGCodeProviderDelete(IGCodeProvider provider) throws GkException {
// Nothing yet
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IGCodeProviderRepositoryListener#onGCodeProviderLocked(org.goko.core.gcode.element.IGCodeProvider)
*/
@Override
public void onGCodeProviderLocked(IGCodeProvider provider) throws GkException {
// TODO Auto-generated method stub
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IGCodeProviderRepositoryListener#onGCodeProviderUnlocked(org.goko.core.gcode.element.IGCodeProvider)
*/
@Override
public void onGCodeProviderUnlocked(IGCodeProvider provider) throws GkException {
// TODO Auto-generated method stub
}
@Override
public ExecutionToken<ExecutionTokenState> getExecutionTokenByGCodeProvider(ExecutionQueueType queueType, IGCodeProvider gcodeProvider) throws GkException {
ExecutionToken<ExecutionTokenState> token = findExecutionTokenByGCodeProvider(queueType, gcodeProvider);
if(token == null){
throw new GkTechnicalException("No Execution token for GCode Provider ["+gcodeProvider.getId()+"]");
}
return token;
}
@Override
public ExecutionToken<ExecutionTokenState> findExecutionTokenByGCodeProvider(ExecutionQueueType queueType, IGCodeProvider gcodeProvider) throws GkException {
List<ExecutionToken<ExecutionTokenState>> lstTokens = getExecutionQueue(queueType).getExecutionToken();
if(CollectionUtils.isNotEmpty(lstTokens)){
for (ExecutionToken<ExecutionTokenState> executionToken : lstTokens) {
if(ObjectUtils.equals(gcodeProvider, executionToken.getGCodeProvider())){
return executionToken;
}
}
}
return null;
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#findExecutionTokenAfter(org.goko.core.gcode.execution.IExecutionToken)
*/
@Override
public ExecutionToken<ExecutionTokenState> findExecutionTokenAfter(ExecutionQueueType queueType, ExecutionToken<ExecutionTokenState> token) throws GkException {
List<ExecutionToken<ExecutionTokenState>> lstTokens = getExecutionQueue(queueType).getExecutionToken();
if(CollectionUtils.isNotEmpty(lstTokens)){
boolean isNext = false;
for (ExecutionToken<ExecutionTokenState> executionToken : lstTokens) {
if(isNext){
return executionToken;
}
if(ObjectUtils.equals(token.getId(), executionToken.getId())){
isNext = true;
}
}
}
return null;
}
/** (inheritDoc)
* @see org.goko.core.gcode.service.IExecutionService#findExecutionTokenBefore(org.goko.core.gcode.execution.IExecutionToken)
*/
@Override
public ExecutionToken<ExecutionTokenState> findExecutionTokenBefore(ExecutionQueueType queueType, ExecutionToken<ExecutionTokenState> token) throws GkException {
List<ExecutionToken<ExecutionTokenState>> lstTokens = getExecutionQueue(queueType).getExecutionToken();
if(CollectionUtils.isNotEmpty(lstTokens)){
ExecutionToken<ExecutionTokenState> previous = null;
for (ExecutionToken<ExecutionTokenState> executionToken : lstTokens) {
if(ObjectUtils.equals(token.getId(), executionToken.getId())){
return previous;
}
previous = executionToken;
}
}
return null;
}
}