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.plugins.workflow.EnhancedFunctionExtensionPoint;
029import org.ametys.plugins.workflow.component.WorkflowArgument;
030import org.ametys.plugins.workflow.support.WorkflowElementDefinitionHelper;
031import org.ametys.runtime.i18n.I18nizableText;
032import org.ametys.runtime.model.StaticEnumerator;
033import org.ametys.runtime.plugin.ExtensionPoint;
034import org.ametys.runtime.plugin.component.AbstractLogEnabled;
035
036import com.opensymphony.module.propertyset.PropertySet;
037import com.opensymphony.workflow.FunctionProvider;
038import com.opensymphony.workflow.WorkflowException;
039
040/**
041 * Workflow function that will call each function registered on the extension point given as an argument 
042 */
043public class ExtensibleFunction extends AbstractLogEnabled implements EnhancedFunction, Serviceable
044{
045    /** The rights key. */
046    protected static final String EXTENSION_POINT_ROLE_ARGS_KEY = "extension-point";
047    /** The service manager */
048    protected ServiceManager _manager;
049    /** The enhanced function extension point */
050    protected EnhancedFunctionExtensionPoint _enhancedFunctionEP;
051    
052    public void service(ServiceManager manager) throws ServiceException
053    {
054        _manager = manager;
055        _enhancedFunctionEP  = (EnhancedFunctionExtensionPoint) manager.lookup(EnhancedFunctionExtensionPoint.ROLE);
056    }
057    
058    
059    public void execute(Map transientVars, Map args, PropertySet ps) throws WorkflowException
060    {
061        ExtensionPoint<String> functionsExtensionPoint = _getFunctionsExtensionPoint(args);
062        for (String functionId : functionsExtensionPoint.getExtensionsIds())
063        {
064            getLogger().debug("{} is delegating to extension {} of point {}", ExtensibleFunction.class.getName(), functionId);
065            String functionProviderRole = functionsExtensionPoint.getExtension(functionId);
066            FunctionProvider functionProvider = _getFunctionProvider(functionId, functionProviderRole);
067            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
068        }
069
070    }
071    
072    /**
073     * Get the function provider denoted
074     * @param functionId The id of the extension that gave the role
075     * @param functionProviderRole The role of the component to find
076     * @return The workflow function
077     * @throws WorkflowException If the role cannot be found
078     */
079    protected FunctionProvider _getFunctionProvider(String functionId, String functionProviderRole) throws WorkflowException
080    {
081        EnhancedFunction extension = _enhancedFunctionEP.getExtension(functionProviderRole);
082        if (extension == null)
083        {
084            throw new WorkflowException("Cannot find workflow function with id '" + functionProviderRole + "' configured as an extension with id '" + functionId + "'");
085        }
086        return extension;
087    }
088
089
090    /**
091     * Get the function extension point given in args
092     * @param args The workflow arguments
093     * @return The extension point
094     * @throws WorkflowException If the extension point is not configured or does not exist
095     */
096    @SuppressWarnings("unchecked")
097    protected ExtensionPoint<String> _getFunctionsExtensionPoint(Map args) throws WorkflowException
098    {
099        String extensionPoint = (String) args.get(EXTENSION_POINT_ROLE_ARGS_KEY);
100        if (StringUtils.isBlank(extensionPoint))
101        {
102            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");
103        }
104        
105        try
106        {
107            return (ExtensionPoint<String>) _manager.lookup(extensionPoint);
108        }
109        catch (ServiceException e)
110        {
111            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);
112        }
113    }
114    
115    @Override
116    public FunctionType getFunctionExecType()
117    {
118        return FunctionType.POST;
119    }
120    
121    @SuppressWarnings("unchecked")
122    @Override
123    public List<WorkflowArgument> getArguments()
124    {
125        WorkflowArgument extensionPoint = WorkflowElementDefinitionHelper.getElementDefinition(
126            EXTENSION_POINT_ROLE_ARGS_KEY,
127            new I18nizableText("plugin.cms", "PLUGINS_CMS_EXTENSIBLE_FUNCTION_ARGUMENT_EXTENSION_POINT_LABEL"),
128            new I18nizableText("plugin.cms", "PLUGINS_CMS_EXTENSIBLE_FUNCTION_ARGUMENT_EXTENSION_POINT_DESC"),
129            true,
130            false
131        );
132        StaticEnumerator<String> extensionPointsStaticEnumerator = new StaticEnumerator<>();
133        extensionPointsStaticEnumerator.add(new I18nizableText("plugin.cms", "PLUGINS_CMS_EXTENSIBLE_FUNCTION_POST_CONTENT_EDITION_LABEL"), "org.ametys.cms.workflow.extensions.PostContentEditionFunctionsExtensionPoint");
134        extensionPointsStaticEnumerator.add(new I18nizableText("plugin.cms", "PLUGINS_CMS_EXTENSIBLE_FUNCTION_POST_CONTENT_VALIDATION_LABEL"), "org.ametys.cms.workflow.extensions.PostContentValidationFunctionsExtensionPoint");
135        extensionPoint.setEnumerator(extensionPointsStaticEnumerator);
136        extensionPoint.setDefaultValue("org.ametys.cms.workflow.extensions.PostContentEditionFunctionsExtensionPoint");
137        return List.of(extensionPoint);
138    }
139    
140    @Override
141    public I18nizableText getLabel()
142    {
143        return new I18nizableText("plugin.cms", "PLUGINS_CMS_EXTENSIBLE_FUNCTION_LABEL");
144    }
145
146    @Override
147    public I18nizableText getFullLabel(Map<String, String> args)
148    {
149        return (PostContentEditionFunctionsExtensionPoint.class.getName().equals(args.get(EXTENSION_POINT_ROLE_ARGS_KEY)))
150                ? new I18nizableText("plugin.cms", "PLUGINS_CMS_EXTENSIBLE_FUNCTION_EDITION_DESCRIPTION")
151                : new I18nizableText("plugin.cms", "PLUGINS_CMS_EXTENSIBLE_FUNCTION_VALIDATION_DESCRIPTION");
152    }
153}