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