Nov 10, 2021 4:14:12 PM Thomas Dumont avatar

wiki : Technical documentation > Code with workflows > Create a prerequisite for automatic actions

Create a prerequisite for automatic actions

Within a workflow, it is possible to define prerequisites for the execution of the actions designated as automatic so that when a resource arrives in the starting state of the action, it is executed only if the resource checks all the prerequisites.

The list of prerequisites of an action can be modified in the back office, in the modification page of the action.

Add a prerequisite type

Creating a new prerequisite type requires you to implement the fr.paris.lutece.plugins.workflowcore.service.prerequisite.IAutomaticActionPrerequisiteService interface.

Example of implementing a prerequisite service without configuration :

/**
 * Example of prerequisite without configuration
 */
public class NoConfigPrerequisiteService implements IAutomaticActionPrerequisiteService
{
    private static final String PREREQUISITE_TYPE = "no_config_prerequisite";
    private static final String MESSAGE_PREREQUISITE_TITLE = "portal.util.labelNo";

    /**
     * Get the type of prerequisites associated with this service
     * @return The type of prerequisites associated with this service
     */
    @Override
    public String getPrerequisiteType( )
    {
        return PREREQUISITE_TYPE;
    }

    /**
     * Get the I18n key of the title of the prerequisite
     * @return the I18n key of the title of the prerequisite
     */
    @Override
    public String getTitleI18nKey( )
    {
        return MESSAGE_PREREQUISITE_TITLE;
    }

    /**
     * Check if the prerequisite type of the this service needs a configuration
     * @return True if the prerequisite type need a configuration, false
     *         otherwise
     */
    @Override
    public boolean hasConfiguration( )
    {
        return false;
    }

    /**
     * Get a new instance of the configuration of this prerequisite type.<br />
     * The configuration bean must implement the interface
     * {@link fr.paris.lutece.plugins.workflowcore.business.prerequisite.IPrerequisiteConfig
     * IPrerequisiteConfig}
     * @return A new instance of the configuration of this prerequisite type, or
     *         null if the prerequisite has no configuration
     */
    @Override
    public IPrerequisiteConfig getEmptyConfiguration( )
    {
        return null;
    }

    /**
     * Get the bean name of the DAO for configurations of this prerequisite
     * type.<br />
     * The configuration bean must implement the interface
     * {@link fr.paris.lutece.plugins.workflowcore.business.prerequisite.IPrerequisiteConfigDAO
     * IPrerequisiteConfigDAO}
     * @return The name of the bean of the configuration, or null if the
     *         prerequisite has no configuration
     */
    @Override
    public String getConfigurationDaoBeanName( )
    {
        return null;
    }

    /**
     * Get the HTML form to create or modify a configuration for a new
     * prerequisite.<br />
     * The returned HTML will be inserted into a HTML frameset that already
     * contains a form tag.<br />
     * Data entered by the user will be saved into the configuration bean with
     * populating methods. The bean will also be validated before it is saved.
     * @param config The configuration to display the form of
     * @param request The request
     * @param locale The locale
     * @return The HTML content to display, or null if there is no form to
     *         display
     */
    @Override
    public String getConfigHtml( IPrerequisiteConfig config, HttpServletRequest request, Locale locale )
    {
        return null;
    }

    /**
     * Check if a resource matches this prerequisite.
     * @param nIdResource The id of the resource
     * @param strResourceType The resource type
     * @param config The configuration of the prerequisite, or null if the
     *            prerequisite has no configuration
     * @param nIdAction The id of the action that will be performed if the
     *            resource matches every prerequisites
     * @return True if the resource matches this prerequisite, false otherwise
     */
    @Override
    public boolean canActionBePerformed( int nIdResource, String strResourceType, IPrerequisiteConfig config,
            int nIdAction )
    {
        return false;
    }
}

The implementation must be declared as a Spring bean (with the default scope, that is singleton).

Prerequisites with configuration

If the prerequisite type requires a specific configuration for each prerequisite instance, it is also necessary to implement the following interfaces:

  • fr.paris.lutece.plugins.workflowcore.business.prerequisite.IPrerequisiteConfigDAO
  • fr.paris.lutece.plugins.workflowcore.business.prerequisite.IPrerequisiteConfig

