BatchJspBean.java
/*
* Copyright (c) 2002-2024, City of Paris
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright notice
* and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice
* and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* License 1.0
*/
package fr.paris.lutece.plugins.identityimport.web;
import fr.paris.lutece.plugins.identityimport.business.Batch;
import fr.paris.lutece.plugins.identityimport.business.BatchHome;
import fr.paris.lutece.plugins.identityimport.business.CandidateIdentity;
import fr.paris.lutece.plugins.identityimport.business.CandidateIdentityAttribute;
import fr.paris.lutece.plugins.identityimport.business.CandidateIdentityAttributeHome;
import fr.paris.lutece.plugins.identityimport.business.CandidateIdentityHome;
import fr.paris.lutece.plugins.identityimport.business.ResourceState;
import fr.paris.lutece.plugins.identityimport.service.BatchService;
import fr.paris.lutece.plugins.identityimport.service.CandidateIdentityService;
import fr.paris.lutece.plugins.identityimport.service.ServiceContractService;
import fr.paris.lutece.plugins.identityimport.wf.WorkflowBean;
import fr.paris.lutece.plugins.identityimport.wf.WorkflowBeanService;
import fr.paris.lutece.plugins.identityquality.v3.web.service.IdentityQualityService;
import fr.paris.lutece.plugins.identitystore.v3.csv.CsvIdentityService;
import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.common.AttributeDto;
import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.common.AuthorType;
import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.common.BatchDto;
import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.common.IdentityDto;
import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.common.RequestAuthor;
import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.contract.ServiceContractDto;
import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.search.DuplicateSearchRequest;
import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.search.DuplicateSearchResponse;
import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.search.IdentitySearchResponse;
import fr.paris.lutece.plugins.identitystore.v3.web.rs.util.ResponseStatusFactory;
import fr.paris.lutece.plugins.identitystore.v3.web.service.IdentityService;
import fr.paris.lutece.plugins.identitystore.web.exception.IdentityStoreException;
import fr.paris.lutece.portal.service.admin.AccessDeniedException;
import fr.paris.lutece.portal.service.progressmanager.ProgressManagerService;
import fr.paris.lutece.portal.service.security.SecurityTokenService;
import fr.paris.lutece.portal.service.spring.SpringContextService;
import fr.paris.lutece.portal.service.util.AppException;
import fr.paris.lutece.portal.service.util.AppPropertiesService;
import fr.paris.lutece.portal.util.mvc.admin.annotations.Controller;
import fr.paris.lutece.portal.util.mvc.commons.annotations.Action;
import fr.paris.lutece.portal.util.mvc.commons.annotations.View;
import fr.paris.lutece.portal.web.upload.MultipartHttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* This class provides the user interface to manage Batch features
*/
@Controller( controllerJsp = "ManageBatchs.jsp", controllerPath = "jsp/admin/plugins/identityimport/", right = "IDENTITYIMPORT_BATCH_MANAGEMENT" )
public class BatchJspBean extends AbstractManageItemsJspBean<Integer, WorkflowBean<Batch>>
{
// Templates
private static final String TEMPLATE_IMPORT_BATCH = "/admin/plugins/identityimport/import_batch.html";
private static final String TEMPLATE_MANAGE_BATCHS = "/admin/plugins/identityimport/manage_batchs.html";
private static final String TEMPLATE_MANAGE_IDENTITIES = "/admin/plugins/identityimport/manage_candidateidentities.html";
private static final String TEMPLATE_IMPORT_CANDIDATE_IDENTITY = "/admin/plugins/identityimport/import_candidateidentity.html";
private static final String TEMPLATE_COMPLETE_IDENTITY = "/admin/plugins/identityimport/complete_identity.html";
private static final String JSP_MANAGE_CANDIDATEIDENTITIES = "jsp/admin/plugins/identityimport/ManageBatchs.jsp";
// Parameters
private static final String PARAMETER_ID_BATCH = "id_batch";
private static final String PARAMETER_ID_CANDIDATEIDENTITY = "id_identity";
private static final String PARAMETER_SELECTED_CUSTOMER_ID = "selected_customer_id";
private static final String PARAMETER_RETURN_URL = "return_url";
private static final String PARAMETER_ID_BATCH_STATE = "id_state";
private static final String PARAMETER_ID_ACTION = "id_action";
private static final String PARAMETER_CSV_FILE = "csvFile";
private static final String PARAMETER_REFERENCE = "reference";
private static final String PARAMETER_FILTER_APP_CODE = "application_code";
private static final String PARAMETER_FROM_PAGINATION = "from_pagination";
private final static String PARAMETER_BATCH_PAGE = "batch_page";
private final static String IDENTITIES_PARAMETER_PAGE = "identities_page";
private static final String MARK_FEED_TOKEN = "feed_token";
// Properties for page titles
private static final String PROPERTY_PAGE_TITLE_IMPORT_BATCH = "identityimport.import_batch.pageTitle";
private static final String PROPERTY_PAGE_TITLE_MANAGE_BATCHS = "identityimport.manage_batchs.pageTitle";
private static final String PROPERTY_DEFAULT_LIST_ITEM_PER_PAGE = "identityimport.listItems.itemsPerPage";
private static final String PROPERTY_PAGE_TITLE_IMPORT_CANDIDATEIDENTITY = "identityimport.import_candidateidentity.pageTitle";
private static final String PROPERTY_DUPLICATE_RULES = "identityimport.duplicate.search.rules";
private static final String PROPERTY_PAGE_TITLE_COMPLETE_IDENTITY = "identityimport.complete_identity.pageTitle";
private static final String PROPERTY_IMPORT_CLIENT_CODE = "identityimport.client.code";
// Markers
private static final String MARK_BATCH_LIST = "batch_list";
private static final String MARK_CURRENT_BATCH_ID = "current_batch_id";
private static final String MARK_IDENTITY_LIST = "identity_list";
private static final String MARK_BATCH = "batch";
private static final String MARK_NEW_IMPORT = "newImport";
private static final String MARK_BATCH_STATE_LIST = "batch_state_list";
private static final String MARK_CURRENT_BATCH_STATE = "current_batch_state";
private static final String MARK_BATCH_TOTAL_PAGES = "batch_total_pages";
private static final String MARK_CURRENT_BATCH_PAGE = "batch_current_page";
private static final String MARK_IDENTITIES_TOTAL_PAGES = "identities_total_pages";
private static final String MARK_CURRENT_IDENTITIES_PAGE = "identities_current_page";
private static final String MARK_FILTER_APP_CODE = "application_code";
private static final String MARK_CANDIDATE_IDENTITY_DUPLICATE_LIST = "duplicate_list";
private static final String MARK_CANDIDATE_IDENTITY = "identity";
private static final String MARK_CANDIDATE_IDENTITY_WORKFLOW = "identity_workflow";
private static final String MARK_IDENTITY_TO_KEEP = "identity_to_keep";
private static final String MARK_SERVICE_CONTRACT = "client_service_contract";
private static final String MARK_ATTRIBUTE_KEY_LIST = "key_list";
private static final String MARK_RETURN_URL = "return_url";
private static final String MARK_FROM_PAGINATION = "from_pagination";
// Validations
private static final String VALIDATION_ATTRIBUTES_PREFIX = "identityimport.model.entity.batch.attribute.";
// Views
private static final String VIEW_IMPORT_BATCH = "importBatch";
private static final String VIEW_MANAGE_BATCHS = "manageBatchs";
private static final String VIEW_MANAGE_IDENTITIES = "manageIdentities";
private static final String VIEW_CREATE_BATCH = "createBatch";
private static final String VIEW_IMPORT_CANDIDATEIDENTITY = "importCandidateIdentity";
private static final String VIEW_COMPLETE_IDENTITY = "completeIdentity";
// Actions
private static final String ACTION_IMPORT_BATCH = "importBatch";
private static final String ACTION_CREATE_BATCH = "createBatch";
private static final String ACTION_PROCESS_BATCH_WORKFLOW_ACTION = "processAction";
private static final String ACTION_PROCESS_IDENTITY_WORKFLOW_ACTION = "processIdentityAction";
// Infos
private static final String INFO_BATCH_CREATED = "identityimport.info.batch.created";
// Errors
private static final String ERROR_RESOURCE_NOT_FOUND = "Resource not found";
// Workflow
private static final String BATCH_WFBEANSERVICE = "identityimport.batch.wfbeanservice";
private static final String CANDIDATEIDENTITY_WFBEANSERVICE = "identityimport.candidateidentity.wfbeanservice";
private final WorkflowBeanService<Batch> _wfBatchBeanService = SpringContextService.getBean( BATCH_WFBEANSERVICE );
private final WorkflowBeanService<CandidateIdentity> _wfIdentitiesBeanService = SpringContextService.getBean( CANDIDATEIDENTITY_WFBEANSERVICE );
// Feed
private static final String FEED_NAME = "importBatchFeed";
private final ProgressManagerService progressManagerService = ProgressManagerService.getInstance( );
// Session variable to store working values
private Batch _batch;
private String _filterAppCode;
private ResourceState _current_batch_state;
private Integer _batchCurrentPage;
private Integer _batchTotalPages;
private Integer _identitiesCurrentPage;
private Integer _identitiesTotalPages;
private WorkflowBean<Batch> _wfBatchBean;
private List<Integer> _listIdBatchs = new ArrayList<>( );
private List<ResourceState> _batchStates = new ArrayList<>( );
private String _feedToken;
private Integer _currentBatchId;
private List<Integer> _listIdCandidateIdentities;
private CandidateIdentity _candidateidentity;
private WorkflowBean<CandidateIdentity> _wfCandidateIdentityBean;
private Integer _currentIdentityId;
// Services
private final IdentityQualityService identityQualityService = SpringContextService.getBean( "qualityService.rest" );
private final IdentityService identityService = SpringContextService.getBean( "identityService.rest" );
private final List<String> DUPLICATE_RULE_CODES = Arrays.asList( AppPropertiesService.getProperty( PROPERTY_DUPLICATE_RULES, "" ).split( "," ) );
private final int NB_ITEMS_PER_PAGES = AppPropertiesService.getPropertyInt( PROPERTY_DEFAULT_LIST_ITEM_PER_PAGE, 10 );
private final String IMPORT_CLIENT_CODE = AppPropertiesService.getProperty( PROPERTY_IMPORT_CLIENT_CODE );
/**
* Build the Manage View
*
* @param request
* The HTTP request
* @return The page
*/
@View( value = VIEW_MANAGE_BATCHS, defaultView = true )
public String getManageBatchs( final HttpServletRequest request )
{
this.globalInit( request );
this.unregisterFeed( );
final Map<String, Object> model = this.globalModel( request );
return getPage( PROPERTY_PAGE_TITLE_MANAGE_BATCHS, TEMPLATE_MANAGE_BATCHS, model );
}
/**
* Build the Manage View
*
* @param request
* The HTTP request
* @return The page
*/
@View( value = VIEW_MANAGE_IDENTITIES )
public String getManageBatchIdentities( final HttpServletRequest request )
{
this.globalInit( request );
this.unregisterFeed( );
final String fromPagination = request.getParameter( PARAMETER_FROM_PAGINATION ) != null ? request.getParameter( PARAMETER_FROM_PAGINATION ) : "false";
final Optional<String> idBatchOpt = Optional.ofNullable( request.getParameter( PARAMETER_ID_BATCH ) );
idBatchOpt.ifPresent( idBatch -> {
_currentBatchId = Integer.parseInt( idBatch );
_identitiesCurrentPage = Optional.ofNullable( request.getParameter( IDENTITIES_PARAMETER_PAGE ) ).map( Integer::parseInt ).orElse( 1 );
_listIdCandidateIdentities = CandidateIdentityHome.getIdCandidateIdentitiesList( _currentBatchId );
final int totalRecords = _listIdCandidateIdentities.size( );
_identitiesTotalPages = (int) Math.ceil( (double) totalRecords / NB_ITEMS_PER_PAGES );
if ( _identitiesTotalPages == 0 )
{
_identitiesTotalPages = 1;
}
final int start = ( _identitiesCurrentPage - 1 ) * NB_ITEMS_PER_PAGES;
final int end = Math.min( start + NB_ITEMS_PER_PAGES, totalRecords );
_listIdCandidateIdentities = _listIdCandidateIdentities.subList( start, end );
if ( _batch == null || ( _batch.getId( ) != _currentBatchId ) )
{
final Optional<Batch> optBatch = BatchHome.findByPrimaryKey( _currentBatchId );
_batch = optBatch.orElseThrow( ( ) -> new AppException( ERROR_RESOURCE_NOT_FOUND ) );
}
if ( _wfBatchBean == null || _wfBatchBean.getResourceId( ) != _currentBatchId )
{
_wfBatchBean = _wfBatchBeanService.createWorkflowBean( _batch, _batch.getId( ), getUser( ) );
_wfBatchBeanService.addHistory( _wfBatchBean, request, getLocale( ) );
_wfBatchBeanService.countSubResources( _wfBatchBean );
_wfBatchBeanService.addSubResourceStates( _wfBatchBean );
}
} );
final Map<String, Object> model = this.globalModel( request );
model.put( MARK_FROM_PAGINATION, fromPagination );
return getPage( PROPERTY_PAGE_TITLE_MANAGE_BATCHS, TEMPLATE_MANAGE_IDENTITIES, model );
}
/**
* Returns the form to update info about a candidateidentity
*
* @param request
* The Http request
* @return The HTML form to update info
*/
@View( VIEW_IMPORT_CANDIDATEIDENTITY )
public String getImportCandidateIdentity( final HttpServletRequest request )
{
final Optional<String> idIdentityOpt = Optional.ofNullable( request.getParameter( PARAMETER_ID_CANDIDATEIDENTITY ) );
idIdentityOpt.ifPresent( idIdentity -> {
_currentIdentityId = Integer.parseInt( idIdentity );
final Optional<CandidateIdentity> optCandidateIdentity = CandidateIdentityHome.findByPrimaryKey( _currentIdentityId );
_candidateidentity = optCandidateIdentity.orElseThrow( ( ) -> new AppException( ERROR_RESOURCE_NOT_FOUND ) );
_candidateidentity.setAttributes( CandidateIdentityAttributeHome.getCandidateIdentityAttributesList( _currentIdentityId ) );
_wfCandidateIdentityBean = _wfIdentitiesBeanService.createWorkflowBean( _candidateidentity, _candidateidentity.getId( ),
_candidateidentity.getIdBatch( ), getUser( ) );
_wfIdentitiesBeanService.addHistory( _wfCandidateIdentityBean, request, getLocale( ) );
} );
final Map<String, Object> model = getModel( );
// Appel API Recherche
final DuplicateSearchRequest searchRequest = new DuplicateSearchRequest( );
searchRequest.getRuleCodes( ).addAll( DUPLICATE_RULE_CODES );
final Map<String, String> searchAttributes = _candidateidentity.getAttributes( ).stream( )
.collect( Collectors.toMap( CandidateIdentityAttribute::getCode, CandidateIdentityAttribute::getValue ) );
searchRequest.getAttributes( ).putAll( searchAttributes );
// init attributes key list
final List<String> keyList = _candidateidentity.getAttributes( ).stream( ).map( CandidateIdentityAttribute::getCode ).collect( Collectors.toList( ) );
try
{
final DuplicateSearchResponse response = identityQualityService.searchDuplicates( searchRequest, IMPORT_CLIENT_CODE, this.buildAuthor( ) );
keyList.addAll( response.getIdentities( ).stream( ).flatMap( duplicate -> duplicate.getAttributes( ).stream( ) ).map( AttributeDto::getKey )
.distinct( ).collect( Collectors.toList( ) ) );
model.put( MARK_CANDIDATE_IDENTITY_DUPLICATE_LIST, response.getIdentities( ) );
final ServiceContractDto clientServiceContract = ServiceContractService.instance( )
.getActiveServiceContract( _candidateidentity.getClientAppCode( ) );
model.put( MARK_SERVICE_CONTRACT, clientServiceContract );
}
catch( IdentityStoreException e )
{
this.addInfo( e.getLocalizedMessage( ) );
}
final Optional<String> returnUrlOpt = Optional.ofNullable( request.getParameter( PARAMETER_RETURN_URL ) );
returnUrlOpt.ifPresent( url -> {
final String idState = request.getParameter( PARAMETER_ID_BATCH_STATE );
final String idBatch = request.getParameter( PARAMETER_ID_BATCH );
final String batchPage = request.getParameter( PARAMETER_BATCH_PAGE );
final String applicationCode = request.getParameter( PARAMETER_FILTER_APP_CODE );
final String returnUrl = String.format( "%s&%s=%s&%s=%s&%s=%s&%s=%s", url, PARAMETER_ID_BATCH_STATE, idState, PARAMETER_ID_BATCH, idBatch,
PARAMETER_BATCH_PAGE, batchPage, PARAMETER_FILTER_APP_CODE, applicationCode );
model.put( MARK_RETURN_URL, returnUrl );
} );
model.put( MARK_CANDIDATE_IDENTITY_WORKFLOW, _wfCandidateIdentityBean );
model.put( MARK_CANDIDATE_IDENTITY, CandidateIdentityService.instance( ).getIdentityDto( _wfCandidateIdentityBean.getResource( ) ) );
model.put( MARK_ATTRIBUTE_KEY_LIST, keyList.stream( ).distinct( ).collect( Collectors.toList( ) ) );
return getPage( PROPERTY_PAGE_TITLE_IMPORT_CANDIDATEIDENTITY, TEMPLATE_IMPORT_CANDIDATE_IDENTITY, model );
}
/**
* Returns the form to manually resolve an identity duplicates
*
* @param request
* The Http request
* @return the html code of the form
*/
@View( value = VIEW_COMPLETE_IDENTITY )
public String getCompleteIdentity( final HttpServletRequest request )
{
final Optional<String> idIdentityOpt = Optional.ofNullable( request.getParameter( PARAMETER_ID_CANDIDATEIDENTITY ) );
idIdentityOpt.ifPresent( idIdentity -> {
_currentIdentityId = Integer.parseInt( idIdentity );
final Optional<CandidateIdentity> optCandidateIdentity = CandidateIdentityHome.findByPrimaryKey( _currentIdentityId );
_candidateidentity = optCandidateIdentity.orElseThrow( ( ) -> new AppException( ERROR_RESOURCE_NOT_FOUND ) );
_candidateidentity.setAttributes( CandidateIdentityAttributeHome.getCandidateIdentityAttributesList( _currentIdentityId ) );
_wfCandidateIdentityBean = _wfIdentitiesBeanService.createWorkflowBean( _candidateidentity, _candidateidentity.getId( ),
_candidateidentity.getIdBatch( ), getUser( ) );
_wfIdentitiesBeanService.addHistory( _wfCandidateIdentityBean, request, getLocale( ) );
} );
final Map<String, Object> model = getModel( );
// init attributes key list
final List<String> keyList = _candidateidentity.getAttributes( ).stream( ).map( CandidateIdentityAttribute::getCode ).collect( Collectors.toList( ) );
final String selectedCustomerId = request.getParameter( PARAMETER_SELECTED_CUSTOMER_ID );
try
{
final IdentitySearchResponse response = identityService.getIdentity( selectedCustomerId, IMPORT_CLIENT_CODE, this.buildAuthor( ) );
if ( ResponseStatusFactory.ok( ).equals( response.getStatus( ) ) )
{
keyList.addAll( response.getIdentities( ).stream( ).flatMap( duplicate -> duplicate.getAttributes( ).stream( ) ).map( AttributeDto::getKey )
.distinct( ).collect( Collectors.toList( ) ) );
model.put( MARK_IDENTITY_TO_KEEP, response.getIdentities( ).get( 0 ) );
}
final ServiceContractDto clientServiceContract = ServiceContractService.instance( )
.getActiveServiceContract( _candidateidentity.getClientAppCode( ) );
model.put( MARK_SERVICE_CONTRACT, clientServiceContract );
}
catch( IdentityStoreException e )
{
this.addInfo( e.getLocalizedMessage( ) );
}
final Optional<String> returnUrlOpt = Optional.ofNullable( request.getParameter( PARAMETER_RETURN_URL ) );
returnUrlOpt.ifPresent( url -> {
final String idState = request.getParameter( PARAMETER_ID_BATCH_STATE );
final String idBatch = request.getParameter( PARAMETER_ID_BATCH );
final String batchPage = request.getParameter( PARAMETER_BATCH_PAGE );
final String applicationCode = request.getParameter( PARAMETER_FILTER_APP_CODE );
final String returnUrl = String.format( "%s&%s=%s&%s=%s&%s=%s&%s=%s", url, PARAMETER_ID_BATCH_STATE, idState, PARAMETER_ID_BATCH, idBatch,
PARAMETER_BATCH_PAGE, batchPage, PARAMETER_FILTER_APP_CODE, applicationCode );
model.put( MARK_RETURN_URL, returnUrl );
} );
model.put( MARK_CANDIDATE_IDENTITY_WORKFLOW, _wfCandidateIdentityBean );
model.put( MARK_CANDIDATE_IDENTITY, CandidateIdentityService.instance( ).getIdentityDto( _wfCandidateIdentityBean.getResource( ) ) );
model.put( MARK_ATTRIBUTE_KEY_LIST, keyList.stream( ).distinct( ).collect( Collectors.toList( ) ) );
return getPage( PROPERTY_PAGE_TITLE_COMPLETE_IDENTITY, TEMPLATE_COMPLETE_IDENTITY, model );
}
/**
* reset the _listIdBatchs list
*/
public void resetListId( )
{
_listIdBatchs = new ArrayList<>( );
}
/**
* Import a new batch
*
* @param request
* The Http Request
* @return The Jsp URL of the process result
* @throws AccessDeniedException
*/
@View( VIEW_IMPORT_BATCH )
public String getViewImportBatch( final HttpServletRequest request ) throws AccessDeniedException
{
this.registerFeed( );
_batch = new Batch( );
final Map<String, Object> model = getModel( );
model.put( MARK_NEW_IMPORT, true );
model.put( MARK_BATCH, _batch );
model.put( MARK_FEED_TOKEN, _feedToken );
model.put( SecurityTokenService.MARK_TOKEN, SecurityTokenService.getInstance( ).getToken( request, ACTION_CREATE_BATCH ) );
return getPage( PROPERTY_PAGE_TITLE_IMPORT_BATCH, TEMPLATE_IMPORT_BATCH, model );
}
/**
* Process the data capture form of a new batch
*
* @param request
* The Http Request
* @return The Jsp URL of the process result
* @throws AccessDeniedException
*/
@Action( ACTION_IMPORT_BATCH )
public String doImportBatch( final HttpServletRequest request ) throws AccessDeniedException
{
if ( !SecurityTokenService.getInstance( ).validate( request, ACTION_CREATE_BATCH ) )
{
throw new AccessDeniedException( "Invalid security token" );
}
int batchId;
try
{
this.populate( _batch, request, getLocale( ) );
final MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
final FileItem fileItem = multipartRequest.getFile( PARAMETER_CSV_FILE );
final BatchDto batchDto = BatchService.instance( ).getDto( _batch );
if ( StringUtils.isBlank( request.getParameter( PARAMETER_REFERENCE ) ) )
{
batchDto.setReference( UUID.randomUUID( ).toString( ) );
}
final List<IdentityDto> importedIdentities = CsvIdentityService.instance( ).read( fileItem.getInputStream( ) );
batchDto.getIdentities( ).addAll( importedIdentities );
// Check constraints
if ( !validateBean( _batch, VALIDATION_ATTRIBUTES_PREFIX ) )
{
return redirectView( request, VIEW_CREATE_BATCH );
}
batchId = BatchService.instance( ).importBatch( batchDto, getUser( ), _feedToken );
this.addInfo( INFO_BATCH_CREATED, getLocale( ) );
this.resetListId( );
}
catch( IdentityStoreException | IOException e )
{
this.addError( e.getMessage( ) );
return redirectView( request, VIEW_IMPORT_BATCH );
}
return redirect( request, VIEW_MANAGE_BATCHS, PARAMETER_ID_BATCH, batchId );
}
/**
* process a workflow action
*
* @param request
* The Http request
* @return the jsp URL to display the form to manage batchs
*/
@Action( ACTION_PROCESS_BATCH_WORKFLOW_ACTION )
public String doProcessBatchAction( final HttpServletRequest request )
{
final int nId = Integer.parseInt( request.getParameter( PARAMETER_ID_BATCH ) );
final int nAction = Integer.parseInt( request.getParameter( PARAMETER_ID_ACTION ) );
final String appCode = request.getParameter( PARAMETER_FILTER_APP_CODE );
if ( _batch == null || ( _batch.getId( ) != nId ) )
{
final Optional<Batch> optBatch = BatchHome.findByPrimaryKey( nId );
_batch = optBatch.orElseThrow( ( ) -> new AppException( ERROR_RESOURCE_NOT_FOUND ) );
_wfBatchBean = _wfBatchBeanService.createWorkflowBean( _batch, _batch.getId( ), getUser( ) );
}
_wfBatchBeanService.processAction( _wfBatchBean, nAction, request, getLocale( ) );
_wfBatchBean = _wfBatchBeanService.createWorkflowBean( _batch, _batch.getId( ), getUser( ) );
final Map<String, String> params = new HashMap<>( );
params.put( PARAMETER_ID_BATCH_STATE, String.valueOf( _wfBatchBean.getState( ).getId( ) ) );
params.put( PARAMETER_ID_BATCH, String.valueOf( nId ) );
params.put( PARAMETER_FILTER_APP_CODE, appCode );
return redirect( request, VIEW_MANAGE_IDENTITIES, params );
}
/**
* process a workflow action
*
* @param request
* The Http request
* @return the jsp URL to display the form to manage batchs
*/
@Action( ACTION_PROCESS_IDENTITY_WORKFLOW_ACTION )
public String doProcessIdentityAction( final HttpServletRequest request )
{
final int nResourceId = Integer.parseInt( request.getParameter( WorkflowBeanService.PARAMETER_RESOURCE_ID ) );
final int nActionId = Integer.parseInt( request.getParameter( WorkflowBeanService.PARAMETER_ACTION_ID ) );
// check and refresh resource if necessary
if ( _candidateidentity == null || ( _candidateidentity.getId( ) != nResourceId ) )
{
final Optional<CandidateIdentity> optIdentity = CandidateIdentityHome.findByPrimaryKey( nResourceId );
_candidateidentity = optIdentity.orElseThrow( ( ) -> new AppException( ERROR_RESOURCE_NOT_FOUND ) );
_wfCandidateIdentityBean = _wfIdentitiesBeanService.createWorkflowBean( _candidateidentity, _candidateidentity.getId( ),
_candidateidentity.getIdBatch( ), getUser( ) );
}
// Process the action, and redirect,
// or redirect to the task form if exists
if ( !_wfIdentitiesBeanService.existsTaskForm( nActionId, getLocale( ) ) )
{
// The task does not need a form
_wfIdentitiesBeanService.processAction( _wfCandidateIdentityBean, nActionId, request, getLocale( ) );
final int batchId = _wfCandidateIdentityBean.getExternalParentId( );
final Optional<Batch> optBatch = BatchHome.findByPrimaryKey( batchId );
_batch = optBatch.orElseThrow( ( ) -> new AppException( ERROR_RESOURCE_NOT_FOUND ) );
_wfBatchBean = _wfBatchBeanService.createWorkflowBean( _batch, _batch.getId( ), getUser( ) );
final Map<String, String> params = new HashMap<>( );
params.put( PARAMETER_ID_BATCH_STATE, String.valueOf( _wfBatchBean.getState( ).getId( ) ) );
params.put( PARAMETER_ID_BATCH, String.valueOf( batchId ) );
return redirect( request, VIEW_MANAGE_IDENTITIES, params );
}
else
if ( request.getParameter( WorkflowBeanService.PARAMETER_SUBMITTED_TASK_FORM ) == null )
{
// A task form should be displayed
return _wfIdentitiesBeanService.getTaskForm( _wfCandidateIdentityBean, nActionId, request, getLocale( ), JSP_MANAGE_CANDIDATEIDENTITIES,
ACTION_PROCESS_IDENTITY_WORKFLOW_ACTION );
}
else
{
// The task form was submitted
final String errMsg = _wfIdentitiesBeanService.validateTaskForm( _wfCandidateIdentityBean, nActionId, request, getLocale( ) );
if ( errMsg == null )
{
return redirect( request, VIEW_IMPORT_CANDIDATEIDENTITY, PARAMETER_ID_CANDIDATEIDENTITY, _wfCandidateIdentityBean.getResourceId( ) );
}
else
{
// error message
return redirect( request, errMsg );
}
}
}
private void globalInit( final HttpServletRequest request )
{
_wfBatchBean = null;
_batch = null;
_current_batch_state = null;
_listIdBatchs = new ArrayList<>( );
_currentBatchId = null;
_listIdCandidateIdentities = new ArrayList<>( );
_filterAppCode = request.getParameter( PARAMETER_FILTER_APP_CODE );
_batchStates = BatchHome.getBatchStates( _filterAppCode );
_batchStates.sort( Comparator.comparingInt( ResourceState::getOrder ) );
final Optional<String> idStateOpt = Optional.ofNullable( request.getParameter( PARAMETER_ID_BATCH_STATE ) );
idStateOpt.ifPresent( idState -> {
final Integer nCurrentBatchId = Integer.parseInt( idState );
_current_batch_state = _batchStates.stream( ).filter( resourceState -> nCurrentBatchId.equals( resourceState.getId( ) ) ).findAny( ).orElse( null );
_batchCurrentPage = Optional.ofNullable( request.getParameter( PARAMETER_BATCH_PAGE ) ).map( Integer::parseInt ).orElse( 1 );
if ( _current_batch_state != null && _current_batch_state.getResourceCount( ) > 0 )
{
_listIdBatchs = BatchHome.getIdBatchsList( _current_batch_state, _filterAppCode );
final int totalRecords = _listIdBatchs.size( );
_batchTotalPages = (int) Math.ceil( (double) totalRecords / NB_ITEMS_PER_PAGES );
if ( _batchTotalPages == 0 )
{
_batchTotalPages = 1;
}
final int start = ( _batchCurrentPage - 1 ) * NB_ITEMS_PER_PAGES;
final int end = Math.min( start + NB_ITEMS_PER_PAGES, totalRecords );
_listIdBatchs = _listIdBatchs.subList( start, end );
}
} );
}
private Map<String, Object> globalModel( final HttpServletRequest request )
{
final Map<String, Object> model = new HashMap<>( );
model.put( MARK_BATCH, _wfBatchBean );
model.put( MARK_BATCH_LIST, this.getItemsFromIds( _listIdBatchs ) );
model.put( MARK_CURRENT_BATCH_ID, _currentBatchId );
model.put( MARK_BATCH_STATE_LIST, _batchStates );
model.put( MARK_CURRENT_BATCH_STATE, _current_batch_state );
model.put( MARK_CURRENT_BATCH_PAGE, _batchCurrentPage );
model.put( MARK_BATCH_TOTAL_PAGES, _batchTotalPages );
model.put( MARK_IDENTITY_LIST, this.getIdentitiesFromIds( _listIdCandidateIdentities, request ) );
model.put( MARK_CURRENT_IDENTITIES_PAGE, _identitiesCurrentPage );
model.put( MARK_IDENTITIES_TOTAL_PAGES, _identitiesTotalPages );
model.put( MARK_FILTER_APP_CODE, _filterAppCode );
return model;
}
/**
* Get Items from Ids list
*
* @param listIds
* @return the populated list of items corresponding to the id List
*/
@Override
protected List<WorkflowBean<Batch>> getItemsFromIds( final List<Integer> listIds )
{
final List<Batch> listBatch = BatchHome.getBatchsListByIds( listIds );
// keep original order
return listBatch.stream( ).sorted( Comparator.comparingInt( notif -> listIds.indexOf( notif.getId( ) ) ) ).map( b -> {
final WorkflowBean<Batch> workflowBean = _wfBatchBeanService.createWorkflowBean( b, b.getId( ), getUser( ) );
_wfBatchBeanService.countSubResources( workflowBean );
return workflowBean;
} ).collect( Collectors.toList( ) );
}
protected List<WorkflowBean<CandidateIdentity>> getIdentitiesFromIds( final List<Integer> listIds, final HttpServletRequest request )
{
final List<CandidateIdentity> listCandidateIdentity = CandidateIdentityHome.getCandidateIdentitiesListByIds( listIds );
// keep original order
return listCandidateIdentity.stream( )
.peek( candidateIdentity -> candidateIdentity
.setAttributes( CandidateIdentityAttributeHome.getCandidateIdentityAttributesList( candidateIdentity.getId( ) ) ) )
.sorted( Comparator.comparingInt( notif -> listIds.indexOf( notif.getId( ) ) ) ).map( b -> {
final WorkflowBean<CandidateIdentity> workflowBean = _wfIdentitiesBeanService.createWorkflowBean( b, b.getId( ), b.getIdBatch( ),
getUser( ) );
_wfIdentitiesBeanService.addHistory( workflowBean, request, getLocale( ) );
return workflowBean;
} ).collect( Collectors.toList( ) );
}
private void unregisterFeed( )
{
_feedToken = null;
progressManagerService.unRegisterFeed( FEED_NAME );
}
private void registerFeed( )
{
_feedToken = progressManagerService.registerFeed( FEED_NAME, 0 );
}
private RequestAuthor buildAuthor( )
{
final RequestAuthor author = new RequestAuthor( );
author.setName( getUser( ).getEmail( ) );
author.setType( AuthorType.application );
return author;
}
}