/**
 * RequestKeyLookup.java
 * Created Aug 23, 2006
 * Copyright (C) Tandberg Television 2006
 */
package com.tandbergtv.workflow.driver.command.locate;

import static com.tandbergtv.workflow.core.ProcessStatus.BUSY;
import static com.tandbergtv.workflow.core.ProcessStatus.QUEUED;
import static com.tandbergtv.workflow.core.ProcessStatus.RUNNING;

import org.jbpm.graph.def.Node;
import org.jbpm.graph.exe.Token;

import com.tandbergtv.workflow.core.CustomToken;
import com.tandbergtv.workflow.core.service.ServiceRegistry;
import com.tandbergtv.workflow.driver.service.IPersistenceService;
import com.tandbergtv.workflow.message.WorkflowMessage;

/**
 * Default implementation of the token locator strategy. This can be used when a subsystem sends us
 * a message that contains the correlation id or the message key that we generated
 * and sent in the call. The message key is just the token id.
 * 
 * @author Sahil Verma
 */
public class RequestKeyLookup extends AbstractTokenLocator {

	/**
	 * Finds the Token using the Request Key in the incoming message. The Key is expected to equal
	 * the Token Id to locate. Also verifies that the Token located currently actually wants the
	 * specified message.
	 * 
	 * @see com.tandbergtv.workflow.driver.command.locate.ITokenLocatorStrategy#locate(com.tandbergtv.workflow.message.WorkflowMessage)
	 */
	public Token locate(WorkflowMessage message) throws TokenLocatorException {
		String uid = message.getMessageUID().getUID();
		IPersistenceService service = ServiceRegistry.getDefault().lookup(IPersistenceService.class); 
		CustomToken token = service.getToken(new Long(message.getKey().toString()));

		/* For a sync response, we clearly don't need to check whether this message is spurious */
		if (message.getMessageUID().isMessageOutgoing())
			return token;
		
		/* Check the status - unless the token actually using a device or queued for a resource
		 * it shouldn't get messages */
		if (token.getStatus() != BUSY && token.getStatus() != RUNNING && token.getStatus() != QUEUED)
			throw new TokenLocatorException("Message [" + uid + "]: found process " + token + 
				", status is unexpected");
		
		Node node = getNode(token);
		
		/* Verify that token is expecting the message */
		if (!needsMessage(node, message))
			return null;

		return token;
	}
}
