View Javadoc
1   /*
2    * Copyright (c) 2002-2022, 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.service.provider;
35  
36  import java.util.ArrayList;
37  import java.util.Collection;
38  import java.util.HashMap;
39  import java.util.List;
40  import java.util.Locale;
41  import java.util.Map;
42  
43  import javax.servlet.http.HttpServletRequest;
44  
45  import fr.paris.lutece.plugins.forms.business.Form;
46  import fr.paris.lutece.plugins.forms.business.FormHome;
47  import fr.paris.lutece.plugins.forms.business.FormQuestionResponse;
48  import fr.paris.lutece.plugins.forms.business.FormQuestionResponseHome;
49  import fr.paris.lutece.plugins.forms.business.FormResponse;
50  import fr.paris.lutece.plugins.forms.business.Question;
51  import fr.paris.lutece.plugins.forms.business.QuestionHome;
52  import fr.paris.lutece.plugins.forms.service.entrytype.EntryTypeAutomaticFileReading;
53  import fr.paris.lutece.plugins.forms.service.entrytype.EntryTypeCamera;
54  import fr.paris.lutece.plugins.forms.service.entrytype.EntryTypeComment;
55  import fr.paris.lutece.plugins.forms.service.entrytype.EntryTypeFile;
56  import fr.paris.lutece.plugins.forms.service.entrytype.EntryTypeGalleryImage;
57  import fr.paris.lutece.plugins.forms.service.entrytype.EntryTypeImage;
58  import fr.paris.lutece.plugins.forms.util.FormsConstants;
59  import fr.paris.lutece.plugins.genericattributes.business.Response;
60  import fr.paris.lutece.plugins.genericattributes.service.entrytype.EntryTypeServiceManager;
61  import fr.paris.lutece.plugins.genericattributes.service.entrytype.IEntryTypeService;
62  import fr.paris.lutece.plugins.workflowcore.service.provider.InfoMarker;
63  import fr.paris.lutece.portal.business.file.File;
64  import fr.paris.lutece.portal.business.file.FileHome;
65  import fr.paris.lutece.portal.business.physicalfile.PhysicalFile;
66  import fr.paris.lutece.portal.business.physicalfile.PhysicalFileHome;
67  import fr.paris.lutece.portal.service.i18n.I18nService;
68  import fr.paris.lutece.portal.service.util.AppPathService;
69  import fr.paris.lutece.portal.service.util.AppPropertiesService;
70  import fr.paris.lutece.util.url.UrlItem;
71  
72  public abstract class GenericFormsProvider {
73  	
74  	// PROPERTY
75  	private static final String PROPERTY_EXPORT_IMAGES_IN_BASE64 = "forms.export.image.base64";
76  	
77  	// MARKS
78  	private static final String MARK_POSITION = "position_";
79  	private static final String MARK_URL_ADMIN_RESPONSE = "url_admin_forms_response_detail";
80  	private static final String MARK_URL_FO_RESPONSE = "url_fo_forms_response_detail";
81  	private static final String MARK_CREATION_DATE = "creation_date";
82  	private static final String MARK_UPDATE_DATE = "update_date";
83  	private static final String MARK_STATUS = "status";
84  	private static final String MARK_STATUS_UPDATE_DATE = "update_date_status";
85  	private static final String MARK_BASE_URL = "base_url";
86  	private static final String MARKER_DESCRIPTION_BASE64 = "base64";
87  	private static final String MARKER_FORM_TITLE = "form_title";
88  	
89  	// URL PARAMETERS
90  	private static final String PARAMETER_VIEW_FORM_RESPONSE_DETAILS = "view_form_response_details";
91  	private static final String PARAMETER_VIEW_FORM_RESPONSE_DETAILS_FO = "formResponseView";
92  	private static final String PARAMETER_ID_FORM_RESPONSES = "id_form_response";
93  	private static final String PARAMETER_ID_FORM_RESPONSES_FO = "id_response";
94  	private static final String PARAMETER_PAGE_FORM_RESPONSE = "formsResponse";
95  	
96      // Infomarkers description I18n keys
97      private static final String MESSAGE_I18N_DESCRIPTION = "forms.marker.provider.url.admin.detail.reponse.description";
98      private static final String MESSAGE_I18N_FO_DESCRIPTION = "forms.marker.provider.url.fo.detail.reponse.description";
99      private static final String MESSAGE_I18N_CREATION_DATE = "forms.marker.provider.url.detail.reponse.creation_date";
100     private static final String MESSAGE_I18N_UPDATE_DATE = "forms.marker.provider.url.detail.reponse.update_date";
101     private static final String MESSAGE_I18N_STATUS = "forms.marker.provider.url.detail.reponse.status";
102     private static final String MESSAGE_I18N_STATUS_UPDATE_DATE = "forms.marker.provider.url.detail.reponse.status_update_date";
103     private static final String MESSAGE_I18N_FORM = "forms.marker.provider.url.detail.reponse.form";
104 
105 	/**
106 	 * provide forms values as model (map)
107 	 * 
108 	 * @param formResponse
109 	 * @param request
110 	 * @return the model map
111 	 */
112 	public static Map<String, Object> getValuesModel( FormResponse formResponse, HttpServletRequest request )
113 	{
114 		Map<String, Object> model = new HashMap<>( );
115 
116 		List<FormQuestionResponse> listFormQuestionResponse = FormQuestionResponseHome.getFormQuestionResponseListByFormResponse( formResponse.getId( ) );
117 		Boolean bExportImageBase64 = AppPropertiesService.getPropertyBoolean( PROPERTY_EXPORT_IMAGES_IN_BASE64, false);
118 		
119 		for ( FormQuestionResponse formQuestionResponse : listFormQuestionResponse )
120 		{
121 			IEntryTypeService entryTypeService = EntryTypeServiceManager.getEntryTypeService(formQuestionResponse.getQuestion().getEntry());
122 			
123 			if ( entryTypeService instanceof EntryTypeComment || entryTypeService instanceof EntryTypeImage || entryTypeService instanceof EntryTypeCamera || entryTypeService instanceof EntryTypeGalleryImage || entryTypeService instanceof EntryTypeFile || entryTypeService instanceof EntryTypeAutomaticFileReading) 
124 			{
125 				List<fr.paris.lutece.plugins.genericattributes.business.Response> responses = formQuestionResponse.getEntryResponse( );
126 				for (int i = 0; i < responses.size(); i++) 
127 				{
128 					if (responses.get(i).getFile() != null) 
129 					{
130 						File file = FileHome.findByPrimaryKey( responses.get(i).getFile().getIdFile( ) );
131 						if (entryTypeService instanceof EntryTypeImage || entryTypeService instanceof EntryTypeCamera || entryTypeService instanceof EntryTypeGalleryImage) 
132 						{
133 							// if property forms.export.image.base64 is true
134 							if (bExportImageBase64) 
135 							{
136 								PhysicalFile physicalFile = PhysicalFileHome.findByPrimaryKey(file.getPhysicalFile().getIdPhysicalFile());
137 								byte[] bytes = physicalFile.getValue();
138 								String strBase64 = java.util.Base64.getEncoder().encodeToString(bytes);
139 								responses.get(i).setResponseValue(strBase64);
140 							}
141 						}
142 						responses.get(i).setFile(file);
143 					}
144 				}
145 			}
146 			
147 			// in case of multiple FormQuestionResponse for the same question (when there is an iteration), 
148 			// we merge them into one FormQuestionResponse and update the marker
149 			String strMultipleFormQuestionResponseKey = MARK_POSITION + formQuestionResponse.getQuestion().getId( ) ;
150 			if (model.containsKey( strMultipleFormQuestionResponseKey ) )
151 			{
152 				FormQuestionResponse existingFormQuestionResponse = (FormQuestionResponse) model.get( strMultipleFormQuestionResponseKey );
153 				
154 				List<Response> existingResponses = existingFormQuestionResponse.getEntryResponse();
155 				List<Response> newResponses = formQuestionResponse.getEntryResponse();
156 				List<Response> allResponses = new ArrayList<>();
157 				
158 				allResponses.addAll(existingResponses);
159 				allResponses.addAll(newResponses);
160 				
161 				existingFormQuestionResponse.setEntryResponse(allResponses);
162 				model.replace( strMultipleFormQuestionResponseKey, existingFormQuestionResponse);
163 			} 
164 			else 
165 			{
166 				model.put( strMultipleFormQuestionResponseKey , formQuestionResponse);
167 			}
168 		}
169 		
170 		// Additional markers
171 		model.put( MARKER_DESCRIPTION_BASE64, bExportImageBase64 );
172 		model.put( MARK_CREATION_DATE, formResponse.getCreation( )  );
173 		model.put( MARK_UPDATE_DATE, formResponse.getUpdate( ) );
174 		model.put( MARK_STATUS, formResponse.isPublished( ) );
175 		model.put( MARK_STATUS_UPDATE_DATE, formResponse.getUpdateStatus( )  );
176 		model.put( MARKER_FORM_TITLE, FormHome.findByPrimaryKey( formResponse.getFormId( ) ).getTitle( ) );
177 		
178 		// request may be null in case of daemon execution
179 		if ( request != null )
180 		{
181 			model.put( MARK_BASE_URL, AppPathService.getBaseUrl( request ) );
182 		
183 			UrlItem adminUrl = new UrlItem( AppPathService.getProdUrl( request ) + AppPathService.getAdminMenuUrl( ) );
184 			adminUrl.addParameter( FormsConstants.PARAMETER_TARGET_VIEW, PARAMETER_VIEW_FORM_RESPONSE_DETAILS );
185 			adminUrl.addParameter( PARAMETER_ID_FORM_RESPONSES, formResponse.getId( ) );
186 			model.put( MARK_URL_ADMIN_RESPONSE, adminUrl.getUrl( )  );
187 	
188 			UrlItem url = new UrlItem( AppPathService.getProdUrl( request ) + AppPathService.getPortalUrl( ) );
189 			url.addParameter( FormsConstants.PARAMETER_PAGE, PARAMETER_PAGE_FORM_RESPONSE );
190 			url.addParameter( FormsConstants.PARAMETER_TARGET_VIEW, PARAMETER_VIEW_FORM_RESPONSE_DETAILS_FO );
191 			url.addParameter( PARAMETER_ID_FORM_RESPONSES_FO, formResponse.getId( ) );
192 			model.put( MARK_URL_FO_RESPONSE, url.getUrl( ) );
193 		}
194 
195 		return model;
196 	}
197 
198 
199 	/**
200 	 * Get the question titles as model, for the given form
201 	 * 
202 	 * @param form
203 	 *            The form
204 	 * @return the map of markers
205 	 */
206 	public static Map<String, Object> getTitlesModel( Form form )
207 	{
208 		Map<String, Object> model = new HashMap<>( );
209 
210 		if (form != null )
211 		{	
212 			List<Question> listFormQuestions = QuestionHome.getListQuestionByIdForm( form.getId( ) );
213 	
214 			for ( Question formQuestion : listFormQuestions )
215 			{
216 				model.put( MARK_POSITION + formQuestion.getId( ), formQuestion.getTitle( ) );
217 			}
218 		}
219 		
220 		return model;
221 	}
222 	
223 	  /**
224      * Get the reference list of available InfoMarkers
225      * 
226      * @param form
227      *            The form
228      * @return the collection of the Markers
229      */
230     public static Collection<InfoMarker> getProviderMarkerDescriptions( Form form )
231     {
232         Collection<InfoMarker> descriptionMarkersList = new ArrayList<>( );
233         
234         if ( form != null )
235         {
236 	        List<Question> listFormQuestions = QuestionHome.getListQuestionByIdForm( form.getId( ) );
237 	
238 	        for ( Question formQuestion : listFormQuestions )
239 	        {
240 	            InfoMarker marker = new InfoMarker( MARK_POSITION + formQuestion.getId( ) );
241 	            marker.setDescription( formQuestion.getTitle( ) );
242 	            descriptionMarkersList.add( marker );
243 	        }
244         }
245         
246         InfoMarker markerAdminURl = new InfoMarker( MARK_URL_ADMIN_RESPONSE );
247         markerAdminURl.setDescription( MESSAGE_I18N_DESCRIPTION );
248         InfoMarker markerFoUrl = new InfoMarker( MARK_URL_FO_RESPONSE );
249         markerFoUrl.setDescription( MESSAGE_I18N_FO_DESCRIPTION );
250         InfoMarker creationDateMarker = new InfoMarker( MARK_CREATION_DATE );
251         creationDateMarker.setDescription( MESSAGE_I18N_CREATION_DATE );
252         InfoMarker updateDateMarker = new InfoMarker( MARK_UPDATE_DATE );
253         updateDateMarker.setDescription( MESSAGE_I18N_UPDATE_DATE );
254         InfoMarker statusMarker = new InfoMarker( MARK_STATUS );
255         statusMarker.setDescription( MESSAGE_I18N_STATUS );
256         InfoMarker updateStatusDateMarker = new InfoMarker( MARK_STATUS_UPDATE_DATE );
257         updateStatusDateMarker.setDescription( MESSAGE_I18N_STATUS_UPDATE_DATE );
258         InfoMarker formTitleMarker = new InfoMarker( MARKER_FORM_TITLE );
259         formTitleMarker.setDescription( MESSAGE_I18N_FORM );
260         
261         descriptionMarkersList.add( markerAdminURl );
262         descriptionMarkersList.add( markerFoUrl );
263         descriptionMarkersList.add( creationDateMarker );
264         descriptionMarkersList.add( updateDateMarker );
265         descriptionMarkersList.add( statusMarker );
266         descriptionMarkersList.add( updateStatusDateMarker );
267         descriptionMarkersList.add( formTitleMarker );
268         
269         return descriptionMarkersList;
270     }
271 }