The abstract class fr.paris.lutece.plugins.workflowcore.business.prerequisite.DefaultPrerequisiteConfig provides a default implementation of some methods of the last interface.

The implementation of the IPrerequisiteConfig interface is used to specify the business class in which the data of the prerequisite configuration will be stored. The implementation of the IPrerequisiteConfigDAO interface allows to provide the DAO that will manage the persistence of the configurations. This last implementation must be declared as a Spring bean, and the name of the corresponding bean must be provided by the preamble String getConfigurationDaoBeanName() method.

Example of implementing a prerequisite service with configuration :

/**
 * Prerequisite to check that the resource has not been modifies since a given
 * number of days before processing an automatic action
 */
public class DateModificationPrerequisiteService implements IAutomaticActionPrerequisiteService
{
    private static final String PREREQUISITE_TYPE = "date_modificiation_prerequisite";
    private static final String MESSAGE_PREREQUISITE_TITLE = "portal.util.labelYes";
    private static final String DATE_MODIFICATION_PREREQUISITE_DAO_BEAN_NAME = "workflow.dateModificationPrerequisiteConfigDAO";

    /**
     * Get the type of prerequisites associated with this service
     * @return The type of prerequisites associated with this service
     */
    @Override
    public String getPrerequisiteType( )
    {
        return PREREQUISITE_TYPE;
    }

    /**
     * Get the I18n key of the title of the prerequisite
     * @return the I18n key of the title of the prerequisite
     */
    @Override
    public String getTitleI18nKey( )
    {
        return MESSAGE_PREREQUISITE_TITLE;
    }

    /**
     * Check if the prerequisite type of the this service needs a configuration
     * @return True if the prerequisite type need a configuration, false
     *         otherwise
     */
    @Override
    public boolean hasConfiguration( )
    {
        return true;
    }

    /**
     * Get a new instance of the configuration of this prerequisite type.<br />
     * The configuration bean must implement the interface
     * {@link fr.paris.lutece.plugins.workflowcore.business.prerequisite.IPrerequisiteConfig
     * IPrerequisiteConfig}
     * @return A new instance of the configuration of this prerequisite type, or
     *         null if the prerequisite has no configuration
     */
    @Override
    public IPrerequisiteConfig getEmptyConfiguration( )
    {
        return new DateModificationPrerequisiteConfig( );
    }

    /**
     * Get the bean name of the DAO for configurations of this prerequisite
     * type.<br />
     * The configuration bean must implement the interface
     * {@link fr.paris.lutece.plugins.workflowcore.business.prerequisite.IPrerequisiteConfigDAO
     * IPrerequisiteConfigDAO}
     * @return The name of the bean of the configuration, or null if the
     *         prerequisite has no configuration
     */
    @Override
    public String getConfigurationDaoBeanName( )
    {
        return DATE_MODIFICATION_PREREQUISITE_DAO_BEAN_NAME;
    }

    /**
     * Get the HTML form to create or modify a configuration for a new
     * prerequisite.<br />
     * The returned HTML will be inserted into a HTML frameset that already
     * contains a form tag.<br />
     * Data entered by the user will be saved into the configuration bean with
     * populating methods. The bean will also be validated before it is saved.
     * @param config The configuration to display the form of
     * @param request The request
     * @param locale The locale
     * @return The HTML content to display, or null if there is no form to
     *         display
     */
    @Override
    public String getConfigHtml( IPrerequisiteConfig config, HttpServletRequest request, Locale locale )
    {
        return "<div class=\"control-group\"><label class=\"control-label\">Nombre de jour d'attente avant l'execution de l'action :</label><div class=\"controls\"><input type='text' name='nb_days' value='"
                + ( (DateModificationPrerequisiteConfig) config ).getNbDays( ) + "' ></div></div>";
    }

