001/*
002 *  Copyright 2018 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.cms.workflow.extensions;
017
018import java.util.Collections;
019import java.util.List;
020import java.util.Map;
021
022import org.apache.avalon.framework.service.ServiceException;
023import org.apache.avalon.framework.service.ServiceManager;
024import org.apache.avalon.framework.service.Serviceable;
025import org.apache.commons.lang3.StringUtils;
026
027import org.ametys.plugins.workflow.EnhancedFunction;
028import org.ametys.runtime.i18n.I18nizableText;
029import org.ametys.runtime.plugin.ExtensionPoint;
030import org.ametys.runtime.plugin.component.AbstractLogEnabled;
031
032import com.opensymphony.module.propertyset.PropertySet;
033import com.opensymphony.workflow.FunctionProvider;
034import com.opensymphony.workflow.WorkflowException;
035
036/**
037 * Workflow function that will call each function registered on the extension point given as an argument 
038 */
039public class ExtensibleFunction extends AbstractLogEnabled implements EnhancedFunction, Serviceable
040{
041    /** The rights key. */
042    protected static final String EXTENSION_POINT_ROLE_ARGS_KEY = "extension-point";
043    /** The service manager */
044    protected ServiceManager _manager;
045    
046    public void service(ServiceManager manager) throws ServiceException
047    {
048        _manager = manager;
049        
050    }
051    
052    
053    public void execute(Map transientVars, Map args, PropertySet ps) throws WorkflowException
054    {
055        ExtensionPoint<String> functionsExtensionPoint = _getFunctionsExtensionPoint(args);
056        for (String functionId : functionsExtensionPoint.getExtensionsIds())
057        {
058            getLogger().debug("{} is delegating to extension {} of point {}", ExtensibleFunction.class.getName(), functionId);
059            String functionProviderRole = functionsExtensionPoint.getExtension(functionId);
060            FunctionProvider functionProvider = _getFunctionProvider(functionId, functionProviderRole);
061            functionProvider.execute(transientVars, Collections.emptyMap(), ps); // We do not transmit 'args', since those args are for this function, not for the extended functions that thus cannot use args
062        }
063
064    }
065    
066    /**
067     * Get the function provider denoted
068     * @param functionId The id of the extension that gave the role
069     * @param functionProviderRole The role of the component to find
070     * @return The workflow function
071     * @throws WorkflowException If the role cannot be found
072     */
073    protected FunctionProvider _getFunctionProvider(String functionId, String functionProviderRole) throws WorkflowException
074    {
075        try
076        {
077            return (FunctionProvider) _manager.lookup(functionProviderRole);
078        }
079        catch (ServiceException e)
080        {
081            throw new WorkflowException("Cannot find workflow function with role '" + functionProviderRole + "' configured as an extension with id '" + functionId + "'", e);
082        }
083    }
084
085
086    /**
087     * Get the function extension point given in args
088     * @param args The workflow arguments
089     * @return The extension point
090     * @throws WorkflowException If the extension point is not configured or does not exist
091     */
092    @SuppressWarnings("unchecked")
093    protected ExtensionPoint<String> _getFunctionsExtensionPoint(Map args) throws WorkflowException
094    {
095        String extensionPoint = (String) args.get(EXTENSION_POINT_ROLE_ARGS_KEY);
096        if (StringUtils.isBlank(extensionPoint))
097        {
098            throw new WorkflowException("Cannot use the workflow function '" + ExtensibleFunction.class.getName() + "' without the argument '" + EXTENSION_POINT_ROLE_ARGS_KEY + "' describing the role of the extension point of function components to use");
099        }
100        
101        try
102        {
103            return (ExtensionPoint<String>) _manager.lookup(extensionPoint);
104        }
105        catch (ServiceException e)
106        {
107            throw new WorkflowException("The workflow function '" + ExtensibleFunction.class.getName() + "' has the argument '" + EXTENSION_POINT_ROLE_ARGS_KEY + "' valued to '" + extensionPoint + "', that does not denote a String extension point", e);
108        }
109    }
110    
111    @Override
112    public List<FunctionArgument> getArguments()
113    {
114        return List.of(new FunctionArgument(EXTENSION_POINT_ROLE_ARGS_KEY));
115    }
116
117    @Override
118    public I18nizableText getDescription(Map<String, String> args)
119    {
120        return (PostContentEditionFunctionsExtensionPoint.class.getName().equals(args.get(EXTENSION_POINT_ROLE_ARGS_KEY)))
121                ? new I18nizableText("plugin.cms", "PLUGINS_CMS_EXTENSIBLE_FUNCTION_EDITION_DESCRIPTION")
122                : new I18nizableText("plugin.cms", "PLUGINS_CMS_EXTENSIBLE_FUNCTION_VALIDATION_DESCRIPTION");
123    }
124}