1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package fr.paris.lutece.plugins.identitystore.service.contract;
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.contract.AttributeCertification;
40 import fr.paris.lutece.plugins.identitystore.business.contract.AttributeRequirement;
41 import fr.paris.lutece.plugins.identitystore.business.contract.AttributeRight;
42 import fr.paris.lutece.plugins.identitystore.business.contract.ServiceContract;
43 import fr.paris.lutece.plugins.identitystore.business.contract.ServiceContractHome;
44 import fr.paris.lutece.plugins.identitystore.business.referentiel.RefAttributeCertificationProcessus;
45 import fr.paris.lutece.plugins.identitystore.cache.ActiveServiceContractCache;
46 import fr.paris.lutece.plugins.identitystore.service.attribute.IdentityAttributeService;
47 import fr.paris.lutece.plugins.identitystore.service.identity.IdentityAttributeNotFoundException;
48 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.common.AttributeChangeStatus;
49 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.common.AttributeDto;
50 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.common.AttributeStatus;
51 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.crud.IdentityChangeRequest;
52 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.crud.IdentityChangeResponse;
53 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.exporting.IdentityExportRequest;
54 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.exporting.IdentityExportResponse;
55 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.merge.IdentityMergeRequest;
56 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.merge.IdentityMergeResponse;
57 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.search.IdentitySearchMessage;
58 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.search.IdentitySearchRequest;
59 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.search.IdentitySearchResponse;
60 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.search.SearchAttribute;
61 import fr.paris.lutece.plugins.identitystore.v3.web.rs.util.Constants;
62 import fr.paris.lutece.plugins.identitystore.v3.web.rs.util.ResponseStatusFactory;
63 import fr.paris.lutece.plugins.identitystore.web.exception.IdentityStoreException;
64 import fr.paris.lutece.portal.service.i18n.I18nService;
65 import fr.paris.lutece.portal.service.spring.SpringContextService;
66 import fr.paris.lutece.util.sql.TransactionManager;
67 import org.apache.commons.collections.CollectionUtils;
68 import org.apache.commons.lang3.StringUtils;
69
70 import java.util.ArrayList;
71 import java.util.Date;
72 import java.util.List;
73 import java.util.Locale;
74 import java.util.Objects;
75 import java.util.Optional;
76 import java.util.stream.Collectors;
77 import java.util.stream.Stream;
78
79 public class ServiceContractService
80 {
81
82 private final ActiveServiceContractCache _cache = SpringContextService.getBean( "identitystore.activeServiceContractCache" );
83 private static ServiceContractService _instance;
84
85 public static ServiceContractService instance( )
86 {
87 if ( _instance == null )
88 {
89 _instance = new ServiceContractService( );
90 _instance._cache.refresh( );
91 }
92 return _instance;
93 }
94
95 private ServiceContractService( )
96 {
97 }
98
99
100
101
102
103
104
105
106
107 public ServiceContract getActiveServiceContract( final String clientCode ) throws ServiceContractNotFoundException
108 {
109 return _cache.get( clientCode );
110 }
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128 public IdentityChangeResponse validateIdentityChange( final IdentityChangeRequest identityChangeRequest, final String clientCode )
129 throws ServiceContractNotFoundException, IdentityAttributeNotFoundException
130 {
131 final IdentityChangeResponse response = new IdentityChangeResponse( );
132 final List<AttributeStatus> attrStatusList = new ArrayList<>( );
133 final ServiceContract serviceContract = this.getActiveServiceContract( clientCode );
134 for ( final AttributeDto attributeDto : identityChangeRequest.getIdentity( ).getAttributes( ) )
135 {
136 boolean canWriteAttribute = IdentityAttributeService.instance( ).getAttributeKey( attributeDto.getKey( ) ) != null;
137 if ( !canWriteAttribute )
138 {
139 attrStatusList.add( this.buildAttributeStatus( attributeDto, AttributeChangeStatus.NOT_FOUND ) );
140 continue;
141 }
142
143 canWriteAttribute = serviceContract.getAttributeRights( ).stream( )
144 .anyMatch( attributeRight -> StringUtils.equals( attributeRight.getAttributeKey( ).getKeyName( ), attributeDto.getKey( ) )
145 && attributeRight.isWritable( ) );
146 if ( !canWriteAttribute )
147 {
148 attrStatusList.add( this.buildAttributeStatus( attributeDto, AttributeChangeStatus.UNAUTHORIZED ) );
149 continue;
150 }
151
152 if ( attributeDto.getCertifier( ) != null )
153 {
154 canWriteAttribute = serviceContract.getAttributeCertifications( ).stream( ).anyMatch(
155 attributeCertification -> StringUtils.equals( attributeCertification.getAttributeKey( ).getKeyName( ), attributeDto.getKey( ) )
156 && attributeCertification.getRefAttributeCertificationProcessus( ).stream( )
157 .anyMatch( processus -> StringUtils.equals( processus.getCode( ), attributeDto.getCertifier( ) ) ) );
158 if ( !canWriteAttribute )
159 {
160 attrStatusList.add( this.buildAttributeStatus( attributeDto, AttributeChangeStatus.INSUFFICIENT_RIGHTS ) );
161 }
162 }
163 }
164
165 if ( !attrStatusList.isEmpty( ) )
166 {
167 response.setStatus(
168 ResponseStatusFactory.failure( ).setAttributeStatuses( attrStatusList ).setMessage( "The request violates service contract definition" )
169 .setMessageKey( Constants.PROPERTY_REST_ERROR_SERVICE_CONTRACT_VIOLATION ) );
170 }
171
172 return response;
173 }
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189 public IdentityMergeResponse validateIdentityMerge( final IdentityMergeRequest identityMergeRequest, final String clientCode )
190 throws ServiceContractNotFoundException
191 {
192 final IdentityMergeResponse response = new IdentityMergeResponse( );
193 final ServiceContract serviceContract = this.getActiveServiceContract( clientCode );
194 if ( !serviceContract.getAuthorizedMerge( ) )
195 {
196 response.setStatus( ResponseStatusFactory.failure( ).setMessage( "The client application is not authorized to merge identities" )
197 .setMessageKey( Constants.PROPERTY_REST_ERROR_MERGE_UNAUTHORIZED ) );
198 }
199
200 return response;
201 }
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217 public IdentityChangeResponse validateIdentityImport( final IdentityChangeRequest identityChangeRequest, final String clientCode )
218 throws ServiceContractNotFoundException, IdentityAttributeNotFoundException
219 {
220 final IdentityChangeResponse response = new IdentityChangeResponse( );
221 final ServiceContract serviceContract = this.getActiveServiceContract( clientCode );
222 if ( !serviceContract.getAuthorizedImport( ) )
223 {
224 response.setStatus( ResponseStatusFactory.failure( ).setMessage( "The client application is not authorized to import identities " )
225 .setMessageKey( Constants.PROPERTY_REST_ERROR_IMPORT_UNAUTHORIZED ) );
226 }
227 else
228 {
229 return this.validateIdentityChange( identityChangeRequest, clientCode );
230 }
231
232 return response;
233 }
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248 public IdentityExportResponse validateIdentityExport(final IdentityExportRequest identityExportRequest, final String clientCode ) throws ServiceContractNotFoundException
249 {
250 final ServiceContract serviceContract = this.getActiveServiceContract( clientCode );
251 final IdentityExportResponse response = new IdentityExportResponse( );
252 if ( !serviceContract.getAuthorizedExport( ) )
253 {
254 response.setStatus( ResponseStatusFactory.failure( ).setMessage( "The client application is not authorized to export identities." )
255 .setMessageKey( Constants.PROPERTY_REST_ERROR_EXPORT_UNAUTHORIZED ) );
256 return response;
257 }
258
259 if ( identityExportRequest.getAttributeKeyList( ) != null && !identityExportRequest.getAttributeKeyList( ).isEmpty( ) )
260 {
261
262 for ( final String searchAttributeKey : identityExportRequest.getAttributeKeyList( ) )
263 {
264 final Optional<AttributeRight> attributeRight = serviceContract.getAttributeRights( ).stream( )
265 .filter( a -> StringUtils.equals( a.getAttributeKey( ).getKeyName( ), searchAttributeKey ) ).findFirst( );
266 if ( attributeRight.isPresent( ) )
267 {
268 boolean canReadAttribute = attributeRight.get( ).isReadable( );
269
270 if ( !canReadAttribute )
271 {
272 response.setStatus( ResponseStatusFactory.failure( ).setMessageKey( Constants.PROPERTY_REST_ERROR_SERVICE_CONTRACT_VIOLATION ).setMessage( searchAttributeKey + " key is not readable in service contract definition." ) );
273 }
274 }
275 else
276 {
277 response.setStatus( ResponseStatusFactory.failure( ).setMessageKey( Constants.PROPERTY_REST_ERROR_SERVICE_CONTRACT_VIOLATION ).setMessage( searchAttributeKey + " key does not exist in service contract definition." ) );
278 }
279 }
280 }
281
282 return response;
283 }
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298 public IdentitySearchResponse validateIdentitySearch( final IdentitySearchRequest identitySearchRequest, final String clientCode,
299 final boolean checkContract ) throws ServiceContractNotFoundException
300 {
301 final ServiceContract serviceContract = this.getActiveServiceContract( clientCode );
302 final IdentitySearchResponse response = new IdentitySearchResponse( );
303 if ( checkContract && !serviceContract.getAuthorizedSearch( ) )
304 {
305 response.setStatus( ResponseStatusFactory.failure( ).setMessage( "The client application is not authorized to search an identity." )
306 .setMessageKey( Constants.PROPERTY_REST_ERROR_SEARCH_UNAUTHORIZED ) );
307 final IdentitySearchMessage message = new IdentitySearchMessage( );
308 message.setMessage( "The client application is not authorized to search an identity." );
309 response.getAlerts( ).add( message );
310 return response;
311 }
312
313 if ( identitySearchRequest.getSearch( ) != null )
314 {
315
316 for ( final SearchAttribute searchAttribute : identitySearchRequest.getSearch( ).getAttributes( ) )
317 {
318 final Optional<AttributeRight> attributeRight = serviceContract.getAttributeRights( ).stream( )
319 .filter( a -> StringUtils.equals( a.getAttributeKey( ).getKeyName( ), searchAttribute.getKey( ) ) ).findFirst( );
320 if ( attributeRight.isPresent( ) )
321 {
322 boolean canSearchAttribute = attributeRight.get( ).isSearchable( );
323
324 if ( !canSearchAttribute )
325 {
326 final IdentitySearchMessage alert = new IdentitySearchMessage( );
327 alert.setAttributeName( searchAttribute.getKey( ) );
328 alert.setMessage( "This attribute is not searchable in service contract definition." );
329 response.getAlerts( ).add( alert );
330 response.setStatus( ResponseStatusFactory.failure( ).setMessageKey( Constants.PROPERTY_REST_ERROR_SERVICE_CONTRACT_VIOLATION ) );
331 }
332 }
333 else
334 {
335 final List<AttributeRight> commonAttributes = serviceContract.getAttributeRights( ).stream( )
336 .filter( a -> StringUtils.equals( a.getAttributeKey( ).getCommonSearchKeyName( ), searchAttribute.getKey( ) ) )
337 .collect( Collectors.toList( ) );
338 if ( CollectionUtils.isNotEmpty( commonAttributes ) )
339 {
340 boolean canSearchAttribute = commonAttributes.stream( ).allMatch( a -> a.isSearchable( ) );
341 if ( !canSearchAttribute )
342 {
343 final IdentitySearchMessage alert = new IdentitySearchMessage( );
344 alert.setAttributeName( searchAttribute.getKey( ) );
345 alert.setMessage( "This attribute group is not searchable in service contract definition." );
346 response.getAlerts( ).add( alert );
347 response.setStatus( ResponseStatusFactory.failure( ).setMessageKey( Constants.PROPERTY_REST_ERROR_SERVICE_CONTRACT_VIOLATION ) );
348 }
349 }
350 else
351 {
352 final IdentitySearchMessage alert = new IdentitySearchMessage( );
353 alert.setAttributeName( searchAttribute.getKey( ) );
354 alert.setMessage( "This attribute does not exist in service contract definition." );
355 response.getAlerts( ).add( alert );
356 response.setStatus( ResponseStatusFactory.failure( ).setMessageKey( Constants.PROPERTY_REST_ERROR_SERVICE_CONTRACT_VIOLATION ) );
357 }
358 }
359 }
360 }
361
362 return response;
363 }
364
365 public List<String> getMandatoryAttributes( final String clientCode, final List<AttributeKey> sharedMandatoryAttributeList )
366 throws ServiceContractNotFoundException
367 {
368 final List<AttributeRight> rights = this.getActiveServiceContract( clientCode ).getAttributeRights( );
369 return Stream
370 .concat( sharedMandatoryAttributeList.stream( ).map( AttributeKey::getKeyName ),
371 rights.stream( ).filter( AttributeRight::isMandatory ).map( ar -> ar.getAttributeKey( ).getKeyName( ) ) )
372 .distinct( ).collect( Collectors.toList( ) );
373
374 }
375
376 public boolean canModifyConnectedIdentity( final String clientCode ) throws ServiceContractNotFoundException
377 {
378 final ServiceContract serviceContract = this.getActiveServiceContract( clientCode );
379 return serviceContract.getAuthorizedAccountUpdate( );
380 }
381
382 public boolean canCreateIdentity( final String clientCode ) throws ServiceContractNotFoundException
383 {
384 final ServiceContract serviceContract = this.getActiveServiceContract( clientCode );
385 return serviceContract.getAuthorizedCreation( );
386 }
387
388 public boolean canUpdateIdentity( final String clientCode ) throws ServiceContractNotFoundException
389 {
390 final ServiceContract serviceContract = this.getActiveServiceContract( clientCode );
391 return serviceContract.getAuthorizedUpdate( );
392 }
393
394 public boolean canUncertifyIdentity( final String clientCode ) throws ServiceContractNotFoundException
395 {
396 final ServiceContract serviceContract = this.getActiveServiceContract( clientCode );
397 return serviceContract.getAuthorizedDecertification( );
398 }
399
400 public boolean canDeleteIdentity( String clientCode ) throws ServiceContractNotFoundException
401 {
402 final ServiceContract serviceContract = this.getActiveServiceContract( clientCode );
403 return serviceContract.getAuthorizedDeletion( );
404 }
405
406 public int getDataRetentionPeriodInMonths( final String clientCode ) throws ServiceContractNotFoundException
407 {
408 final ServiceContract serviceContract = this.getActiveServiceContract( clientCode );
409 return serviceContract.getDataRetentionPeriodInMonths( );
410 }
411
412 private AttributeStatus buildAttributeStatus( final AttributeDto attributeDto, final AttributeChangeStatus status )
413 {
414 final AttributeStatus attributeStatus = new AttributeStatus( );
415 attributeStatus.setKey( attributeDto.getKey( ) );
416 attributeStatus.setStatus( status );
417 return attributeStatus;
418 }
419
420
421
422
423
424
425
426
427
428
429
430
431 public ServiceContractitystore/business/contract/ServiceContract.html#ServiceContract">ServiceContract create( final ServiceContract serviceContract, final Integer applicationId ) throws IdentityStoreException
432 {
433 TransactionManager.beginTransaction( null );
434 try
435 {
436 final ClientApplication clientApplication = ClientApplicationHome.findByPrimaryKey( applicationId );
437 this.validateContractDefinition( serviceContract, clientApplication );
438 ServiceContractHome.create( serviceContract, applicationId );
439 if ( CollectionUtils.isNotEmpty( serviceContract.getAttributeRights( ) ) )
440 {
441 ServiceContractHome.addAttributeRights( serviceContract.getAttributeRights( ), serviceContract );
442 }
443 if ( CollectionUtils.isNotEmpty( serviceContract.getAttributeRequirements( ) ) )
444 {
445 ServiceContractHome.addAttributeRequirements( serviceContract.getAttributeRequirements( ), serviceContract );
446 }
447 if ( CollectionUtils.isNotEmpty( serviceContract.getAttributeCertifications( ) ) )
448 {
449 ServiceContractHome.addAttributeCertifications( serviceContract.getAttributeCertifications( ), serviceContract );
450 }
451 serviceContract.setClientCode( clientApplication.getClientCode( ) );
452
453 if ( serviceContract.isActive( ) )
454 {
455 this._cache.put( clientApplication.getClientCode( ), serviceContract );
456 }
457 TransactionManager.commitTransaction( null );
458 }
459 catch( Exception e )
460 {
461 TransactionManager.rollBack( null );
462 throw new IdentityStoreException( e.getMessage( ), e );
463 }
464
465 return serviceContract;
466 }
467
468
469
470
471
472
473
474
475
476
477
478
479 public ServiceContractitystore/business/contract/ServiceContract.html#ServiceContract">ServiceContract update( final ServiceContract serviceContract, final Integer applicationId ) throws IdentityStoreException
480 {
481
482 TransactionManager.beginTransaction( null );
483 try
484 {
485 final ClientApplication clientApplication = ClientApplicationHome.findByPrimaryKey( applicationId );
486 this.validateContractDefinition( serviceContract, clientApplication );
487 ServiceContractHome.update( serviceContract, applicationId );
488 ServiceContractHome.removeAttributeRights( serviceContract );
489 ServiceContractHome.addAttributeRights( serviceContract.getAttributeRights( ), serviceContract );
490 ServiceContractHome.removeAttributeRequirements( serviceContract );
491 ServiceContractHome.addAttributeRequirements( serviceContract.getAttributeRequirements( ), serviceContract );
492 ServiceContractHome.removeAttributeCertifications( serviceContract );
493 ServiceContractHome.addAttributeCertifications( serviceContract.getAttributeCertifications( ), serviceContract );
494 serviceContract.setClientCode( clientApplication.getClientCode( ) );
495
496 if ( serviceContract.isActive( ) )
497 {
498 this._cache.deleteById( serviceContract.getId( ) );
499 this._cache.put( clientApplication.getClientCode( ), serviceContract );
500 }
501 TransactionManager.commitTransaction( null );
502 }
503 catch( Exception e )
504 {
505 TransactionManager.rollBack( null );
506 throw new IdentityStoreException( e.getMessage( ), e );
507 }
508 return serviceContract;
509 }
510
511
512
513
514
515
516
517 public ServiceContracttitystore/business/contract/ServiceContract.html#ServiceContract">ServiceContract close( final ServiceContract serviceContract ) throws IdentityStoreException
518 {
519
520 TransactionManager.beginTransaction( null );
521 try
522 {
523 ServiceContractHome.close( serviceContract );
524 TransactionManager.commitTransaction( null );
525 }
526 catch( Exception e )
527 {
528 TransactionManager.rollBack( null );
529 throw new IdentityStoreException( e.getMessage( ), e );
530 }
531 return serviceContract;
532 }
533
534
535
536
537
538
539 public void delete( final Integer id )
540 {
541 ServiceContractHome.remove( id );
542 _cache.deleteById( id );
543 }
544
545
546
547
548
549
550 public void deleteApplication( final ClientApplication clientApplication ) throws IdentityStoreException
551 {
552 TransactionManager.beginTransaction( null );
553 try
554 {
555 ClientApplicationHome.removeContracts( clientApplication );
556 ClientApplicationHome.remove( clientApplication );
557 _cache.removeKey( clientApplication.getClientCode( ) );
558 TransactionManager.commitTransaction( null );
559 }
560 catch( Exception e )
561 {
562 TransactionManager.rollBack( null );
563 throw new IdentityStoreException( e.getMessage( ), e );
564 }
565 }
566
567
568
569
570
571
572
573
574 private void validateContractDefinition( final ServiceContract serviceContract, final ClientApplication clientApplication )
575 throws ServiceContractDefinitionException
576 {
577 final List<ServiceContract> serviceContracts = ClientApplicationHome.selectServiceContracts( clientApplication );
578 if ( serviceContracts == null || serviceContracts.isEmpty( ) )
579 {
580 return;
581 }
582 if ( serviceContract.getStartingDate( ) == null )
583 {
584 throw new ServiceContractDefinitionException( "The start date of the contract shall be set" );
585 }
586
587 final List<ServiceContract> filteredServiceContracts = serviceContracts.stream( ).filter( c -> !Objects.equals( c.getId( ), serviceContract.getId( ) ) )
588 .collect( Collectors.toList( ) );
589 if ( filteredServiceContracts.stream( )
590 .anyMatch( contract -> isInRange( serviceContract.getStartingDate( ), contract.getStartingDate( ), contract.getEndingDate( ) ) ) )
591 {
592 throw new ServiceContractDefinitionException( "The start date of the contract is in the range of an existing service contract" );
593 }
594 if ( filteredServiceContracts.stream( )
595 .anyMatch( contract -> isInRange( serviceContract.getEndingDate( ), contract.getStartingDate( ), contract.getEndingDate( ) ) ) )
596 {
597 throw new ServiceContractDefinitionException( "The end date of the contract is in the range of an existing service contract" );
598 }
599
600 if ( filteredServiceContracts.stream( )
601 .anyMatch( contract -> contract.getEndingDate( ) == null && contract.getStartingDate( ).before( serviceContract.getStartingDate( ) ) ) )
602 {
603 throw new ServiceContractDefinitionException( "A contract exists with an infinite end date" );
604 }
605
606
607
608 final List<AttributeRequirement> filledRequirements = serviceContract.getAttributeRequirements( ).stream( )
609 .filter( requirement -> requirement.getRefCertificationLevel( ) != null && requirement.getRefCertificationLevel( ).getLevel( ) != null )
610 .collect( Collectors.toList( ) );
611 final StringBuilder message = new StringBuilder( );
612 boolean hasLevelError = false;
613 for ( final AttributeRequirement requirement : filledRequirements )
614 {
615 final Optional<AttributeCertification> result = serviceContract.getAttributeCertifications( ).stream( )
616 .filter( certification -> certification.getAttributeKey( ).getId( ) == requirement.getAttributeKey( ).getId( ) ).findFirst( );
617 if ( result.isPresent( ) )
618 {
619 final AttributeCertification attributeCertification = result.get( );
620 final int minLevel = Integer.parseInt( requirement.getRefCertificationLevel( ).getLevel( ) );
621 for ( final RefAttributeCertificationProcessus processus : attributeCertification.getRefAttributeCertificationProcessus( ) )
622 {
623 final int processLevel = AttributeCertificationDefinitionService.instance( ).getLevelAsInteger( processus.getCode( ),
624 attributeCertification.getAttributeKey( ).getKeyName( ) );
625 if ( processLevel < minLevel )
626 {
627 hasLevelError = true;
628 final String [ ] params = {
629 processus.getLabel( ), requirement.getAttributeKey( ).getName( ), String.valueOf( processLevel ), String.valueOf( minLevel )
630 };
631 message.append(
632 I18nService.getLocalizedString( "identitystore.message.error.servicecontract.processus.level", params, Locale.getDefault( ) ) );
633 message.append( "<br>" );
634 }
635 }
636 }
637 }
638 if ( hasLevelError )
639 {
640 throw new ServiceContractDefinitionException( message.toString( ) );
641 }
642 }
643
644 public boolean isInRange( final Date testedDate, final Date min, final Date max )
645 {
646 if ( testedDate != null && min != null && max != null )
647 {
648 return testedDate.getTime( ) >= min.getTime( ) && testedDate.getTime( ) <= max.getTime( );
649 }
650 return false;
651 }
652
653
654
655
656
657
658
659
660 public List<String> getClientCodesFromAppCode( String appCode )
661 {
662 final List<ClientApplication> clientApplicationList = ClientApplicationHome.findByApplicationCode( appCode );
663 return clientApplicationList.stream( ).map( ClientApplication::getClientCode ).collect( Collectors.toList( ) );
664 }
665
666 }