View Javadoc
1   /*
2    * Copyright (c) 2002-2025, 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.forms.business;
35  
36  import javax.validation.constraints.NotEmpty;
37  import javax.validation.constraints.Size;
38  
39  import org.apache.commons.lang3.StringUtils;
40  import org.apache.commons.lang3.math.NumberUtils;
41  
42  import fr.paris.lutece.portal.business.file.File;
43  import fr.paris.lutece.portal.service.rbac.RBACResource;
44  import fr.paris.lutece.portal.service.workgroup.AdminWorkgroupResource;
45  
46  import java.sql.Date;
47  import java.sql.Timestamp;
48  import java.util.Base64;
49  import java.util.Comparator;
50  import java.util.List;
51  
52  /**
53   * This is the business class for the object Form
54   */
55  public class Form implements AdminWorkgroupResource, RBACResource, Comparator<Form>
56  {
57  
58      /**
59       * Form resource type
60       */
61      public static final String RESOURCE_TYPE = "FORMS_FORM";
62  
63      /**
64       * State of forms that are enabled
65       */
66      public static final int STATE_ENABLE = 1;
67  
68      /**
69       * State of forms that are disabled
70       */
71      public static final int STATE_DISABLE = 0;
72  
73      // Variables declarations
74      private int _nId;
75  
76      @NotEmpty( message = "#i18n{forms.validation.form.Title.notEmpty}" )
77      @Size( max = 255, message = "#i18n{forms.validation.form.Title.size}" )
78      private String _strTitle;
79  
80      @Size( max = 255, message = "#i18n{forms.validation.form.Description.size}" )
81      private String _strDescription;
82  
83      private Timestamp _dateCreation;
84  
85      private Timestamp _dateAvailabilityStartDate;
86  
87      private Timestamp _dateAvailabilityEndDate;
88  
89      private Timestamp _dateUpdate;
90  
91      private String _strWorkgroup;
92  
93      private List<FormAction> _listActions;
94  
95      private int _nIdWorkflow;
96  
97      private boolean _bAuthentificationNeeded;
98  
99      @NotEmpty( message = "#i18n{forms.validation.form.Breadcrumb.notEmpty}" )
100     @Size( max = 255, message = "#i18n{forms.validation.form.Breadcrumb.size}" )
101     private String _strBreadcrumbName;
102 
103     @Size( max = 255, message = "#i18n{forms.validation.form.ReturnUrl.size}" )
104     private String _strReturnUrl;
105 
106     private boolean _bDisplaySummary;
107     private int _nMaxNumberResponse;
108     private boolean _bOneResponseByUser;
109 
110     private int _nCurrentNumberResponse;
111 
112     private boolean _bCaptchaStepInitial;
113     private boolean _bCaptchaStepFinal;
114     private boolean _bCaptchaRecap;
115 
116     private boolean _bCountResponses;
117 
118     private String _labelFinalButton;
119 
120     @Size( max = 3000, message = "#i18n{forms.validation.form.UnavailableMessage.size}" )
121     private String _strUnavailableMessage;
122 
123     private File _logo;
124 
125     private int _nIdCategory;
126     
127     private boolean _bBackupEnabled;
128     private int _nBackupStoragePeriod;
129     
130     /**
131      *  Access to responses management on FO by role
132      **/
133     private boolean _bAccessToResponsesByRole;
134 
135     /**
136      * Default constructor
137      */
138     public Form( )
139     {
140         super( );
141         _nBackupStoragePeriod = -1;
142     }
143 
144     /**
145      * Copy constructor
146      * 
147      * Leaves out dynamic data
148      * 
149      * @param source
150      *            source Form to copy
151      */
152     Formorm" href="../../../../../../fr/paris/lutece/plugins/forms/business/Form.html#Form">Form( Form source )
153     {
154         _bAccessToResponsesByRole = source._bAccessToResponsesByRole;
155         _bAuthentificationNeeded = source._bAuthentificationNeeded;
156         _bBackupEnabled = source._bBackupEnabled;
157         _nBackupStoragePeriod = source._nBackupStoragePeriod;
158         _bCaptchaRecap = source._bCaptchaRecap;
159         _bCaptchaStepFinal = source._bCaptchaStepFinal;
160         _bCaptchaStepInitial = source._bCaptchaStepInitial;
161         _bCountResponses = source._bCountResponses;
162         _bDisplaySummary = source._bDisplaySummary;
163         _bOneResponseByUser = source._bOneResponseByUser;
164         _dateAvailabilityEndDate = source._dateAvailabilityEndDate;
165         _dateAvailabilityStartDate = source._dateAvailabilityStartDate;
166         _dateCreation = source._dateCreation;
167         _dateUpdate = source._dateUpdate;
168         _labelFinalButton = source._labelFinalButton;
169         // _listActions = null;
170         _logo = source._logo;
171         // _nCurrentNumberResponse = 0;
172         _nId = source._nId;
173         _nIdCategory = source._nIdCategory;
174         _nIdWorkflow = source._nIdWorkflow;
175         _nMaxNumberResponse = source._nMaxNumberResponse;
176         _strBreadcrumbName = source._strBreadcrumbName;
177         _strDescription = source._strDescription;
178         _strReturnUrl = source._strReturnUrl;
179         _strTitle = source._strTitle;
180         _strUnavailableMessage = source._strUnavailableMessage;
181         _strWorkgroup = source._strWorkgroup;
182     }
183 
184     /**
185      * Returns the Id
186      * 
187      * @return The Id
188      */
189     public int getId( )
190     {
191         return _nId;
192     }
193 
194     /**
195      * Sets the Id
196      * 
197      * @param nId
198      *            The Id
199      */
200     public void setId( int nId )
201     {
202         _nId = nId;
203     }
204 
205     /**
206      * Returns the Title
207      * 
208      * @return The Title
209      */
210     public String getTitle( )
211     {
212         return _strTitle;
213     }
214 
215     /**
216      * Sets the Title
217      * 
218      * @param strTitle
219      *            The Title
220      */
221     public void setTitle( String strTitle )
222     {
223         _strTitle = strTitle;
224     }
225 
226     /**
227      * Returns the Description
228      * 
229      * @return The Description
230      */
231     public String getDescription( )
232     {
233         return _strDescription;
234     }
235 
236     /**
237      * Sets the Description
238      * 
239      * @param strDescription
240      *            The Description
241      */
242     public void setDescription( String strDescription )
243     {
244         _strDescription = strDescription;
245     }
246 
247     /**
248      * Returns the CreationDate
249      * 
250      * @return The CreationDate
251      */
252     public Timestamp getCreationDate( )
253     {
254         return _dateCreation;
255     }
256 
257     /**
258      * Sets the CreationDate
259      * 
260      * @param creationDate
261      *            The CreationDate
262      */
263     public void setCreationDate( Timestamp creationDate )
264     {
265         _dateCreation = creationDate;
266     }
267 
268     /**
269      * Returns the UpdateDate
270      * 
271      * @return The UpdateDate
272      */
273     public Timestamp getUpdateDate( )
274     {
275         return _dateUpdate;
276     }
277 
278     /**
279      * Sets the UpdateDate
280      * 
281      * @param dateUpdate
282      *            The UpdateDate
283      */
284     public void setUpdateDate( Timestamp dateUpdate )
285     {
286 
287         _dateUpdate = dateUpdate;
288     }
289 
290     /**
291      * Returns the AvailabilityStartDate
292      * 
293      * @return The AvailabilityStartDate
294      */
295     public Timestamp getAvailabilityStartDate( )
296     {
297         return _dateAvailabilityStartDate;
298     }
299 
300     /**
301      * Sets the AvailabilityStartDate
302      * 
303      * @param dateAvailabilityStartDate
304      *            The AvailabilityStartDate
305      */
306     public void setAvailabilityStartDate( Timestamp dateAvailabilityStartDate )
307     {
308         _dateAvailabilityStartDate = dateAvailabilityStartDate;
309     }
310 
311     /**
312      * Returns the AvailabilityEndDate
313      * 
314      * @return The AvailabilityEndDate
315      */
316     public Timestamp getAvailabilityEndDate( )
317     {
318         return _dateAvailabilityEndDate;
319     }
320 
321     /**
322      * Sets the AvailabilityEndDate
323      * 
324      * @param dateAvailabilityEndDate
325      *            The AvailabilityEndDate
326      */
327     public void setAvailabilityEndDate( Timestamp dateAvailabilityEndDate )
328     {
329         _dateAvailabilityEndDate = dateAvailabilityEndDate;
330     }
331 
332     /**
333      * {@inheritDoc}
334      */
335     @Override
336     public String getResourceTypeCode( )
337     {
338         return RESOURCE_TYPE;
339     }
340 
341     /**
342      * {@inheritDoc}
343      */
344     @Override
345     public String getResourceId( )
346     {
347         return StringUtils.EMPTY + _nId;
348     }
349 
350     /**
351      * {@inheritDoc}
352      */
353     @Override
354     public String getWorkgroup( )
355     {
356         return _strWorkgroup;
357     }
358 
359     /**
360      * set the work group associate to the form
361      * 
362      * @param workGroup
363      *            the work group associate to the form
364      */
365     public void setWorkgroup( String workGroup )
366     {
367         _strWorkgroup = workGroup;
368     }
369 
370     /**
371      *
372      * @return a list of action can be use for the form
373      */
374     public List<FormAction> getActions( )
375     {
376         return _listActions;
377     }
378 
379     /**
380      * set a list of action can be use for the form
381      * 
382      * @param formActions
383      *            a list of action must be use for the form
384      */
385     public void setActions( List<FormAction> formActions )
386     {
387         _listActions = formActions;
388     }
389 
390     /**
391      * Returns the active status of a form by checking if we are currently within its availability period
392      * 
393      * @return true if the form is active
394      */
395     public boolean isActive( )
396     {
397         boolean bActive = false;
398         Date dToday = new Date( System.currentTimeMillis( ) );
399 
400         if ( _dateAvailabilityStartDate != null && _dateAvailabilityStartDate.before( dToday )
401                 && ( _dateAvailabilityEndDate == null || _dateAvailabilityEndDate.after( dToday ) ) )
402         {
403             bActive = true;
404         }
405         if ( _dateAvailabilityStartDate == null && ( _dateAvailabilityEndDate != null && _dateAvailabilityEndDate.after( dToday ) ) )
406         {
407             bActive = true;
408         }
409 
410         return bActive;
411     }
412 
413     /**
414      * Getter for id_workflow
415      * 
416      * @return the _nIdWorkflow
417      */
418     public int getIdWorkflow( )
419     {
420         return _nIdWorkflow;
421     }
422 
423     /**
424      * setter for id_workflow
425      * 
426      * @param nIdWorkflow
427      *            the Id Workflow to set
428      */
429     public void setIdWorkflow( int nIdWorkflow )
430     {
431         _nIdWorkflow = nIdWorkflow;
432     }
433 
434     /**
435      * @return the _bAuthentificationNeeded
436      */
437     public boolean isAuthentificationNeeded( )
438     {
439         return _bAuthentificationNeeded;
440     }
441 
442     /**
443      * @param bAuthentificationNeeded
444      *            the bAuthentificationNeeded to set
445      */
446     public void setAuthentificationNeeded( boolean bAuthentificationNeeded )
447     {
448         this._bAuthentificationNeeded = bAuthentificationNeeded;
449     }
450 
451     /**
452      * Returns the BreadcrumbName
453      * 
454      * @return The BreadcrumbName
455      */
456     public String getBreadcrumbName( )
457     {
458         return _strBreadcrumbName;
459     }
460 
461     /**
462      * Sets the Title
463      * 
464      * @param strBreadcrumbName
465      *            The breadcrumb bean name
466      */
467     public void setBreadcrumbName( String strBreadcrumbName )
468     {
469         _strBreadcrumbName = strBreadcrumbName;
470     }
471 
472     /**
473      * Returns the return URL
474      * 
475      * @return The return URL
476      */
477     public String getReturnUrl( )
478     {
479         return _strReturnUrl;
480     }
481 
482     /**
483      * Sets the return URL
484      * 
485      * @param strReturnUrl
486      *            The form return page URL
487      */
488     public void setReturnUrl( String strReturnUrl )
489     {
490         _strReturnUrl = strReturnUrl;
491     }
492 
493     /**
494      * Tells if the summary must be displayed
495      * 
496      * @return {@code true} if the summary must be displayed, {@code false} otherwise
497      */
498     public boolean isDisplaySummary( )
499     {
500         return _bDisplaySummary;
501     }
502 
503     /**
504      * Sets if the summary must be displayed
505      * 
506      * @param bDisplaySummary
507      *            {@code true} if the summary must be displayed, {@code false} otherwise
508      */
509     public void setDisplaySummary( boolean bDisplaySummary )
510     {
511         _bDisplaySummary = bDisplaySummary;
512     }
513 
514     /**
515      * Returns the number Max of response form
516      * 
517      * @return The number max of reponse for
518      */
519     public int getMaxNumberResponse( )
520     {
521         return _nMaxNumberResponse;
522     }
523 
524     /**
525      * Sets the number Max of response form
526      * 
527      * @param nMaxNumberResponse
528      *            The number max of reponse form
529      */
530     public void setMaxNumberResponse( int nMaxNumberResponse )
531     {
532         _nMaxNumberResponse = nMaxNumberResponse;
533     }
534 
535     /**
536      * Check the user can only submit one form.
537      * 
538      * @return true if the user can submit just one form
539      */
540     public boolean isOneResponseByUser( )
541     {
542         return _bOneResponseByUser;
543     }
544 
545     /**
546      * set true if the user can submit just once the form
547      * 
548      * @param bOneResponseByUser
549      *            true if the user can submit just one form
550      */
551     public void setOneResponseByUser( boolean bOneResponseByUser )
552     {
553         _bOneResponseByUser = bOneResponseByUser;
554     }
555 
556     /**
557      * @return the nCurrentNumberResponse
558      */
559     public int getCurrentNumberResponse( )
560     {
561         return _nCurrentNumberResponse;
562     }
563 
564     /**
565      * @param nCurrentNumberResponse
566      *            the nCurrentNumberResponse to set
567      */
568     public void setCurrentNumberResponse( int nCurrentNumberResponse )
569     {
570         _nCurrentNumberResponse = nCurrentNumberResponse;
571     }
572 
573     /**
574      * @return the bCaptchaStepInitial
575      */
576     public boolean isCaptchaStepInitial( )
577     {
578         return _bCaptchaStepInitial;
579     }
580 
581     /**
582      * @param bCaptchaStepInitial
583      *            the bCaptchaStepInitial to set
584      */
585     public void setCaptchaStepInitial( boolean bCaptchaStepInitial )
586     {
587         _bCaptchaStepInitial = bCaptchaStepInitial;
588     }
589 
590     /**
591      * @return the bCaptchaStepFinal
592      */
593     public boolean isCaptchaStepFinal( )
594     {
595         return _bCaptchaStepFinal;
596     }
597 
598     /**
599      * @param bCaptchaStepFinal
600      *            the bCaptchaStepFinel to set
601      */
602     public void setCaptchaStepFinal( boolean bCaptchaStepFinal )
603     {
604         _bCaptchaStepFinal = bCaptchaStepFinal;
605     }
606 
607     /**
608      * @return the bCaptchaRecap
609      */
610     public boolean isCaptchaRecap( )
611     {
612         return _bCaptchaRecap;
613     }
614 
615     /**
616      * @param bCaptchaRecap
617      *            the bCaptchaRecap to set
618      */
619     public void setCaptchaRecap( boolean bCaptchaRecap )
620     {
621         _bCaptchaRecap = bCaptchaRecap;
622     }
623 
624     /**
625      * @return the bCountResponse
626      */
627     public boolean isCountResponses( )
628     {
629         return _bCountResponses;
630     }
631 
632     /**
633      * @param bCountResponse
634      *            the bCountResponse to set
635      */
636     public void setCountResponses( boolean bCountResponse )
637     {
638         _bCountResponses = bCountResponse;
639     }
640 
641     /**
642      * @return the labelFinalButton
643      */
644     public String getLabelFinalButton( )
645     {
646         return _labelFinalButton;
647     }
648 
649     /**
650      * @param labelFinalButton
651      *            the labelFinalButton to set
652      */
653     public void setLabelFinalButton( String labelFinalButton )
654     {
655         _labelFinalButton = labelFinalButton;
656     }
657 
658     /**
659      * @return the strUnavailableMessage
660      */
661     public String getUnavailableMessage( )
662     {
663         return _strUnavailableMessage;
664     }
665 
666     /**
667      * @param strUnavailableMessage
668      *            the strUnavailableMessage to set
669      */
670     public void setUnavailableMessage( String strUnavailableMessage )
671     {
672         _strUnavailableMessage = strUnavailableMessage;
673     }
674 
675     /**
676      * @return the logo
677      */
678     public File getLogo( )
679     {
680         return _logo;
681     }
682 
683     /**
684      * @param logo
685      *            the logo to set
686      */
687     public void setLogo( File logo )
688     {
689         _logo = logo;
690     }
691 
692     /**
693      * Get the content of the logo as base64
694      * 
695      * @return
696      */
697     public String getLogoBase64( )
698     {
699         if ( _logo == null || _logo.getPhysicalFile( ) == null )
700         {
701             return null;
702         }
703         return Base64.getEncoder( ).encodeToString( _logo.getPhysicalFile( ).getValue( ) );
704     }
705 
706     /**
707      * @return the id of the category linked to the form
708      */
709     public int getIdCategory( )
710     {
711         return _nIdCategory;
712     }
713 
714     /**
715      * @param _nIdCategory
716      *            the _nIdCategory to set
717      */
718     public void setIdCategory( int nIdCategory )
719     {
720         this._nIdCategory = nIdCategory;
721     }
722 
723     /**
724      * @return the bBackupEnabled
725      */
726     public boolean isBackupEnabled( )
727     {
728         return _bBackupEnabled;
729     }
730 
731     /**
732      * @param bBackupEnabled the bBackupEnabled to set
733      */
734     public void setBackupEnabled( boolean bBackupEnabled )
735     {
736         _bBackupEnabled = bBackupEnabled;
737     }
738 
739     /**
740      * @return the nBackupStoragePeriod
741      */
742     public int getBackupStoragePeriod( ) {return _nBackupStoragePeriod; }
743 
744     /**
745      * @param backupStoragePeriod the backupStoragePeriod to set
746      */
747     public void setBackupStoragePeriod( int backupStoragePeriod )
748     {
749         _nBackupStoragePeriod = backupStoragePeriod;
750     }
751 
752     /**
753      * @return the id of the category linked to the form
754      */
755     public FormCategory getCategory( )
756     {
757         return FormCategoryHome.findByPrimaryKey( _nIdCategory );
758     }
759     /**
760      * Returns true if the access to responses management on FO is based on the roles, false otherwise
761      * @return true if the access to responses management on FO is based on the roles, false otherwise
762      */ 
763      public boolean isAccessToResponsesByRole()
764      {
765          return _bAccessToResponsesByRole;
766      }
767  
768     /**
769      * Sets the AccessToResponsesByRole
770      * @param bAccessToResponsesByRole The AccessToResponsesByRole
771      */ 
772      public void setAccessToResponsesByRole( boolean bAccessToResponsesByRole )
773      {
774          _bAccessToResponsesByRole = bAccessToResponsesByRole;
775      }
776     /**
777      * Custom comparator for Availability Period sorting
778      */
779 	@Override
780 	public int compare(Formref="../../../../../../fr/paris/lutece/plugins/forms/business/Form.html#Form">Form form1, Form form2) {
781 		int nComparisonResult = NumberUtils.INTEGER_ZERO;
782 		if (form1 == null) {
783 			if (form2 != null) {
784 				nComparisonResult = NumberUtils.INTEGER_MINUS_ONE;
785 			}
786 		} else {
787 			if (form2 == null) {
788 				nComparisonResult = NumberUtils.INTEGER_ONE;
789 			} else {
790 				nComparisonResult = compareFormsAviability(form1, form2);
791 			}
792 		}
793 		return nComparisonResult;
794 	}
795 	
796 	private int compareFormsAviability(Formref="../../../../../../fr/paris/lutece/plugins/forms/business/Form.html#Form">Form form1, Form form2) {
797 		int nComparisonResult = NumberUtils.INTEGER_ZERO;
798 		if (form1.isActive()) {
799 			if (!form2.isActive()) {
800 				nComparisonResult = NumberUtils.INTEGER_ONE;
801 			}
802 		} else {
803 			if (form2.isActive()) {
804 				nComparisonResult = NumberUtils.INTEGER_MINUS_ONE;
805 			} else {
806 				boolean bIsSoonToBeActivatedForm1 = isSoonToBeActivated(form1);
807 				boolean bIsSoonToBeActivatedForm2 = isSoonToBeActivated(form2);
808 				if (bIsSoonToBeActivatedForm1 && !bIsSoonToBeActivatedForm2) {
809 					nComparisonResult = NumberUtils.INTEGER_ONE;
810 				} else if (!bIsSoonToBeActivatedForm1 && bIsSoonToBeActivatedForm2) {
811 					nComparisonResult = NumberUtils.INTEGER_MINUS_ONE;
812 				}
813 			}
814 		}
815 		return nComparisonResult;
816 	}
817 	
818 	/**
819 	 * Returns the soon to be activated status of a form
820 	 * @param form
821 	 * @return true if the form is soon to be activated, false otherwise
822 	 */
823 	private boolean isSoonToBeActivated(Form form) {
824 		Date dToday = new Date(System.currentTimeMillis());
825 		if (form != null && form.getAvailabilityStartDate() != null && form.getAvailabilityStartDate().after(dToday) ) {
826 			return true;
827 		}
828 		return false;
829 	}
830 }