AnnounceService.java
/*
* Copyright (c) 2002-2021, City of Paris
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright notice
* and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice
* and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* License 1.0
*/
package fr.paris.lutece.plugins.announce.service;
import fr.paris.lutece.plugins.announce.business.Announce;
import fr.paris.lutece.plugins.announce.business.AnnounceDTO;
import fr.paris.lutece.plugins.announce.business.AnnounceHome;
import fr.paris.lutece.plugins.announce.business.Category;
import fr.paris.lutece.plugins.announce.business.Sector;
import fr.paris.lutece.plugins.announce.business.SectorHome;
import fr.paris.lutece.plugins.announce.service.upload.AnnounceAsynchronousUploadHandler;
import fr.paris.lutece.plugins.genericattributes.business.Entry;
import fr.paris.lutece.plugins.genericattributes.business.EntryFilter;
import fr.paris.lutece.plugins.genericattributes.business.EntryHome;
import fr.paris.lutece.plugins.genericattributes.business.Field;
import fr.paris.lutece.plugins.genericattributes.business.FieldHome;
import fr.paris.lutece.plugins.genericattributes.business.GenAttFileItem;
import fr.paris.lutece.plugins.genericattributes.business.GenericAttributeError;
import fr.paris.lutece.plugins.genericattributes.business.Response;
import fr.paris.lutece.plugins.genericattributes.service.entrytype.AbstractEntryTypeUpload;
import fr.paris.lutece.plugins.genericattributes.service.entrytype.EntryTypeServiceManager;
import fr.paris.lutece.plugins.genericattributes.service.entrytype.IEntryTypeService;
import fr.paris.lutece.portal.business.file.File;
import fr.paris.lutece.portal.business.file.FileHome;
import fr.paris.lutece.portal.business.physicalfile.PhysicalFile;
import fr.paris.lutece.portal.business.physicalfile.PhysicalFileHome;
import fr.paris.lutece.portal.service.content.XPageAppService;
import fr.paris.lutece.portal.service.security.LuteceUser;
import fr.paris.lutece.portal.service.security.SecurityService;
import fr.paris.lutece.portal.service.security.UserNotSignedException;
import fr.paris.lutece.portal.service.template.AppTemplateService;
import fr.paris.lutece.portal.service.util.AppPathService;
import fr.paris.lutece.portal.util.mvc.utils.MVCUtils;
import fr.paris.lutece.util.html.HtmlTemplate;
import fr.paris.lutece.util.url.UrlItem;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.fileupload.FileItem;
import java.io.Serializable;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
/**
* Service for announces
*/
public class AnnounceService implements Serializable
{
/**
* Pattern for dates
*/
public static final String PATTERN_DATE = "dd/MM/yyyy";
/**
* Name of the bean of the service
*/
public static final String BEAN_NAME = "announce.announceService";
private static final long serialVersionUID = 6197939507943704211L;
private static final String VIEW_GET_FORM = "viewForm";
private static final String PARAMETER_ID_CATEGORY = "id_form";
private static final String PREFIX_ATTRIBUTE = "attribute";
// marks
private static final String MARK_LOCALE = "locale";
private static final String MARK_ENTRY = "entry";
private static final String MARK_FIELD = "field";
private static final String MARK_STR_LIST_CHILDREN = "str_list_entry_children";
private static final String MARK_CATEGORY = "category";
private static final String MARK_SECTOR = "sector";
private static final String MARK_STR_ENTRY = "str_entry";
private static final String MARK_USER = "user";
private static final String MARK_LIST_RESPONSES = "list_responses";
private static final String MARK_UPLOAD_HANDLER = "uploadHandler";
// Templates
private static final String TEMPLATE_DIV_CONDITIONAL_ENTRY = "skin/plugins/announce/html_code_div_conditional_entry.html";
private static final String TEMPLATE_HTML_CODE_FORM = "skin/plugins/announce/html_code_form.html";
private static final String TEMPLATE_HTML_CODE_FORM_ADMIN = "admin/plugins/announce/html_code_form.html";
/**
* Return the HTML code of the form
*
* @param announce
* The announce the get the HTML form of, or null to get a default form for the given category. The list of responses of the announce must have
* been set if the announce is not null.
* @param category
* the category to display the form of
* @param locale
* the locale
* @param bDisplayFront
* True if the entry will be displayed in Front Office, false if it will be displayed in Back Office.
* @param request
* HttpServletRequest
* @return the HTML code of the form
*/
public String getHtmlAnnounceForm( Announce announce, Category category, Locale locale, boolean bDisplayFront, HttpServletRequest request )
{
Map<String, Object> model = new HashMap<>( );
StringBuffer strBuffer = new StringBuffer( );
EntryFilter filter = new EntryFilter( );
filter.setIdResource( category.getId( ) );
filter.setResourceType( Category.RESOURCE_TYPE );
filter.setEntryParentNull( EntryFilter.FILTER_TRUE );
filter.setFieldDependNull( EntryFilter.FILTER_TRUE );
AnnounceDTO announceDTO = null;
if ( announce != null )
{
if ( ( announce.getListResponse( ) == null ) && ( announce.getId( ) > 0 ) )
{
announce.setListResponse( AnnounceHome.findListResponse( announce.getId( ), true ) );
}
announceDTO = new AnnounceDTO( announce );
if ( announce.getListResponse( ) != null )
{
for ( Response response : announce.getListResponse( ) )
{
if ( ( response.getFile( ) != null ) && ( response.getFile( ).getIdFile( ) > 0 ) )
{
File file = FileHome.findByPrimaryKey( response.getFile( ).getIdFile( ) );
PhysicalFile physicalFile = PhysicalFileHome.findByPrimaryKey( file.getPhysicalFile( ).getIdPhysicalFile( ) );
FileItem fileItem = new GenAttFileItem( physicalFile.getValue( ), file.getTitle( ) );
AnnounceAsynchronousUploadHandler.getHandler( ).addFileItemToUploadedFilesList( fileItem,
IEntryTypeService.PREFIX_ATTRIBUTE + Integer.toString( response.getEntry( ).getIdEntry( ) ), request );
}
}
Map<Integer, List<Response>> mapResponsesByIdEntry = announceDTO.getMapResponsesByIdEntry( );
for ( Response response : announce.getListResponse( ) )
{
List<Response> listResponse = mapResponsesByIdEntry.get( response.getEntry( ).getIdEntry( ) );
if ( listResponse == null )
{
listResponse = new ArrayList<>( );
mapResponsesByIdEntry.put( response.getEntry( ).getIdEntry( ), listResponse );
}
listResponse.add( response );
}
}
}
List<Entry> listEntryFirstLevel = EntryHome.getEntryList( filter );
for ( Entry entry : listEntryFirstLevel )
{
getHtmlEntry( announceDTO, entry.getIdEntry( ), strBuffer, locale, bDisplayFront, request );
}
Sector sector = SectorHome.findByPrimaryKey( category.getIdSector( ) );
model.put( MARK_CATEGORY, category );
model.put( MARK_SECTOR, sector );
model.put( MARK_STR_ENTRY, strBuffer.toString( ) );
model.put( MARK_LOCALE, locale );
HtmlTemplate template = AppTemplateService.getTemplate( bDisplayFront ? TEMPLATE_HTML_CODE_FORM : TEMPLATE_HTML_CODE_FORM_ADMIN, locale, model );
return template.getHtml( );
}
/**
* Insert in the string buffer the content of the HTML code of the entry
*
* @param announce
* The announce to load current values, or null to use default values
* @param nIdEntry
* the key of the entry which HTML code must be insert in the stringBuffer
* @param stringBuffer
* the buffer which contains the HTML code
* @param locale
* the locale
* @param bDisplayFront
* True if the entry will be displayed in Front Office, false if it will be displayed in Back Office.
* @param request
* HttpServletRequest
*/
public void getHtmlEntry( AnnounceDTO announce, int nIdEntry, StringBuffer stringBuffer, Locale locale, boolean bDisplayFront, HttpServletRequest request )
{
Map<String, Object> model = new HashMap<>( );
StringBuilder strConditionalQuestionStringBuffer = null;
HtmlTemplate template;
Entry entry = EntryHome.findByPrimaryKey( nIdEntry );
if ( Boolean.TRUE.equals( entry.getEntryType( ).getGroup( ) ) )
{
StringBuffer strGroupStringBuffer = new StringBuffer( );
for ( Entry entryChild : entry.getChildren( ) )
{
getHtmlEntry( announce, entryChild.getIdEntry( ), strGroupStringBuffer, locale, bDisplayFront, request );
}
model.put( MARK_STR_LIST_CHILDREN, strGroupStringBuffer.toString( ) );
}
else
{
if ( entry.getNumberConditionalQuestion( ) != 0 )
{
for ( Field field : entry.getFields( ) )
{
field.setConditionalQuestions( FieldHome.findByPrimaryKey( field.getIdField( ) ).getConditionalQuestions( ) );
}
}
}
if ( entry.getNumberConditionalQuestion( ) != 0 )
{
strConditionalQuestionStringBuffer = new StringBuilder( );
for ( Field field : entry.getFields( ) )
{
if ( CollectionUtils.isNotEmpty( field.getConditionalQuestions( ) ) )
{
StringBuffer strGroupStringBuffer = new StringBuffer( );
for ( Entry entryConditional : field.getConditionalQuestions( ) )
{
getHtmlEntry( announce, entryConditional.getIdEntry( ), strGroupStringBuffer, locale, bDisplayFront, request );
}
model.put( MARK_STR_LIST_CHILDREN, strGroupStringBuffer.toString( ) );
model.put( MARK_FIELD, field );
template = AppTemplateService.getTemplate( TEMPLATE_DIV_CONDITIONAL_ENTRY, locale, model );
strConditionalQuestionStringBuffer.append( template.getHtml( ) );
}
}
model.put( MARK_STR_LIST_CHILDREN, strConditionalQuestionStringBuffer.toString( ) );
}
model.put( MARK_ENTRY, entry );
model.put( MARK_LOCALE, locale );
LuteceUser user = SecurityService.getInstance( ).getRegisteredUser( request );
if ( ( user == null ) && SecurityService.isAuthenticationEnable( ) && SecurityService.getInstance( ).isExternalAuthentication( ) )
{
try
{
user = SecurityService.getInstance( ).getRemoteUser( request );
}
catch( UserNotSignedException e )
{
// Nothing to do : lutece user is not mandatory
}
}
model.put( MARK_USER, user );
if ( ( announce != null ) && ( announce.getMapResponsesByIdEntry( ) != null ) )
{
List<Response> listResponses = announce.getMapResponsesByIdEntry( ).get( entry.getIdEntry( ) );
if ( listResponses != null )
{
for ( Response response : listResponses )
{
for ( Field filed : entry.getFields( ) )
{
if ( response.getField( ) != null && filed.getIdField( ) == response.getField( ).getIdField( ) )
{
response.setField( filed );
}
}
}
}
model.put( MARK_LIST_RESPONSES, listResponses );
}
IEntryTypeService entryTypeService = EntryTypeServiceManager.getEntryTypeService( entry );
// If the entry type is a file, we add the
if ( entryTypeService instanceof AbstractEntryTypeUpload )
{
model.put( MARK_UPLOAD_HANDLER, ( (AbstractEntryTypeUpload) entryTypeService ).getAsynchronousUploadHandler( ) );
}
template = AppTemplateService.getTemplate( EntryTypeServiceManager.getEntryTypeService( entry ).getTemplateHtmlForm( entry, bDisplayFront ), locale,
model );
stringBuffer.append( template.getHtml( ) );
}
/**
* Get the responses associated with an entry.<br />
* Return null if there is no error in the response, or return the list of errors Response created are stored the map of {@link AnnounceDTO}. The key of the
* map is this id of the entry, and the value the list of responses
*
* @param request
* the request
* @param nIdEntry
* the key of the entry
* @param locale
* the locale
* @param announce
* The announce
* @return null if there is no error in the response or the list of errors found
*/
public List<GenericAttributeError> getResponseEntry( HttpServletRequest request, int nIdEntry, Locale locale, AnnounceDTO announce )
{
List<Response> listResponse = new ArrayList<>( );
announce.getMapResponsesByIdEntry( ).put( nIdEntry, listResponse );
return getResponseEntry( request, nIdEntry, listResponse, false, locale, announce );
}
/**
* Get the responses associated with an entry.<br />
* Return null if there is no error in the response, or return the list of errors
*
* @param request
* the request
* @param nIdEntry
* the key of the entry
* @param listResponse
* The list of response to add responses found in
* @param bResponseNull
* true if the response created must be null
* @param locale
* the locale
* @param announce
* The announce
* @return null if there is no error in the response or the list of errors found
*/
private List<GenericAttributeError> getResponseEntry( HttpServletRequest request, int nIdEntry, List<Response> listResponse, boolean bResponseNull,
Locale locale, AnnounceDTO announce )
{
List<GenericAttributeError> listFormErrors = new ArrayList<>( );
Entry entry = EntryHome.findByPrimaryKey( nIdEntry );
List<Field> listField = new ArrayList<>( );
for ( Field field : entry.getFields( ) )
{
field = FieldHome.findByPrimaryKey( field.getIdField( ) );
listField.add( field );
}
entry.setFields( listField );
if ( Boolean.TRUE.equals( entry.getEntryType( ).getGroup( ) ) )
{
for ( Entry entryChild : entry.getChildren( ) )
{
List<Response> listResponseChild = new ArrayList<>( );
announce.getMapResponsesByIdEntry( ).put( entryChild.getIdEntry( ), listResponseChild );
listFormErrors.addAll( getResponseEntry( request, entryChild.getIdEntry( ), listResponseChild, false, locale, announce ) );
}
}
else
if ( !Boolean.TRUE.equals( entry.getEntryType( ).getComment( ) ) )
{
GenericAttributeError formError = null;
if ( !bResponseNull )
{
formError = EntryTypeServiceManager.getEntryTypeService( entry ).getResponseData( entry, request, listResponse, locale );
if ( formError != null )
{
formError.setUrl( getEntryUrl( entry ) );
}
}
else
{
Response response = new Response( );
response.setEntry( entry );
listResponse.add( response );
}
if ( formError != null )
{
entry.setError( formError );
listFormErrors.add( formError );
}
if ( entry.getNumberConditionalQuestion( ) != 0 )
{
for ( Field field : entry.getFields( ) )
{
boolean bIsFieldInResponseList = isFieldInTheResponseList( field.getIdField( ), listResponse );
for ( Entry conditionalEntry : field.getConditionalQuestions( ) )
{
List<Response> listResponseChild = new ArrayList<>( );
announce.getMapResponsesByIdEntry( ).put( conditionalEntry.getIdEntry( ), listResponseChild );
listFormErrors.addAll(
getResponseEntry( request, conditionalEntry.getIdEntry( ), listResponseChild, !bIsFieldInResponseList, locale, announce ) );
}
}
}
}
return listFormErrors;
}
/**
* Check if a field is in a response list
*
* @param nIdField
* the id of the field to search
* @param listResponse
* the list of responses
* @return true if the field is in the response list, false otherwise
*/
public Boolean isFieldInTheResponseList( int nIdField, List<Response> listResponse )
{
for ( Response response : listResponse )
{
if ( ( response.getField( ) != null ) && ( response.getField( ).getIdField( ) == nIdField ) )
{
return true;
}
}
return false;
}
/**
* Get the URL to modify an entry of the form in front office
*
* @param entry
* the entry
* @return The URL to modify the entry in front office
*/
public String getEntryUrl( Entry entry )
{
UrlItem url = new UrlItem( AppPathService.getPortalUrl( ) );
url.addParameter( XPageAppService.PARAM_XPAGE_APP, AnnouncePlugin.PLUGIN_NAME );
url.addParameter( MVCUtils.PARAMETER_VIEW, VIEW_GET_FORM );
if ( ( entry != null ) && ( entry.getIdResource( ) > 0 ) )
{
url.addParameter( PARAMETER_ID_CATEGORY, entry.getIdResource( ) );
url.setAnchor( PREFIX_ATTRIBUTE + entry.getIdEntry( ) );
}
return url.getUrl( );
}
/**
* Convert an AppointmentDTO to an Appointment by transferring response from the map of class AppointmentDTO to the list of class Appointment.
*
* @param announce
* The announce to get the map to convert
*/
public void convertMapResponseToList( AnnounceDTO announce )
{
List<Response> listResponse = new ArrayList<>( );
for ( List<Response> listResponseByEntry : announce.getMapResponsesByIdEntry( ).values( ) )
{
listResponse.addAll( listResponseByEntry );
}
announce.setMapResponsesByIdEntry( null );
announce.setListResponse( listResponse );
}
/**
* Get the date format to use
*
* @return The date format to use
*/
public static DateFormat getDateFormat( )
{
DateFormat dateFormat = new SimpleDateFormat( PATTERN_DATE, Locale.FRENCH );
dateFormat.setLenient( false );
return dateFormat;
}
}