001/*
002 *  Copyright 2010 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;
017
018import java.util.HashMap;
019import java.util.List;
020import java.util.Map;
021import java.util.Optional;
022
023import org.apache.avalon.framework.logger.LogEnabled;
024import org.apache.avalon.framework.logger.Logger;
025import org.apache.avalon.framework.service.ServiceException;
026import org.apache.avalon.framework.service.ServiceManager;
027import org.apache.avalon.framework.service.Serviceable;
028
029import org.ametys.core.user.UserIdentity;
030import org.ametys.runtime.i18n.I18nizableText;
031import org.ametys.runtime.parameter.ValidationResult;
032
033import com.opensymphony.workflow.WorkflowContext;
034import com.opensymphony.workflow.WorkflowException;
035
036/**
037 * Abstract class for easily retrieving environment components
038 * in a condition or a function.
039 */
040public abstract class AbstractWorkflowComponent implements LogEnabled, Serviceable
041{
042    /** Constant for storing the content into the transient variables map. */
043    public static final String CONTEXT_PARAMETERS_KEY = AbstractWorkflowComponent.class.getName() + "$Parameters";
044    
045    /** Constant for storing the result map into the transient variables map. */
046    public static final String RESULT_MAP_KEY = AbstractWorkflowComponent.class.getName() + ";resultMap";
047    
048    /** Constant for storing the content into the transient variables map. */
049    public static final String FAIL_CONDITIONS_KEY = AbstractWorkflowComponent.class.getName() + "$failConditions";
050    
051    /** Constant for storing the workflow validation in result map. */
052    public static final String WORKFLOW_VALIDATION_KEY = "workflowValidation";
053    
054    /** Service manager available to subclasses. */
055    protected ServiceManager _manager;
056    /** Logger available to subclasses. */
057    protected Logger _logger;
058     
059    @Override
060    public void enableLogging(Logger logger)
061    {
062        _logger = logger;
063    }
064    
065    @Override
066    public void service(ServiceManager manager) throws ServiceException
067    {
068        _manager = manager;
069    }
070    
071    /**
072     * Retrieve the user responsible of the call.
073     * @param transientVars the parameters from the call.
074     * @return the user responsible of the call.
075     * @throws WorkflowException if the user is not present.
076     */
077    public UserIdentity getUser(Map transientVars) throws WorkflowException
078    {
079        WorkflowContext workflowContext = (WorkflowContext) transientVars.get("context");
080
081        if (workflowContext == null)
082        {
083            throw new WorkflowException("Unable to get the workflow context");
084        }
085
086        return UserIdentity.stringToUserIdentity(workflowContext.getCaller());
087    }
088
089    /**
090     * Retrieve the workflow parameters map, or an empty map if there is no parameters
091     * @param transientVars the parameters from the call.
092     * @return the workflow parameters map
093     */
094    public Map<String, Object> getContextParameters(Map transientVars)
095    {
096        return Optional.ofNullable(transientVars.get(CONTEXT_PARAMETERS_KEY))
097            .filter(Map.class::isInstance)
098            .map(Map.class::cast)
099            .orElseGet(() -> new HashMap<>());
100    }
101    
102    /**
103     * Retrieve the list condition failure
104     * @param transientVars the parameters from the call.
105     * @return the list of failed condition
106     */
107    @SuppressWarnings("unchecked")
108    public List<ConditionFailure> getConditionFailures (Map transientVars)
109    {
110        return (List<ConditionFailure>) transientVars.get(FAIL_CONDITIONS_KEY);
111    }
112    
113    /**
114     * Retrieve the map to write return values
115     * @param transientVars the parameters from the call.
116     * @return the map to render.
117     * @throws WorkflowException if the result map is not found.
118     */
119    @SuppressWarnings("unchecked")
120    public Map<String, Object> getResultsMap(Map transientVars) throws WorkflowException
121    {
122        Map<String, Object> resultMap = (Map<String, Object>) transientVars.get(RESULT_MAP_KEY);
123        
124        if (resultMap == null)
125        {
126            throw new WorkflowException("Unable to retrieve result map");
127        }
128        
129        // Found in transient variables map
130        return resultMap;
131    }
132    
133    /**
134     * Add a global workflow error such as fail condition
135     * @param transientVars the parameters from the call.
136     * @param errorLabel The error label
137     * @throws WorkflowException if the result map is not found.
138     */
139    public void addWorkflowError (Map transientVars, I18nizableText errorLabel) throws WorkflowException
140    {
141        Map<String, Object> resultMap = getResultsMap(transientVars);
142        
143        ValidationResult validationResult = (ValidationResult) resultMap.computeIfAbsent(WORKFLOW_VALIDATION_KEY, __ -> new ValidationResult());
144        validationResult.addError(errorLabel);
145    }
146    
147    /**
148     * Add a global workflow errors that will be traited as warnings
149     * @param transientVars the parameters from the call.
150     * @param warnLabel The warning label
151     * @throws WorkflowException if the result map is not found.
152     */
153    public void addWorkflowWarning (Map transientVars, I18nizableText warnLabel) throws WorkflowException
154    {
155        Map<String, Object> resultMap = getResultsMap(transientVars);
156        
157        ValidationResult validationResult = (ValidationResult) resultMap.computeIfAbsent(WORKFLOW_VALIDATION_KEY, __ -> new ValidationResult());
158        validationResult.addWarning(warnLabel);
159    }
160    
161    /**
162     * Record representing a condition failure
163     * @param text the failure text
164     * @param type the type of failure
165     */
166    public record ConditionFailure(String text, String type) { /** */ }
167}