/* * Copyright 2016 Anyware Services * * Licensed 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.ametys.plugins.workflow.support; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.apache.avalon.framework.component.Component; import org.apache.avalon.framework.logger.AbstractLogEnabled; import org.apache.avalon.framework.service.ServiceException; import org.apache.avalon.framework.service.ServiceManager; import org.apache.avalon.framework.service.Serviceable; import com.opensymphony.workflow.AbstractWorkflow; import com.opensymphony.workflow.FactoryException; import com.opensymphony.workflow.Workflow; import com.opensymphony.workflow.WorkflowException; import com.opensymphony.workflow.loader.ActionDescriptor; import com.opensymphony.workflow.loader.StepDescriptor; import com.opensymphony.workflow.loader.WorkflowDescriptor; import com.opensymphony.workflow.spi.Step; import com.opensymphony.workflow.spi.WorkflowStore; /** * Helper to get information on the workflow structures */ public class WorkflowHelper extends AbstractLogEnabled implements Component, Serviceable { /** The Avalon role */ public static final String ROLE = WorkflowHelper.class.getName(); /** The content types extension point */ protected WorkflowProvider _workflowProvider; @Override public void service(ServiceManager smanager) throws ServiceException { _workflowProvider = (WorkflowProvider) smanager.lookup(WorkflowProvider.ROLE); } /** * Get a list of workflow names available * @return String[] an array of workflow names. */ public String[] getWorkflowNames() { try { return _workflowProvider.getWorkflowFactory().getWorkflowNames(); } catch (FactoryException e) { getLogger().error("Error getting workflow names", e); } return new String[0]; } /** * Returns a workflow definition object associated with the given name. * @param workflowName the name of the workflow * @return the object graph that represents a workflow definition */ public WorkflowDescriptor getWorkflowDescriptor(String workflowName) { try { return _workflowProvider.getWorkflowFactory().getWorkflow(workflowName); } catch (FactoryException e) { getLogger().error("Error loading workflow " + workflowName, e); } return null; } /** * Retrieves all actions of the workflow of a particular type of workflow * except initial actions. * @param workflowName the name of the workflow. * @return all actions ids. * @throws IllegalArgumentException If the workflow name is not valid. */ public int[] getAllActions(String workflowName) throws IllegalArgumentException { WorkflowDescriptor workflowDesc = getWorkflowDescriptor(workflowName); if (workflowDesc == null) { throw new IllegalArgumentException("Bad workflow name \"" + workflowName + "\""); } Set<Integer> actions = new HashSet<>(); // Récupérer des actions globales Iterator iterGlobalActions = workflowDesc.getGlobalActions().iterator(); // Parcourir la liste des actions globales while (iterGlobalActions.hasNext()) { // Récupérer la description de l'action globale courante ActionDescriptor actionDesc = (ActionDescriptor) iterGlobalActions.next(); // Ajouter l'action globale courante actions.add(new Integer(actionDesc.getId())); } // Récupérer la liste des steps Iterator iterSteps = workflowDesc.getSteps().iterator(); // Parcourir la liste des steps while (iterSteps.hasNext()) { // Récupérer le step courant StepDescriptor stepDesc = (StepDescriptor) iterSteps.next(); // Récupérer la liste des actions associés au step courant Iterator iterActions = stepDesc.getActions().iterator(); // Parcourir la liste des actions while (iterActions.hasNext()) { // Récupérer la description de chaque action ActionDescriptor actionDesc = (ActionDescriptor) iterActions.next(); // Ajouter l'action courante actions.add(new Integer(actionDesc.getId())); } } // Convertir la liste en tableau d'entier int[] array = new int[actions.size()]; Iterator<Integer> itAction = actions.iterator(); // Remplir le tableau for (int i = 0; itAction.hasNext(); i++) { array[i] = itAction.next().intValue(); } return array; } /** * Retrieves the name of an action. * @param workflowName The name of the workflow. * @param actionID The id of the action. * @return The name of the action or an empty string. */ public String getActionName(String workflowName, int actionID) { // Récupérer la description du workflow WorkflowDescriptor workflowDesc = getWorkflowDescriptor(workflowName); if (workflowDesc == null) { return ""; } // Récupérer la description de l'action ActionDescriptor actionDesc = workflowDesc.getAction(actionID); if (actionDesc == null) { return ""; } return actionDesc.getName(); } /** * Retrieves the name of a step. * @param workflowName the name of the workflow. * @param stepId the id of the step. * @return the name of the step or an empty string. */ public String getStepName(String workflowName, int stepId) { // Récupérer la description du workflow WorkflowDescriptor workflowDesc = getWorkflowDescriptor(workflowName); if (workflowDesc == null) { return ""; } // Récupérer la description de l'action StepDescriptor stepDesc = workflowDesc.getStep(stepId); if (stepDesc == null) { return ""; } return stepDesc.getName(); } /** * Retrieves the initial action id of a workflow. * @param workflowName the name of the workflow. * @return the first initial action id or <code>-1</code> * if the workflow does not exist. */ public int getInitialAction(String workflowName) { // Récupérer la description du workflow WorkflowDescriptor workflowDesc = getWorkflowDescriptor(workflowName); if (workflowDesc == null) { return -1; } // Retourner la première action initiale return ((ActionDescriptor) workflowDesc.getInitialActions().get(0)).getId(); } /** * Retrieves the action ids from a particular step. * @param workflowName the name of the workflow. * @param stepId the id of the step. * @return the ids of the actions of the step. */ public int[] getAllActionsFromStep(String workflowName, int stepId) { // Récupérer la description du workflow WorkflowDescriptor workflowDesc = getWorkflowDescriptor(workflowName); if (workflowDesc == null) { return new int[0]; } List<Integer> actions = new ArrayList<>(); // Vérifier que l'identifiant est valide StepDescriptor stepDesc = workflowDesc.getStep(stepId); if (stepDesc == null) { return new int[0]; } // Récupérer la liste des actions associés au step courant Iterator iterator = stepDesc.getActions().iterator(); // Parcourir la liste des actions while (iterator.hasNext()) { // Récupérer la description de chaque action ActionDescriptor actionDesc = (ActionDescriptor) iterator.next(); // Ajouter l'action courante actions.add(new Integer(actionDesc.getId())); } // Récupérer les actions globales iterator = workflowDesc.getGlobalActions().iterator(); // Parcourir la liste des actions globales while (iterator.hasNext()) { // Récupérer la description de l'action globale courante ActionDescriptor actionDesc = (ActionDescriptor) iterator.next(); // Ajouter l'action globale courant actions.add(new Integer(actionDesc.getId())); } // Convertir la liste en tableau d'entier int[] array = new int[actions.size()]; // Remplir le tableau for (int i = 0; i < array.length; i++) { array[i] = actions.get(i).intValue(); } return array; } /** * Get the steps the workflow was "in" at a given date. * @param workflow workflow * @param entryId the workflow entry ID. * @param timestamp the date. * @return the list of steps the workflow was in. * @throws WorkflowException if an error occurs. */ public List<Step> getStepAt(Workflow workflow, long entryId, Date timestamp) throws WorkflowException { return getStepsBetween(workflow, entryId, timestamp, timestamp); } /** * Get the steps the workflow was "in" between two dates. * @param workflow workflow * @param entryId the workflow entry ID. * @param start the start date. * @param end the end date. * @return the list of steps the workflow was in between the two dates. * @throws WorkflowException if an error occurs. */ public List<Step> getStepsBetween(Workflow workflow, long entryId, Date start, Date end) throws WorkflowException { WorkflowStore store = ((AbstractWorkflow) workflow).getConfiguration().getWorkflowStore(); List<Step> steps = new ArrayList<>(); List<Step> allSteps = new ArrayList<>(); allSteps.addAll(store.findCurrentSteps(entryId)); allSteps.addAll(store.findHistorySteps(entryId)); for (Step step : allSteps) { Date stepStartDate = step.getStartDate(); Date stepFinishDate = step.getFinishDate(); if (stepStartDate != null) { if (end.after(stepStartDate)) { if (stepFinishDate == null || start.before(stepFinishDate)) { steps.add(step); } } } else { if (stepFinishDate == null || start.before(stepFinishDate)) { steps.add(step); } } } return steps; } }