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.service.indexer.search;
35  
36  import fr.paris.lutece.plugins.identitystore.business.identity.Identity;
37  import fr.paris.lutece.plugins.identitystore.business.identity.IdentityHome;
38  import fr.paris.lutece.plugins.identitystore.service.contract.AttributeCertificationDefinitionService;
39  import fr.paris.lutece.plugins.identitystore.service.indexer.elastic.index.model.AttributeObject;
40  import fr.paris.lutece.plugins.identitystore.service.indexer.elastic.index.model.IdentityObject;
41  import fr.paris.lutece.plugins.identitystore.service.indexer.elastic.search.model.inner.response.Response;
42  import fr.paris.lutece.plugins.identitystore.service.indexer.elastic.search.service.IIdentitySearcher;
43  import fr.paris.lutece.plugins.identitystore.service.search.ISearchIdentityService;
44  import fr.paris.lutece.plugins.identitystore.v3.web.rs.DtoConverter;
45  import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.common.AttributeDto;
46  import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.common.ConsolidateDefinition;
47  import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.common.ExpirationDefinition;
48  import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.common.IdentityDto;
49  import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.common.MergeDefinition;
50  import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.search.QualifiedIdentitySearchResult;
51  import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.search.SearchAttribute;
52  import fr.paris.lutece.plugins.identitystore.web.exception.IdentityStoreException;
53  
54  import java.util.ArrayList;
55  import java.util.List;
56  import java.util.Map;
57  import java.util.stream.Collectors;
58  
59  public class ElasticSearchIdentityService implements ISearchIdentityService
60  {
61      private final IIdentitySearcher _identitySearcher;
62  
63      /**
64       * private constructor
65       */
66      private ElasticSearchIdentityService( IIdentitySearcher _identitySearcher )
67      {
68          this._identitySearcher = _identitySearcher;
69      }
70  
71      /**
72       * {@inheritDoc }
73       */
74      @Override
75      public QualifiedIdentitySearchResult getQualifiedIdentities( final List<SearchAttribute> attributes,
76              final List<List<SearchAttribute>> specialTreatmentAttributes, final Integer nbEqualAttributes, final Integer nbMissingAttributes, final int max,
77              final boolean connected, final List<String> attributesFilter ) throws IdentityStoreException
78      {
79          final List<SearchAttribute> searchAttributes = this.computeOutputKeys( attributes );
80          final List<List<SearchAttribute>> specialAttributes = specialTreatmentAttributes == null ? null
81                  : specialTreatmentAttributes.stream( ).map( this::computeOutputKeys ).collect( Collectors.toList( ) );
82  
83          final Response search = _identitySearcher.multiSearch( searchAttributes, specialAttributes, nbEqualAttributes, nbMissingAttributes, max, connected,
84                  attributesFilter );
85  
86          return new QualifiedIdentitySearchResult( this.getEntities( search ), search.getMetadata( ) );
87      }
88  
89      @Override
90      public QualifiedIdentitySearchResult getQualifiedIdentities( List<SearchAttribute> attributes, int max, boolean connected,
91              final List<String> attributesFilter ) throws IdentityStoreException
92      {
93          final List<SearchAttribute> searchAttributes = this.computeOutputKeys( attributes );
94  
95          final Response search = _identitySearcher.search( searchAttributes, max, connected, attributesFilter );
96  
97          return new QualifiedIdentitySearchResult( this.getEntities( search ), search.getMetadata( ) );
98      }
99  
100     @Override
101     public QualifiedIdentitySearchResult getQualifiedIdentities( String customerId, final List<String> attributesFilter ) throws IdentityStoreException
102     {
103         final Response search = _identitySearcher.search( customerId, attributesFilter );
104 
105         return new QualifiedIdentitySearchResult( this.getEntities( search ), search.getMetadata( ) );
106     }
107 
108     @Override
109     public QualifiedIdentitySearchResult getQualifiedIdentitiesByConnectionId( String connectionId, List<String> attributesFilter ) throws IdentityStoreException
110     {
111         final Response search = _identitySearcher.searchByConnectionId( connectionId, attributesFilter );
112 
113         return new QualifiedIdentitySearchResult( this.getEntities( search ), search.getMetadata( ) );
114     }
115 
116     @Override
117     public QualifiedIdentitySearchResult getQualifiedIdentities( List<String> customerIds, final List<String> attributesFilter ) throws IdentityStoreException
118     {
119         final Response search = _identitySearcher.search( customerIds, attributesFilter );
120 
121         return new QualifiedIdentitySearchResult( this.getEntities( search ), search.getMetadata( ) );
122     }
123 
124     private List<IdentityDto> getEntities( Response search )
125     {
126         final List<IdentityDto> identities = new ArrayList<>( );
127 
128         if ( search != null )
129         {
130             search.getResult( ).getHits( ).forEach( hit -> {
131                 identities.add( this.toQualifiedIdentity( hit.getSource( ) ) );
132             } );
133         }
134         return identities;
135     }
136 
137     private IdentityDto toQualifiedIdentity( final IdentityObject identityObject )
138     {
139         final IdentityDto identity = new IdentityDto( );
140         identity.setConnectionId( identityObject.getConnectionId( ) );
141         identity.setCustomerId( identityObject.getCustomerId( ) );
142         identity.setCreationDate( identityObject.getCreationDate( ) );
143         identity.setLastUpdateDate( identityObject.getLastUpdateDate( ) );
144         if( identityObject.getExpirationDate( ) != null )
145         {
146             identity.setExpiration( new ExpirationDefinition());
147             identity.getExpiration().setExpirationDate(identityObject.getExpirationDate());
148             identity.getExpiration().setDeleted(false);
149             identity.getExpiration().setDeleteDate(null);
150         }
151         Identity identityDetails = IdentityHome.findByCustomerId( identity.getCustomerId( ) );
152         if( identityDetails != null && identityDetails.isMerged( ) ) {
153             identity.setMerge( new MergeDefinition( ) );
154             identity.getMerge().setMasterCustomerId( identityDetails.getMasterIdentityId().toString( ) );
155             identity.getMerge().setMerged( true );
156             identity.getMerge().setMergeDate( identityDetails.getMergeDate( ));
157         }
158         List<Identity> mergedIdentities = IdentityHome.findMergedIdentities(identityDetails.getId());
159         if( mergedIdentities != null && !mergedIdentities.isEmpty() )
160         {
161             identity.setConsolidate(new ConsolidateDefinition());
162             List<IdentityDto> mergedIdentitiesDto = new ArrayList<>( );
163             for (Identity megedIdentity : mergedIdentities)
164             {
165                 mergedIdentitiesDto.add(DtoConverter.convertIdentityToDto( megedIdentity ));
166             }
167             identity.getConsolidate().setMergedIdentities(mergedIdentitiesDto);
168         }
169         identity.setMonParisActive( identityObject.isMonParisActive( ) );
170         for ( final Map.Entry<String, AttributeObject> entry : identityObject.getAttributes( ).entrySet( ) )
171         {
172             final String s = entry.getKey( );
173             AttributeObject attributeObject = entry.getValue( );
174             final AttributeDto attribute = new AttributeDto( );
175             attribute.setKey( s );
176             attribute.setValue( attributeObject.getValue( ) );
177             attribute.setType( attributeObject.getType( ) );
178             attribute.setCertifier( attributeObject.getCertifierCode( ) );
179             attribute.setCertificationDate( attributeObject.getCertificateDate( ) );
180             attribute.setCertificationLevel( AttributeCertificationDefinitionService.instance( ).getLevelAsInteger( attribute.getCertifier( ), s ) );
181             identity.getAttributes( ).add( attribute );
182         }
183         return identity;
184     }
185 }