blob: 5135554c6663ff11237ddf038fae592fb8428990 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.lenya.workflow.impl;
import java.util.ArrayList;
import java.util.List;
import org.apache.lenya.workflow.Action;
import org.apache.lenya.workflow.Condition;
import org.apache.lenya.workflow.Transition;
import org.apache.lenya.workflow.Version;
import org.apache.lenya.workflow.Workflow;
import org.apache.lenya.workflow.WorkflowEngine;
import org.apache.lenya.workflow.WorkflowException;
import org.apache.lenya.workflow.Workflowable;
/**
* Workflow engine implementation.
*
* @version $Id$
*/
public class WorkflowEngineImpl implements WorkflowEngine {
/**
* @see org.apache.lenya.workflow.WorkflowEngine#canInvoke(org.apache.lenya.workflow.Workflowable,
* org.apache.lenya.workflow.Workflow, java.lang.String)
*/
public boolean canInvoke(Workflowable workflowable, Workflow workflow, String event)
throws WorkflowException {
List firingTransitions = getFiringTransitions(workflowable, workflow, event);
return firingTransitions.size() == 1;
}
/**
* @see org.apache.lenya.workflow.WorkflowEngine#invoke(org.apache.lenya.workflow.Workflowable,
* org.apache.lenya.workflow.Workflow, java.lang.String)
*/
public void invoke(Workflowable workflowable, Workflow workflow, String event)
throws WorkflowException {
Transition firingTransition = null;
List firingTransitions = getFiringTransitions(workflowable, workflow, event);
if (firingTransitions.size() == 0) {
throw new WorkflowException("No transition can fire!");
} else if (firingTransitions.size() > 1) {
throw new WorkflowException("More than one transitions can fire!");
} else {
firingTransition = (Transition) firingTransitions.get(0);
}
String destination = firingTransition.getDestination();
Version newVersion = createNewVersion(workflowable, workflow, event, destination);
Action[] actions = firingTransition.getActions();
for (int i = 0; i < actions.length; i++) {
actions[i].execute(newVersion);
}
workflowable.newVersion(workflow, newVersion);
}
/**
* Creates a new version.
* @param workflowable The workflowable.
* @param workflow The workflow.
* @param event The event.
* @param destination The destination.
* @return A version.
* @throws WorkflowException if an error occurs.
*/
protected Version createNewVersion(Workflowable workflowable, Workflow workflow, String event,
String destination) throws WorkflowException {
Version latestVersion = workflowable.getLatestVersion();
Version newVersion = new VersionImpl(event, destination);
String[] variableNames = workflow.getVariableNames();
for (int i = 0; i < variableNames.length; i++) {
String name = variableNames[i];
boolean value;
if (latestVersion == null) {
value = workflow.getInitialValue(name);
} else {
value = latestVersion.getValue(name);
}
newVersion.setValue(name, value);
}
return newVersion;
}
/**
* Returns the transitions that would fire in a certain situation.
* @param workflowable The workflowable.
* @param workflow The workflow.
* @param event The event.
* @return A list of transitions.
* @throws WorkflowException if an error occurs.
*/
protected List getFiringTransitions(Workflowable workflowable, Workflow workflow, String event)
throws WorkflowException {
Version lastVersion = workflowable.getLatestVersion();
String currentState;
if (lastVersion == null) {
currentState = workflow.getInitialState();
} else {
currentState = lastVersion.getState();
}
Transition[] transitions = workflow.getLeavingTransitions(currentState);
List firingTransitions = new ArrayList();
for (int i = 0; i < transitions.length; i++) {
if (transitions[i].getEvent().equals(event)
&& canFire(transitions[i], workflow, workflowable)) {
firingTransitions.add(transitions[i]);
}
}
return firingTransitions;
}
/**
* Checks if a transition can fire.
* @param transition The transition.
* @param workflow The workflow.
* @param workflowable The workflowable.
* @return A boolean value.
* @throws WorkflowException if an error occurs.
*/
public boolean canFire(Transition transition, Workflow workflow, Workflowable workflowable)
throws WorkflowException {
Condition[] _conditions = transition.getConditions();
boolean canFire = true;
int i = 0;
while (canFire && i < _conditions.length) {
canFire = canFire && _conditions[i].isComplied(workflow, workflowable);
i++;
}
return canFire;
}
}