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  package fr.paris.lutece.plugins.broadcastproxy.business.providers.dolist;
35  
36  import java.util.ArrayList;
37  import java.util.HashMap;
38  import java.util.List;
39  import java.util.Map;
40  import java.util.Optional;
41  import java.util.TreeMap;
42  
43  import org.apache.commons.lang3.StringUtils;
44  import org.json.simple.JSONObject;
45  
46  import com.fasterxml.jackson.databind.JsonNode;
47  import com.fasterxml.jackson.databind.ObjectMapper;
48  
49  import fr.paris.lutece.plugins.broadcastproxy.business.Feed;
50  import fr.paris.lutece.plugins.broadcastproxy.business.IBroadcastProvider;
51  import fr.paris.lutece.plugins.broadcastproxy.business.Subscription;
52  import fr.paris.lutece.plugins.broadcastproxy.business.SubscriptionLink;
53  import fr.paris.lutece.plugins.broadcastproxy.business.SubscriptionLinkHome;
54  import fr.paris.lutece.portal.service.util.AppLogService;
55  import fr.paris.lutece.portal.service.util.AppPropertiesService;
56  
57  public class DolistProvider implements IBroadcastProvider
58  {
59      // Constants
60      private static final String PROVIDER_NAME = "Dolist";
61  
62      private static final String JSON_NODE_ITEMLIST = AppPropertiesService.getProperty( "dolist.jsonNode.ItemList" );
63      private static final String JSON_NODE_ITEM_INTERESTLIST = AppPropertiesService.getProperty( "dolist.jsonNode.item.InterestList" );
64      private static final String JSON_NODE_ITEM_GROUP = AppPropertiesService.getProperty( "dolist.jsonNode.item.Group" );
65      private static final String JSON_NODE_SUB_ID = AppPropertiesService.getProperty( "dolist.jsonNode.sub.SubscriptionID" );
66      private static final String JSON_NODE_INTEREST_NAME = AppPropertiesService.getProperty( "dolist.jsonNode.interest.Name" );
67      private static final String JSON_NODE_INTEREST_IS_ACTIVE = AppPropertiesService.getProperty( "dolist.jsonNode.interest.isActive" );
68      private static final String JSON_NODE_GROUP_NAME = AppPropertiesService.getProperty( "dolist.jsonNode.group.Name" );
69      private static final String JSON_NODE_SUB_NAME = AppPropertiesService.getProperty( "dolist.jsonNode.sub.Name" );
70      private static final String JSON_NODE_SUB_SUBSCRIBED = AppPropertiesService.getProperty( "dolist.jsonNode.sub.Subscribed" );
71      private static final String JSON_NODE_SUB_UNSUBSCRIBED = AppPropertiesService.getProperty( "dolist.jsonNode.sub.Unsubscribed" );
72  
73      private static final String CONSTANT_OPERATION_MODE_ADD = AppPropertiesService.getProperty( "dolist.CONSTANTE_OPERATION_MODE_ADD" );
74      private static final String CONSTANT_OPERATION_MODE_DELETE = AppPropertiesService.getProperty( "dolist.CONSTANTE_OPERATION_MODE_DELETE" );
75  
76      // instance variables
77      private DolistAPI _dolistAPI;
78  
79      private TreeMap<Integer, String> _groupViewRang = new TreeMap<>( );
80      private Map<String, String> _groupsMapIdName = new HashMap<>( );
81      private Map<String, String> _interestsMapIdName = new HashMap<>( );
82      private Map<String, String> _subscriptionsMapIdName = new HashMap<>( );
83      
84      /**
85       * Constructor
86       * 
87       * @throws Exception
88       */
89      private DolistProvider( ) throws Exception
90      {
91          _dolistAPI = new DolistAPI( );
92      }
93  
94      @Override
95      public String getName( )
96      {
97          return PROVIDER_NAME;
98      }
99  
100     @Override
101     public boolean updateSubscribtions( String userId, List<Subscription> subscriptionsList ) throws Exception
102     {
103         return false;
104     }
105 
106     @Override
107     public boolean updateSubscribtions( String userId, String jsonSubscriptions, String strAccountId ) throws Exception
108     {
109         Map<String, String> subscriptionStatus = new HashMap<>( );
110         List<Integer> interestsToAdd = new ArrayList<>( );
111         List<Integer> interestsToDelete = new ArrayList<>( );
112         try
113         {
114             Map<Integer, Boolean> subscriptionsToUpdate = getUserSubscribtionsToUpdate( jsonSubscriptions );
115 
116             for ( Map.Entry<Integer, Boolean> sub : subscriptionsToUpdate.entrySet( ) )
117             {
118                 Optional<SubscriptionLink> subscriptionLink = SubscriptionLinkHome.findBySubscriptionId( sub.getKey( ) );
119                 if(  subscriptionLink.isPresent( ) )
120                 {
121                     if ( sub.getValue( ) )
122                     {
123                         subscriptionStatus.put( String.valueOf( sub.getKey( ) ), JSON_NODE_SUB_SUBSCRIBED );
124                         if( subscriptionLink.get( ).getInterestId( ) > 0)
125                         {
126                             interestsToAdd.add( subscriptionLink.get( ).getInterestId( ) );
127                         }
128                     }
129                     else
130                     {
131                         subscriptionStatus.put( String.valueOf( sub.getKey( ) ), JSON_NODE_SUB_UNSUBSCRIBED );
132                         if( subscriptionLink.get( ).getInterestId( ) > 0)
133                         {
134                             interestsToDelete.add( subscriptionLink.get( ).getInterestId( ) );
135                         }
136                     }
137                 }
138             }
139 
140             updateSubAndInterests( userId, strAccountId, subscriptionStatus, interestsToAdd, interestsToDelete );
141 
142         }
143         catch( Exception e )
144         {
145             AppLogService.error( "An error occured while updating subscriptions : " + e.getMessage( ) );
146             return false;
147         }
148 
149         return true;
150     }
151     
152     @Override
153     public boolean updateArrondissementSubscribtions( String userId, String jsonSubscriptions, String strAccountId ) throws Exception
154     {
155         Map<String, String> subscriptionStatus = new HashMap<>( );
156         List<Integer> interestsToAdd = new ArrayList<>( );
157         List<Integer> interestsToDelete = new ArrayList<>( );
158         initMapIdNameArrondissement( strAccountId );
159         
160         try
161         {
162             Map<Integer, Boolean> subscriptionsToUpdate = getUserSubscribtionsToUpdate( jsonSubscriptions );
163 
164             for ( Map.Entry<Integer, Boolean> sub : subscriptionsToUpdate.entrySet( ) )
165             {
166                 for( Map.Entry<String, String>  subscription: _subscriptionsMapIdName.entrySet( ) )
167                 {
168                     subscriptionStatus.put( subscription.getKey( ), sub.getValue( ) ? JSON_NODE_SUB_SUBSCRIBED : JSON_NODE_SUB_UNSUBSCRIBED);
169                 }  
170                 for( Map.Entry<String, String>  interest: _interestsMapIdName.entrySet( ) )
171                 {
172                     if ( sub.getValue( ) )
173                     {
174                         interestsToAdd.add( Integer.parseInt( interest.getKey( ) ) );
175                     }
176                     else
177                     {
178                         interestsToDelete.add( Integer.parseInt( interest.getKey( ) ) );
179                     }
180                 }
181             }
182             
183             updateSubAndInterests( userId, strAccountId, subscriptionStatus, interestsToAdd, interestsToDelete );
184 
185         }
186         catch( Exception e )
187         {
188             AppLogService.error( "An error occured while updating subscriptions : " + e.getMessage( ) );
189             return false;
190         }
191 
192         return true;
193     }
194     
195     private void updateSubAndInterests( String userId, String strAccountId, Map<String, String> subscriptionStatus, List<Integer> interestsToAdd, List<Integer> interestsToDelete ) throws Exception
196     {
197         // update dolist subscriptions
198         _dolistAPI.updateSubscribtions( userId, subscriptionStatus, strAccountId );
199 
200         // Update Dolist Interests
201         if ( !interestsToAdd.isEmpty( ) )
202         {
203             _dolistAPI.updateInterests( userId, interestsToAdd, CONSTANT_OPERATION_MODE_ADD, strAccountId );
204         }
205 
206         if ( !interestsToDelete.isEmpty( ) )
207         {
208             _dolistAPI.updateInterests( userId, interestsToDelete, CONSTANT_OPERATION_MODE_DELETE, strAccountId );
209         }
210     }
211 
212 
213     @Override
214     public boolean update( Subscription sub, String strAccountId ) throws Exception
215     {
216         Map<String, String> subscriptionStatus = new HashMap<String, String>( );
217         initMapIdName( strAccountId );
218         if ( sub.isActive( ) )
219         {
220             subscriptionStatus.put( getSubscriptionDolistId( sub.getName( ), _interestsMapIdName ), JSON_NODE_SUB_SUBSCRIBED );
221         }
222         else
223         {
224             subscriptionStatus.put( getSubscriptionDolistId( sub.getName( ), _interestsMapIdName ), JSON_NODE_SUB_UNSUBSCRIBED );
225         }
226 
227         _dolistAPI.updateSubscribtions( sub.getUserId( ), subscriptionStatus, strAccountId );
228 
229         return true;
230     }
231 
232     @Override
233     public List<Feed> getFeeds( )
234     {
235         return null;
236     }
237     
238     @Override
239     public String getAllSubscriptionByGroup( String typeSubscription, String strAccountId )
240     {
241         String strAllSubscription = StringUtils.EMPTY;
242         try
243         {
244             strAllSubscription = _dolistAPI.getAllSubscriptions( typeSubscription, strAccountId );
245         }
246         catch ( Exception e )
247         {
248             AppLogService.error( "Error occured while getting all subscriptions.", e.getMessage( ) );
249         }
250         return strAllSubscription;
251     }
252 
253     public Map<Integer, Boolean> getUserSubscribtionsToUpdate( String jsonSubscriptions ) throws Exception
254     {
255         ObjectMapper mapper = new ObjectMapper( );
256         Map<Integer, Boolean> subscriptionsToUpdate = new HashMap<>( );
257 
258         try
259         {
260             JsonNode jsonNodes = mapper.readTree( jsonSubscriptions );
261             subscriptionsToUpdate.put( jsonNodes.get( "id" ).asInt( ),
262             Boolean.valueOf( jsonNodes.get( "active" ).asText( ) ) );
263         }
264         catch( Exception e )
265         {
266             AppLogService.error( "An error occured while updating subscriptions : " + e.getMessage( ) );
267             return null;
268         }
269 
270         return subscriptionsToUpdate;
271     }
272 
273     /**
274      * init
275      * @param strAccountId
276      * @throws Exception
277      */
278     private void initMapIdName( String strAccountId ) throws Exception
279     {
280         ObjectMapper mapper = new ObjectMapper( );
281 
282         String subscriptionsInJson = _dolistAPI.getAllSubscriptions( DolistConstants.TYPE_SUBSCRIPTION, strAccountId );
283         String interestsInJson = _dolistAPI.getAllSubscriptions( DolistConstants.TYPE_INTEREST, strAccountId );
284 
285         try
286         {
287             // Get subscriptions data (id and name)
288             JsonNode nodes = mapper.readTree( subscriptionsInJson );
289 
290             JsonNode itemListNode = nodes.get( JSON_NODE_ITEMLIST );
291 
292             for ( JsonNode node : itemListNode )
293             {
294                 if ( node.get( "IsEnabled" ).asBoolean( ) )
295                 {
296                     _subscriptionsMapIdName.put( node.get( "ID" ).asText( ), node.get( JSON_NODE_SUB_NAME ).asText( ) );
297                 }
298             }
299 
300             // Get interests data (id and name)
301             nodes = null;
302             itemListNode = null;
303 
304             nodes = mapper.readTree( interestsInJson );
305 
306             itemListNode = nodes.get( JSON_NODE_ITEMLIST );
307 
308             for ( JsonNode node : itemListNode )
309             {
310                 JsonNode groupData = node.get( JSON_NODE_ITEM_GROUP );
311 
312                 String dolistGroupName = groupData.get( JSON_NODE_GROUP_NAME ).asText( );
313                 if ( dolistGroupName.substring( 0, 1 ).equals( "[" )
314                         && dolistGroupName.substring( dolistGroupName.length( ) - 1, dolistGroupName.length( ) ).equals( "]" ) )
315                 {
316                     String [ ] splitDlGrName = dolistGroupName.split( "\\]" );
317 
318                     if ( splitDlGrName.length > 0 )
319                     {
320                         String groupName = splitDlGrName [0].substring( 1, splitDlGrName [0].length( ) );
321 
322                         if ( splitDlGrName.length == 2 && splitDlGrName [1].length( ) > 0 && !groupName.equals( "Alertes" ) )
323                         {
324                             _groupViewRang.put( Integer.valueOf( splitDlGrName [1].substring( 1, splitDlGrName [1].length( ) ) ), groupName );
325                         }
326 
327                         _groupsMapIdName.put( groupData.get( "ID" ).asText( ), groupName );
328 
329                         JsonNode intersts = node.get( JSON_NODE_ITEM_INTERESTLIST );
330                         for ( JsonNode interest : intersts )
331                         {
332                             if ( !interest.has( JSON_NODE_INTEREST_IS_ACTIVE ) )
333                             {
334                                 _interestsMapIdName.put( interest.get( "ID" ).asText( ), interest.get( JSON_NODE_INTEREST_NAME ).asText( ) );
335                             }
336                         }
337                     }
338                 }
339             }
340         }
341         catch( Exception e )
342         {
343             String strError = "Error occured while mapping Ids and Names of subscriptions.";
344             AppLogService.error( strError + e.getMessage( ), e );
345         }
346     }
347 
348     /**
349      * init
350      * @param strAccountId
351      * @throws Exception
352      */
353     private void initMapIdNameArrondissement( String strAccountId ) throws Exception
354     {
355         ObjectMapper mapper = new ObjectMapper( );
356         _interestsMapIdName = new HashMap<>( );
357         _subscriptionsMapIdName = new HashMap<>( );
358         
359         String subscriptionsInJson = _dolistAPI.getAllSubscriptions( DolistConstants.TYPE_SUBSCRIPTION, strAccountId );
360         String interestsInJson = _dolistAPI.getAllSubscriptions( DolistConstants.TYPE_INTEREST, strAccountId );
361 
362         try
363         {
364             // Get subscriptions data (id and name)
365             JsonNode nodes = mapper.readTree( subscriptionsInJson );
366 
367             JsonNode itemListNode = nodes.get( JSON_NODE_ITEMLIST );
368 
369             for ( JsonNode node : itemListNode )
370             {
371                 if ( node.get( "IsEnabled" ).asBoolean( ) )
372                 {
373                     _subscriptionsMapIdName.put( node.get( "ID" ).asText( ), node.get( JSON_NODE_SUB_NAME ).asText( ) );
374                 }
375             }
376 
377             // Get interests data (id and name)
378             nodes = mapper.readTree( interestsInJson );
379 
380             itemListNode = nodes.get( JSON_NODE_ITEMLIST );
381 
382             for ( JsonNode node : itemListNode )
383             {
384                 if ( node != null )
385                 {
386                     JsonNode intersts = node.get( JSON_NODE_ITEM_INTERESTLIST );
387                     for ( JsonNode interest : intersts )
388                     {
389                         if ( !interest.has( JSON_NODE_INTEREST_IS_ACTIVE ) )
390                         {
391                             _interestsMapIdName.put( interest.get( "ID" ).asText( ), interest.get( JSON_NODE_INTEREST_NAME ).asText( ) );
392                         }
393                     }
394                 }
395             }
396         }
397         catch( Exception e )
398         {
399             String strError = "Error occured while mapping Ids and Names of subscriptions.";
400             AppLogService.error( strError + e.getMessage( ), e );
401         }
402     }
403     
404 
405     /**
406      * get subscription dolist ID
407      * 
408      * @param sub
409      * @return the map
410      */
411     public String getSubscriptionDolistId( String subscriptionName, Map<String, String> mapIdName )
412     {
413         String subscriptionDolistId = null;
414 
415         for ( Map.Entry<String, String> subMapIdName : mapIdName.entrySet( ) )
416         {
417             if ( subMapIdName.getValue( ).equals( subscriptionName ) )
418             {
419                 subscriptionDolistId = subMapIdName.getKey( );
420             }
421         }
422 
423         return subscriptionDolistId;
424     }
425 
426     @SuppressWarnings( "unchecked" )
427     @Override
428     public List<JSONObject> getUserSubscriptionIds( String strUserId, String strAccountId )
429     {        
430         ObjectMapper mapper = new ObjectMapper( );
431         List<JSONObject> jsonLsit = new ArrayList<>();
432         
433         try
434         {
435             String userDolistSubscriptionsList = _dolistAPI.getUserSubscriptions( strUserId, DolistConstants.TYPE_SUBSCRIPTION, strAccountId );
436 
437             JsonNode nodes = mapper.readTree( userDolistSubscriptionsList );
438             JsonNode itemListNode = nodes.get( JSON_NODE_ITEMLIST );
439                     
440             if ( itemListNode != null )
441             {
442                 for ( JsonNode itemNode : itemListNode )
443                 {
444                     if( itemNode.get( "Status").asText( ).equals( "Subscribed" )  )
445                     {
446                         JSONObject json = new JSONObject();
447                         json.put( "id", itemNode.get( JSON_NODE_SUB_ID ).asInt( )  );
448                         
449                         jsonLsit.add( json );
450                     }
451                 }
452             }
453         }
454         catch (Exception e)
455         {
456             AppLogService.error( "Error occured while getting the list of user subscriptions ids :", e.getMessage( ) );
457         }
458         
459         return jsonLsit;
460     }
461 
462 }