001/*
002 *  Copyright 2023 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.plugins.workflow.dao;
017
018import java.util.ArrayList;
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022
023import org.apache.avalon.framework.component.Component;
024import org.apache.avalon.framework.service.ServiceException;
025import org.apache.avalon.framework.service.ServiceManager;
026import org.apache.avalon.framework.service.Serviceable;
027
028import org.ametys.core.ui.Callable;
029import org.ametys.plugins.workflow.EnhancedFunction;
030import org.ametys.plugins.workflow.EnhancedFunction.FunctionArgument;
031import org.ametys.plugins.workflow.support.AvalonTypeResolver;
032import org.ametys.plugins.workflow.support.WorkflowHelper;
033import org.ametys.runtime.i18n.I18nizableText;
034import org.ametys.runtime.plugin.component.AbstractLogEnabled;
035
036import com.opensymphony.workflow.FunctionProvider;
037import com.opensymphony.workflow.TypeResolver;
038import com.opensymphony.workflow.WorkflowException;
039import com.opensymphony.workflow.loader.ActionDescriptor;
040import com.opensymphony.workflow.loader.FunctionDescriptor;
041import com.opensymphony.workflow.loader.StepDescriptor;
042import com.opensymphony.workflow.loader.WorkflowDescriptor;
043
044/**
045 * DAO for workflow element's pre and pos functions
046 */
047public class WorkflowFunctionDAO extends AbstractLogEnabled implements Component, Serviceable
048{
049    /** The workflow helper */
050    protected WorkflowHelper _workflowHelper;
051    
052    /** The service manager */
053    protected ServiceManager _manager;
054
055    public void service(ServiceManager smanager) throws ServiceException
056    {
057        _workflowHelper = (WorkflowHelper) smanager.lookup(WorkflowHelper.ROLE);
058        _manager = smanager;
059    }
060    
061    @SuppressWarnings("unchecked")
062    @Callable(right = "Workflow_Right_Read")
063    /**
064     * Get pre and postfunctions of current step
065     * @param workflowName the workflow unique name
066     * @param stepId id of the current step
067     * @return a list of the step's functions
068     */
069    public Map<String, Object> getStepFunctions(String workflowName, String stepId)
070    {
071        WorkflowDescriptor workflowDescriptor = _workflowHelper.getWorkflowDescriptor(workflowName);
072        StepDescriptor step = workflowDescriptor.getStep(Integer.valueOf(stepId));
073        
074        List<Map<String, Object>> functions2json = new ArrayList<>();
075        
076        if (step != null)
077        {
078            functions2json.addAll(_functions2JSON(step.getPreFunctions()));
079            functions2json.addAll(_functions2JSON(step.getPostFunctions()));
080        }
081        
082        return Map.of("data", functions2json);
083    }
084    
085    @SuppressWarnings("unchecked")
086    @Callable(right = "Workflow_Right_Read")
087    /**
088     * Get pre and postfunctions of current action
089     * @param workflowName the workflow unique name
090     * @param actionId id of the current action
091     * @return a list of the action's functions
092     */
093    public Map<String, Object> getActionFunctions(String workflowName, String actionId)
094    {
095        WorkflowDescriptor workflowDescriptor = _workflowHelper.getWorkflowDescriptor(workflowName);
096        ActionDescriptor action = workflowDescriptor.getAction(Integer.valueOf(actionId));
097        
098        List<Map<String, Object>> functions2json = new ArrayList<>();
099        
100        if (action != null)
101        {
102            functions2json.addAll(_functions2JSON(action.getPreFunctions()));
103            functions2json.addAll(_functions2JSON(action.getPostFunctions()));
104        }
105        
106        return Map.of("data", functions2json);
107    }
108    
109    private List<Map<String, Object>> _functions2JSON(List<FunctionDescriptor> functions)
110    {
111        List<Map<String, Object>> functions2json = new ArrayList<>();
112        for (FunctionDescriptor function : functions)
113        {
114            functions2json.add(_function2JSON(function));
115        }
116        return functions2json;
117    }
118    
119    private Map<String, Object> _function2JSON(FunctionDescriptor workflowFunction)
120    {
121        String role = (String) workflowFunction.getArgs().get("role");
122        try
123        {
124            TypeResolver typeResolver = new AvalonTypeResolver(_manager);
125            FunctionProvider function = typeResolver.getFunction(workflowFunction.getType(), workflowFunction.getArgs());
126            if (function instanceof EnhancedFunction)
127            {
128                List<FunctionArgument> arguments = ((EnhancedFunction) function).getArguments();
129                Map<String, String> values = new HashMap<>();
130                for (FunctionArgument arg : arguments)
131                {
132                    values.put(arg.name(), (String) workflowFunction.getArgs().get(arg.name()));
133                }
134                
135                I18nizableText description = ((EnhancedFunction) function).getDescription(values);
136                return Map.of("role", description != null ? description : role);
137            }
138        }
139        catch (WorkflowException e)
140        {
141            getLogger().error("Function " + role + " couldn't be resolved", e);
142        }
143        
144        return Map.of("role", role);
145    }
146}