import openwfe.org.ApplicationContext;
import openwfe.org.decision.DecisionException;
import openwfe.org.decision.DecisionService;
import openwfe.org.embed.impl.engine.AbstractEmbeddedParticipant;
import openwfe.org.engine.Definitions;
import openwfe.org.engine.dispatch.DispatchingException;
import openwfe.org.engine.expool.ExpressionPool;
import openwfe.org.engine.expressions.FlowExpression;
import openwfe.org.engine.workitem.InFlowWorkItem;
import openwfe.org.engine.workitem.WorkItem;

/**
 * @author gjoseph
 * @version $Revision: $ ($Author: $)
 */
public class EmbeddedDecisionParticipant extends AbstractEmbeddedParticipant {
    private final DecisionService decisionService;
    private final ExpressionPool expressionPool;
    private final String tableName;
    private final String participantNamePrefix;

    /**
     * Constructs an EmbeddedDecisionParticipant with the given name. You must pass either tableName
     * or participantNamePrefix, if you want the service to be applied to a given table or to a table whose name depends
     * on the participant, respectively. Set the other arguement to null.
     */
    public EmbeddedDecisionParticipant(String name, DecisionService decisionService, ApplicationContext ctx, String tableName, String participantNamePrefix) {
        super(name);
        this.decisionService = decisionService;
        this.expressionPool = Definitions.getExpressionPool(ctx);
        if (tableName != null && participantNamePrefix != null) {
            throw new IllegalArgumentException("Only one of tableName or participantNamePrefix is allowed, not both");
        }
        this.tableName = tableName;
        this.participantNamePrefix = participantNamePrefix;
    }

    public void consume(WorkItem wi) throws Exception {
        final InFlowWorkItem ifwi = (InFlowWorkItem) wi;

        final FlowExpression fe = expressionPool.fetch(ifwi.getLastExpressionId());

        String tName = null;
        try {
            if (this.tableName != null) {
                tName = this.tableName;
            } else {
                final String participantName = ifwi.getParticipantName();
                tName = participantName.substring(this.participantNamePrefix.length());
            }

            decisionService.apply(tName, fe, ifwi);

        } catch (final DecisionException e) {
            throw new DispatchingException("Failed to apply the workitem in the decision table '" + tName + "'", e);
        }

        replyToEngine(ifwi);
    }
}
