View Javadoc
1   /*
2    * Copyright (c) 2002-2020, 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.broadcastproxy.business.providers.dolist;
35  
36  import java.io.BufferedReader;
37  import java.io.IOException;
38  import java.io.InputStreamReader;
39  import java.util.ArrayList;
40  import java.util.HashMap;
41  import java.util.List;
42  import java.util.Map;
43  
44  import org.apache.commons.lang.StringUtils;
45  import org.apache.http.HttpResponse;
46  
47  import com.fasterxml.jackson.databind.JsonNode;
48  import com.fasterxml.jackson.databind.ObjectMapper;
49  
50  import fr.paris.lutece.portal.service.util.AppLogService;
51  import fr.paris.lutece.portal.service.util.AppPropertiesService;
52  import fr.paris.lutece.util.httpaccess.HttpAccess;
53  import fr.paris.lutece.util.httpaccess.HttpAccessException;
54  
55  public class DolistAPI
56  {
57  
58      // URLs
59      private static final String URL_BASE_API = AppPropertiesService.getProperty( "dolist.URL_PATH_BASE_API" );
60      private static final String URL_CONTACTS = AppPropertiesService.getProperty( "dolist.URL_PATH_CONTACTS" );
61      private static final String URL_SEARCH = AppPropertiesService.getProperty( "dolist.URL_PATH_SEARCH" );
62      private static final String URL_ACCOUNT_ID = AppPropertiesService.getProperty( "dolist.URL_PATH_ACCOUNT_ID" );
63      private static final String URL_SUBSRIPTIONS = AppPropertiesService.getProperty( "dolist.URL_PATH_SUBSRIPTIONS" );
64      private static final String URL_INTERESTS = AppPropertiesService.getProperty( "dolist.URL_PATH_INTERESTS" );
65      private static final String URL_CHANNEL = AppPropertiesService.getProperty( "dolist.URL_PATH_CHANNEL" );
66      private static final String URL_GROUP_INTERESTS = AppPropertiesService.getProperty( "dolist.URL_PATH_GROUP_INTERESTS" );
67      private static final String URL_OPERATION_MODE = AppPropertiesService.getProperty( "dolist.URL_PATH_OPERATION_MODE" );
68      private static final String URL_CONTACT_INTEREST_ORIGIN = AppPropertiesService.getProperty( "dolist.URL_PATH_CONTACT_INTEREST_ORIGIN" );
69      private static final String URL_INTERESTS_ACTIVE_ONLY = AppPropertiesService.getProperty( "dolist.URL_PATH_INTERESTS_ACTIVE_ONLY" );
70  
71      // Markers
72      private static final String MARK_HEADER_CONTENT_TYPE = AppPropertiesService.getProperty( "dolist.MARK_HEADER_CONTENT_TYPE" );
73      private static final String MARK_HEADER_ACCEPT = AppPropertiesService.getProperty( "dolist.MARK_HEADER_ACCEPT" );
74      private static final String MARK_HEADER_ACCEPT_LANGUAGE = AppPropertiesService.getProperty( "dolist.MARK_HEADER_ACCEPT_LANGUAGE" );
75      private static final String MARK_HEADER_X_API_KEY = AppPropertiesService.getProperty( "dolist.MARK_HEADER_X_API_KEY" );
76  
77      // Header constants
78      private static final String CONSTANTE_HEADER_CONTENT_TYPE = AppPropertiesService.getProperty( "dolist.CONSTANTE_HEADER_CONTENT_TYPE" );
79      private static final String CONSTANTE_HEADER_ACCEPT = AppPropertiesService.getProperty( "dolist.CONSTANTE_HEADER_ACCEPT" );
80      private static final String CONSTANTE_HEADER_ACCEPT_LANGUAGE = AppPropertiesService.getProperty( "dolist.CONSTANTE_HEADER_ACCEPT_LANGUAGE" );
81      private static final String CONSTANTE_HEADER_X_API_KEY = AppPropertiesService.getProperty( "dolist.CONSTANTE_HEADER_X_API_KEY" );
82  
83      // URL parameter's constants
84      private static final String CONSTANTE_ACCOUNT_ID = AppPropertiesService.getProperty( "dolist.CONSTANTE_ACCOUNT_ID" );
85      private static final String CONSTANTE_CHANNEL = AppPropertiesService.getProperty( "dolist.CONSTANTE_CHANNEL" );
86      private static final String CONSTANTE_EMAIL_FIELD_ID = AppPropertiesService.getProperty( "dolist.CONSTANTE_EMAIL_FIELD_ID" );
87      private static final String CONSTANTE_CONTACT_INTEREST_ORIGIN = AppPropertiesService.getProperty( "dolist.CONSTANTE_CONTACT_INTEREST_ORIGIN" );
88      private static final String CONSTANTE_INTERESTS_ACTIVE_ONLY = AppPropertiesService.getProperty( "dolist.CONSTANTE_INTERESTS_ACTIVE_ONLY" );
89  
90      private static final String CONSTANTE_REQUEST_BODY_CONTACT = AppPropertiesService.getProperty( "dolist.CONSTANTE_REQUEST_BODY_CONTACT" );
91      private static final String CONSTANTE_REQUEST_BODY_QUERY = AppPropertiesService.getProperty( "dolist.CONSTANTE_REQUEST_BODY_QUERY" );
92      private static final String CONSTANTE_REQUEST_BODY_SUBSCRIPTIONS_LIST = AppPropertiesService
93              .getProperty( "dolist.CONSTANTE_REQUEST_BODY_SUBSCRIPTIONS_LIST" );
94      private static final String CONSTANTE_REQUEST_BODY_INTERESTS_LIST = AppPropertiesService.getProperty( "dolist.CONSTANTE_REQUEST_BODY_INTERESTS_LIST" );
95  
96      // Other constants
97      private static final String JSON_NODE_ITEMLIST = AppPropertiesService.getProperty( "dolist.jsonNode.ItemList" );
98      private static final String JSON_NODE_USER_ID = AppPropertiesService.getProperty( "dolist.jsonNode.user.ID" );
99      private static final String JSON_NODE_SEARCH_VALUE = AppPropertiesService.getProperty( "dolist.jsonNode.SearchValue" );
100     private static final String JSON_NODE_SEARCH_FIELD_ID_LIST = AppPropertiesService.getProperty( "dolist.jsonNode.SearchFieldIDList" );
101     private static final String JSON_NODE_FIELD_LIST = AppPropertiesService.getProperty( "dolist.jsonNode.FieldList" );
102 
103     // Instance variables
104     private String _userEmail;
105     private String _contactId;
106 
107     /**
108      * get ContactID
109      * 
110      * @param userEmail
111      * @return Dolist contact id
112      */
113     public String getDolistContactId( String userEmail )
114     {
115         if ( userEmail == null )
116             return null;
117 
118         if ( userEmail.equals( _userEmail ) )
119             return _contactId;
120 
121         ObjectMapper mapper = new ObjectMapper( );
122         Map<String, Object> queryParams = new HashMap<>( );
123         List<Integer> listFieldId = new ArrayList<>( );
124         String strResponse = null;
125         String strContactId = "";
126 
127         String strUrl = URL_BASE_API + URL_CONTACTS + URL_SEARCH + "?" + URL_ACCOUNT_ID + "=" + CONSTANTE_ACCOUNT_ID;
128 
129         try
130         {
131             // Set Headers
132             Map<String, String> mapHeaders = constructHeader( );
133 
134             // Set request parameters
135             listFieldId.add( Integer.parseInt( CONSTANTE_EMAIL_FIELD_ID ) );
136             queryParams.put( JSON_NODE_SEARCH_VALUE, userEmail );
137             queryParams.put( JSON_NODE_SEARCH_FIELD_ID_LIST, listFieldId );
138 
139             String strParamsInJson = "{ \"" + CONSTANTE_REQUEST_BODY_QUERY + "\":" + mapper.writeValueAsString( queryParams ) + "}";
140 
141             // Call Dolist API
142             strResponse = callDoPost( strUrl, strParamsInJson, mapHeaders );
143 
144             // Get ContactId from response
145             JsonNode nodes = mapper.readTree( strResponse );
146 
147             if ( Integer.parseInt( nodes.get( "Count" ).asText( ) ) == 1 )
148             {
149                 strContactId = nodes.get( JSON_NODE_ITEMLIST ).findValue( JSON_NODE_USER_ID ).asText( );
150 
151                 // set instance variables
152                 _userEmail = userEmail;
153                 _contactId = strContactId;
154             }
155             else
156                 if ( Integer.parseInt( nodes.get( "Count" ).asText( ) ) != 0 ) // There is some accounts with the same email
157                 {
158                     return null;
159                 }
160 
161         }
162         catch( IOException | HttpAccessException e )
163         {
164             String strError = "Error occured while getting Contact ID from '" + strUrl + "' : ";
165             AppLogService.error( strError + e.getMessage( ), e );
166             return null;
167         }
168 
169         return strContactId;
170     }
171 
172     /**
173      * ADD user
174      * 
175      * @param eMail
176      * @throws IOException
177      */
178     public String addUser( String userEmail ) throws IOException
179     {
180         ObjectMapper mapper = new ObjectMapper( );
181         Map<String, String> param = new HashMap<>( );
182         List<Map<String, String>> paramsList = new ArrayList<Map<String, String>>( );
183         String strResponse = null;
184         String strContactId = "";
185 
186         // Set URL
187         String strUrl = URL_BASE_API + URL_CONTACTS + "?" + URL_ACCOUNT_ID + "=" + CONSTANTE_ACCOUNT_ID;
188 
189         try
190         {
191             // Set Headers
192             Map<String, String> mapHeaders = constructHeader( );
193 
194             param.put( "ID", CONSTANTE_EMAIL_FIELD_ID );
195             param.put( "Value", userEmail );
196 
197             paramsList.add( param );
198 
199             String strParamsInJson = "{ \"" + CONSTANTE_REQUEST_BODY_CONTACT + "\":{\"" + JSON_NODE_FIELD_LIST + "\":" + mapper.writeValueAsString( paramsList )
200                     + "}}";
201 
202             // Call Dolist API
203             strResponse = callDoPost( strUrl, strParamsInJson, mapHeaders );
204 
205             // Get ContactId from response
206             JsonNode nodes = mapper.readTree( strResponse );
207 
208             strContactId = nodes.get( JSON_NODE_USER_ID ).asText( );
209         }
210         catch( IOException | HttpAccessException e )
211         {
212             String strError = "Error occured while add/delete user. '" + strUrl + "' : ";
213             AppLogService.error( strError + e.getMessage( ), e );
214             return null;
215         }
216 
217         // set instance variables
218         _userEmail = userEmail;
219         _contactId = strContactId;
220 
221         return strContactId;
222     }
223 
224     /**
225      * get subscriptions Names (label)
226      * 
227      * @param typeSubscription
228      * @return json
229      */
230     public String getAllSubscriptions( String typeSubscription )
231     {
232         String strResponse = StringUtils.EMPTY;
233         String strUrl = StringUtils.EMPTY;
234 
235         try
236         {
237             if ( typeSubscription.equals( DolistConstants.TYPE_SUBSCRIPTION ) )
238             {
239                 // Get dolist newsletters ids and names (Dolist subscriptions)
240                 strUrl = URL_BASE_API + URL_SUBSRIPTIONS + "?" + URL_CHANNEL + "=" + CONSTANTE_CHANNEL + "&" + URL_ACCOUNT_ID + "=" + CONSTANTE_ACCOUNT_ID;
241             }
242             else
243                 if ( typeSubscription.equals( DolistConstants.TYPE_INTEREST ) )
244                 {
245                     // Get dolist alerts ids and names (Dolist interests)
246                     strUrl = URL_BASE_API + URL_INTERESTS + URL_GROUP_INTERESTS + "?" + URL_ACCOUNT_ID + "=" + CONSTANTE_ACCOUNT_ID + "&"
247                             + URL_INTERESTS_ACTIVE_ONLY + "=" + CONSTANTE_INTERESTS_ACTIVE_ONLY;
248                 }
249 
250             Map<String, String> mapHeaders = constructHeader( );
251 
252             strResponse = callDoGet( strUrl, mapHeaders );
253         }
254         catch( IOException e )
255         {
256             String strError = "Error occured while getting the list of subscriptions names '" + strUrl + "' : ";
257             AppLogService.error( strError + e.getMessage( ), e );
258         }
259 
260         return strResponse;
261     }
262 
263     /**
264      * get Contact's subscriptions
265      * 
266      * @param userEmail
267      * @return json
268      */
269     public String getUserSubscriptions( String userEmail, String typeSubscription )
270     {
271         String strResponse = StringUtils.EMPTY;
272         String strUrl = StringUtils.EMPTY;
273 
274         // Get contact ID
275         String idContact = getDolistContactId( userEmail );
276 
277         try
278         {
279             if ( typeSubscription.equals( DolistConstants.TYPE_SUBSCRIPTION ) )
280             {
281                 // Get user newsletters (Dolist subscriptions)
282                 strUrl = URL_BASE_API + URL_CONTACTS + "/" + idContact + URL_SUBSRIPTIONS + "?" + URL_ACCOUNT_ID + "=" + CONSTANTE_ACCOUNT_ID + "&"
283                         + URL_CHANNEL + "=" + CONSTANTE_CHANNEL;
284             }
285             else
286                 if ( typeSubscription.equals( DolistConstants.TYPE_INTEREST ) )
287                 {
288                     // Get user alerts (Dolist interests)
289                     strUrl = URL_BASE_API + URL_CONTACTS + "/" + idContact + URL_INTERESTS + "?" + URL_ACCOUNT_ID + "=" + CONSTANTE_ACCOUNT_ID;
290                 }
291 
292             Map<String, String> mapHeaders = constructHeader( );
293 
294             strResponse = callDoGet( strUrl, mapHeaders );
295 
296         }
297         catch( IOException e )
298         {
299             String strError = "Error occured while getting Contact subscriptions list from '" + strUrl + "' : ";
300             AppLogService.error( strError + e.getMessage( ), e );
301         }
302 
303         return strResponse;
304     }
305 
306     /**
307      * update subscriptions
308      * 
309      * @param ContactName
310      * @param mapSubscriptions
311      * @param typeSubscription
312      * @return response
313      * @throws Exception
314      */
315     public String updateSubscribtions( String userEmail, Map<String, String> subscriptionsToUpdate ) throws Exception
316     {
317         ObjectMapper mapper = new ObjectMapper( );
318         List<Map<String, Object>> listModifiedSubscriptions = new ArrayList<>( );
319 
320         // Get dolist contact ID
321         String userDolistId = getDolistContactId( userEmail );
322 
323         // if Email (user) does not exist ==> Create user
324         if ( userDolistId.equals( "" ) )
325             userDolistId = addUser( userEmail );
326 
327         // Set Headers
328         Map<String, String> mapHeaders = constructHeader( );
329 
330         // Update Dolist Subscriptions
331         String strUrl = URL_BASE_API + URL_CONTACTS + "/" + userDolistId + URL_SUBSRIPTIONS + "?" + URL_ACCOUNT_ID + "=" + CONSTANTE_ACCOUNT_ID;
332 
333         // Set request parameters
334         for ( Map.Entry<String, String> subStatus : subscriptionsToUpdate.entrySet( ) )
335         {
336             Map<String, Object> sub = new HashMap<>( );
337             sub.put( "SubscriptionID", Integer.parseInt( subStatus.getKey( ) ) );
338             sub.put( "Status", subStatus.getValue( ) );
339             listModifiedSubscriptions.add( sub );
340         }
341 
342         String strParamsInJson = "{ \"" + CONSTANTE_REQUEST_BODY_SUBSCRIPTIONS_LIST + "\":" + mapper.writeValueAsString( listModifiedSubscriptions ) + "}";
343 
344         // Call http method (PUT)
345         String response = callDoPut( strUrl, strParamsInJson, mapHeaders );
346 
347         return response;
348     }
349 
350     public String updateInterests( String userEmail, List<Integer> subscriptionsToUpdate, String action ) throws Exception
351     {
352         ObjectMapper mapper = new ObjectMapper( );
353         String response = StringUtils.EMPTY;
354 
355         // Get dolist contact ID
356         String userDolistId = getDolistContactId( userEmail );
357 
358         // if Email (user) does not exist ==> Create user
359         if ( userDolistId.equals( "" ) )
360             userDolistId = addUser( userEmail );
361 
362         // Set Headers
363         Map<String, String> mapHeaders = constructHeader( );
364 
365         String strUrl = URL_BASE_API + URL_CONTACTS + "/" + userDolistId + URL_INTERESTS + "?" + URL_CONTACT_INTEREST_ORIGIN + "="
366                 + CONSTANTE_CONTACT_INTEREST_ORIGIN + "&" + URL_OPERATION_MODE + "=" + action + "&" + URL_ACCOUNT_ID + "=" + CONSTANTE_ACCOUNT_ID;
367 
368         try
369         {
370             // Update Dolist Interests
371             String strParamsInJson = "{\"" + CONSTANTE_REQUEST_BODY_INTERESTS_LIST + "\":" + mapper.writeValueAsString( subscriptionsToUpdate ) + "}";
372 
373             // Call http method (PUT)
374             response = callDoPut( strUrl, strParamsInJson, mapHeaders );
375 
376         }
377         catch( IOException e )
378         {
379             String strError = "Error connecting to '" + strUrl + "' : ";
380             AppLogService.error( strError + e.getMessage( ), e );
381             return null;
382         }
383 
384         return response;
385     }
386 
387     /*** HTTP METHODS ***/
388 
389     /**
390      * call get method
391      * 
392      * @param strUrl
393      * @param mapHeaders
394      * @param typeSubscription
395      * @return the response message
396      * @throws IOException
397      */
398     private String callDoGet( String strUrl, Map<String, String> mapHeaders ) throws IOException
399     {
400         HttpAccess httpAccess = new HttpAccess( );
401 
402         String strResponse = StringUtils.EMPTY;
403 
404         try
405         {
406             strResponse = httpAccess.doGet( strUrl, null, null, mapHeaders );
407         }
408         catch( HttpAccessException e )
409         {
410             AppLogService.error( "Returned Dolist error : " + strResponse );
411         }
412 
413         return strResponse;
414     }
415 
416     /**
417      * call post method
418      * 
419      * @param strUrl
420      * @param params
421      * @param mapHeaders
422      * @return true or false
423      * @throws IOException
424      * @throws HttpAccessException
425      */
426     private String callDoPost( String strUrl, String jsonParams, Map<String, String> mapHeaders ) throws IOException, HttpAccessException
427     {
428         HttpResponse httpResponse;
429         DolistHttpAccesstproxy/business/providers/dolist/DolistHttpAccess.html#DolistHttpAccess">DolistHttpAccess dlhttpaccess = new DolistHttpAccess( );
430 
431         httpResponse = dlhttpaccess.doPost( strUrl, jsonParams, mapHeaders );
432 
433         // Get response in String
434         String strResponse = httpToStrResponse( httpResponse );
435 
436         // If error
437         if ( httpResponse != null && httpResponse.getStatusLine( ).getStatusCode( ) != 200 )
438         {
439             AppLogService.error( "Returned Dolist error : " + strResponse );
440         }
441 
442         return strResponse;
443     }
444 
445     /**
446      * call post method
447      * 
448      * @param strUrl
449      * @param params
450      * @param mapHeaders
451      * @return true or false
452      * @throws IOException
453      * @throws HttpAccessException
454      */
455     private String callDoPut( String strUrl, String jsonParams, Map<String, String> mapHeaders ) throws IOException, HttpAccessException
456     {
457 
458         HttpResponse httpResponse;
459         DolistHttpAccesstproxy/business/providers/dolist/DolistHttpAccess.html#DolistHttpAccess">DolistHttpAccess dlhttpaccess = new DolistHttpAccess( );
460 
461         httpResponse = dlhttpaccess.doPut( strUrl, jsonParams, mapHeaders );
462 
463         // Get response in String
464         String strResponse = httpToStrResponse( httpResponse );
465 
466         // If error
467         if ( httpResponse != null && httpResponse.getStatusLine( ).getStatusCode( ) != 200 )
468         {
469             AppLogService.error( "Returned Dolist error : " + strResponse );
470         }
471 
472         return strResponse;
473     }
474 
475     private Map<String, String> constructHeader( )
476     {
477         Map<String, String> mapHeader = new HashMap<>( );
478 
479         mapHeader.put( MARK_HEADER_X_API_KEY, CONSTANTE_HEADER_X_API_KEY );
480         mapHeader.put( MARK_HEADER_CONTENT_TYPE, CONSTANTE_HEADER_CONTENT_TYPE );
481         mapHeader.put( MARK_HEADER_ACCEPT, CONSTANTE_HEADER_ACCEPT );
482         mapHeader.put( MARK_HEADER_ACCEPT_LANGUAGE, CONSTANTE_HEADER_ACCEPT_LANGUAGE );
483 
484         return mapHeader;
485     }
486 
487     /**
488      * Stringify httpResponse
489      * 
490      * @param httpResponse
491      * @return the response as string
492      * @throws IOException
493      */
494     private String httpToStrResponse( HttpResponse httpResponse ) throws IOException
495     {
496         StringBuilder strResponse = new StringBuilder( );
497 
498         // Get response data in string
499         if ( httpResponse != null && httpResponse.getEntity( ) != null && httpResponse.getEntity( ).getContent( ) != null )
500         {
501             BufferedReader bufferedreader = new BufferedReader( new InputStreamReader( httpResponse.getEntity( ).getContent( ) ) );
502             String line = "";
503             while ( ( line = bufferedreader.readLine( ) ) != null )
504             {
505                 strResponse.append( line );
506             }
507         }
508 
509         return strResponse.toString( );
510     }
511 
512 }