    /**
     * Check if a resource matches this prerequisite.
     * @param nIdResource The id of the resource
     * @param strResourceType The resource type
     * @param config The configuration of the prerequisite, or null if the
     *            prerequisite has no configuration
     * @param nIdAction The id of the action that will be performed if the
     *            resource matches every prerequisites
     * @return True if the resource matches this prerequisite, false otherwise
     */
    @Override
    public boolean canActionBePerformed( int nIdResource, String strResourceType, IPrerequisiteConfig config,
            int nIdAction )
    {
        DateModificationPrerequisiteConfig dateconfig = (DateModificationPrerequisiteConfig) config;
        IResourceWorkflowService resourceWorkflowService = SpringContextService
                .getBean( ResourceWorkflowService.BEAN_SERVICE );
        IActionService actionService = SpringContextService.getBean( ActionService.BEAN_SERVICE );
        Action action = actionService.findByPrimaryKey( nIdAction );
        ResourceWorkflow resource = resourceWorkflowService.findByPrimaryKey( nIdResource, strResourceType, action
                .getWorkflow( ).getId( ) );
        IResourceHistoryService resourceHistoryService = SpringContextService
                .getBean( ResourceHistoryService.BEAN_SERVICE );
        ResourceHistory resourceHistory = resourceHistoryService.getLastHistoryResource( resource.getIdResource( ),
                resource.getResourceType( ), action.getWorkflow( ).getId( ) );
        Calendar calendar = GregorianCalendar.getInstance( );
        calendar.add( -1 * Calendar.DAY_OF_MONTH, dateconfig.getNbDays( ) );
        return calendar.getTime( ).getTime( ) > resourceHistory.getCreationDate( ).getTime( );
    }
}

Example of Prerequisite Configuration Implementation :

/**
 * Configuration of prerequisite that requires that the resource is not modified
 * during a given number of day
 */
public class DateModificationPrerequisiteConfig extends DefaultPrerequisiteConfig
{
    @Min( value = 2, message = "portal.util.labelWarning" )
    private int _nNbDays;

    /**
     * Get the number of days to wait before the action is performed
     * @return The number of days to wait before the action is performed
     */
    public int getNbDays( )
    {
        return _nNbDays;
    }

    /**
     * Set the number of days to wait before the action is performed
     * @param nNbDays The number of days to wait before the action is performed
     */
    public void setNbDays( int nNbDays )
    {
        this._nNbDays = nNbDays;
    }
}

Example of implementation of the DAO of the configuration of a prerequisite :

/**
 * DAO to manage DateModificationPrerequisiteConfig
 */
public class DateModificationPrerequisiteConfigDAO implements IPrerequisiteConfigDAO
{
    @Override
    public void createConfig( IPrerequisiteConfig config )
    {
        DAOUtil daoUtil = new DAOUtil( "insert into days (id_config, nb_days) values ( " + config.getIdPrerequisite( )
                + "," + ( (DateModificationPrerequisiteConfig) config ).getNbDays( ) + ")" );
        daoUtil.executeUpdate( );
        daoUtil.free( );
    }

    @Override
    public void updateConfig( IPrerequisiteConfig config )
    {
        DAOUtil daoUtil = new DAOUtil( "update days set nb_days = "
                + ( (DateModificationPrerequisiteConfig) config ).getNbDays( ) + " where id_config = "
                + config.getIdPrerequisite( ) );
        daoUtil.executeUpdate( );
        daoUtil.free( );
    }

    @Override
    public void removeConfig( int nIdPrerequisite )
    {
        DAOUtil daoUtil = new DAOUtil( "delete from days where id_config = " + nIdPrerequisite );
        daoUtil.executeUpdate( );
        daoUtil.free( );
    }
    @Override
    public IPrerequisiteConfig findByPrimaryKey( int nIdPrerequisite )
    {
        DAOUtil daoUtil = new DAOUtil( "select id_config, nb_days from days where id_config = " + nIdPrerequisite );
        daoUtil.executeQuery( );
        DateModificationPrerequisiteConfig config = null;
        if ( daoUtil.next( ) )
        {
            config = new DateModificationPrerequisiteConfig( );
            config.setIdPrerequisite( daoUtil.getInt( 1 ) );
            config.setNbDays( daoUtil.getInt( 2 ) );
        }
        daoUtil.free( );
        return config;
    }
}

HTML form for creating and modifying prerequisite

The HTML form for creating and modifying prerequisite is generated by the String method getConfigHtml of IAutomaticActionPrerequisiteService(). The HTML returned by this method must not contain a <form> tag.

The population of the data submitted by the user in the configuration is done by introspection. The names of the inputs must therefore correspond to the names of the attributes of the configuration.

Before saving any data submitted by the user, the configuration is validated. If the validation fails, the configuration is not created or modified.