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.workflow.modules.appointmentants.service;
35
36 import java.io.IOException;
37 import java.io.UnsupportedEncodingException;
38 import java.net.URLEncoder;
39 import java.util.ArrayList;
40 import java.util.Arrays;
41 import java.util.Collections;
42 import java.util.HashMap;
43 import java.util.Iterator;
44 import java.util.List;
45 import java.util.Map;
46
47 import javax.inject.Inject;
48 import javax.inject.Named;
49 import javax.servlet.http.HttpServletRequest;
50
51 import org.apache.commons.collections4.CollectionUtils;
52 import org.apache.commons.lang.StringUtils;
53 import org.apache.commons.lang3.ArrayUtils;
54
55 import com.fasterxml.jackson.databind.JsonNode;
56 import com.fasterxml.jackson.databind.ObjectMapper;
57
58 import fr.paris.lutece.plugins.appointment.business.appointment.Appointment;
59 import fr.paris.lutece.plugins.appointment.business.localization.Localization;
60 import fr.paris.lutece.plugins.appointment.service.AppointmentResponseService;
61 import fr.paris.lutece.plugins.appointment.service.AppointmentService;
62 import fr.paris.lutece.plugins.appointment.service.AppointmentUtilities;
63 import fr.paris.lutece.plugins.appointment.service.LocalizationService;
64 import fr.paris.lutece.plugins.appointment.web.AppointmentApp;
65 import fr.paris.lutece.plugins.appointment.web.dto.AppointmentDTO;
66 import fr.paris.lutece.plugins.genericattributes.business.Response;
67 import fr.paris.lutece.plugins.workflow.modules.appointmentants.business.TaskAntsAppointmentConfigDAO;
68 import fr.paris.lutece.plugins.workflow.modules.appointmentants.business.history.TaskAntsAppointmentHistory;
69 import fr.paris.lutece.plugins.workflow.modules.appointmentants.pojo.AntsAddAppointmentResponsePOJO;
70 import fr.paris.lutece.plugins.workflow.modules.appointmentants.pojo.AntsDeleteAppointmentResponsePOJO;
71 import fr.paris.lutece.plugins.workflow.modules.appointmentants.pojo.AntsStatusResponsePOJO;
72 import fr.paris.lutece.plugins.workflow.modules.appointmentants.service.rest.TaskAntsAppointmentRest;
73 import fr.paris.lutece.plugins.workflow.modules.appointmentants.service.rest.TaskAntsAppointmentRestConstants;
74 import fr.paris.lutece.portal.service.util.AppLogService;
75 import fr.paris.lutece.portal.service.util.AppPropertiesService;
76 import fr.paris.lutece.util.httpaccess.HttpAccessException;
77 import fr.paris.lutece.util.url.UrlItem;
78
79
80
81
82
83
84 public class TaskAntsAppointmentService implements ITaskAntsAppointmentService {
85
86 public static final String BEAN_SERVICE = WorkflowAppointmentAntsPlugin.PLUGIN_NAME + ".taskAntsAppointmentService";
87
88 @Inject
89 @Named( TaskAntsAppointmentConfigDAO.BEAN_NAME )
90 private TaskAntsAppointmentConfigDAO _task_ants_appointment_dao;
91
92
93
94
95 private static final String ANTS_BASE_URL =
96 AppPropertiesService.getProperty( TaskAntsAppointmentRestConstants.ANTS_URL );
97 private static final String ANTS_STATUS_URL =
98 AppPropertiesService.getProperty( TaskAntsAppointmentRestConstants.ANTS_URL_STATUS_APPOINTMENT );
99
100
101
102
103 private static final String URL_PARAMETER_APPLICATION_ID =
104 AppPropertiesService.getProperty( TaskAntsAppointmentRestConstants.ANTS_APPLICATION_ID );
105 private static final String URL_PARAMETER_APPLICATION_IDS =
106 AppPropertiesService.getProperty( TaskAntsAppointmentRestConstants.ANTS_APPLICATION_IDS );
107 private static final String URL_PARAMETER_MANAGEMENT_URL =
108 AppPropertiesService.getProperty( TaskAntsAppointmentRestConstants.ANTS_MANAGEMENT_URL );
109 private static final String URL_PARAMETER_MEETING_POINT =
110 AppPropertiesService.getProperty( TaskAntsAppointmentRestConstants.ANTS_MEETING_POINT );
111 private static final String URL_PARAMETER_APPOINTMENT_DATE =
112 AppPropertiesService.getProperty( TaskAntsAppointmentRestConstants.ANTS_APPOINTMENT_DATE );
113
114
115
116
117 private static final String PROPERTY_API_OPT_AUTH_TOKEN_VALUE =
118 AppPropertiesService.getProperty( TaskAntsAppointmentRestConstants.ANTS_TOKEN_VALUE );
119
120
121
122
123 private static final String STATUS_VALIDATED =
124 AppPropertiesService.getProperty( TaskAntsAppointmentRestConstants.ANTS_APPOINTMENT_VALIDATED );
125
126
127
128
129 private static final String APPLICATION_NUMBERS_SEPARATOR =
130 AppPropertiesService.getProperty( "ants.api.application.numbers.separator" );
131
132 private static final String PARIS_USER_ACCOUNT_URL =
133 AppPropertiesService.getProperty( "paris.user.account.url" );
134
135
136
137
138 public static final String KEY_URL = "url";
139 public static final String KEY_LOCATION = "location";
140 public static final String KEY_DATE = "date";
141
142 private TaskAntsAppointmentService( )
143 {
144 }
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160 @Override
161 public boolean createAntsAppointment( HttpServletRequest request, int idAppointment, int idTask, TaskAntsAppointmentHistory antsAppointmentHistory )
162 {
163 Map<String, String> applicationContent = getAppointmentData( request, idAppointment, false );
164
165 boolean isAppointmentCreated = false;
166
167
168 String strAntsApplicationNumbers = getAntsApplicationValuesFromResponse(
169 idAppointment,
170 getAntsApplicationFieldId( idTask )
171 );
172
173
174 List<String> applicationNumberList = splitAntsApplicationValues( strAntsApplicationNumbers, APPLICATION_NUMBERS_SEPARATOR );
175
176
177 if( CollectionUtils.isEmpty( applicationNumberList ) )
178 {
179 AppLogService.info( "{} - Appointment with ID {} has no ANTS number", BEAN_SERVICE, idAppointment );
180
181 return true;
182 }
183
184
185 antsAppointmentHistory.setAntsApplicationNumbers( strAntsApplicationNumbers );
186
187
188 if( isApplicationNumberListValidForCreation( idAppointment, applicationNumberList ) ) {
189
190
191 for( String appplicationNumber : applicationNumberList ) {
192
193
194 String antsURL = buildAntsAddAppointmentUrl(
195 AppPropertiesService.getProperty( TaskAntsAppointmentRestConstants.ANTS_URL),
196 AppPropertiesService.getProperty( TaskAntsAppointmentRestConstants.ANTS_URL_ADD_APPOINTMENT),
197 appplicationNumber,
198 applicationContent.get( KEY_URL ),
199 applicationContent.get( KEY_LOCATION ),
200 applicationContent.get( KEY_DATE )
201 );
202 try {
203
204 isAppointmentCreated = addAntsAppointmentRestCall( antsURL );
205
206 AppLogService.debug(
207 "{} ANTS appointment with number '{}' was {} for appointment with ID {}",
208 BEAN_SERVICE,
209 appplicationNumber,
210 isAppointmentCreated ? "created" : "not created",
211 idAppointment
212 );
213
214
215 if( !isAppointmentCreated )
216 {
217 return isAppointmentCreated;
218 }
219 }
220 catch( Exception e )
221 {
222 AppLogService.error( BEAN_SERVICE, e );
223 }
224 }
225 }
226 return isAppointmentCreated;
227 }
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243 @Override
244 public boolean deleteAntsAppointment( HttpServletRequest request, int idAppointment, int idTask, TaskAntsAppointmentHistory antsAppointmentHistory )
245 {
246 Map<String, String> applicationContent = getAppointmentData( request, idAppointment, true );
247
248 boolean isAppointmentDeleted = false;
249
250
251 String strAntsApplicationNumbers = getAntsApplicationValuesFromResponse(
252 idAppointment,
253 getAntsApplicationFieldId( idTask )
254 );
255
256
257 List<String> applicationNumberList = splitAntsApplicationValues( strAntsApplicationNumbers, APPLICATION_NUMBERS_SEPARATOR );
258
259
260 if( CollectionUtils.isEmpty( applicationNumberList ) )
261 {
262 AppLogService.info( "{} - Appointment with ID {} has no ANTS number", BEAN_SERVICE, idAppointment );
263
264 return true;
265 }
266
267
268 antsAppointmentHistory.setAntsApplicationNumbers( strAntsApplicationNumbers );
269
270
271 if( isApplicationNumberListValidForDeletion( idAppointment, applicationNumberList ) ) {
272
273 for( String appplicationNumber : applicationNumberList ) {
274
275
276 String antsURL = buildAntsDeleteAppointmentUrl(
277 AppPropertiesService.getProperty( TaskAntsAppointmentRestConstants.ANTS_URL),
278 AppPropertiesService.getProperty( TaskAntsAppointmentRestConstants.ANTS_URL_DELETE_APPOINTMENT),
279 appplicationNumber,
280 applicationContent.get( KEY_LOCATION ),
281 applicationContent.get( KEY_DATE )
282 );
283 try {
284
285 isAppointmentDeleted = deleteAntsAppointmentRestCall( antsURL );
286
287 AppLogService.debug(
288 "{} ANTS appointment with number '{}' was {} for appointment with ID {}",
289 BEAN_SERVICE,
290 appplicationNumber,
291 isAppointmentDeleted ? "deleted" : "not deleted",
292 idAppointment
293 );
294
295
296 if( !isAppointmentDeleted )
297 {
298 return isAppointmentDeleted;
299 }
300 }
301 catch ( Exception e )
302 {
303 AppLogService.error( BEAN_SERVICE, e );
304 }
305 }
306 }
307 return isAppointmentDeleted;
308 }
309
310
311
312
313
314
315
316
317
318 public static boolean isAppointmentCreatedInFrontOffice( Appointment appointment )
319 {
320
321
322
323 return appointment.getAdminUserCreate( ) == null ||
324 appointment.getAdminUserCreate( ).isEmpty( );
325 }
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346 public static String buildAntsAddAppointmentUrl( String baseUrl, String addAppointmentUrl, String applicationId,
347 String managementUrl, String meetingPoint, String dateTime )
348 {
349 StringBuilder antsApiUrl = new StringBuilder( baseUrl ).
350 append( addAppointmentUrl );
351
352 UrlItem urlItem = new UrlItem( antsApiUrl.toString( ) );
353 urlItem.addParameter(URL_PARAMETER_APPLICATION_ID, applicationId );
354 urlItem.addParameter(URL_PARAMETER_MANAGEMENT_URL, managementUrl );
355 urlItem.addParameter(URL_PARAMETER_MEETING_POINT, meetingPoint );
356 urlItem.addParameter(URL_PARAMETER_APPOINTMENT_DATE, dateTime );
357
358 return urlItem.getUrl( );
359 }
360
361
362
363
364
365
366
367
368
369
370
371 public static boolean addAntsAppointmentRestCall( String antsUrl ) throws HttpAccessException, IOException
372 {
373 String response = TaskAntsAppointmentRest.addAntsAppointment( antsUrl, PROPERTY_API_OPT_AUTH_TOKEN_VALUE );
374
375 return isAppointmentCreationSuccessful( response );
376 }
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396 public static String buildAntsDeleteAppointmentUrl( String baseUrl, String deleteAppointmentUrl, String applicationId,
397 String meetingPoint, String dateTime )
398 {
399 StringBuilder antsApiUrl = new StringBuilder( baseUrl ).
400 append( deleteAppointmentUrl );
401
402 UrlItem urlItem = new UrlItem( antsApiUrl.toString( ) );
403 urlItem.addParameter(URL_PARAMETER_APPLICATION_ID, applicationId );
404 urlItem.addParameter(URL_PARAMETER_MEETING_POINT, meetingPoint );
405 urlItem.addParameter(URL_PARAMETER_APPOINTMENT_DATE, dateTime );
406
407 return urlItem.getUrl( );
408 }
409
410
411
412
413
414
415
416
417
418
419
420 public static boolean deleteAntsAppointmentRestCall( String antsUrl ) throws HttpAccessException, IOException
421 {
422 String response = TaskAntsAppointmentRest.deleteAntsAppointment( antsUrl, PROPERTY_API_OPT_AUTH_TOKEN_VALUE );
423
424 return isAppointmentDeletionSuccessful( response );
425 }
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440 public static Map<String, String> getAppointmentData( HttpServletRequest request, int idAppointment, boolean isDeletingAppointment )
441 {
442 Map<String, String> appointmentDataMap = new HashMap<>( );
443 AppointmentDTO appointmentDto = null;
444
445
446 if( isDeletingAppointment )
447 {
448
449 appointmentDto = getOldAppointment( request );
450
451 if( appointmentDto == null )
452 {
453
454 appointmentDto = AppointmentService.buildAppointmentDTOFromIdAppointment( idAppointment );
455 }
456 }
457 else
458 {
459
460 appointmentDto = AppointmentService.buildAppointmentDTOFromIdAppointment( idAppointment );
461 }
462
463
464 appointmentDataMap.put(
465 KEY_URL,
466 cleanUrl( PARIS_USER_ACCOUNT_URL ) );
467
468
469 String appointmentLocation = "";
470
471 if( appointmentDto != null ) {
472 Localization localization = LocalizationService.findLocalizationWithFormId( appointmentDto.getIdForm( ) );
473 if( localization != null && localization.getAddress( ) != null )
474 {
475 appointmentLocation = localization.getAddress( );
476 }
477 }
478 appointmentDataMap.put(
479 KEY_LOCATION,
480 cleanUrl( appointmentLocation ).replace( "+" , "%20" ) );
481
482
483 String appointmentDateTime = "";
484
485 if( appointmentDto != null )
486 {
487 String startingDateTime = appointmentDto.getStartingDateTime( ).toString( );
488
489
490 appointmentDateTime = cleanUrl( startingDateTime ).replace( "+" , "%20" );
491 }
492 appointmentDataMap.put(
493 KEY_DATE,
494 appointmentDateTime );
495
496 return appointmentDataMap;
497 }
498
499
500
501
502
503
504
505
506
507
508
509 private static AppointmentDTO getOldAppointment( HttpServletRequest request )
510 {
511 AppointmentDTO oldAppointment = null;
512
513 try
514 {
515
516 oldAppointment = ( AppointmentDTO ) request.getAttribute( AppointmentUtilities.OLD_APPOINTMENT_DTO );
517 }
518 catch ( Exception e )
519 {
520 AppLogService.info( BEAN_SERVICE + " removing appointment from ants database: {}", e.getMessage( ) );
521 }
522 return oldAppointment;
523 }
524
525
526
527
528
529
530
531
532
533
534
535
536 public static List<AntsStatusResponsePOJO> getAntsStatusResponseAsObjects( List<String> applicationNumberList )
537 throws HttpAccessException
538 {
539 String getStatusUrl = buildAntsGetStatusAppointmentUrl( applicationNumberList );
540
541 String response = "";
542
543 List<AntsStatusResponsePOJO> statusObjectsList = new ArrayList<>( );
544
545 response = TaskAntsAppointmentRest.getAntsAppointmentStatus( getStatusUrl, PROPERTY_API_OPT_AUTH_TOKEN_VALUE );
546 AppLogService.debug( "{} - ANTS GET STATUS request successful - Response: {}", BEAN_SERVICE, response );
547
548
549 if( StringUtils.isNotBlank( response ) )
550 {
551 try
552 {
553 statusObjectsList = getStatusResponseAsObject( response );
554 }
555 catch( IOException e)
556 {
557 AppLogService.error( BEAN_SERVICE, e );
558 }
559 }
560 return statusObjectsList;
561 }
562
563
564
565
566
567
568
569
570
571
572 public static String buildAntsGetStatusAppointmentUrl( List<String> applicationIdsList )
573 {
574
575 StringBuilder antsApisUrl = new StringBuilder(
576 ANTS_BASE_URL ).append( ANTS_STATUS_URL );
577
578 UrlItem urlItem = new UrlItem( antsApisUrl.toString( ) );
579
580
581 for( String applicationId : applicationIdsList )
582 {
583 urlItem.addParameter( URL_PARAMETER_APPLICATION_IDS, applicationId );
584 }
585 return urlItem.getUrl();
586 }
587
588
589
590
591
592
593
594
595
596
597
598
599 public static boolean isApplicationNumberListValidForCreation( int idAppointment, List<String> applicationNumberList )
600 {
601 List<AntsStatusResponsePOJO> statusResponseList = null;
602 try
603 {
604
605 statusResponseList = getAntsStatusResponseAsObjects( applicationNumberList );
606 }
607 catch ( Exception e )
608 {
609 AppLogService.error( BEAN_SERVICE, e );
610 return false;
611 }
612
613 if( CollectionUtils.isEmpty( statusResponseList ) )
614 {
615 AppLogService.info( "{} - No status retrieved for the ANTS numbers {}",
616 BEAN_SERVICE, Arrays.toString( applicationNumberList.toArray( ) ) );
617 return false;
618 }
619
620
621 for( AntsStatusResponsePOJO statusResponse : statusResponseList )
622 {
623 String statusAntsNumber = statusResponse.getStatus( );
624 Object[] listAntsNumberAppointments = statusResponse.getAppointments( );
625
626
627
628
629 if( !StringUtils.equals( statusAntsNumber, STATUS_VALIDATED ) ||
630 ArrayUtils.isNotEmpty( listAntsNumberAppointments ) )
631 {
632 AppLogService.error(
633 "{} - ANTS appointment not valid for creation: Appointment {} with ANTS number '{}' has a status '{}' and {} appointment(s)",
634 BEAN_SERVICE, idAppointment, Arrays.toString( applicationNumberList.toArray( ) ), statusAntsNumber, listAntsNumberAppointments.length );
635 return false;
636 }
637 }
638 return true;
639 }
640
641
642
643
644
645
646
647
648
649
650
651
652
653 public static boolean isApplicationNumberListValidForDeletion( int idAppointment, List<String> applicationNumberList )
654 {
655 List<AntsStatusResponsePOJO> statusResponseList = null;
656 try
657 {
658
659 statusResponseList = getAntsStatusResponseAsObjects( applicationNumberList );
660 }
661 catch ( Exception e )
662 {
663 AppLogService.error( BEAN_SERVICE, e );
664 return false;
665 }
666
667 if( CollectionUtils.isEmpty( statusResponseList ) )
668 {
669 AppLogService.info( "{} - No status retrieved for the ANTS numbers {}",
670 BEAN_SERVICE, Arrays.toString( applicationNumberList.toArray( ) ) );
671 return false;
672 }
673
674
675 for( AntsStatusResponsePOJO statusResponse : statusResponseList )
676 {
677 String statusAntsNumber = statusResponse.getStatus( );
678 Object[] listAntsNumberAppointments = statusResponse.getAppointments( );
679
680
681
682
683 if( !StringUtils.equals( statusAntsNumber, STATUS_VALIDATED ) ||
684 ArrayUtils.isEmpty( listAntsNumberAppointments ) )
685 {
686 AppLogService.error(
687 "{} - ANTS appointment not valid for deletion: Appointment {} with ANTS number '{}' has a status '{}' and no appointment",
688 BEAN_SERVICE, idAppointment, Arrays.toString( applicationNumberList.toArray( ) ), statusAntsNumber );
689 return false;
690 }
691 }
692 return true;
693 }
694
695
696
697
698
699
700
701
702
703
704
705
706
707 public static List<AntsStatusResponsePOJO> getStatusResponseAsObject( String response ) throws IOException
708 {
709 ObjectMapper mapper = new ObjectMapper( );
710 JsonNode jsonNode = mapper.readTree( response );
711
712 List<AntsStatusResponsePOJO> statusList = new ArrayList<>( );
713
714 Iterator<String> fieldNames = jsonNode.fieldNames();
715
716
717 while( fieldNames.hasNext( ) )
718 {
719 String fieldName = fieldNames.next( );
720 JsonNode field = jsonNode.get( fieldName );
721 statusList.add(
722 mapper.readerFor( AntsStatusResponsePOJO.class )
723 .readValue( field.toString() )
724 );
725 }
726 return statusList;
727 }
728
729
730
731
732
733
734
735
736
737 public static String cleanUrl( String urlToClean )
738 {
739 try
740 {
741 return URLEncoder.encode( urlToClean, "utf-8" );
742 }
743 catch( UnsupportedEncodingException e)
744 {
745 AppLogService.error( BEAN_SERVICE, e );
746 return urlToClean;
747 }
748 }
749
750
751
752
753
754
755
756
757
758
759
760 public static boolean isAppointmentCreationSuccessful( String response ) throws IOException
761 {
762 ObjectMapper mapper = new ObjectMapper( );
763
764
765 AntsAddAppointmentResponsePOJO responseObject =
766 mapper.readValue( response, AntsAddAppointmentResponsePOJO.class );
767
768
769 return responseObject.isSuccess( );
770 }
771
772
773
774
775
776
777
778
779
780
781
782 public static boolean isAppointmentDeletionSuccessful( String response ) throws IOException
783 {
784 ObjectMapper mapper = new ObjectMapper( );
785
786
787 AntsDeleteAppointmentResponsePOJO responseObject =
788 mapper.readValue( response, AntsDeleteAppointmentResponsePOJO.class );
789
790
791
792
793
794
795 if ( responseObject.getRowcount( ) > 0 )
796 {
797
798 return true;
799 }
800 else
801 {
802
803 AppLogService.error( "{} - The ANTS appointment was not deleted. HTTP response: '{}'", BEAN_SERVICE, response );
804 return false;
805 }
806 }
807
808
809
810
811
812
813
814
815
816
817
818 public static String getAntsApplicationValuesFromResponse( int idAppointment, int entryFieldId )
819 {
820 List<Response> responseList = AppointmentResponseService.findListResponse( idAppointment );
821
822 for( Response response : responseList )
823 {
824
825 if( response.getEntry( ).getIdEntry( ) == entryFieldId )
826 {
827 return response.getResponseValue( );
828 }
829 }
830 return null;
831 }
832
833
834
835
836
837
838
839
840
841
842
843 public static List<String> splitAntsApplicationValues( String antsApplicationValues, String separator )
844 {
845 if( StringUtils.isNotBlank( antsApplicationValues ) )
846 {
847 String[] appNumbersArray = StringUtils.split( antsApplicationValues, separator );
848 return Arrays.asList( appNumbersArray );
849 }
850 return Collections.emptyList( );
851 }
852
853
854
855
856
857
858
859
860
861
862 @Override
863 public int getAntsApplicationFieldId( int idTask )
864 {
865 return _task_ants_appointment_dao.load( idTask ).getIdFieldEntry( );
866 }
867 }