View Javadoc
1   /*
2    * Copyright (c) 2002-2023, 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  
35  package fr.paris.lutece.plugins.appointment.modules.ants.service;
36  
37  import java.io.IOException;
38  import java.util.Collections;
39  import java.util.HashMap;
40  import java.util.List;
41  import java.util.Map;
42  
43  import com.fasterxml.jackson.core.type.TypeReference;
44  import com.fasterxml.jackson.databind.ObjectMapper;
45  
46  import fr.paris.lutece.plugins.appointment.modules.ants.utils.HttpCallsUtils;
47  import fr.paris.lutece.plugins.appointment.modules.ants.web.PreDemandeStatusEnum;
48  import fr.paris.lutece.plugins.appointment.modules.ants.web.PredemandeResponse;
49  import fr.paris.lutece.portal.service.util.AppLogService;
50  import fr.paris.lutece.portal.service.util.AppPropertiesService;
51  import fr.paris.lutece.util.httpaccess.HttpAccess;
52  import fr.paris.lutece.util.httpaccess.HttpAccessException;
53  import fr.paris.lutece.util.url.UrlItem;
54  
55  /**
56   * This class provides methods for processing and validating predemande codes.
57   */
58  public class PreDemandeValidationService
59  {
60  
61      private static final String PROPERTY_ENDPOINT_STATUS = AppPropertiesService.getProperty( "ants.api.opt.get.status" );
62      private static final String PROPERTY_API_OPT_AUTH_TOKEN_KEY = AppPropertiesService.getProperty( "ants.auth.token" );
63      private static final String PROPERTY_API_OPT_AUTH_TOKEN_VALUE = AppPropertiesService.getProperty( "ants.api.opt.auth.token" );
64      private static final String PROPERTY_ID_APPLICATION_PARAMETER = AppPropertiesService.getProperty( "ants.ids_application.parameters" );
65  
66      // Timeout properties specific to the ANTS HTTP calls
67      private static final String PROPERTY_SOCKET_TIMEOUT = "ants.api.socketTimeout";
68      private static final String PROPERTY_CONNECTION_TIMEOUT = "ants.api.connectionTimeout";
69  
70      private PreDemandeValidationService( )
71      {
72      }
73  
74      /**
75       * Processes a list of predemande codes to check their status and appointments.
76       *
77       * @param codes
78       *            The list of predemande codes to process.
79       * @return True if all predemande codes are validated and have appointments; otherwise, false.
80       * @throws IOException
81       *             If there is an error while processing the predemande codes.
82       */
83      public static boolean checkPredemandeCodesValidationAndAppointments( List<String> codes ) throws IOException
84      {
85          Map<String, PredemandeResponse> responseMap = getPreDemandeStatusAndAppointments( codes );
86  
87          if ( responseMap.isEmpty( ) )
88          {
89              return false;
90          }
91  
92          for ( PredemandeResponse predemande : responseMap.values( ) )
93          {
94              List<PredemandeResponse.Appointment> appointments = predemande.getAppointments( );
95  
96              if ( !appointments.isEmpty( ) || !PreDemandeStatusEnum.VALIDATED.name( ).equalsIgnoreCase( predemande.getStatus( ) ) )
97              {
98                  return false;
99              }
100         }
101 
102         return true;
103     }
104 
105     /**
106      * Retrieves the pre-demande status and appointments from the API.
107      *
108      * @param codes
109      *            The list of predemande codes to retrieve.
110      * @return The JSON response from the API.
111      * @throws IOException
112      *             If there is an error while processing the predemande codes.
113      */
114     private static Map<String, PredemandeResponse> getPreDemandeStatusAndAppointments( List<String> codes ) throws IOException
115     {
116         UrlItem urlItem;
117         String apiUrl = null;
118 
119         if ( !codes.isEmpty( ) )
120         {
121             urlItem = new UrlItem( PROPERTY_ENDPOINT_STATUS + PROPERTY_ID_APPLICATION_PARAMETER + "=" + codes.get( 0 ) );
122             for ( int i = 1; i < codes.size( ); i++ )
123             {
124                 urlItem.addParameter( PROPERTY_ID_APPLICATION_PARAMETER, codes.get( i ) );
125             }
126 
127             apiUrl = urlItem.toString( );
128         }
129 
130         // Create a new HttpAccess object with specific timeout values, if any was set,
131         // otherwise the default configuration will be used
132         HttpAccess httpAccess = HttpCallsUtils.getHttpAccessTimeoutFromProperties( PROPERTY_SOCKET_TIMEOUT, PROPERTY_CONNECTION_TIMEOUT );
133 
134         Map<String, String> headers = new HashMap<>( );
135         headers.put( PROPERTY_API_OPT_AUTH_TOKEN_KEY, PROPERTY_API_OPT_AUTH_TOKEN_VALUE );
136 
137         try
138         {
139             String jsonResponse = httpAccess.doGet( apiUrl, null, null, headers );
140             ObjectMapper mapper = new ObjectMapper( );
141             TypeReference<HashMap<String, PredemandeResponse>> typeRef = new TypeReference<HashMap<String, PredemandeResponse>>( )
142             {
143             };
144             return mapper.readValue( jsonResponse, typeRef );
145         }
146         catch( HttpAccessException | IOException ex )
147         {
148             AppLogService.error( "Error calling API {}", apiUrl, ex );
149             return Collections.emptyMap( );
150         }
151     }
152 }