View Javadoc
1   /*
2    * Copyright (c) 2002-2014, Mairie de 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.directory.modules.pdfproducer.utils;
35  
36  import fr.paris.lutece.plugins.directory.business.Directory;
37  import fr.paris.lutece.plugins.directory.business.DirectoryHome;
38  import fr.paris.lutece.plugins.directory.business.EntryFilter;
39  import fr.paris.lutece.plugins.directory.business.EntryTypeDownloadUrl;
40  import fr.paris.lutece.plugins.directory.business.EntryTypeGeolocation;
41  import fr.paris.lutece.plugins.directory.business.IEntry;
42  import fr.paris.lutece.plugins.directory.business.Record;
43  import fr.paris.lutece.plugins.directory.business.RecordField;
44  import fr.paris.lutece.plugins.directory.business.RecordFieldFilter;
45  import fr.paris.lutece.plugins.directory.business.RecordFieldHome;
46  import fr.paris.lutece.plugins.directory.business.RecordHome;
47  import fr.paris.lutece.plugins.directory.modules.pdfproducer.business.producerconfig.IConfigProducer;
48  import fr.paris.lutece.plugins.directory.service.DirectoryPlugin;
49  import fr.paris.lutece.plugins.directory.utils.DirectoryUtils;
50  import fr.paris.lutece.portal.business.user.AdminUser;
51  import fr.paris.lutece.portal.service.admin.AdminUserService;
52  import fr.paris.lutece.portal.service.plugin.Plugin;
53  import fr.paris.lutece.portal.service.plugin.PluginService;
54  import fr.paris.lutece.portal.service.util.AppLogService;
55  import fr.paris.lutece.portal.service.util.AppPathService;
56  import fr.paris.lutece.portal.service.util.AppPropertiesService;
57  import fr.paris.lutece.util.string.StringUtil;
58  
59  import java.io.File;
60  import java.io.IOException;
61  import java.io.OutputStream;
62  import java.net.MalformedURLException;
63  import java.text.SimpleDateFormat;
64  import java.util.ArrayList;
65  import java.util.List;
66  import java.util.Locale;
67  import java.util.Map;
68  
69  import javax.imageio.ImageIO;
70  import javax.servlet.http.HttpServletRequest;
71  import javax.servlet.http.HttpServletResponse;
72  
73  import org.apache.commons.collections.CollectionUtils;
74  import org.apache.commons.io.IOUtils;
75  import org.apache.commons.lang.StringUtils;
76  import org.springframework.web.util.HtmlUtils;
77  
78  import com.lowagie.text.BadElementException;
79  import com.lowagie.text.Chunk;
80  import com.lowagie.text.Document;
81  import com.lowagie.text.DocumentException;
82  import com.lowagie.text.Element;
83  import com.lowagie.text.Font;
84  import com.lowagie.text.Image;
85  import com.lowagie.text.ListItem;
86  import com.lowagie.text.PageSize;
87  import com.lowagie.text.Paragraph;
88  import com.lowagie.text.Phrase;
89  import com.lowagie.text.pdf.PdfWriter;
90  
91  
92  /**
93   * class for generate PDF document from directory records
94   */
95  public final class PDFUtils
96  {
97      // PROPERTIES
98      private static final String PROPERTY_POLICE_FORMAT_DATE = "directory.pdfgenerate.format.date";
99      private static final String PROPERTY_POLICE_SIZE_DATE = "directory.pdfgenerate.font.size.date";
100     private static final String PROPERTY_POLICE_STYLE_DATE = "directory.pdfgenerate.font.style.date";
101     private static final String PROPERTY_POLICE_ALIGN_DATE = "directory.pdfgenerate.font.align.date";
102     private static final String PROPERTY_POLICE_SIZE_TITLE_DIRECTORY = "directory.pdfgenerate.font.size.title.directory";
103     private static final String PROPERTY_POLICE_STYLE_TITLE_DIRECTORY = "directory.pdfgenerate.font.style.title.directory";
104     private static final String PROPERTY_POLICE_SPACING_BEFORE_TITLE_DIRECTORY = "directory.pdfgenerate.font.spacing_before.title.directory";
105     private static final String PROPERTY_POLICE_SPACING_AFTER_TITLE_DIRECTORY = "directory.pdfgenerate.font.spacing_after.title.directory";
106     private static final String PROPERTY_POLICE_SIZE_ENTRY_GROUP = "directory.pdfgenerate.font.size.entry.group";
107     private static final String PROPERTY_POLICE_STYLE_ENTRY_GROUP = "directory.pdfgenerate.font.style.entry.group";
108     private static final String PROPERTY_POLICE_MARGIN_LEFT_ENTRY_GROUP = "directory.pdfgenerate.font.margin_left.entry.group";
109     private static final String PROPERTY_POLICE_SPACING_BEFORE_ENTRY_GROUP = "directory.pdfgenerate.font.spacing_before.entry.group";
110     private static final String PROPERTY_POLICE_SPACING_AFTER_ENTRY_GROUP = "directory.pdfgenerate.font.spacing_after.entry.group";
111     private static final String PROPERTY_POLICE_SIZE_ENTRY_TITLE = "directory.pdfgenerate.font.size.entry.title";
112     private static final String PROPERTY_POLICE_STYLE_ENTRY_TITLE = "directory.pdfgenerate.font.style.entry.title";
113     private static final String PROPERTY_POLICE_SIZE_ENTRY_VALUE = "directory.pdfgenerate.font.size.entry.value";
114     private static final String PROPERTY_POLICE_STYLE_ENTRY_VALUE = "directory.pdfgenerate.font.style.entry.value";
115     private static final String PROPERTY_POLICE_MARGIN_LEFT_ENTRY_VALUE = "directory.pdfgenerate.font.margin_left.entry.value";
116     private static final String PROPERTY_POLICE_NAME = "directory.pdfgenerate.font.name";
117     private static final String PROPERTY_IMAGE_URL = "directory.pdfgenerate.image.url";
118     private static final String PROPERTY_IMAGE_ALIGN = "directory.pdfgenerate.image.align";
119     private static final String PROPERTY_IMAGE_FITWIDTH = "directory.pdfgenerate.image.fitWidth";
120     private static final String PROPERTY_IMAGE_FITHEIGHT = "directory.pdfgenerate.image.fitHeight";
121 
122     // private static final String PROPERTY_MESSAGE_COULD_NOT_FETCH_FILE_NAME = "module.directory.pdfproducer.message.could_not_fetch_file_name";
123     private static final String PARAMETER_ID_DIRECTORY_RECORD = "id_directory_record";
124     private static final String PARAMETER_ID_RECORD = "id_record";
125 
126     // FIELDS
127     private static final String FIELD_THUMBNAIL = "little_thumbnail";
128     private static final String FIELD_BIG_THUMBNAIL = "big_thumbnail";
129 
130     // CONSTANTS
131     private static final String DEFAULT_TYPE_FILE_NAME = "default";
132     private static final String DIRECTORY_ENTRY_FILE_NAME = "directory_entry";
133 
134     /**
135      * Constructor
136      */
137     private PDFUtils( )
138     {
139     }
140 
141     /**
142      * method to create PDF without config
143      * @param request request
144      * @param strNameFile PDF name
145      * @param out OutputStream
146      * @param nIdRecord the id record
147      * @param bExtractNotFilledField if true, extract empty fields, false
148      *            otherwise
149      */
150     public static void doCreateDocumentPDF( HttpServletRequest request, String strNameFile, OutputStream out,
151             int nIdRecord, Boolean bExtractNotFilledField )
152     {
153         List<Integer> listIdEntryConfig = new ArrayList<Integer>( );
154         doCreateDocumentPDF( request, strNameFile, out, nIdRecord, listIdEntryConfig, bExtractNotFilledField );
155     }
156 
157     /**
158      * method to create PDF
159      * @param request request
160      * @param strNameFile PDF name
161      * @param out OutputStream
162      * @param nIdRecord the id record
163      * @param listIdEntryConfig list of config id entry
164      * @param bExtractNotFilledField if true, extract empty fields, false
165      *            otherwise
166      */
167     public static void doCreateDocumentPDF( HttpServletRequest request, String strNameFile, OutputStream out,
168             int nIdRecord, List<Integer> listIdEntryConfig, Boolean bExtractNotFilledField )
169     {
170         AdminUser adminUser = AdminUserService.getAdminUser( request );
171         Locale locale = request.getLocale( );
172         doCreateDocumentPDF( adminUser, locale, strNameFile, out, nIdRecord, listIdEntryConfig, bExtractNotFilledField );
173     }
174 
175     /**
176      * method to create PDF
177      * @param adminUser The admin user
178      * @param locale The locale
179      * @param strNameFile PDF name
180      * @param out OutputStream
181      * @param nIdRecord the id record
182      * @param listIdEntryConfig list of config id entry
183      * @param bExtractNotFilledField if true, extract empty fields, false
184      */
185     public static void doCreateDocumentPDF( AdminUser adminUser, Locale locale, String strNameFile, OutputStream out,
186             int nIdRecord, List<Integer> listIdEntryConfig, Boolean bExtractNotFilledField )
187     {
188         Document document = new Document( PageSize.A4 );
189 
190         Plugin plugin = PluginService.getPlugin( DirectoryPlugin.PLUGIN_NAME );
191 
192         EntryFilter filter;
193 
194         Record record = RecordHome.findByPrimaryKey( nIdRecord, plugin );
195 
196         filter = new EntryFilter( );
197         filter.setIdDirectory( record.getDirectory( ).getIdDirectory( ) );
198         filter.setIsGroup( EntryFilter.FILTER_TRUE );
199 
200         List<IEntry> listEntry = DirectoryUtils.getFormEntries( record.getDirectory( ).getIdDirectory( ), plugin,
201                 adminUser );
202         int nIdDirectory = record.getDirectory( ).getIdDirectory( );
203         Directory directory = DirectoryHome.findByPrimaryKey( nIdDirectory, plugin );
204 
205         try
206         {
207             PdfWriter.getInstance( document, out );
208         }
209         catch ( DocumentException e )
210         {
211             AppLogService.error( e );
212         }
213 
214         document.open( );
215 
216         if ( record.getDateCreation( ) != null )
217         {
218             SimpleDateFormat monthDayYearformatter = new SimpleDateFormat(
219                     AppPropertiesService.getProperty( PROPERTY_POLICE_FORMAT_DATE ) );
220 
221             Font fontDate = new Font( DirectoryUtils.convertStringToInt( AppPropertiesService
222                     .getProperty( PROPERTY_POLICE_NAME ) ), DirectoryUtils.convertStringToInt( AppPropertiesService
223                     .getProperty( PROPERTY_POLICE_SIZE_DATE ) ),
224                     DirectoryUtils.convertStringToInt( AppPropertiesService.getProperty( PROPERTY_POLICE_STYLE_DATE ) ) );
225 
226             Paragraph paragraphDate = new Paragraph( new Phrase( monthDayYearformatter
227                     .format( record.getDateCreation( ) ).toString( ), fontDate ) );
228 
229             paragraphDate.setAlignment( DirectoryUtils.convertStringToInt( AppPropertiesService
230                     .getProperty( PROPERTY_POLICE_ALIGN_DATE ) ) );
231 
232             try
233             {
234                 document.add( paragraphDate );
235             }
236             catch ( DocumentException e )
237             {
238                 AppLogService.error( e );
239             }
240         }
241 
242         Image image;
243 
244         try
245         {
246 
247             image = Image.getInstance( ImageIO.read( new File( AppPathService
248                     .getAbsolutePathFromRelativePath( AppPropertiesService.getProperty( PROPERTY_IMAGE_URL ) ) ) ),
249                     null );
250             image.setAlignment( DirectoryUtils.convertStringToInt( AppPropertiesService
251                     .getProperty( PROPERTY_IMAGE_ALIGN ) ) );
252             float fitWidth;
253             float fitHeight;
254 
255             try
256             {
257                 fitWidth = Float.parseFloat( AppPropertiesService.getProperty( PROPERTY_IMAGE_FITWIDTH ) );
258                 fitHeight = Float.parseFloat( AppPropertiesService.getProperty( PROPERTY_IMAGE_FITHEIGHT ) );
259             }
260             catch ( NumberFormatException e )
261             {
262                 fitWidth = 100f;
263                 fitHeight = 100f;
264             }
265 
266             image.scaleToFit( fitWidth, fitHeight );
267 
268             try
269             {
270                 document.add( image );
271             }
272             catch ( DocumentException e )
273             {
274                 AppLogService.error( e );
275             }
276         }
277         catch ( BadElementException e )
278         {
279             AppLogService.error( e );
280         }
281         catch ( MalformedURLException e )
282         {
283             AppLogService.error( e );
284         }
285         catch ( IOException e )
286         {
287             AppLogService.error( e );
288         }
289 
290         directory.getTitle( );
291 
292         Font fontTitle = new Font( DirectoryUtils.convertStringToInt( AppPropertiesService
293                 .getProperty( PROPERTY_POLICE_NAME ) ), DirectoryUtils.convertStringToInt( AppPropertiesService
294                 .getProperty( PROPERTY_POLICE_SIZE_TITLE_DIRECTORY ) ),
295                 DirectoryUtils.convertStringToInt( AppPropertiesService
296                         .getProperty( PROPERTY_POLICE_STYLE_TITLE_DIRECTORY ) ) );
297         fontTitle.isUnderlined( );
298 
299         Paragraph paragraphHeader = new Paragraph( new Phrase( directory.getTitle( ), fontTitle ) );
300         paragraphHeader.setAlignment( Element.ALIGN_CENTER );
301         paragraphHeader.setSpacingBefore( DirectoryUtils.convertStringToInt( AppPropertiesService
302                 .getProperty( PROPERTY_POLICE_SPACING_BEFORE_TITLE_DIRECTORY ) ) );
303         paragraphHeader.setSpacingAfter( DirectoryUtils.convertStringToInt( AppPropertiesService
304                 .getProperty( PROPERTY_POLICE_SPACING_AFTER_TITLE_DIRECTORY ) ) );
305 
306         try
307         {
308             document.add( paragraphHeader );
309         }
310         catch ( DocumentException e )
311         {
312             AppLogService.error( e );
313         }
314 
315         builderPDFWithEntry( document, plugin, nIdRecord, listEntry, listIdEntryConfig, locale, bExtractNotFilledField );
316         document.close( );
317     }
318 
319     /**
320      * method to builder PDF with directory entry
321      * @param document document pdf
322      * @param plugin plugin
323      * @param nIdRecord id record
324      * @param listEntry list of entry
325      * @param listIdEntryConfig list of config id entry
326      * @param locale the locale
327      * @param bExtractNotFilledField if true, extract empty fields, false
328      */
329     private static void builderPDFWithEntry( Document document, Plugin plugin, int nIdRecord, List<IEntry> listEntry,
330             List<Integer> listIdEntryConfig, Locale locale, Boolean bExtractNotFilledField )
331     {
332         Map<String, List<RecordField>> mapIdEntryListRecordField = DirectoryUtils.getMapIdEntryListRecordField(
333                 listEntry, nIdRecord, plugin );
334 
335         for ( IEntry entry : listEntry )
336         {
337             if ( entry.getEntryType( ).getGroup( )
338                     && ( listIdEntryConfig.isEmpty( ) || listIdEntryConfig.contains( Integer.valueOf( entry
339                             .getIdEntry( ) ) ) ) )
340             {
341                 Font fontEntryTitleGroup = new Font( DirectoryUtils.convertStringToInt( AppPropertiesService
342                         .getProperty( PROPERTY_POLICE_NAME ) ), DirectoryUtils.convertStringToInt( AppPropertiesService
343                         .getProperty( PROPERTY_POLICE_SIZE_ENTRY_GROUP ) ),
344                         DirectoryUtils.convertStringToInt( AppPropertiesService
345                                 .getProperty( PROPERTY_POLICE_STYLE_ENTRY_GROUP ) ) );
346                 Paragraph paragraphTitleGroup = new Paragraph( new Phrase( entry.getTitle( ), fontEntryTitleGroup ) );
347                 paragraphTitleGroup.setAlignment( Element.ALIGN_LEFT );
348                 paragraphTitleGroup.setIndentationLeft( DirectoryUtils.convertStringToInt( AppPropertiesService
349                         .getProperty( PROPERTY_POLICE_MARGIN_LEFT_ENTRY_GROUP ) ) );
350                 paragraphTitleGroup.setSpacingBefore( DirectoryUtils.convertStringToInt( AppPropertiesService
351                         .getProperty( PROPERTY_POLICE_SPACING_BEFORE_ENTRY_GROUP ) ) );
352                 paragraphTitleGroup.setSpacingAfter( DirectoryUtils.convertStringToInt( AppPropertiesService
353                         .getProperty( PROPERTY_POLICE_SPACING_AFTER_ENTRY_GROUP ) ) );
354 
355                 try
356                 {
357                     document.add( paragraphTitleGroup );
358                 }
359                 catch ( DocumentException e )
360                 {
361                     AppLogService.error( e );
362                 }
363 
364                 if ( entry.getChildren( ) != null )
365                 {
366                     for ( IEntry child : entry.getChildren( ) )
367                     {
368                         if ( listIdEntryConfig.isEmpty( )
369                                 || listIdEntryConfig.contains( Integer.valueOf( child.getIdEntry( ) ) ) )
370                         {
371                             try
372                             {
373                                 builFieldsInPDF(
374                                         mapIdEntryListRecordField.get( Integer.toString( child.getIdEntry( ) ) ),
375                                         document, child, locale, bExtractNotFilledField );
376                             }
377                             catch ( DocumentException e )
378                             {
379                                 AppLogService.error( e );
380                             }
381                         }
382                     }
383                 }
384             }
385             else
386             {
387                 if ( listIdEntryConfig.isEmpty( )
388                         || listIdEntryConfig.contains( Integer.valueOf( entry.getIdEntry( ) ) ) )
389                 {
390                     try
391                     {
392                         builFieldsInPDF( mapIdEntryListRecordField.get( Integer.toString( entry.getIdEntry( ) ) ),
393                                 document, entry, locale, bExtractNotFilledField );
394                     }
395                     catch ( DocumentException e )
396                     {
397                         AppLogService.error( e );
398                     }
399                 }
400             }
401         }
402     }
403 
404     /**
405      * This method build the different label and value of directory fields in
406      * the document PDF
407      * 
408      * @param listRecordFields recordfield map
409      * @param document document pdf
410      * @param entry entry
411      * @param locale the locale
412      * @param bExtractNotFilledField if true, extract empty fields, false
413      * @throws DocumentException DocumentException
414      */
415     private static void builFieldsInPDF( List<RecordField> listRecordFields, Document document, IEntry entry,
416             Locale locale, Boolean bExtractNotFilledField ) throws DocumentException
417     {
418         Phrase phraseEntry = new Phrase( );
419         Paragraph paragraphEntry = new Paragraph( );
420 
421         if ( StringUtils.isNotBlank( entry.getTitle( ) ) )
422         {
423             entry.getTitle( );
424 
425             Font fontEntryTitle = new Font( DirectoryUtils.convertStringToInt( AppPropertiesService
426                     .getProperty( PROPERTY_POLICE_NAME ) ), DirectoryUtils.convertStringToInt( AppPropertiesService
427                     .getProperty( PROPERTY_POLICE_SIZE_ENTRY_TITLE ) ),
428                     DirectoryUtils.convertStringToInt( AppPropertiesService
429                             .getProperty( PROPERTY_POLICE_STYLE_ENTRY_TITLE ) ) );
430             Chunk chunkEntryTitle = new Chunk( entry.getTitle( ), fontEntryTitle );
431             phraseEntry.add( chunkEntryTitle );
432             phraseEntry.add( " : " );
433         }
434 
435         if ( ( listRecordFields != null ) && ( listRecordFields.size( ) > 0 ) )
436         {
437             // Must separate the behaviour whether the list of record fiels contains 1 or more record fields
438             if ( ( listRecordFields.size( ) > 1 )
439                     && !( entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeGeolocation ) )
440             {
441                 builFieldsInParagraph( listRecordFields, entry, locale, phraseEntry, paragraphEntry,
442                         bExtractNotFilledField );
443             }
444             else
445             {
446                 builFieldsInSinglePhrase( listRecordFields, entry, locale, phraseEntry, paragraphEntry,
447                         bExtractNotFilledField );
448             }
449         }
450 
451         document.add( paragraphEntry );
452     }
453 
454     /**
455      * Build the fields in a whole paragraph.
456      * @param listRecordFields the list of record fields
457      * @param entry the entry
458      * @param locale the locale
459      * @param phraseEntry the phrase entry
460      * @param paragraphEntry the paragraph entry
461      * @param bExtractNotFilledField if true, extract empty fields, false
462      * @throws DocumentException exception if there is an error
463      */
464     private static void builFieldsInParagraph( List<RecordField> listRecordFields, IEntry entry, Locale locale,
465             Phrase phraseEntry, Paragraph paragraphEntry, Boolean bExtractNotFilledField ) throws DocumentException
466     {
467         com.lowagie.text.List listValue = new com.lowagie.text.List( true );
468         listValue.setPreSymbol( "- " );
469         listValue.setNumbered( false );
470         listValue.setIndentationLeft( DirectoryUtils.convertStringToInt( AppPropertiesService
471                 .getProperty( PROPERTY_POLICE_MARGIN_LEFT_ENTRY_VALUE ) ) );
472 
473         Font fontEntryValue = new Font(
474                 DirectoryUtils.convertStringToInt( AppPropertiesService.getProperty( PROPERTY_POLICE_NAME ) ),
475                 DirectoryUtils.convertStringToInt( AppPropertiesService.getProperty( PROPERTY_POLICE_SIZE_ENTRY_VALUE ) ),
476                 DirectoryUtils.convertStringToInt( AppPropertiesService.getProperty( PROPERTY_POLICE_STYLE_ENTRY_VALUE ) ) );
477 
478         for ( RecordField recordField : listRecordFields )
479         {
480             String strValue = StringUtils.EMPTY;
481 
482             if ( entry instanceof EntryTypeDownloadUrl && StringUtils.isNotBlank( recordField.getFileName( ) ) )
483             {
484                 strValue = recordField.getFileName( );
485             }
486             else if ( ( recordField.getFile( ) != null ) && StringUtils.isNotBlank( recordField.getFile( ).getTitle( ) ) )
487             {
488                 // The thumbnails and big thumbnails should not be displayed
489                 if ( !( ( StringUtils.isNotBlank( recordField.getValue( ) ) && recordField.getValue( ).startsWith(
490                         FIELD_THUMBNAIL ) ) || ( StringUtils.isNotBlank( recordField.getValue( ) ) && recordField
491                         .getValue( ).startsWith( FIELD_BIG_THUMBNAIL ) ) ) )
492                 {
493                     strValue = recordField.getFile( ).getTitle( );
494                 }
495             }
496             else
497             {
498                 strValue = entry.convertRecordFieldValueToString( recordField, locale, false, false );
499             }
500 
501             if ( bExtractNotFilledField || ( !bExtractNotFilledField && StringUtils.isNotBlank( strValue ) ) )
502             {
503                 listValue.add( new ListItem( strValue, fontEntryValue ) );
504             }
505         }
506 
507         if ( bExtractNotFilledField
508                 || ( !bExtractNotFilledField && CollectionUtils.isNotEmpty( listValue.getItems( ) ) ) )
509         {
510             paragraphEntry.add( phraseEntry );
511             paragraphEntry.add( listValue );
512         }
513     }
514 
515     /**
516      * Build the fields in a single paragraph.
517      * @param listRecordFields the list of record fields
518      * @param entry the entry
519      * @param locale the locale
520      * @param phraseEntry the phrase entry
521      * @param paragraphEntry the paragraph entry
522      * @param bExtractNotFilledField if true, extract empty fields, false
523      * @throws DocumentException exception if there is an error
524      */
525     private static void builFieldsInSinglePhrase( List<RecordField> listRecordFields, IEntry entry, Locale locale,
526             Phrase phraseEntry, Paragraph paragraphEntry, Boolean bExtractNotFilledField ) throws DocumentException
527     {
528         RecordField recordField = listRecordFields.get( 0 );
529         Chunk chunkEntryValue = null;
530         Font fontEntryValue = new Font(
531                 DirectoryUtils.convertStringToInt( AppPropertiesService.getProperty( PROPERTY_POLICE_NAME ) ),
532                 DirectoryUtils.convertStringToInt( AppPropertiesService.getProperty( PROPERTY_POLICE_SIZE_ENTRY_VALUE ) ),
533                 DirectoryUtils.convertStringToInt( AppPropertiesService.getProperty( PROPERTY_POLICE_STYLE_ENTRY_VALUE ) ) );
534 
535         if ( entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeDownloadUrl )
536         {
537             if ( StringUtils.isNotBlank( recordField.getFileName( ) ) )
538             {
539                 chunkEntryValue = new Chunk( recordField.getFileName( ) );
540             }
541             else
542             {
543                 chunkEntryValue = new Chunk( StringUtils.EMPTY );
544             }
545         }
546         else if ( entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeGeolocation )
547         {
548             for ( RecordField recordFieldGeo : listRecordFields )
549             {
550                 if ( ( recordFieldGeo.getField( ) != null )
551                         && EntryTypeGeolocation.CONSTANT_ADDRESS.equals( recordFieldGeo.getField( ).getTitle( ) ) )
552                 {
553                     chunkEntryValue = new Chunk( entry.convertRecordFieldValueToString( recordFieldGeo, locale, false,
554                             false ), fontEntryValue );
555                 }
556             }
557         }
558         else if ( entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeCheckBox
559                 || entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeSelect
560                 || entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeRadioButton )
561         {
562             chunkEntryValue = new Chunk( entry.convertRecordFieldTitleToString( recordField, locale, false ),
563                     fontEntryValue );
564         }
565         else if ( entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeFile
566                 || entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeImg )
567         {
568             String strFileName = StringUtils.EMPTY;
569 
570             if ( ( recordField.getFile( ) != null ) && StringUtils.isNotBlank( recordField.getFile( ).getTitle( ) ) )
571             {
572                 // The thumbnails and big thumbnails should not be displayed
573                 if ( !( ( StringUtils.isNotBlank( recordField.getValue( ) ) && recordField.getValue( ).startsWith(
574                         FIELD_THUMBNAIL ) ) || ( StringUtils.isNotBlank( recordField.getValue( ) ) && recordField
575                         .getValue( ).startsWith( FIELD_BIG_THUMBNAIL ) ) ) )
576                 {
577                     strFileName = recordField.getFile( ).getTitle( );
578                 }
579             }
580 
581             chunkEntryValue = new Chunk( strFileName, fontEntryValue );
582         }
583         else if ( entry instanceof fr.paris.lutece.plugins.directory.business.EntryTypeRichText )
584         {
585             String strValue = entry.convertRecordFieldValueToString( recordField, locale, false, false );
586             strValue = StringUtils.defaultString( HtmlUtils.htmlUnescape( strValue ) ).replaceAll( "<[^>]*>", "" );
587             chunkEntryValue = new Chunk( strValue, fontEntryValue );
588         }
589         else
590         {
591             chunkEntryValue = new Chunk( entry.convertRecordFieldValueToString( recordField, locale, false, false ),
592                     fontEntryValue );
593         }
594 
595         if ( chunkEntryValue != null )
596         {
597             if ( bExtractNotFilledField
598                     || ( !bExtractNotFilledField && StringUtils.isNotBlank( chunkEntryValue.getContent( ) ) ) )
599             {
600                 phraseEntry.add( chunkEntryValue );
601                 paragraphEntry.add( phraseEntry );
602             }
603         }
604     }
605 
606     /**
607      * Method to download a PDF file generated by directory record
608      * @param request request
609      * @param response response
610      * @param plugin plugin
611      * @param configProducer configuration
612      * @param listIdEntryConfig list of config id entry
613      * @param locale locale
614      * @param nIdRecord the id record
615      */
616     public static void doDownloadPDF( HttpServletRequest request, HttpServletResponse response, Plugin plugin,
617             IConfigProducer configProducer, List<Integer> listIdEntryConfig, Locale locale, int nIdRecord )
618     {
619         Record record = RecordHome.findByPrimaryKey( nIdRecord, plugin );
620         Directory directory = DirectoryHome.findByPrimaryKey( record.getDirectory( ).getIdDirectory( ), plugin );
621 
622         String strName = getFileNameFromConfig( directory, configProducer, nIdRecord, locale );
623         String strFileName = doPurgeNameFile( strName ) + ".pdf";
624 
625         response.setHeader( "Content-Disposition", "attachment ;filename=\"" + strFileName + "\"" );
626         response.setHeader( "Pragma", "public" );
627         response.setHeader( "Expires", "0" );
628         response.setHeader( "Cache-Control", "must-revalidate,post-check=0,pre-check=0" );
629 
630         response.setContentType( "application/pdf" );
631 
632         OutputStream os = null;
633 
634         try
635         {
636             os = response.getOutputStream( );
637 
638             if ( listIdEntryConfig != null )
639             {
640                 PDFUtils.doCreateDocumentPDF( request, strName, os, nIdRecord, listIdEntryConfig,
641                         configProducer.getExtractNotFilled( ) );
642             }
643             else
644             {
645                 PDFUtils.doCreateDocumentPDF( request, strName, os, nIdRecord, configProducer.getExtractNotFilled( ) );
646             }
647         }
648         catch ( IOException e )
649         {
650             AppLogService.error( e );
651         }
652         finally
653         {
654             IOUtils.closeQuietly( os );
655         }
656     }
657 
658     public static String getFileNameFromConfig( Directory directory, IConfigProducer configProducer, int nIdRecord,
659             Locale locale )
660     {
661         String strName = null;
662         String strTypeConfigFileName = configProducer.getTypeConfigFileName( );
663         if ( strTypeConfigFileName.equals( DEFAULT_TYPE_FILE_NAME ) )
664         {
665             strName = StringUtil.replaceAccent( directory.getTitle( ) ).replace( " ", "_" ) + "_" + nIdRecord;
666         }
667         else if ( strTypeConfigFileName.equals( DIRECTORY_ENTRY_FILE_NAME ) )
668         {
669             Plugin pluginDirectory = PluginService.getPlugin( DirectoryPlugin.PLUGIN_NAME );
670             RecordFieldFilter filter = new RecordFieldFilter( );
671             filter.setIdRecord( nIdRecord );
672             filter.setIdEntry( configProducer.getIdEntryFileName( ) );
673 
674             List<RecordField> listRecordField = RecordFieldHome.getRecordFieldList( filter, pluginDirectory );
675 
676             for ( RecordField recordField : listRecordField )
677             {
678                 strName = recordField.getEntry( ).convertRecordFieldValueToString( recordField, locale, false, false );
679             }
680         }
681         else
682         {
683             strName = configProducer.getTextFileName( ) + "_" + nIdRecord;
684         }
685         return strName;
686     }
687 
688     /**
689      * Method to purge file name, (replace accent and punctuation)
690      * @param strNameFile name file
691      * @return purged name file
692      */
693     public static String doPurgeNameFile( String strNameFile )
694     {
695         return StringUtil.replaceAccent( strNameFile ).replaceAll( "\\W", "_" );
696     }
697 }