IdeationApp.java
/*
* Copyright (c) 2002-2020, 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.participatoryideation.web;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.lang.StringUtils;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import fr.paris.lutece.plugins.leaflet.business.GeolocItem;
import fr.paris.lutece.plugins.participatoryideation.business.capgeo.QpvQva;
import fr.paris.lutece.plugins.participatoryideation.business.proposal.Proposal;
import fr.paris.lutece.plugins.participatoryideation.service.IdeationErrorException;
import fr.paris.lutece.plugins.participatoryideation.service.IdeationStaticService;
import fr.paris.lutece.plugins.participatoryideation.service.IdeationUploadHandler;
import fr.paris.lutece.plugins.participatoryideation.service.ProposalService;
import fr.paris.lutece.plugins.participatoryideation.service.ProposalWSService;
import fr.paris.lutece.plugins.participatoryideation.service.campaign.IdeationCampaignDataProvider;
import fr.paris.lutece.plugins.participatoryideation.service.capgeo.QpvQvaService;
import fr.paris.lutece.plugins.participatoryideation.service.myinfos.MyInfosService;
import fr.paris.lutece.plugins.participatoryideation.util.ParticipatoryIdeationConstants;
import fr.paris.lutece.plugins.participatoryideation.web.etape.FormEtapeApprox;
import fr.paris.lutece.plugins.participatoryideation.web.etape.FormEtapeDescription;
import fr.paris.lutece.plugins.participatoryideation.web.etape.FormEtapeLocation;
import fr.paris.lutece.plugins.participatoryideation.web.etape.FormEtapeRecap;
import fr.paris.lutece.plugins.participatoryideation.web.etape.FormEtapeTitle;
import fr.paris.lutece.plugins.participatoryideation.web.etape.FormEtapeUpload;
import fr.paris.lutece.plugins.participatoryideation.web.etape.IFormEtape;
import fr.paris.lutece.plugins.search.solr.business.SolrHighlights;
import fr.paris.lutece.plugins.search.solr.business.SolrSearchResult;
import fr.paris.lutece.plugins.search.solr.business.SolrServerService;
import fr.paris.lutece.plugins.search.solr.indexer.SolrItem;
import fr.paris.lutece.plugins.search.solr.util.SolrUtil;
import fr.paris.lutece.portal.business.file.File;
import fr.paris.lutece.portal.business.physicalfile.PhysicalFile;
import fr.paris.lutece.portal.service.datastore.DatastoreService;
import fr.paris.lutece.portal.service.message.SiteMessage;
import fr.paris.lutece.portal.service.message.SiteMessageException;
import fr.paris.lutece.portal.service.message.SiteMessageService;
import fr.paris.lutece.portal.service.plugin.Plugin;
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.spring.SpringContextService;
import fr.paris.lutece.portal.service.util.AppLogService;
import fr.paris.lutece.portal.service.util.AppPathService;
import fr.paris.lutece.portal.service.util.AppPropertiesService;
import fr.paris.lutece.portal.service.workflow.WorkflowService;
import fr.paris.lutece.portal.util.mvc.commons.annotations.Action;
import fr.paris.lutece.portal.util.mvc.commons.annotations.View;
import fr.paris.lutece.portal.util.mvc.utils.MVCUtils;
import fr.paris.lutece.portal.util.mvc.xpage.MVCApplication;
import fr.paris.lutece.portal.util.mvc.xpage.annotations.Controller;
import fr.paris.lutece.portal.web.xpages.XPage;
import fr.paris.lutece.util.filesystem.FileSystemUtil;
/**
* This class provides a simple implementation of an XPage
*/
@Controller( xpageName = "ideation", pageTitleI18nKey = "participatoryideation.xpage.ideation.pageTitle", pagePathI18nKey = "participatoryideation.xpage.ideation.pagePathLabel" )
public class IdeationApp extends MVCApplication
{
// *********************************************************************************************
// * STATIC STATIC STATIC STATIC STATIC STATIC STATIC STATIC STATIC STATIC STATIC STATIC STATI *
// * STATIC STATIC STATIC STATIC STATIC STATIC STATIC STATIC STATIC STATIC STATIC STATIC STATI *
// *********************************************************************************************
private static final long serialVersionUID = -3590277455677622883L;
private static final String TEMPLATE_ETAPES = "/skin/plugins/participatoryideation/etapes.html";
private static final String TEMPLATE_LOCATION = "/skin/plugins/participatoryideation/location.html";
private static final String TEMPLATE_TITLE = "/skin/plugins/participatoryideation/title.html";
private static final String TEMPLATE_APPROX = "/skin/plugins/participatoryideation/approx.html";
private static final String TEMPLATE_DESCRIPTION = "/skin/plugins/participatoryideation/description.html";
private static final String TEMPLATE_UPLOAD = "/skin/plugins/participatoryideation/upload.html";
private static final String TEMPLATE_RECAP = "/skin/plugins/participatoryideation/recap.html";
private static final String TEMPLATE_CONFIRMED = "/skin/plugins/participatoryideation/confirmed.html";
// Jsp redirections
private static final String JSP_PORTAL = "jsp/site/Portal.jsp";
// Views/Actions
private static final String STEP_LOCATION = "location";
private static final String STEP_TITLE = "title";
private static final String STEP_APPROX = "approx";
private static final String STEP_DESCRIPTION = "description";
private static final String STEP_UPLOAD = "upload";
private static final String STEP_RECAP = "recap";
private static final String STEP_CONFIRMED = "confirmed";
private static final String ACTION_ABANDON = "abandon";
// Parameters
private static final String PARAMETER_APPROX_SOLR_DBG = "mdpdbg";
private static final String PARAMETER_PAGE = "page";
private static final String PARAMETER_CONF = "conf";
private static final String PARAMETER_CAMPAIGN = "campaign";
private static final String PARAMETER_REINIT = "init";
private static final String PARAMETER_REINIT_VALUE = "true";
// Markers
private static final String MARK_APPROX_KEYWORD_LIST = "results_keyword_list";
private static final String MARK_APPROX_PREVIOUS_CAMPAIGNS_LIST = "results_previous_campaigns_list";
private static final String MARK_APPROX_LOCATION_LIST = "results_location_list";
private static final String MARK_APPROX_KEYWORD_SOLR_DBG = "solr_keyword_query_dbg";
private static final String MARK_APPROX_LOCATION_SOLR_DBG = "solr_location_query_dbg";
private static final String MARK_STEPS_INDEX = "cur_etape_index";
private static final String MARK_STEPS_CONTENT = "cur_etape_content";
private static final String MARK_FORM_ETAPE_LOCATION = "form_etape_location";
private static final String MARK_FORM_ETAPE_TITLE = "form_etape_title";
private static final String MARK_FORM_ETAPE_APPROX = "form_etape_approx";
private static final String MARK_FORM_ETAPE_DESCRIPTION = "form_etape_description";
private static final String MARK_FORM_ETAPE_UPLOAD = "form_etape_upload";
private static final String MARK_FORM_ETAPE_RECAP = "form_etape_recap";
private static final String MARK_HANDLER = "handler";
private static final String MARK_UPLOAD_DOCS = "docs";
private static final String MARK_UPLOAD_IMGS = "imgs";
private static final String MARK_RECAP_CODE_THEME = "recap_code_theme";
private static final String MARK_RECAP_LOCATION_TYPE = "recap_location_type";
private static final String MARK_RECAP_LOCATION_ARDT = "recap_location_ardt";
private static final String MARK_RECAP_LOCATION_ADRESS = "recap_location_adress";
private static final String MARK_RECAP_TITLE = "recap_title";
private static final String MARK_RECAP_SUBMITTER_TYPE = "recap_submitter_type";
private static final String MARK_RECAP_SUBMITTER = "recap_submitter";
private static final String MARK_RECAP_DESCRIPTION = "recap_description";
private static final String MARK_RECAP_COUT = "recap_cout";
private static final String MARK_RECAP_DOCS = "recap_docs";
private static final String MARK_RECAP_IMGS = "recap_imgs";
private static final String MARK_RECAP_PROPOSAL_CREATED_CODE = "proposal_created_code";
private static final String MARK_RECAP_PROPOSAL_CREATED_CAMPAIGN = "proposal_created_campaign";
private static final String MARK_RECAP_PROPOSAL_CREATED_REFERENCE = "proposal_created_reference";
private static final String MARK_CAMPAIGN_THEMES = "themes";
private static final String MARK_CAMPAIGN_LOCALIZED_AREA_LABELS = "localized_area_labels";
private static final String MARK_CAMPAIGN_WHOLE_AREA_LABEL = "whole_area_label";
private static final String MARK_CAMPAIGN_SUBMITTER_TYPES = "submitter_types";
public static final String QPV_QVA_QPV = "NQPV";
public static final String QPV_QVA_QVA = "QVA";
public static final String QPV_QVA_NO = "NON";
public static final String QPV_QVA_ERR = "ERR";
public static final String QPV_QVA_GPRU = "GPRU";
public static final String QPV_QVA_QBP = "QBP";
public static final String FIELD4_LABEL_YES = "yes";
public static final String FIELD4_LABEL_NO = "no";
private static final String PROPERTY_NEWPROJECTS_GEOLOC_FIELD = "participatoryideation.approx.newprojects.geoloc_field";
private static final String PROPERTY_NEWPROJECTS_ARDT_FIELD = "participatoryideation.approx.newprojects.ardt_field";
private static final String PROPERTY_OLDPROJECTS_ARDT_FIELD = "participatoryideation.approx.oldprojects.ardt_field";
private static final String PROPERTY_NEWPROJECTS_TYPE = "participatoryideation.approx.newprojects.type";
private static final String MESSAGE_CAMPAIGN_UNSPECIFIED = "participatoryideation.messages.campaign.unspecified";
private static final String MESSAGE_CAMPAIGN_UNKNOWN = "participatoryideation.messages.campaign.unknown";
private static final String MESSAGE_CAMPAIGN_IDEATION_CLOSED_SUBMIT = "participatoryideation.messages.campaign.ideation.closed.submit";
private static final String SOLR_NEWPROJECTS_GEOLOC_FIELD = AppPropertiesService.getProperty( PROPERTY_NEWPROJECTS_GEOLOC_FIELD, "proposal_geoloc" );
private static final String SOLR_NEWPROJECTS_ARDT_FIELD = AppPropertiesService.getProperty( PROPERTY_NEWPROJECTS_ARDT_FIELD, "location_ardt_text" );
private static final String SOLR_OLDPROJECTS_ARDT_FIELD = AppPropertiesService.getProperty( PROPERTY_OLDPROJECTS_ARDT_FIELD, "location_text" );
private static final String SOLR_NEWPROJECTS_TYPE = AppPropertiesService.getProperty( PROPERTY_NEWPROJECTS_TYPE, "proposal" );
private static final String SOLR_PREVIOUS_CAMPAIGNS = "((type:proposal AND statut_publique_project_text:\"NONRETENU\") OR (type:\"PB Project\" AND statut_project_text:\"SUIVI\"))";
private static final String DSKEY_APPROX_SCORE_RATIO_LIMIT = "participatoryideation.site_property.form.approx.scoreRatioLimit";
private static final String DSKEY_APPROX_DISTANCE_LIMIT = "participatoryideation.site_property.form.approx.distanceLimit";
private static final String DSKEY_APPROX_KEYWORD_RESULTS_COUNT = "participatoryideation.site_property.form.approx.keywordResultsCount";
private static final String DSKEY_APPROX_LOCATION_RESULTS_COUNT = "participatoryideation.site_property.form.approx.locationResultsCount";
private static final String DSKEY_APPROX_PREVIOUS_CAMPAIGNS_RESULTS_COUNT = "participatoryideation.site_property.form.approx.previousCampaignsResultsCount";
// *********************************************************************************************
// * ATTRIBUTES ATTRIBUTES ATTRIBUTES ATTRIBUTES ATTRIBUTES ATTRIBUTES ATTRIBUTES ATTRIBUTES A *
// * ATTRIBUTES ATTRIBUTES ATTRIBUTES ATTRIBUTES ATTRIBUTES ATTRIBUTES ATTRIBUTES ATTRIBUTES A *
// *********************************************************************************************
// To accumulate the results of the form. These represent user input.
FormEtapeLocation _formEtapeLocation;
FormEtapeTitle _formEtapeTitle;
FormEtapeApprox _formEtapeApprox;
FormEtapeDescription _formEtapeDescription;
FormEtapeUpload _formEtapeUpload;
FormEtapeRecap _formEtapeRecap;
Proposal _proposalCreate; // The proposal we are building
Proposal _proposalDisplay; // The last proposal submitted to show in recap, but avoid double submissions
String _strNextStep; // The first non validated step of the form
// *********************************************************************************************
// * CONSTRUCTOR CONSTRUCTOR CONSTRUCTOR CONSTRUCTOR CONSTRUCTOR CONSTRUCTOR CONSTRUCTOR CONST *
// * CONSTRUCTOR CONSTRUCTOR CONSTRUCTOR CONSTRUCTOR CONSTRUCTOR CONSTRUCTOR CONSTRUCTOR CONST *
// *********************************************************************************************
public IdeationApp( )
{
reInitFormSession( );
}
// *********************************************************************************************
// * XPAGE XPAGE XPAGE XPAGE XPAGE XPAGE XPAGE XPAGE XPAGE XPAGE XPAGE XPAGE XPAGE XPAGE XPAGE *
// * XPAGE XPAGE XPAGE XPAGE XPAGE XPAGE XPAGE XPAGE XPAGE XPAGE XPAGE XPAGE XPAGE XPAGE XPAGE *
// *********************************************************************************************
@Override
public XPage getPage( HttpServletRequest request, int nMode, Plugin plugin ) throws SiteMessageException, UserNotSignedException
{
String strAction = MVCUtils.getAction( request );
String strView = MVCUtils.getView( request );
// Reinit the form if requested
if ( PARAMETER_REINIT_VALUE.equals( request.getParameter( PARAMETER_REINIT ) ) )
{
reInitFormSession( request );
}
// Check campaign constraints, except if confirmation step because in this case,
// the proposal was stored then the form reinitialized (so there is no stored campaign data anymore).
if ( !STEP_CONFIRMED.equals( strView ) )
{
checkIdeationCampaignPhase( request );
}
// If user's personal infos not filled, then redirect to the 'complete myinfos' webpage
if ( !checkUserAuthorized( request ) )
{
return redirect( request, AppPathService.getProdUrl( request ) + MyInfosService.getInstance( ).getUrlMyInfosFillAction( ) );
}
// Some automatic stuff
if ( SecurityService.isAuthenticationEnable( ) && SecurityService.getInstance( ).getRegisteredUser( request ) != null )
{
_proposalCreate.setLuteceUserName( SecurityService.getInstance( ).getRegisteredUser( request ).getName( ) );
}
else
{
_proposalCreate.setLuteceUserName( "guid" );
}
_proposalCreate.setFromBackOffice(false);
if ( STEP_CONFIRMED.equals( strView ) )
{
// The confirmed step is special, you can view it if you have already completed the form at least once
if ( _proposalDisplay == null )
{
return redirectView( request, _strNextStep );
}
}
else
if ( !ACTION_ABANDON.equals( strAction ) )
{
// View and actions from the steps
if ( !( ( strView == null || allValidBeforeEtape( strView ) ) && ( strAction == null || allValidBeforeEtape( strAction ) ) ) )
{
return redirectView( request, _strNextStep );
}
}
return super.getPage( request, nMode, plugin );
}
// *********************************************************************************************
// * STEP STEP STEP STEP STEP STEP STEP STEP STEP STEP STEP STEP STEP STEP STEP STEP STEP STEP *
// * STEP STEP STEP STEP STEP STEP STEP STEP STEP STEP STEP STEP STEP STEP STEP STEP STEP STEP *
// *********************************************************************************************
/**
* Returns the content of the page ideation.
*
* @param request
* The HTTP request
* @return The view
*/
@View( value = STEP_LOCATION, defaultView = true )
public XPage viewLocation( HttpServletRequest request )
{
Map<String, Object> model = getModel( request );
model.put( MARK_STEPS_INDEX, STEPS.LOCATION_INDEX.ordinal( ) );
model.put( MARK_STEPS_CONTENT, TEMPLATE_LOCATION );
model.put( MARK_CAMPAIGN_THEMES, IdeationCampaignDataProvider.getInstance( ).getCampaignThemes( _proposalCreate.getCodeCampaign( ) ) );
model.put( MARK_CAMPAIGN_LOCALIZED_AREA_LABELS,
IdeationCampaignDataProvider.getInstance( ).getCampaignLocalizedAreaLabels( _proposalCreate.getCodeCampaign( ) ) );
model.put( MARK_CAMPAIGN_WHOLE_AREA_LABEL,
IdeationCampaignDataProvider.getInstance( ).getCampaignWholeAreaLabel( _proposalCreate.getCodeCampaign( ) ) );
model.put( MARK_CAMPAIGN_SUBMITTER_TYPES, IdeationCampaignDataProvider.getInstance( ).getCampaignSubmitterTypes( _proposalCreate.getCodeCampaign( ) ) );
return getXPage( TEMPLATE_ETAPES, request.getLocale( ), model );
}
/**
* Process the form of the page ideation.
*
* @param request
* The HTTP request
* @return The view
*/
@Action( value = STEP_LOCATION )
public XPage doLocation( HttpServletRequest request )
{
populate( _formEtapeLocation, request );
if ( !isValidateFormEtape( request, _formEtapeLocation ) )
{
return redirectView( request, STEP_LOCATION );
}
convertFormEtapeLocation( _formEtapeLocation, _proposalCreate );
_strNextStep = STEP_TITLE;
return redirectView( request, STEP_TITLE );
}
/**
* Returns the content of the title step.
*
* @param request
* The HTTP request
* @return The view
*/
@View( value = STEP_TITLE )
public XPage viewTitle( HttpServletRequest request )
{
Map<String, Object> model = getModel( request );
model.put( MARK_STEPS_INDEX, STEPS.TITLE_INDEX.ordinal( ) );
model.put( MARK_STEPS_CONTENT, TEMPLATE_TITLE );
return getXPage( TEMPLATE_ETAPES, request.getLocale( ), model );
}
/**
* Process the form of the page ideation.
*
* @param request
* The HTTP request
* @return The view
*/
@Action( value = STEP_TITLE )
public XPage doTitle( HttpServletRequest request )
{
populate( _formEtapeTitle, request );
if ( !isValidateFormEtape( request, _formEtapeTitle ) )
{
return redirectView( request, STEP_TITLE );
}
convertFormEtapeTitle( _formEtapeTitle, _proposalCreate );
_strNextStep = STEP_APPROX;
return redirectView( request, STEP_APPROX );
}
/**
* Returns the content of the approx step.
*
* @param request
* The HTTP request
* @return The view
*/
@View( value = STEP_APPROX )
public XPage viewApprox( HttpServletRequest request )
{
SolrClient solrClient = SolrServerService.getInstance( ).getSolrServer( );
List<SolrSearchResult> results_keyword = null;
List<SolrSearchResult> results_location = null;
List<SolrSearchResult> results_previous_campaigns = null;
SolrQuery queryKeyword = new SolrQuery( );
SolrQuery queryLocation = null;
SolrQuery queryPreviousCampaigns = new SolrQuery( );
if ( solrClient == null )
{
AppLogService.error( "IdeationApp, SolrServerService.getInstance( ).getSolrServer( ) returns null." );
}
else
{
HashSet<String> setProjects = new HashSet<String>( );
results_previous_campaigns = getPreviousCampaignsApproxResults( queryPreviousCampaigns, solrClient );
if ( results_previous_campaigns != null && results_previous_campaigns.size( ) > 0 )
{
for ( SolrSearchResult solrSearchResult : results_previous_campaigns )
{
setProjects.add( solrSearchResult.getId( ) );
}
}
results_keyword = getKeywordApproxResults( queryKeyword, solrClient );
if ( results_keyword != null && results_keyword.size( ) > 0 )
{
for ( Iterator<SolrSearchResult> iterator = results_keyword.iterator( ); iterator.hasNext( ); )
{
SolrSearchResult item = iterator.next( );
if ( setProjects.contains( item.getId( ) ) )
{
iterator.remove( );
}
else
{
setProjects.add( item.getId( ) );
}
}
}
if ( StringUtils.isNotEmpty( _proposalCreate.getAdress( ) ) )
{
queryLocation = new SolrQuery( );
results_location = getLocationApproxResults( queryLocation, solrClient );
if ( results_location != null )
{
for ( Iterator<SolrSearchResult> iterator = results_location.iterator( ); iterator.hasNext( ); )
{
SolrSearchResult item = iterator.next( );
if ( setProjects.contains( item.getId( ) ) )
{
iterator.remove( );
}
}
}
}
}
Map<String, Object> model = getModel( request );
if ( request.getParameter( PARAMETER_APPROX_SOLR_DBG ) != null )
{
model.put( MARK_APPROX_KEYWORD_SOLR_DBG, queryKeyword );
model.put( MARK_APPROX_LOCATION_SOLR_DBG, queryLocation );
}
model.put( MARK_APPROX_PREVIOUS_CAMPAIGNS_LIST, results_previous_campaigns );
model.put( MARK_APPROX_KEYWORD_LIST, results_keyword );
model.put( MARK_APPROX_LOCATION_LIST, results_location );
model.put( MARK_STEPS_INDEX, STEPS.APPROX_INDEX.ordinal( ) );
model.put( MARK_STEPS_CONTENT, TEMPLATE_APPROX );
return getXPage( TEMPLATE_ETAPES, request.getLocale( ), model );
}
/**
* set the common part of the location and keyword queries
*
* @param query
* a query object to modify
* @return The search results
*/
private void setApproxProjectsQuery( SolrQuery query )
{
query.set( "defType", "edismax" );
query.set( "q.op", "OR" );
}
/**
* get the string to limit results around the current proposal, or null if there is no limit
*
* @return the fq string
*/
private String getDistanceFQ( )
{
String strApproxDistanceLimit = DatastoreService.getDataValue( DSKEY_APPROX_DISTANCE_LIMIT, "" );
double distanceLimit = -1;
if ( !"".equals( strApproxDistanceLimit ) )
{
try
{
distanceLimit = Integer.parseInt( strApproxDistanceLimit ) / 1000.0;
}
catch( NumberFormatException e )
{
AppLogService.error( "IdeationApp: error during approx search parsing DistanceLimit " + e.getMessage( ), e );
}
if ( distanceLimit < 0 )
{
AppLogService.error( "IdeationApp: approx search negative DistanceLimit: parsed " + distanceLimit + " from " + strApproxDistanceLimit + ";" );
}
}
if ( distanceLimit > 0 )
{
/*
* String strGeofiltFq = "((type:" + SOLR_NEWPROJECTS_TYPE + " AND {!geofilt pt=" + _proposalCreate.getLatitude() + ","+
* _proposalCreate.getLongitude() +" sfield="+SOLR_NEWPROJECTS_GEOLOC_FIELD+" d="+distanceLimit+"})" + " OR (type:"+ SOLR_OLDPROJECTS_TYPE +
* " AND {!geofilt pt=" + _proposalCreate.getLatitude() + ","+ _proposalCreate.getLongitude() +" sfield="+
* SOLR_OLDPROJECTS_GEOLOC_FIELD+" d="+distanceLimit+"}))";
*/
String strGeofiltFq = "((type:" + SOLR_NEWPROJECTS_TYPE + " AND {!geofilt pt=" + _proposalCreate.getLatitude( ) + ","
+ _proposalCreate.getLongitude( ) + " sfield=" + SOLR_NEWPROJECTS_GEOLOC_FIELD + " d=" + distanceLimit + "}))";
return strGeofiltFq;
}
else
{
return null;
}
}
/**
* Returns the results of a search by location and modifies the query
*
* @param query
* a query object to modify
* @param solrClient
* a solrClient
* @return The search results
*/
private List<SolrSearchResult> getLocationApproxResults( SolrQuery query, SolrClient solrClient )
{
List<SolrSearchResult> results = null;
setApproxProjectsQuery( query );
query.setQuery( _proposalCreate.getAdress( ) );
String strLocationResultsCount = DatastoreService.getDataValue( DSKEY_APPROX_LOCATION_RESULTS_COUNT, "" );
int nLocationResultsCount = 6;
if ( !"".equals( strLocationResultsCount ) )
{
try
{
nLocationResultsCount = Integer.parseInt( strLocationResultsCount );
}
catch( NumberFormatException e )
{
AppLogService.error( "IdeationApp: error during approx search parsing LocationResultsCount " + e.getMessage( ), e );
}
}
query.setRows( nLocationResultsCount );
ArrayList<String> listFQ = new ArrayList<String>( );
// listFQ.add( SOLR_FQ_ALLPROJECTS );
listFQ.add( "(type:proposal AND campaign_text:\"" + _proposalCreate.getCodeCampaign( ) + "\")" );
String strGeofiltFq = getDistanceFQ( );
if ( strGeofiltFq != null )
{
listFQ.add( strGeofiltFq );
}
query.setFilterQueries( listFQ.toArray( new String [ listFQ.size( )] ) );
try
{
QueryResponse response = solrClient.query( query );
List<SolrItem> itemList = response.getBeans( SolrItem.class );
results = SolrUtil.transformSolrItemsToSolrSearchResults( itemList, null );
}
catch( SolrServerException e )
{
AppLogService.error( "IdeationApp: error during approx search; " + e.getMessage( ), e );
}
catch( IOException e )
{
AppLogService.error( "IdeationApp: error during approx search; " + e.getMessage( ), e );
}
return results;
}
/**
* Returns the results of a search by keyword and modifies the query
*
* @param query
* a query object to modify
* @param solrClient
* a solrClient
* @return The search results
*/
private List<SolrSearchResult> getKeywordApproxResults( SolrQuery query, SolrClient solrClient )
{
List<SolrSearchResult> results = null;
setApproxProjectsQuery( query );
query.setQuery( _proposalCreate.getTitre( ) );
String strKeywordResultsCount = DatastoreService.getDataValue( DSKEY_APPROX_KEYWORD_RESULTS_COUNT, "" );
int nKeywordResultsCount = 6;
if ( !"".equals( strKeywordResultsCount ) )
{
try
{
nKeywordResultsCount = Integer.parseInt( strKeywordResultsCount );
}
catch( NumberFormatException e )
{
AppLogService.error( "IdeationApp: error during approx search parsing KeywordResultsCount " + e.getMessage( ), e );
}
}
query.setRows( nKeywordResultsCount );
Double [ ] dLatLon = null;
ArrayList<String> listFQ = new ArrayList<String>( );
// listFQ.add( SOLR_FQ_ALLPROJECTS );
listFQ.add( "(type:proposal AND campaign_text:\"" + _proposalCreate.getCodeCampaign( ) + "\")" );
if ( _proposalCreate.getLongitude( ) != null && _proposalCreate.getLatitude( ) != null )
{
dLatLon = new Double [ ] {
_proposalCreate.getLatitude( ), _proposalCreate.getLongitude( )
};
String strGeofiltFq = getDistanceFQ( );
if ( strGeofiltFq != null )
{
listFQ.add( strGeofiltFq );
}
}
if ( _proposalCreate.getLocationArdt( ) != null )
{
String strArdtFQ = "(" + SOLR_NEWPROJECTS_ARDT_FIELD + ":" + _proposalCreate.getLocationArdt( ) + " OR " + SOLR_OLDPROJECTS_ARDT_FIELD + ":\""
+ getOldArdtText( _proposalCreate.getLocationArdt( ) ) + "\")";
listFQ.add( strArdtFQ );
}
query.setFilterQueries( listFQ.toArray( new String [ listFQ.size( )] ) );
String solrLatLon = null;
if ( dLatLon != null )
{
solrLatLon = dLatLon [0] + "," + dLatLon [1];
}
if ( solrLatLon != null )
{
// We have values between 0 and ~10km because we are in paris
// Using boost recip(X,0.25, 1, 1)
// - means that for 0km, the score is multiplied by 1/(0.25*0+0.75) = 1.33
// - means that for 1km, the score is multiplied by 1/(0.25*1+0.75) = 1.00
// - means that for 10km, the score is multiplied by 1/(0.25*10+0.75) = 0.30
// So a match that is further away needs to be a better match according to solr's "edismax" score
// From empirical tests, this means that a 0km match can match on 3 times less words than a 10km match.
// A match with a very close location (<1km) is better than a match without location which is in turn better
// than a match with a far location (>1km)
// Boost according to different fields depending on the type of the document..
query.set( "boost", "product(if(termfreq(type,'proposal'), recip(geodist(proposal_geoloc," + solrLatLon
+ "),0.25,1,0.75), 1),if(termfreq(type,'PB Project'), recip(geodist(location_precise_geoloc," + solrLatLon + "),0.25,1,0.75), 1))" );
}
query.setIncludeScore( true );
query.setHighlight( true );
try
{
QueryResponse response = solrClient.query( query );
List<SolrItem> itemList = response.getBeans( SolrItem.class );
if ( itemList.size( ) > 0 )
{
String strScoreRatioLimit = DatastoreService.getDataValue( DSKEY_APPROX_SCORE_RATIO_LIMIT, "" );
double scoreRatioLimit = 0;
if ( !"".equals( strScoreRatioLimit ) )
{
try
{
scoreRatioLimit = Integer.parseInt( strScoreRatioLimit ) / 100.0;
}
catch( NumberFormatException e )
{
AppLogService.error( "IdeationApp: error during approx search parsing ScoreRatio " + e.getMessage( ), e );
}
if ( scoreRatioLimit < 0 || scoreRatioLimit > 100 )
{
AppLogService.error( "IdeationApp: approx search scoreRatioLimit not between 0 and 100: parsed " + scoreRatioLimit + " from "
+ strScoreRatioLimit + ";" );
}
}
if ( scoreRatioLimit > 0 && scoreRatioLimit <= 1 )
{
SolrDocumentList listResults = response.getResults( );
double maxScore = (Float) listResults.getMaxScore( );
double filterScore = maxScore * scoreRatioLimit;
Iterator<SolrItem> mainIterator = itemList.iterator( );
Iterator<SolrDocument> scoreIterator = listResults.iterator( );
while ( mainIterator.hasNext( ) && scoreIterator.hasNext( ) )
{
mainIterator.next( );
SolrDocument document = scoreIterator.next( );
if ( ( (Float) document.getFieldValue( "score" ) ) < filterScore )
{
mainIterator.remove( );
}
}
}
}
// HighLight
SolrHighlights highlights = null;
Map<String, Map<String, List<String>>> highlightsMap = response.getHighlighting( );
if ( highlightsMap != null )
{
highlights = new SolrHighlights( highlightsMap );
}
results = SolrUtil.transformSolrItemsToSolrSearchResults( itemList, highlights );
}
catch( SolrServerException e )
{
AppLogService.error( "IdeationApp: error during approx search; " + e.getMessage( ), e );
}
catch( IOException e )
{
AppLogService.error( "IdeationApp: error during approx search; " + e.getMessage( ), e );
}
return results;
}
// These are in the old projects
private String getOldArdtText( String strLocationArdt )
{
// 7500X -> "Xe arrondissement"
// 750XX -> "XXe arrondissement"
// return (Integer.parseInt(strLocationArdt) - 75000) + "e arrondissement" ;
return strLocationArdt;
}
/**
* Returns the results of a search by location and modifies the query
*
* @param query
* a query object to modify
* @param solrClient
* a solrClient
* @return The search results
*/
private List<SolrSearchResult> getPreviousCampaignsApproxResults( SolrQuery query, SolrClient solrClient )
{
List<SolrSearchResult> results = null;
setApproxProjectsQuery( query );
query.setQuery( _proposalCreate.getTitre( ) );
String strPreviousCResultsCount = DatastoreService.getDataValue( DSKEY_APPROX_PREVIOUS_CAMPAIGNS_RESULTS_COUNT, "" );
int nPreviousCResultsCount = 6;
if ( !"".equals( strPreviousCResultsCount ) )
{
try
{
nPreviousCResultsCount = Integer.parseInt( strPreviousCResultsCount );
}
catch( NumberFormatException e )
{
AppLogService.error( "IdeationApp: error during approx search parsing LocationResultsCount " + e.getMessage( ), e );
}
}
query.setRows( nPreviousCResultsCount );
query.setHighlight( true );
ArrayList<String> listFQ = new ArrayList<String>( );
listFQ.add( SOLR_PREVIOUS_CAMPAIGNS );
query.setFilterQueries( listFQ.toArray( new String [ listFQ.size( )] ) );
try
{
QueryResponse response = solrClient.query( query );
List<SolrItem> itemList = response.getBeans( SolrItem.class );
// HighLight
SolrHighlights highlights = null;
Map<String, Map<String, List<String>>> highlightsMap = response.getHighlighting( );
if ( highlightsMap != null )
{
highlights = new SolrHighlights( highlightsMap );
}
results = SolrUtil.transformSolrItemsToSolrSearchResults( itemList, highlights );
}
catch( SolrServerException e )
{
AppLogService.error( "IdeationApp: error during approx search; " + e.getMessage( ), e );
}
catch( IOException e )
{
AppLogService.error( "IdeationApp: error during approx search; " + e.getMessage( ), e );
}
return results;
}
/**
* Process the form of the page ideation.
*
* @param request
* The HTTP request
* @return The view
*/
@Action( value = STEP_APPROX )
public XPage doApprox( HttpServletRequest request )
{
_strNextStep = STEP_DESCRIPTION;
return redirectView( request, STEP_DESCRIPTION );
}
/**
* Process the form of the page ideation.
*
* @param request
* The HTTP request
* @return The view
*/
@Action( value = ACTION_ABANDON )
public XPage doAbandon( HttpServletRequest request )
{
reInitFormSession( request );
return redirect( request, AppPathService.getBaseUrl( request ) );
}
/**
* Returns the content of the description step.
*
* @param request
* The HTTP request
* @return The view
*/
@View( value = STEP_DESCRIPTION )
public XPage viewDescription( HttpServletRequest request )
{
Map<String, Object> model = getModel( request );
model.put( MARK_STEPS_INDEX, STEPS.DESCRIPTION_INDEX.ordinal( ) );
model.put( MARK_STEPS_CONTENT, TEMPLATE_DESCRIPTION );
return getXPage( TEMPLATE_ETAPES, request.getLocale( ), model );
}
/**
* Process the form of the page ideation.
*
* @param request
* The HTTP request
* @return The view
*/
@Action( value = STEP_DESCRIPTION )
public XPage doDescription( HttpServletRequest request )
{
populate( _formEtapeDescription, request );
if ( !isValidateFormEtape( request, _formEtapeDescription ) )
{
return redirectView( request, STEP_DESCRIPTION );
}
convertFormEtapeDescription( _formEtapeDescription, _proposalCreate );
_strNextStep = STEP_UPLOAD;
return redirectView( request, STEP_UPLOAD );
}
/**
* Returns the content of the upload step.
*
* @param request
* The HTTP request
* @return The view
*/
@View( value = STEP_UPLOAD )
public XPage viewUpload( HttpServletRequest request )
{
Map<String, Object> model = getModel( request );
model.put( MARK_STEPS_INDEX, STEPS.UPLOAD_INDEX.ordinal( ) );
model.put( MARK_STEPS_CONTENT, TEMPLATE_UPLOAD );
model.put( MARK_HANDLER, SpringContextService.getBean( IdeationUploadHandler.BEAN_NAME ) );
model.put( MARK_UPLOAD_DOCS, _formEtapeUpload.getDocs( request ) );
model.put( MARK_UPLOAD_IMGS, _formEtapeUpload.getImgs( request ) );
return getXPage( TEMPLATE_ETAPES, request.getLocale( ), model );
}
/**
* Process the form of the page ideation.
*
* @param request
* The HTTP request
* @return The view
*/
@Action( value = STEP_UPLOAD )
public XPage doUpload( HttpServletRequest request )
{
// XXX handle synchronous upload
populate( _formEtapeUpload, request );
String strAccepExploit = request.getParameter( "accept_exploit" );
if ( strAccepExploit != null && strAccepExploit.equals( "true" ) )
{
_formEtapeUpload.setAcceptExploit( strAccepExploit );
_proposalCreate.setAcceptExploit( true );
}
else
{
_formEtapeUpload.setAcceptExploit( "false" );
_proposalCreate.setAcceptExploit( false );
}
boolean hadSynchronousAction = _formEtapeUpload.populateSynchronousUpload( request );
if ( !isValidateFormEtape( request, _formEtapeUpload ) || hadSynchronousAction )
{
return redirectView( request, STEP_UPLOAD );
}
convertFormEtapeUpload( request, _formEtapeUpload, _proposalCreate );
_strNextStep = STEP_RECAP;
return redirectView( request, STEP_RECAP );
}
/**
* Returns the content of the recap step.
*
* @param request
* The HTTP request
* @return The view
*/
@View( value = STEP_RECAP )
public XPage viewRecap( HttpServletRequest request )
{
Map<String, Object> model = getModel( request );
model.put( MARK_STEPS_INDEX, STEPS.RECAP_INDEX.ordinal( ) );
model.put( MARK_STEPS_CONTENT, TEMPLATE_RECAP );
return getXPage( TEMPLATE_ETAPES, request.getLocale( ), model );
}
/**
* Process the form of the page ideation.
*
* @param request
* The HTTP request
* @return The view
*/
@Action( value = STEP_RECAP )
public XPage doRecap( HttpServletRequest request )
{
populate( _formEtapeRecap, request );
String strAccepContact = request.getParameter( "accept_contact" );
if ( strAccepContact != null && strAccepContact.equals( "true" ) )
{
_formEtapeRecap.setAcceptContact( "true" );
_proposalCreate.setAcceptContact( true );
}
else
{
_formEtapeRecap.setAcceptContact( "false" );
_proposalCreate.setAcceptContact( false );
}
if ( !isValidateFormEtape( request, _formEtapeRecap ) )
{
return redirectView( request, STEP_RECAP );
}
try
{
_proposalCreate.setCreationTimestamp( new java.sql.Timestamp( ( new java.util.Date( ) ).getTime( ) ) );
_proposalCreate.setStatusPublic( Proposal.Status.STATUS_SUBMITTED );
ProposalService.getInstance( ).createProposal( _proposalCreate );
createWorkflowResource( _proposalCreate, request );
// Clear the blobs for performance
clearBlobs( _proposalCreate );
reInitFormSession( request );
}
catch( IdeationErrorException e )
{
AppLogService.error( e );
}
return redirectView( request, STEP_CONFIRMED );
}
/**
* Returns the content of the confirmation
*
* @param request
* The HTTP request
* @return The view
*/
@View( value = STEP_CONFIRMED )
public XPage viewConfirmed( HttpServletRequest request )
{
Map<String, Object> model = getModel( request, true );
model.put( MARK_STEPS_INDEX, STEPS.CONFIRMED_INDEX.ordinal( ) );
model.put( MARK_STEPS_CONTENT, TEMPLATE_CONFIRMED );
return getXPage( TEMPLATE_ETAPES, request.getLocale( ), model );
}
// *********************************************************************************************
// * FORM FORM FORM FORM FORM FORM FORM FORM FORM FORM FORM FORM FORM FORM FORM FORM FORM FORM *
// * FORM FORM FORM FORM FORM FORM FORM FORM FORM FORM FORM FORM FORM FORM FORM FORM FORM FORM *
// *********************************************************************************************
/**
* Process the form of the page ideation. Can't have this in the service because it needs to be done after the transaction because the task uses the
* proposal from the database
*
* @param proposal
* The proposal
* @param request
* The HTTP request
*/
private void createWorkflowResource( Proposal proposal, HttpServletRequest request )
{
int idWorkflow = AppPropertiesService.getPropertyInt( ParticipatoryIdeationConstants.PROPERTY_WORKFLOW_ID, -1 );
String strWorkflowActionNameCreateProposal = AppPropertiesService
.getProperty( ParticipatoryIdeationConstants.PROPERTY_WORKFLOW_ACTION_NAME_CREATE_PROPOSAL );
if ( idWorkflow != -1 )
{
try
{
// Initialize the workflow, this creates the state for our resource
WorkflowService.getInstance( ).getState( proposal.getId( ), Proposal.WORKFLOW_RESOURCE_TYPE, idWorkflow, -1 );
ProposalWSService.getInstance( ).processActionByName( strWorkflowActionNameCreateProposal, proposal.getId( ) );
}
catch( Exception e )
{
AppLogService.error( "Ideation: error in proposal creation workflow", e );
}
}
else
{
AppLogService.error( "Ideation: app property idWorkflow not set" );
}
}
private void clearBlobs( Proposal proposal )
{
for ( File f : proposal.getImgs( ) )
{
f.getPhysicalFile( ).setValue( null );
}
for ( File f : proposal.getDocs( ) )
{
f.getPhysicalFile( ).setValue( null );
}
}
/**
* Get a model Object filled with default values
*
* @param request
* The HTTP request
* @return The model
*/
protected Map<String, Object> getModel( HttpServletRequest request )
{
return getModel( request, false );
}
/**
* Get a model Object filled with default values
*
* @param isConfirmed
* true if the parameter for the recap come from the last submitted proposal
* @param request
* The HTTP request
* @return The model
*/
protected Map<String, Object> getModel( HttpServletRequest request, boolean isConfirmed )
{
Map<String, Object> model = super.getModel( );
IdeationStaticService.getInstance( ).fillCampaignStaticContent( model, _proposalCreate.getCodeCampaign( ) );
fillFormEtapes( model );
fillRecap( model, isConfirmed ? _proposalDisplay : _proposalCreate, request );
return model;
}
/**
* Fill the model with commons objects used in templates from the proposal, or from the FormEtapes
*
* @param proposal
* the proposal to use to fill the recap
* @param request
* The HTTP request
* @param model
* The model
*/
protected void fillRecap( Map<String, Object> model, Proposal proposal, HttpServletRequest request )
{
// Step 1
model.put( MARK_RECAP_SUBMITTER_TYPE, proposal.getSubmitterType( ) );
model.put( MARK_RECAP_SUBMITTER, proposal.getSubmitter( ) );
model.put( MARK_RECAP_CODE_THEME, proposal.getCodeTheme( ) );
model.put( MARK_RECAP_LOCATION_TYPE, proposal.getLocationType( ) );
model.put( MARK_RECAP_LOCATION_ARDT, proposal.getLocationArdt( ) );
model.put( MARK_RECAP_LOCATION_ADRESS, proposal.getAdress( ) );
// Step 2
model.put( MARK_RECAP_TITLE, proposal.getTitre( ) );
// step 4
model.put( MARK_RECAP_DESCRIPTION, proposal.getDescription( ) );
model.put( MARK_RECAP_COUT, proposal.getCout( ) );
// step 5
model.put( MARK_RECAP_DOCS, proposal.getDocs( ) );
model.put( MARK_RECAP_IMGS, proposal.getImgs( ) );
// step 6
model.put( MARK_RECAP_PROPOSAL_CREATED_CODE, proposal.getCodeProposal( ) );
model.put( MARK_RECAP_PROPOSAL_CREATED_CAMPAIGN, proposal.getCodeCampaign( ) );
model.put( MARK_RECAP_PROPOSAL_CREATED_REFERENCE, proposal.getReference( ) );
}
protected void fillFormEtapes( Map<String, Object> model )
{
model.put( MARK_FORM_ETAPE_LOCATION, _formEtapeLocation );
model.put( MARK_FORM_ETAPE_TITLE, _formEtapeTitle );
model.put( MARK_FORM_ETAPE_APPROX, _formEtapeApprox );
model.put( MARK_FORM_ETAPE_DESCRIPTION, _formEtapeDescription );
model.put( MARK_FORM_ETAPE_UPLOAD, _formEtapeUpload );
model.put( MARK_FORM_ETAPE_RECAP, _formEtapeRecap );
}
/**
* Returns an exception when it is not the ideation phase
*
* @param request
* The HTTP request
* @throws SiteMessageException
*/
private void checkIdeationCampaignPhase( HttpServletRequest request ) throws SiteMessageException
{
// Verify a campaign is specified
if ( StringUtils.isBlank( _proposalCreate.getCodeCampaign( ) ) )
{
_proposalCreate.setCodeCampaign( request.getParameter( PARAMETER_CAMPAIGN ) );
}
if ( StringUtils.isBlank( _proposalCreate.getCodeCampaign( ) ) )
{
SiteMessageService.setMessage( request, MESSAGE_CAMPAIGN_UNSPECIFIED, SiteMessage.TYPE_ERROR, JSP_PORTAL );
}
else
{
// Verify the campaign exists
if ( IdeationCampaignDataProvider.getInstance( ).getCampaigns( ).stream( ).filter( i -> i.getCode( ).equals( _proposalCreate.getCodeCampaign( ) ) )
.count( ) < 1 )
{
SiteMessageService.setMessage( request, MESSAGE_CAMPAIGN_UNKNOWN, new String [ ] {
_proposalCreate.getCodeCampaign( )
}, SiteMessage.TYPE_ERROR );
}
if ( !IdeationCampaignDataProvider.getInstance( ).isDuring( _proposalCreate.getCodeCampaign( ), ParticipatoryIdeationConstants.IDEATION ) )
{
Map<String, Object> requestParameters = new HashMap<String, Object>( );
requestParameters.put( PARAMETER_PAGE, "search-solr" );
requestParameters.put( PARAMETER_CONF, "proposals_list" );
SiteMessageService.setMessage( request, MESSAGE_CAMPAIGN_IDEATION_CLOSED_SUBMIT, SiteMessage.TYPE_ERROR, JSP_PORTAL, requestParameters );
}
}
}
private boolean allValidBeforeEtape( String strEtape )
{
return STEPS.getByName( strEtape ) != null && STEPS.getByName( strEtape ).ordinal( ) <= STEPS.getByName( _strNextStep ).ordinal( );
}
private boolean checkUserAuthorized( HttpServletRequest request ) throws UserNotSignedException
{
LuteceUser user = null;
if ( SecurityService.isAuthenticationEnable( ) )
{
user = SecurityService.getInstance( ).getRemoteUser( request );
if ( user == null )
{
throw new UserNotSignedException( );
}
return MyInfosService.getInstance( ).isUserValid( user.getName( ) );
}
return false;
}
boolean isValidateFormEtape( HttpServletRequest request, IFormEtape formEtape )
{
if ( validateBean( formEtape ) )
{
List<String> listErrors = formEtape.checkValidationErrors( request, _proposalCreate );
List<String> listErrorsLocalized = formEtape.checkValidationErrorsLocalized( request, _proposalCreate, getLocale( request ) );
if ( !CollectionUtils.isEmpty( listErrors ) )
{
for ( String error : listErrors )
{
addError( error, getLocale( request ) );
}
}
if ( !CollectionUtils.isEmpty( listErrorsLocalized ) )
{
for ( String error : listErrorsLocalized )
{
addError( error );
}
}
if ( !CollectionUtils.isEmpty( listErrors ) || !CollectionUtils.isEmpty( listErrorsLocalized ) )
{
return false;
}
// Validate formEtape
formEtape.setValidated( true );
return true;
}
return false;
}
boolean isAllEtapeValidated( )
{
return _formEtapeLocation.isValidated( ) && _formEtapeTitle.isValidated( ) && _formEtapeDescription.isValidated( ) && _formEtapeUpload.isValidated( )
&& _formEtapeRecap.isValidated( );
}
private void convertFormEtapeLocation( FormEtapeLocation formEtapeLocation, Proposal proposal )
{
proposal.setLocationType( formEtapeLocation.getLocationType( ) );
proposal.setCodeTheme( formEtapeLocation.getCodeTheme( ) );
proposal.setSubmitterType( formEtapeLocation.getSubmitterType( ) );
if ( formEtapeLocation.mustCopySubmitter( ) )
{
proposal.setSubmitter( formEtapeLocation.getSubmitter( ).trim( ) );
}
else
{
proposal.setSubmitter( null );
}
if ( StringUtils.isNotEmpty( formEtapeLocation.getGeojson( ) ) )
{
GeolocItem geolocItem;
try
{
geolocItem = GeolocItem.fromJSON( formEtapeLocation.getGeojson( ) );
proposal.setLatitude( geolocItem.getLat( ) );
proposal.setLongitude( geolocItem.getLon( ) );
proposal.setAdress( geolocItem.getAddress( ) );
proposal.setLocationArdt( formEtapeLocation.getLocationArdt( ) );
List<QpvQva> listQpvqva;
try
{
listQpvqva = QpvQvaService.getQpvQva( proposal.getLongitude( ), proposal.getLatitude( ) );
if ( listQpvqva.size( ) == 0 )
{
proposal.setTypeQpvQva( QPV_QVA_NO );
proposal.setIdQpvQva( null );
proposal.setLibelleQpvQva( null );
}
else
{
// For backwards compatibility, choose a QPV/QVA in priority if it exists
QpvQva resQpvQva = null;
for ( QpvQva qpvqva : listQpvqva )
{
if ( StringUtils.isNotBlank( qpvqva.getType( ) ) )
{
resQpvQva = qpvqva;
break;
}
}
// If not qpvqva, just take the first one...
if ( resQpvQva == null )
{
resQpvQva = listQpvqva.get( 0 );
}
if ( StringUtils.isNotBlank( resQpvQva.getType( ) ) )
{
proposal.setTypeQpvQva( resQpvQva.getType( ) );
proposal.setIdQpvQva( resQpvQva.getId( ) );
proposal.setLibelleQpvQva( resQpvQva.getLibelle( ) );
}
else
if ( StringUtils.isNotBlank( resQpvQva.getGpruNom( ) ) )
{
proposal.setTypeQpvQva( QPV_QVA_GPRU );
proposal.setIdQpvQva( resQpvQva.getFid( ) );
proposal.setLibelleQpvQva( resQpvQva.getGpruNom( ) );
}
else
if ( StringUtils.isNotBlank( resQpvQva.getExtBp( ) ) )
{
proposal.setTypeQpvQva( QPV_QVA_QBP );
proposal.setIdQpvQva( resQpvQva.getFid( ) );
proposal.setLibelleQpvQva( resQpvQva.getExtBp( ) );
}
else
{
proposal.setTypeQpvQva( resQpvQva.getType( ) );
proposal.setIdQpvQva( resQpvQva.getId( ) );
proposal.setLibelleQpvQva( resQpvQva.getLibelle( ) );
}
}
}
catch( Exception e )
{
proposal.setTypeQpvQva( QPV_QVA_ERR );
proposal.setIdQpvQva( null );
proposal.setLibelleQpvQva( null );
AppLogService.error( "IDEATION: error when using capgeo rest QpvQva service", e );
}
}
catch( IOException e )
{
proposal.setTypeQpvQva( QPV_QVA_NO );
proposal.setIdQpvQva( null );
proposal.setLibelleQpvQva( null );
proposal.setLatitude( null );
proposal.setLongitude( null );
proposal.setAdress( null );
proposal.setLocationArdt( null );
AppLogService.error( e );
}
}
else
{
proposal.setTypeQpvQva( QPV_QVA_NO );
proposal.setIdQpvQva( null );
proposal.setLibelleQpvQva( null );
proposal.setLatitude( null );
proposal.setLongitude( null );
proposal.setAdress( null );
if ( formEtapeLocation.getLocationType( ).equals( Proposal.LOCATION_AREA_TYPE_LOCALIZED ) && formEtapeLocation.getLocationArdt( ) != null )
{
proposal.setLocationArdt( formEtapeLocation.getLocationArdt( ) );
}
else
{
proposal.setLocationArdt( null );
}
}
}
private void convertFormEtapeTitle( FormEtapeTitle formEtapeTitle, Proposal proposal )
{
proposal.setTitre( StringUtils.trimToEmpty( formEtapeTitle.getTitre( ) ) );
proposal.setField1( StringUtils.trimToEmpty( formEtapeTitle.getField1( ) ) );
proposal.setfield2( StringUtils.trimToEmpty( formEtapeTitle.getField2( ) ) );
}
private void convertFormEtapeDescription( FormEtapeDescription formEtapeDescription, Proposal proposal )
{
proposal.setDescription( formEtapeDescription.getDescription( ).trim( ) );
if ( StringUtils.isNotBlank( formEtapeDescription.getCout( ) ) )
{
proposal.setCout( Long.parseLong( formEtapeDescription.getCout( ).replaceAll( "\\s+", "" ) ) );
}
else
{
proposal.setCout( null );
}
proposal.setField3( StringUtils.trimToEmpty( formEtapeDescription.getField3( ) ) );
proposal.setField4( StringUtils.trimToEmpty( formEtapeDescription.getField4( ) ) );
proposal.setField4Complement( StringUtils.trimToEmpty( formEtapeDescription.getField4( ) ) );
}
private void convertFormEtapeUpload( HttpServletRequest request, FormEtapeUpload formEtapeUpload, Proposal proposal )
{
proposal.setImgs( convertAllFileItemsToFiles( formEtapeUpload.getImgs( request ) ) );
proposal.setDocs( convertAllFileItemsToFiles( formEtapeUpload.getDocs( request ) ) );
}
private void reInitFormSession( )
{
reInitFormSession( null );
}
private void reInitFormSession( HttpServletRequest request )
{
_formEtapeLocation = new FormEtapeLocation( );
_formEtapeTitle = new FormEtapeTitle( );
_formEtapeApprox = new FormEtapeApprox( );
_formEtapeDescription = new FormEtapeDescription( );
if ( _formEtapeUpload != null && request != null )
{
_formEtapeUpload.reInitFormSession( request );
}
_formEtapeUpload = new FormEtapeUpload( );
_formEtapeRecap = new FormEtapeRecap( );
_proposalDisplay = _proposalCreate;
_proposalCreate = new Proposal( );
_strNextStep = STEP_LOCATION;
}
private List<File> convertAllFileItemsToFiles( List<FileItem> listFileItems )
{
ArrayList<File> listFiles = new ArrayList<File>( listFileItems.size( ) );
for ( FileItem fileItem : listFileItems )
{
File file = new File( );
file.setTitle( fileItem.getName( ) );
file.setSize( ( fileItem.getSize( ) < Integer.MAX_VALUE ) ? (int) fileItem.getSize( ) : Integer.MAX_VALUE );
file.setMimeType( FileSystemUtil.getMIMEType( file.getTitle( ) ) );
PhysicalFile physicalFile = new PhysicalFile( );
physicalFile.setValue( fileItem.get( ) );
file.setPhysicalFile( physicalFile );
listFiles.add( file );
}
return listFiles;
}
/**
* Steps Order
*/
enum STEPS
{
LOCATION_INDEX( STEP_LOCATION ),
TITLE_INDEX( STEP_TITLE ),
APPROX_INDEX( STEP_APPROX ),
DESCRIPTION_INDEX( STEP_DESCRIPTION ),
UPLOAD_INDEX( STEP_UPLOAD ),
RECAP_INDEX( STEP_RECAP ),
CONFIRMED_INDEX( STEP_CONFIRMED );
String _strEtape;
private static final Map<String, STEPS> nameMap;
static
{
nameMap = new HashMap<String, STEPS>( );
for ( STEPS s : STEPS.values( ) )
{
nameMap.put( s._strEtape, s );
}
}
private STEPS( String strEtape )
{
_strEtape = strEtape;
}
public static STEPS getByName( String strEtape )
{
return nameMap.get( strEtape );
}
}
}