View Javadoc
1   /*
2    * Copyright (c) 2002-2024, City of Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.plugins.identitystore.web;
35  
36  import fr.paris.lutece.plugins.identitystore.business.application.ClientApplication;
37  import fr.paris.lutece.plugins.identitystore.business.application.ClientApplicationHome;
38  import fr.paris.lutece.plugins.identitystore.business.attribute.AttributeKey;
39  import fr.paris.lutece.plugins.identitystore.business.attribute.AttributeKeyHome;
40  import fr.paris.lutece.plugins.identitystore.business.contract.AttributeCertification;
41  import fr.paris.lutece.plugins.identitystore.business.contract.AttributeRequirement;
42  import fr.paris.lutece.plugins.identitystore.business.contract.AttributeRight;
43  import fr.paris.lutece.plugins.identitystore.business.contract.ServiceContract;
44  import fr.paris.lutece.plugins.identitystore.business.contract.ServiceContractHome;
45  import fr.paris.lutece.plugins.identitystore.business.referentiel.RefAttributeCertificationProcessusHome;
46  import fr.paris.lutece.plugins.identitystore.business.referentiel.RefCertificationLevel;
47  import fr.paris.lutece.plugins.identitystore.business.referentiel.RefCertificationLevelHome;
48  import fr.paris.lutece.plugins.identitystore.service.contract.ServiceContractService;
49  import fr.paris.lutece.plugins.identitystore.web.exception.IdentityStoreException;
50  import fr.paris.lutece.portal.service.admin.AccessDeniedException;
51  import fr.paris.lutece.portal.service.message.AdminMessage;
52  import fr.paris.lutece.portal.service.message.AdminMessageService;
53  import fr.paris.lutece.portal.service.security.SecurityTokenService;
54  import fr.paris.lutece.portal.service.util.AppException;
55  import fr.paris.lutece.portal.util.mvc.admin.annotations.Controller;
56  import fr.paris.lutece.portal.util.mvc.commons.annotations.Action;
57  import fr.paris.lutece.portal.util.mvc.commons.annotations.View;
58  import fr.paris.lutece.util.html.AbstractPaginator;
59  import fr.paris.lutece.util.url.UrlItem;
60  import org.apache.commons.lang3.StringUtils;
61  import org.apache.commons.lang3.tuple.ImmutablePair;
62  
63  import javax.servlet.http.HttpServletRequest;
64  import java.util.ArrayList;
65  import java.util.Arrays;
66  import java.util.Comparator;
67  import java.util.HashMap;
68  import java.util.List;
69  import java.util.Map;
70  import java.util.Objects;
71  import java.util.Optional;
72  import java.util.Set;
73  import java.util.stream.Collectors;
74  
75  /**
76   * This class provides the user interface to manage ServiceContract features ( manage, create, modify, remove )
77   */
78  @Controller( controllerJsp = "ManageServiceContracts.jsp", controllerPath = "jsp/admin/plugins/identitystore/", right = "IDENTITYSTORE_ADMIN_MANAGEMENT" )
79  public class ServiceContractJspBean extends ManageServiceContractJspBean<Integer, ServiceContract>
80  {
81      // Templates
82      private static final String TEMPLATE_MANAGE_SERVICECONTRACTS = "/admin/plugins/identitystore/manage_servicecontracts.html";
83      private static final String TEMPLATE_DISPLAY_SERVICECONTRACTS = "/admin/plugins/identitystore/view_servicecontract.html";
84      private static final String TEMPLATE_CREATE_SERVICECONTRACT = "/admin/plugins/identitystore/create_servicecontract.html";
85      private static final String TEMPLATE_MODIFY_SERVICECONTRACT = "/admin/plugins/identitystore/create_servicecontract.html";
86  
87      // Parameters
88      private static final String PARAMETER_ID_SERVICECONTRACT = "id";
89      private static final String PARAMETER_RIGHT_MANDATORY = "mandatory";
90      private static final String PARAMETER_RIGHT_SEARCHABLE = "searchable";
91      private static final String PARAMETER_RIGHT_READABLE = "readable";
92      private static final String PARAMETER_RIGHT_WRITABLE = "writable";
93      private static final String PARAMETER_ID_CLIENTAPPLICATION = "id_client_app";
94      private static final String PARAMETER_CODE_CLIENTAPPLICATION = "code_client_app";
95      private static final String PARAMETER_ID_PARENTCLIENTAPPLICATION = "parent_application_id";
96      private static final String PARAMETER_CERTICATION_LEVEL = "certification_level";
97      private static final String PARAMETER_CERTICATION_PROCESSUS = "certification_processus";
98      private static final String PARAMETER_BACK_URL = "back_url";
99  
100     // Properties for page titles
101     private static final String PROPERTY_PAGE_TITLE_MANAGE_SERVICECONTRACTS = "identitystore.manage_servicecontracts.pageTitle";
102     private static final String PROPERTY_PAGE_TITLE_MODIFY_SERVICECONTRACT = "identitystore.modify_servicecontract.pageTitle";
103     private static final String PROPERTY_PAGE_TITLE_CREATE_SERVICECONTRACT = "identitystore.create_servicecontract.pageTitle";
104 
105     // Markers
106     private static final String MARK_SERVICECONTRACT_LIST = "servicecontract_list";
107     private static final String MARK_SERVICECONTRACT = "servicecontract";
108     private static final String MARK_ATTRIBUTE_REQUIREMENTS_LIST = "servicecontract_attribute_list";
109     private static final String MARK_AVAILAIBLE_LEVELS_LIST = "availaible_certification_levels_list";
110     private static final String MARK_AVAILAIBLE_CLIENT_APPLICATIONS_LIST = "availaible_client_applications_list";
111     private static final String MARK_EDIT_ACTION = "edit_action";
112     private static final String MARK_BACK_URL = "back_url";
113     private static final String MARK_MANDATORY_ATTRIBUTE_KEYS_LIST = "mandatory_attribute_keys_list";
114 
115     private static final String JSP_MANAGE_SERVICECONTRACTS = "jsp/admin/plugins/identitystore/ManageServiceContracts.jsp";
116 
117     // Properties
118     private static final String MESSAGE_CONFIRM_REMOVE_SERVICECONTRACT = "contractservice.message.confirmRemoveServiceContract";
119 
120     // Validations
121     private static final String VALIDATION_ATTRIBUTES_PREFIX = "contractservice.model.entity.servicecontract.attribute.";
122 
123     // Views
124     private static final String VIEW_MANAGE_SERVICECONTRACTS = "manageServiceContracts";
125     private static final String VIEW_DISPLAY_SERVICECONTRACTS = "displayServiceContract";
126     private static final String VIEW_CREATE_SERVICECONTRACT = "createServiceContract";
127     private static final String VIEW_MODIFY_SERVICECONTRACT = "modifyServiceContract";
128 
129     // Actions
130     private static final String ACTION_CREATE_SERVICECONTRACT = "createServiceContract";
131     private static final String ACTION_MODIFY_SERVICECONTRACT = "modifyServiceContract";
132     private static final String ACTION_REMOVE_SERVICECONTRACT = "removeServiceContract";
133     private static final String ACTION_CONFIRM_REMOVE_SERVICECONTRACT = "confirmRemoveServiceContract";
134 
135     // Infos
136     private static final String INFO_SERVICECONTRACT_CREATED = "identitystore.info.servicecontract.created";
137     private static final String INFO_SERVICECONTRACT_UPDATED = "identitystore.info.servicecontract.updated";
138     private static final String INFO_SERVICECONTRACT_REMOVED = "identitystore.info.servicecontract.removed";
139 
140     // Errors
141     private static final String ERROR_RESOURCE_NOT_FOUND = "Resource not found";
142 
143     private static final String ERROR_SERVICECONTRACT_NO_DATE = "identitystore.error.servicecontract.nostartingdate";
144     private static final String ERROR_SERVICECONTRACT_INVALID_DATE = "identitystore.error.servicecontract.validatedate";
145     private static final String ERROR_SERVICECONTRACT_INVALID_MANDATORY_ATTRIBUTE = "identitystore.error.servicecontract.validate.mandatory.attribute";
146 
147     // Session variable to store working values
148     private ServiceContract _servicecontract;
149     private List<Integer> _listIdServiceContracts;
150 
151     /**
152      * Build the Manage View
153      *
154      * @param request
155      *            The HTTP request
156      * @return The page
157      */
158     @View( value = VIEW_MANAGE_SERVICECONTRACTS, defaultView = true )
159     public String getManageServiceContracts( HttpServletRequest request )
160     {
161         _servicecontract = null;
162         final Map<String, String> queryParameters = this.getQueryParameters( request );
163 
164         if ( request.getParameter( AbstractPaginator.PARAMETER_PAGE_INDEX ) == null || _listIdServiceContracts.isEmpty( ) )
165         {
166             _listIdServiceContracts = ServiceContractHome.getFilteredIdServiceContractsList( queryParameters );
167         }
168 
169         final Map<String, Object> model = getPaginatedListModel( request, MARK_SERVICECONTRACT_LIST, _listIdServiceContracts, JSP_MANAGE_SERVICECONTRACTS );
170         model.put( QUERY_PARAM_ACTIVE, request.getParameter( QUERY_PARAM_ACTIVE ) );
171         model.put( QUERY_PARAM_CONTRACT_NAME, request.getParameter( QUERY_PARAM_CONTRACT_NAME ) );
172         model.put( QUERY_PARAM_CLIENT_CODE, request.getParameter( QUERY_PARAM_CLIENT_CODE ) );
173         model.put( QUERY_PARAM_START_DATE, request.getParameter( QUERY_PARAM_START_DATE ) );
174         model.put( QUERY_PARAM_END_DATE, request.getParameter( QUERY_PARAM_END_DATE ) );
175 
176         return getPage( PROPERTY_PAGE_TITLE_MANAGE_SERVICECONTRACTS, TEMPLATE_MANAGE_SERVICECONTRACTS, model );
177     }
178 
179     /**
180      * Build the Manage View
181      *
182      * @param request
183      *            The HTTP request
184      * @return The page
185      */
186     @View( value = VIEW_DISPLAY_SERVICECONTRACTS )
187     public String getDisplayServiceContracts( HttpServletRequest request )
188     {
189         final int nId = Integer.parseInt( request.getParameter( PARAMETER_ID_SERVICECONTRACT ) );
190         final String backUrl = request.getParameter( PARAMETER_BACK_URL );
191         _servicecontract = null;
192 
193         final Optional<ServiceContract> optServiceContract = ServiceContractHome.findByPrimaryKey( nId );
194         _servicecontract = optServiceContract.orElseThrow( ( ) -> new AppException( ERROR_RESOURCE_NOT_FOUND ) );
195 
196         final Map<String, Object> model = getModel( );
197         final ClientApplication parentApplication = ClientApplicationHome.getParentApplication( _servicecontract );
198         if ( parentApplication != null )
199         {
200             model.put( PARAMETER_ID_CLIENTAPPLICATION, parentApplication.getId( ) );
201             model.put( PARAMETER_CODE_CLIENTAPPLICATION, parentApplication.getClientCode( ) );
202         }
203         else
204         {
205             throw new AppException( ERROR_RESOURCE_NOT_FOUND );
206         }
207 
208         final List<ServiceContractAttributeDefinitionDto> attributeRequirementList = ServiceContractHome.getDto( _servicecontract );
209         sortAttributeRequirementList( attributeRequirementList );
210 
211         model.put( MARK_BACK_URL, backUrl );
212         model.put( MARK_SERVICECONTRACT, _servicecontract );
213         model.put( MARK_ATTRIBUTE_REQUIREMENTS_LIST, attributeRequirementList );
214 
215         return getPage( PROPERTY_PAGE_TITLE_MANAGE_SERVICECONTRACTS, TEMPLATE_DISPLAY_SERVICECONTRACTS, model );
216     }
217 
218     /**
219      * Get Items from Ids list
220      *
221      * @param listIds
222      * @return the populated list of items corresponding to the id List
223      */
224     @Override
225     List<ImmutablePair<ServiceContract, String>> getItemsFromIds( final List<Integer> listIds )
226     {
227         final List<ImmutablePair<ServiceContract, String>> listServiceContract = ServiceContractHome.getServiceContractsListByIds( listIds );
228 
229         // #134 - sort by ascending application code and descending start date
230         return listServiceContract.stream( ).sorted( Comparator.comparing( ( ImmutablePair<ServiceContract, String> pair ) -> pair.getValue( ) )
231                 .thenComparing( pair -> pair.getKey( ).getStartingDate( ), Comparator.reverseOrder( ) ) ).collect( Collectors.toList( ) );
232     }
233 
234     /**
235      * reset the _listIdServiceContracts list
236      */
237     public void resetListId( )
238     {
239         _listIdServiceContracts = new ArrayList<>( );
240     }
241 
242     /**
243      * Returns the form to create a servicecontract
244      *
245      * @param request
246      *            The Http request
247      * @return the html code of the servicecontract form
248      */
249     @View( VIEW_CREATE_SERVICECONTRACT )
250     public String getCreateServiceContract( HttpServletRequest request )
251     {
252         final Map<String, Object> model = getModel( );
253 
254         _servicecontract = new ServiceContract( );
255         final String idClientApp = request.getParameter( PARAMETER_ID_CLIENTAPPLICATION );
256         if ( StringUtils.isNotEmpty( idClientApp ) )
257         {
258             final int nIdClientApp = Integer.parseInt( idClientApp );
259             model.put( PARAMETER_ID_CLIENTAPPLICATION, nIdClientApp );
260         }
261 
262         final List<ServiceContractAttributeDefinitionDto> attributeRequirementList = ServiceContractHome.getDto( _servicecontract );
263         sortAttributeRequirementList( attributeRequirementList );
264 
265         final List<String> mandatoryAttrKeyList = AttributeKeyHome.getMandatoryForCreationAttributeKeyList( ).stream( ).map( AttributeKey::getKeyName )
266                 .collect( Collectors.toList( ) );
267 
268         model.put( MARK_MANDATORY_ATTRIBUTE_KEYS_LIST, mandatoryAttrKeyList );
269         model.put( MARK_SERVICECONTRACT, _servicecontract );
270         model.put( MARK_EDIT_ACTION, "action_createServiceContract" );
271         model.put( MARK_ATTRIBUTE_REQUIREMENTS_LIST, attributeRequirementList );
272         model.put( MARK_AVAILAIBLE_LEVELS_LIST, ServiceContractHome.selectCertificationLevels( ).stream( )
273                 .sorted( Comparator.comparing( RefCertificationLevel::getLevel ) ).collect( Collectors.toList( ) ) );
274         model.put( MARK_AVAILAIBLE_CLIENT_APPLICATIONS_LIST, ClientApplicationHome.selectApplicationList( ) );
275         model.put( SecurityTokenService.MARK_TOKEN, SecurityTokenService.getInstance( ).getToken( request, ACTION_CREATE_SERVICECONTRACT ) );
276 
277         return getPage( PROPERTY_PAGE_TITLE_CREATE_SERVICECONTRACT, TEMPLATE_CREATE_SERVICECONTRACT, model );
278     }
279 
280     /**
281      * Process the data capture form of a new servicecontract
282      *
283      * @param request
284      *            The Http Request
285      * @return The Jsp URL of the process result
286      * @throws AccessDeniedException
287      */
288     @Action( ACTION_CREATE_SERVICECONTRACT )
289     public String doCreateServiceContract( HttpServletRequest request ) throws AccessDeniedException
290     {
291         populate( _servicecontract, request, getLocale( ) );
292         final String [ ] selectedClienAppId = request.getParameterValues( PARAMETER_ID_PARENTCLIENTAPPLICATION );
293         final String strSelectedClientAppId = selectedClienAppId [0];
294         int selectedClientAppId = Integer.parseInt( strSelectedClientAppId );
295 
296         if ( !SecurityTokenService.getInstance( ).validate( request, ACTION_CREATE_SERVICECONTRACT ) )
297         {
298             throw new AccessDeniedException( "Invalid security token" );
299         }
300 
301         // Check constraints
302         if ( !validateBean( _servicecontract, VALIDATION_ATTRIBUTES_PREFIX ) )
303         {
304             return redirect( request, VIEW_CREATE_SERVICECONTRACT, PARAMETER_ID_CLIENTAPPLICATION, selectedClientAppId );
305         }
306 
307         if ( _servicecontract.getStartingDate( ).equals( null ) )
308         {
309             addError( ERROR_SERVICECONTRACT_NO_DATE, getLocale( ) );
310             return redirect( request, VIEW_CREATE_SERVICECONTRACT, PARAMETER_ID_CLIENTAPPLICATION, selectedClientAppId );
311         }
312         else
313             if ( !checkServiceContractsActivationDate( _servicecontract, selectedClientAppId ) )
314             {
315                 addError( ERROR_SERVICECONTRACT_INVALID_DATE, getLocale( ) );
316                 return redirect( request, VIEW_CREATE_SERVICECONTRACT, PARAMETER_ID_CLIENTAPPLICATION, selectedClientAppId );
317             }
318 
319         final List<AttributeRight> lstAttributeRights = new ArrayList<>( getAttributesRightsFromRequest( request ).values( ) );
320         _servicecontract.setAttributeRights( lstAttributeRights );
321         final List<AttributeRequirement> attributeRequirements = new ArrayList<>( getAttributesRequirementsFromRequest( request ).values( ) );
322         _servicecontract.getAttributeRequirements( )
323                 .addAll( attributeRequirements.stream( ).filter( attributeRequirement -> attributeRequirement.getRefCertificationLevel( ) != null
324                         && attributeRequirement.getRefCertificationLevel( ).getLevel( ) != null ).collect( Collectors.toList( ) ) );
325         final List<AttributeCertification> attributeCertifications = new ArrayList<>( getAttributesCertificationsFromRequest( request ) );
326         _servicecontract.setAttributeCertifications( attributeCertifications.stream( ).filter( certif -> {
327             AttributeRight attributeRight = lstAttributeRights.stream( ).filter( atr -> atr.getAttributeKey( ).getId( ) == certif.getAttributeKey( ).getId( ) )
328                     .findFirst( ).orElse( null );
329             return attributeRight != null && attributeRight.isWritable( );
330         } ).collect( Collectors.toList( ) ) );
331 
332         final boolean validMandatoryConfig = _servicecontract.getAttributeRights( ).stream( ).filter( AttributeRight::isMandatory )
333                 .allMatch( attributeRight -> _servicecontract.getAttributeRequirements( ).stream( )
334                         .anyMatch( req -> Objects.equals( req.getAttributeKey( ).getKeyName( ), attributeRight.getAttributeKey( ).getKeyName( ) )
335                                 && req.getRefCertificationLevel( ) != null && req.getRefCertificationLevel( ).getLevel( ) != null ) );
336         if ( !validMandatoryConfig )
337         {
338             this.addError( ERROR_SERVICECONTRACT_INVALID_MANDATORY_ATTRIBUTE, getLocale( ) );
339             return redirect( request, VIEW_CREATE_SERVICECONTRACT, PARAMETER_ID_CLIENTAPPLICATION, selectedClientAppId );
340         }
341 
342         try
343         {
344             ServiceContractService.instance( ).create( _servicecontract, selectedClientAppId );
345         }
346         catch( Exception e )
347         {
348             addError( e.getMessage( ) );
349             return redirect( request, VIEW_CREATE_SERVICECONTRACT, PARAMETER_ID_CLIENTAPPLICATION, selectedClientAppId );
350         }
351 
352         addInfo( INFO_SERVICECONTRACT_CREATED, getLocale( ) );
353         resetListId( );
354 
355         return redirectView( request, VIEW_MANAGE_SERVICECONTRACTS );
356     }
357 
358     /**
359      * Manages the removal form of a servicecontract whose identifier is in the http request
360      *
361      * @param request
362      *            The Http request
363      * @return the html code to confirm
364      */
365     @Action( ACTION_CONFIRM_REMOVE_SERVICECONTRACT )
366     public String getConfirmRemoveServiceContract( HttpServletRequest request )
367     {
368         int nId = Integer.parseInt( request.getParameter( PARAMETER_ID_SERVICECONTRACT ) );
369         UrlItem url = new UrlItem( getActionUrl( ACTION_REMOVE_SERVICECONTRACT ) );
370         url.addParameter( PARAMETER_ID_SERVICECONTRACT, nId );
371 
372         String strMessageUrl = AdminMessageService.getMessageUrl( request, MESSAGE_CONFIRM_REMOVE_SERVICECONTRACT, url.getUrl( ),
373                 AdminMessage.TYPE_CONFIRMATION );
374 
375         return redirect( request, strMessageUrl );
376     }
377 
378     /**
379      * Handles the removal form of a servicecontract
380      *
381      * @param request
382      *            The Http request
383      * @return the jsp URL to display the form to manage servicecontracts
384      */
385     @Action( ACTION_REMOVE_SERVICECONTRACT )
386     public String doRemoveServiceContract( HttpServletRequest request )
387     {
388         int nId = Integer.parseInt( request.getParameter( PARAMETER_ID_SERVICECONTRACT ) );
389         ServiceContractService.instance( ).delete( nId );
390         addInfo( INFO_SERVICECONTRACT_REMOVED, getLocale( ) );
391         resetListId( );
392 
393         return redirectView( request, VIEW_MANAGE_SERVICECONTRACTS );
394     }
395 
396     /**
397      * Returns the form to update info about a servicecontract
398      *
399      * @param request
400      *            The Http request
401      * @return The HTML form to update info
402      */
403     @View( VIEW_MODIFY_SERVICECONTRACT )
404     public String getModifyServiceContract( HttpServletRequest request )
405     {
406         int nId = Integer.parseInt( request.getParameter( PARAMETER_ID_SERVICECONTRACT ) );
407 
408         if ( _servicecontract == null || ( _servicecontract.getId( ) != nId ) )
409         {
410             Optional<ServiceContract> optServiceContract = ServiceContractHome.findByPrimaryKey( nId );
411             _servicecontract = optServiceContract.orElseThrow( ( ) -> new AppException( ERROR_RESOURCE_NOT_FOUND ) );
412         }
413 
414         final Map<String, Object> model = getModel( );
415         final ClientApplication parentApplication = ClientApplicationHome.getParentApplication( _servicecontract );
416         if ( parentApplication != null )
417         {
418             model.put( PARAMETER_ID_CLIENTAPPLICATION, parentApplication.getId( ) );
419         }
420         else
421         {
422             throw new AppException( ERROR_RESOURCE_NOT_FOUND );
423         }
424 
425         final List<ServiceContractAttributeDefinitionDto> attributeRequirementList = ServiceContractHome.getDto( _servicecontract );
426         sortAttributeRequirementList( attributeRequirementList );
427 
428         final List<String> mandatoryAttrKeyList = AttributeKeyHome.getMandatoryForCreationAttributeKeyList( ).stream( ).map( AttributeKey::getKeyName )
429                 .collect( Collectors.toList( ) );
430 
431         model.put( MARK_MANDATORY_ATTRIBUTE_KEYS_LIST, mandatoryAttrKeyList );
432         model.put( MARK_SERVICECONTRACT, _servicecontract );
433         model.put( MARK_EDIT_ACTION, "action_modifyServiceContract" );
434         model.put( MARK_ATTRIBUTE_REQUIREMENTS_LIST, attributeRequirementList );
435         model.put( MARK_AVAILAIBLE_LEVELS_LIST, ServiceContractHome.selectCertificationLevels( ).stream( )
436                 .sorted( Comparator.comparing( RefCertificationLevel::getLevel ) ).collect( Collectors.toList( ) ) );
437         model.put( MARK_AVAILAIBLE_CLIENT_APPLICATIONS_LIST, ClientApplicationHome.selectApplicationList( ) );
438         model.put( SecurityTokenService.MARK_TOKEN, SecurityTokenService.getInstance( ).getToken( request, ACTION_MODIFY_SERVICECONTRACT ) );
439 
440         return getPage( PROPERTY_PAGE_TITLE_MODIFY_SERVICECONTRACT, TEMPLATE_MODIFY_SERVICECONTRACT, model );
441     }
442 
443     /**
444      * Process the change form of a servicecontract
445      *
446      * @param request
447      *            The Http request
448      * @return The Jsp URL of the process result
449      * @throws AccessDeniedException
450      */
451     @Action( ACTION_MODIFY_SERVICECONTRACT )
452     public String doModifyServiceContract( HttpServletRequest request ) throws AccessDeniedException
453     {
454         populate( _servicecontract, request, getLocale( ) );
455         final String [ ] selectedClienAppId = request.getParameterValues( PARAMETER_ID_PARENTCLIENTAPPLICATION );
456         final String strSelectedClientAppId = selectedClienAppId [0];
457         int selectedClientAppId = Integer.parseInt( strSelectedClientAppId );
458 
459         if ( !SecurityTokenService.getInstance( ).validate( request, ACTION_MODIFY_SERVICECONTRACT ) )
460         {
461             throw new AccessDeniedException( "Invalid security token" );
462         }
463 
464         // Check constraints
465         if ( !validateBean( _servicecontract, VALIDATION_ATTRIBUTES_PREFIX ) )
466         {
467             return redirect( request, VIEW_MODIFY_SERVICECONTRACT, PARAMETER_ID_SERVICECONTRACT, _servicecontract.getId( ) );
468         }
469 
470         if ( _servicecontract.getStartingDate( ).equals( null ) )
471         {
472             addError( ERROR_SERVICECONTRACT_NO_DATE, getLocale( ) );
473             return redirect( request, VIEW_MODIFY_SERVICECONTRACT, PARAMETER_ID_SERVICECONTRACT, _servicecontract.getId( ) );
474         }
475         else
476             if ( !checkServiceContractsActivationDate( _servicecontract, selectedClientAppId ) )
477             {
478                 addError( ERROR_SERVICECONTRACT_INVALID_DATE, getLocale( ) );
479                 return redirect( request, VIEW_MODIFY_SERVICECONTRACT, PARAMETER_ID_SERVICECONTRACT, _servicecontract.getId( ) );
480             }
481 
482         final String [ ] parameterValues = request.getParameterValues( PARAMETER_ID_PARENTCLIENTAPPLICATION );
483         final List<AttributeRight> lstAttributeRights = new ArrayList<>( getAttributesRightsFromRequest( request ).values( ) );
484         _servicecontract.getAttributeRights( ).clear( );
485         _servicecontract.getAttributeRights( ).addAll( lstAttributeRights );
486         final List<AttributeRequirement> attributeRequirements = new ArrayList<>( getAttributesRequirementsFromRequest( request ).values( ) );
487         _servicecontract.getAttributeRequirements( ).clear( );
488         _servicecontract.getAttributeRequirements( )
489                 .addAll( attributeRequirements.stream( ).filter( attributeRequirement -> attributeRequirement.getRefCertificationLevel( ) != null
490                         && attributeRequirement.getRefCertificationLevel( ).getLevel( ) != null ).collect( Collectors.toList( ) ) );
491         final List<AttributeCertification> attributeCertifications = new ArrayList<>( getAttributesCertificationsFromRequest( request ) );
492         _servicecontract.getAttributeCertifications( ).clear( );
493         _servicecontract.getAttributeCertifications( ).addAll( attributeCertifications.stream( ).filter( certif -> {
494             AttributeRight attributeRight = lstAttributeRights.stream( ).filter( atr -> atr.getAttributeKey( ).getId( ) == certif.getAttributeKey( ).getId( ) )
495                     .findFirst( ).orElse( null );
496             return attributeRight != null && attributeRight.isWritable( );
497         } ).collect( Collectors.toList( ) ) );
498 
499         final boolean validMandatoryConfig = _servicecontract.getAttributeRights( ).stream( ).filter( AttributeRight::isMandatory )
500                 .allMatch( attributeRight -> _servicecontract.getAttributeRequirements( ).stream( )
501                         .anyMatch( req -> Objects.equals( req.getAttributeKey( ).getKeyName( ), attributeRight.getAttributeKey( ).getKeyName( ) )
502                                 && req.getRefCertificationLevel( ) != null && req.getRefCertificationLevel( ).getLevel( ) != null ) );
503         if ( !validMandatoryConfig )
504         {
505             this.addError( ERROR_SERVICECONTRACT_INVALID_MANDATORY_ATTRIBUTE, getLocale( ) );
506             return redirect( request, VIEW_MODIFY_SERVICECONTRACT, PARAMETER_ID_SERVICECONTRACT, _servicecontract.getId( ) );
507         }
508 
509         try
510         {
511             ServiceContractService.instance( ).update( _servicecontract, Integer.parseInt( parameterValues [0] ) );
512         }
513         catch( IdentityStoreException e )
514         {
515             addError( e.getMessage( ) );
516             return redirect( request, VIEW_MODIFY_SERVICECONTRACT, PARAMETER_ID_SERVICECONTRACT, _servicecontract.getId( ) );
517         }
518 
519         addInfo( INFO_SERVICECONTRACT_UPDATED, getLocale( ) );
520         resetListId( );
521 
522         return redirectView( request, VIEW_MANAGE_SERVICECONTRACTS );
523     }
524 
525     /**
526      * get AttributeRights to set from httprequest
527      *
528      * @param request
529      *            http request
530      * @return AttributeRights to set from httprequest
531      */
532     private Map<String, AttributeRight> getAttributesRightsFromRequest( HttpServletRequest request )
533     {
534         Map<String, AttributeRight> mapAttributesRights = new HashMap<String, AttributeRight>( );
535         String [ ] tabIdMandatories = request.getParameterValues( PARAMETER_RIGHT_MANDATORY );
536         String [ ] tabIdSearchables = request.getParameterValues( PARAMETER_RIGHT_SEARCHABLE );
537         String [ ] tabIdReadables = request.getParameterValues( PARAMETER_RIGHT_READABLE );
538         String [ ] tabIdWritables = request.getParameterValues( PARAMETER_RIGHT_WRITABLE );
539 
540         for ( int nCpt = 0; ( tabIdSearchables != null ) && ( nCpt < tabIdSearchables.length ); nCpt++ )
541         {
542             final String strIdAttribute = tabIdSearchables [nCpt];
543             final AttributeRightbusiness/contract/AttributeRight.html#AttributeRight">AttributeRight attributeRight = new AttributeRight( );
544             attributeRight.setSearchable( true );
545             attributeRight.setAttributeKey( AttributeKeyHome.findByPrimaryKey( Integer.parseInt( strIdAttribute ), false ) );
546             mapAttributesRights.put( strIdAttribute, attributeRight );
547         }
548 
549         for ( int nCpt = 0; ( tabIdMandatories != null ) && ( nCpt < tabIdMandatories.length ); nCpt++ )
550         {
551             String strIdAttribute = tabIdMandatories [nCpt];
552 
553             if ( mapAttributesRights.get( strIdAttribute ) != null )
554             {
555                 mapAttributesRights.get( strIdAttribute ).setMandatory( true );
556             }
557             else
558             {
559                 final AttributeRightbusiness/contract/AttributeRight.html#AttributeRight">AttributeRight attributeRight = new AttributeRight( );
560                 attributeRight.setMandatory( true );
561                 attributeRight.setAttributeKey( AttributeKeyHome.findByPrimaryKey( Integer.parseInt( strIdAttribute ), false ) );
562                 mapAttributesRights.put( strIdAttribute, attributeRight );
563             }
564         }
565 
566         for ( int nCpt = 0; ( tabIdReadables != null ) && ( nCpt < tabIdReadables.length ); nCpt++ )
567         {
568             String strIdAttribute = tabIdReadables [nCpt];
569 
570             if ( mapAttributesRights.get( strIdAttribute ) != null )
571             {
572                 mapAttributesRights.get( strIdAttribute ).setReadable( true );
573             }
574             else
575             {
576                 AttributeRightbusiness/contract/AttributeRight.html#AttributeRight">AttributeRight attributeRight = new AttributeRight( );
577                 attributeRight.setReadable( true );
578                 attributeRight.setAttributeKey( AttributeKeyHome.findByPrimaryKey( Integer.parseInt( strIdAttribute ), false ) );
579                 mapAttributesRights.put( strIdAttribute, attributeRight );
580             }
581         }
582 
583         for ( int nCpt = 0; ( tabIdWritables != null ) && ( nCpt < tabIdWritables.length ); nCpt++ )
584         {
585             String strIdAttribute = tabIdWritables [nCpt];
586 
587             if ( mapAttributesRights.get( strIdAttribute ) != null )
588             {
589                 mapAttributesRights.get( strIdAttribute ).setWritable( true );
590             }
591             else
592             {
593                 AttributeRightbusiness/contract/AttributeRight.html#AttributeRight">AttributeRight attributeRight = new AttributeRight( );
594                 attributeRight.setWritable( true );
595                 attributeRight.setAttributeKey( AttributeKeyHome.findByPrimaryKey( Integer.parseInt( strIdAttribute ), false ) );
596                 mapAttributesRights.put( strIdAttribute, attributeRight );
597             }
598         }
599 
600         return mapAttributesRights;
601     }
602 
603     private List<AttributeCertification> getAttributesCertificationsFromRequest( HttpServletRequest request )
604     {
605         final List<AttributeCertification> attributeCertifications = new ArrayList<>( );
606         final String [ ] tabIdCertificationLevels = request.getParameterValues( PARAMETER_CERTICATION_PROCESSUS );
607         if ( tabIdCertificationLevels != null )
608         {
609             Arrays.stream( tabIdCertificationLevels ).map( s -> s.split( "," ) )
610                     .collect( Collectors.groupingBy( s -> s [0], Collectors.mapping( s -> s [1], Collectors.toList( ) ) ) )
611                     .forEach( ( attributeId, processusIds ) -> {
612                         final AttributeCertificationt/AttributeCertification.html#AttributeCertification">AttributeCertification attributeCertification = new AttributeCertification( );
613                         attributeCertification.setAttributeKey( AttributeKeyHome.findByPrimaryKey( Integer.parseInt( attributeId ), false ) );
614                         processusIds.forEach( processusId -> attributeCertification.getRefAttributeCertificationProcessus( )
615                                 .add( RefAttributeCertificationProcessusHome.findByPrimaryKey( Integer.parseInt( processusId ) ) ) );
616                         attributeCertifications.add( attributeCertification );
617                     } );
618         }
619 
620         return attributeCertifications;
621     }
622 
623     private Map<String, AttributeRequirement> getAttributesRequirementsFromRequest( HttpServletRequest request )
624     {
625         Map<String, AttributeRequirement> mapAttributesRights = new HashMap<>( );
626         String [ ] tabIdCertificationLevels = request.getParameterValues( PARAMETER_CERTICATION_LEVEL );
627 
628         for ( int nCpt = 0; ( tabIdCertificationLevels != null ) && ( nCpt < tabIdCertificationLevels.length ); nCpt++ )
629         {
630             String strIdAttribute = tabIdCertificationLevels [nCpt];
631             AttributeRequirementtract/AttributeRequirement.html#AttributeRequirement">AttributeRequirement attributeRequirement = new AttributeRequirement( );
632             if ( strIdAttribute != null && strIdAttribute.contains( "," ) )
633             {
634                 String [ ] keyAndLevel = strIdAttribute.split( "," );
635                 attributeRequirement.setAttributeKey( AttributeKeyHome.findByPrimaryKey( Integer.parseInt( keyAndLevel [0] ), false ) );
636                 attributeRequirement.setRefCertificationLevel( RefCertificationLevelHome.findByPrimaryKey( Integer.parseInt( keyAndLevel [1] ) ) );
637             }
638             mapAttributesRights.put( strIdAttribute, attributeRequirement );
639         }
640 
641         return mapAttributesRights;
642     }
643 
644     private boolean checkServiceContractsActivationDate( final ServiceContract serviceContract, final int clientAppId )
645     {
646         final ClientApplication clientApplication = ClientApplicationHome.findByPrimaryKey( clientAppId );
647         final List<ServiceContract> serviceContracts = ClientApplicationHome.selectServiceContracts( clientApplication );
648         final List<ServiceContract> filteredServiceContracts = serviceContracts.stream( ).filter( c -> !Objects.equals( c.getId( ), serviceContract.getId( ) ) )
649                 .collect( Collectors.toList( ) );
650         if ( filteredServiceContracts == null || filteredServiceContracts.isEmpty( ) )
651         {
652             return true;
653         }
654 
655         if ( filteredServiceContracts.stream( ).anyMatch( contract -> ServiceContractService.instance( ).isInRange( serviceContract.getStartingDate( ),
656                 contract.getStartingDate( ), contract.getEndingDate( ) ) ) )
657         {
658             return false;
659         }
660         if ( filteredServiceContracts.stream( ).anyMatch( contract -> ServiceContractService.instance( ).isInRange( serviceContract.getEndingDate( ),
661                 contract.getStartingDate( ), contract.getEndingDate( ) ) ) )
662         {
663             return false;
664         }
665         // TODO traiter le cas où il existe un contrat sans date de fin => soit on interdit soit on ferme le contrat automatiquement
666         return filteredServiceContracts.stream( )
667                 .noneMatch( contract -> contract.getEndingDate( ) == null && contract.getStartingDate( ).before( serviceContract.getStartingDate( ) ) );
668     }
669 
670     private void sortAttributeRequirementList( final List<ServiceContractAttributeDefinitionDto> attributeRequirementList )
671     {
672         if ( attributeRequirementList != null )
673         {
674             attributeRequirementList.sort( ( o1, o2 ) -> {
675                 final boolean p1 = o1.getAttributeKey( ).getPivot( );
676                 final boolean p2 = o2.getAttributeKey( ).getPivot( );
677                 if ( p1 != p2 )
678                 {
679                     return Boolean.compare( p2, p1 );
680                 }
681                 return Integer.compare( o1.getAttributeKey( ).getId( ), o2.getAttributeKey( ).getId( ) );
682             } );
683             attributeRequirementList.forEach( a -> {
684                 a.getCompatibleProcessus( ).sort( Comparator.comparing( p -> p.getLevel( ).getRefCertificationLevel( ).getLevel( ) ) );
685                 a.getRefAttributeCertificationProcessus( ).sort( Comparator.comparingInt( p -> a.getCompatibleProcessus( ).indexOf( p ) ) );
686             } );
687         }
688     }
689 }