View Javadoc
1   /*
2    * Copyright (c) 2002-2023, City of Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.plugins.document.web;
35  
36  import fr.paris.lutece.plugins.document.business.DocumentResource;
37  import fr.paris.lutece.plugins.document.business.DocumentType;
38  import fr.paris.lutece.plugins.document.business.DocumentTypeHome;
39  import fr.paris.lutece.plugins.document.business.attributes.AttributeTypeHome;
40  import fr.paris.lutece.plugins.document.business.attributes.AttributeTypeParameter;
41  import fr.paris.lutece.plugins.document.business.attributes.DocumentAttribute;
42  import fr.paris.lutece.plugins.document.business.attributes.DocumentAttributeHome;
43  import fr.paris.lutece.plugins.document.service.AttributeManager;
44  import fr.paris.lutece.plugins.document.service.AttributeService;
45  import fr.paris.lutece.plugins.document.service.metadata.MetadataService;
46  import fr.paris.lutece.plugins.document.utils.IntegerUtils;
47  import fr.paris.lutece.portal.business.regularexpression.RegularExpression;
48  import fr.paris.lutece.portal.service.cache.CacheService;
49  import fr.paris.lutece.portal.service.fileupload.FileUploadService;
50  import fr.paris.lutece.portal.service.i18n.I18nService;
51  import fr.paris.lutece.portal.service.message.AdminMessage;
52  import fr.paris.lutece.portal.service.message.AdminMessageService;
53  import fr.paris.lutece.portal.service.regularexpression.RegularExpressionService;
54  import fr.paris.lutece.portal.service.template.AppTemplateService;
55  import fr.paris.lutece.portal.service.util.AppPropertiesService;
56  import fr.paris.lutece.portal.web.admin.PluginAdminPageJspBean;
57  import fr.paris.lutece.portal.web.constants.Messages;
58  import fr.paris.lutece.portal.web.upload.MultipartHttpServletRequest;
59  import fr.paris.lutece.portal.web.util.LocalizedPaginator;
60  import fr.paris.lutece.util.ReferenceList;
61  import fr.paris.lutece.util.html.HtmlTemplate;
62  import fr.paris.lutece.util.html.Paginator;
63  import fr.paris.lutece.util.string.StringUtil;
64  import fr.paris.lutece.util.url.UrlItem;
65  
66  import org.apache.commons.fileupload.FileItem;
67  import org.apache.commons.lang3.StringUtils;
68  
69  import org.xml.sax.InputSource;
70  
71  import java.io.ByteArrayInputStream;
72  
73  import java.util.ArrayList;
74  import java.util.Arrays;
75  import java.util.HashMap;
76  import java.util.List;
77  import java.util.Map;
78  
79  import javax.servlet.http.HttpServletRequest;
80  
81  import javax.xml.parsers.SAXParser;
82  import javax.xml.parsers.SAXParserFactory;
83  
84  
85  /**
86   * JSP Bean for document type management
87   */
88  public class DocumentTypeJspBean extends PluginAdminPageJspBean
89  {
90      public static final String RIGHT_DOCUMENT_TYPES_MANAGEMENT = "DOCUMENT_TYPES_MANAGEMENT";
91      private static final String TEMPLATE_MANAGE_DOCUMENT_TYPES = "admin/plugins/document/manage_document_types.html";
92      private static final String TEMPLATE_CREATE_DOCUMENT_TYPE = "admin/plugins/document/create_document_type.html";
93      private static final String TEMPLATE_MODIFY_DOCUMENT_TYPE = "admin/plugins/document/modify_document_type.html";
94      private static final String TEMPLATE_ADD_ATTRIBUTE = "admin/plugins/document/add_document_type_attribute.html";
95      private static final String TEMPLATE_MODIFY_ATTRIBUTE = "admin/plugins/document/modify_document_type_attribute.html";
96      private static final String PROPERTY_PAGE_TITLE_CREATE_DOCUMENT_TYPE = "document.create_document_type.pageTitle";
97      private static final String PROPERTY_PAGE_TITLE_MODIFY_DOCUMENT_TYPE = "document.modify_document_type.pageTitle";
98      private static final String PROPERTY_PAGE_TITLE_ADD_ATTRIBUTE = "document.add_document_type_attribute.pageTitle";
99      private static final String PROPERTY_PAGE_TITLE_MODIFY_ATTRIBUTE = "document.modify_document_type_attribute.pageTitle";
100     private static final String PROPERTY_CANNOT_DELETE_DOCUMENTS = "document.message.cannotRemoveTypeDocuments";
101     private static final String PROPERTY_CONFIRM_DELETE_TYPE = "document.message.confirmDeleteType";
102     private static final String PROPERTY_CONFIRM_DELETE_ATTRIBUTE = "document.message.confirmDeleteAttribute";
103     private static final String PROPERTY_NO_THUMBNAIL_ATTRIBUTE = "document.documentType.noThumbnailAttribute";
104     private static final String PROPERTY_CODE_ATTRIBUTE_BAD_FORMAT_CREATE = "document.add_document_type_attribute.codeAttribute.badFormat";
105     private static final String PROPERTY_CODE_ATTRIBUTE_BAD_FORMAT_MODIFY = "document.modify_document_type_attribute.codeAttribute.badFormat";
106     private static final String PROPERTY_REGULAR_EXPRESSION_PER_PAGE = "document.regularExpressionPerPage";
107     private static final String MESSAGE_DOCUMENT_ALREADY_EXIST = "document.message.documentType.errorAlreadyExist";
108     private static final String MARK_DOCUMENT_TYPES_LIST = "document_types_list";
109     private static final String MARK_THUMBNAIL_ATTRIBUTES_LIST = "thumbnail_attributes_list";
110     private static final String MARK_DOCUMENT_TYPE = "document_type";
111     private static final String MARK_ATTRIBUTE_TYPES_LIST = "attribute_types_list";
112     private static final String MARK_DOCUMENT_TYPE_CODE = "document_type_code";
113     private static final String MARK_ATTRIBUTE_TYPE_CODE = "attribute_type_code";
114     private static final String MARK_ATTRIBUTE_EXTRAS_PARAMETERS = "attribute_parameters";
115     private static final String MARK_ATTRIBUTE = "attribute";
116     private static final String MARK_METADATA_HANDLERS_LIST = "metadata_handlers_list";
117     private static final String MARK_REGULAR_EXPRESSION_TO_ADD_LIST = "regular_expression_to_add_list";
118     private static final String MARK_REGULAR_EXPRESSION_ADDED_LIST = "regular_expression_added_list";
119     private static final String MARK_PAGINATOR = "paginator";
120     private static final String MARK_NB_ITEMS_PER_PAGE = "nb_items_per_page";
121     private static final String MARK_NB_REGULAR_EXPRESSION = "nb_regular_expression";
122     private static final String PARAMETER_DOCUMENT_TYPE_CODE = "document_type_code";
123     private static final String PARAMETER_NAME = "name";
124     private static final String PARAMETER_OLD_CODE = "old_code";
125     private static final String PARAMETER_CODE = "code";
126     private static final String PARAMETER_DESCRIPTION = "description";
127     private static final String PARAMETER_THUMBNAIL_ATTRIBUTE = "thumbnail_attribute";
128     private static final String PARAMETER_ICON_URL = "icon_url";
129     private static final String PARAMETER_REQUIRED = "required";
130     private static final String PARAMETER_SEARCHABLE = "searchable";
131     private static final String PARAMETER_ATTRIBUTE_TYPE_CODE = "attribute_type_code";
132     private static final String PARAMETER_ATTRIBUTE_ID = "attribute_id";
133     private static final String PARAMETER_INDEX = "index";
134     private static final String PARAMETER_METADATA = "metadata";
135     private static final String PARAMETER_STYLESHEET_TYPE = "stylesheet_type";
136     private static final String PARAMETER_STYLESHEET_ADMIN = "stylesheet_admin";
137     private static final String PARAMETER_STYLESHEET_CONTENT = "stylesheet_content";
138     private static final String PARAMETER_UPDATE_STYLESHEET_ADMIN = "stylesheet_admin_update";
139     private static final String PARAMETER_UPDATE_STYLESHEET_CONTENT = "stylesheet_content_update";
140     private static final String PARAMETER_EXPRESSION_ID = "expression_id";
141     private static final String PARAMETER_APPLY = "apply";
142     private static final String PARAMETER_CANCEL = "cancel";
143     private static final String PARAMETER_SAVE = "save";
144     private static final String PARAMETER_SESSION = "session";
145     private static final String JSP_MODIFY_DOCUMENT_TYPE = "ModifyDocumentType.jsp";
146     private static final String JSP_DELETE_DOCUMENT_TYPE = "jsp/admin/plugins/document/DoDeleteDocumentType.jsp";
147     private static final String JSP_DELETE_ATTRIBUTE = "jsp/admin/plugins/document/DoDeleteAttribute.jsp";
148     private static final String JSP_MODIFY_DOCUMENT_TYPE_ATTRIBUTE = "ModifyDocumentTypeAttribute.jsp";
149     private static final String JSP_ADD_DOCUMENT_TYPE_ATTRIBUTE = "AddDocumentTypeAttribute.jsp";
150     private static final String MESSAGE_STYLESHEET_NOT_VALID = "portal.style.message.stylesheetNotValid";
151     private static final String CHECK_ON = "on";
152     private static final String STYLESHEET_CONTENT_TYPE = "text/plain";
153     private static final String SEPARATOR = "_";
154     private static final String FILE_EXTENSION = ".xsl";
155     private static final Object UPDATE_VALUE = "true";
156     private static final String PATTERN_CODE = "[a-zA-Z0-9_\\-]+";
157     private static final int NO_THUMBNAIL_ATTRIBUTE = 0;
158     private String _strDocumentTypeCode;
159     private int _nItemsPerPage;
160     private int _nDefaultItemsPerPage;
161     private String _strCurrentPageIndex;
162     private DocumentAttribute _attribute;
163 
164     /**
165      * Gets the Document Types Management Page
166      * @param request The HTTP request
167      * @return The Document Types Management Page
168      */
169     public String getManageDocumentTypes( HttpServletRequest request )
170     {
171         Map<String, Object> model = new HashMap<String, Object>(  );
172         model.put( MARK_DOCUMENT_TYPES_LIST, DocumentTypeHome.findAll(  ) );
173 
174         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_MANAGE_DOCUMENT_TYPES, getLocale(  ), model );
175 
176         return getAdminPage( template.getHtml(  ) );
177     }
178 
179     /**
180      * Gets the document type creation page
181      * @param request The HTTP request
182      * @return The document type creation page
183      */
184     public String getCreateDocumentType( HttpServletRequest request )
185     {
186         setPageTitleProperty( PROPERTY_PAGE_TITLE_CREATE_DOCUMENT_TYPE );
187 
188         Map<String, Object> model = new HashMap<String, Object>(  );
189         model.put( MARK_METADATA_HANDLERS_LIST, MetadataService.getMetadataHandlersList(  ) );
190 
191         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_CREATE_DOCUMENT_TYPE, getLocale(  ), model );
192 
193         return getAdminPage( template.getHtml(  ) );
194     }
195 
196     /**
197      * Perform the document type creation
198      * @param request The HTTP request
199      * @return The URL to go after performing the action
200      */
201     public String doCreateDocumentType( HttpServletRequest request )
202     {
203         String strName = request.getParameter( PARAMETER_NAME );
204         String strDescription = request.getParameter( PARAMETER_DESCRIPTION );
205         String strCode = request.getParameter( PARAMETER_CODE );
206         String strMetadata = request.getParameter( PARAMETER_METADATA );
207 
208         // Mandatory fields
209         if ( StringUtils.isBlank( strName ) || StringUtils.isBlank( strDescription ) || StringUtils.isBlank( strCode ) )
210         {
211             return AdminMessageService.getMessageUrl( request, Messages.MANDATORY_FIELDS, AdminMessage.TYPE_STOP );
212         }
213 
214         // Check Accentuated Character
215         if ( !checkDocumentTypeCodePattern( strCode ) )
216         {
217             return AdminMessageService.getMessageUrl( request, Messages.MESSAGE_STRING_FORMAT, AdminMessage.TYPE_STOP );
218         }
219 
220         if ( DocumentTypeHome.findByPrimaryKey( strCode ) != null )
221         {
222             return AdminMessageService.getMessageUrl( request, MESSAGE_DOCUMENT_ALREADY_EXIST, AdminMessage.TYPE_STOP );
223         }
224 
225         DocumentTypeusiness/DocumentType.html#DocumentType">DocumentType documentType = new DocumentType(  );
226         documentType.setName( strName );
227         documentType.setCode( strCode );
228         documentType.setDescription( strDescription );
229         documentType.setMetadataHandler( strMetadata );
230         DocumentTypeHome.create( documentType );
231 
232         return JSP_MODIFY_DOCUMENT_TYPE + "?document_type_code=" + strCode;
233     }
234 
235     /**
236      * Gets the document type modification page
237      * @param request The HTTP request
238      * @return The document type modification page
239      */
240     public String getModifyDocumentType( HttpServletRequest request )
241     {
242         setPageTitleProperty( PROPERTY_PAGE_TITLE_MODIFY_DOCUMENT_TYPE );
243 
244         String strDocumentTypeCode = request.getParameter( PARAMETER_DOCUMENT_TYPE_CODE );
245 
246         if ( strDocumentTypeCode != null )
247         {
248             _strDocumentTypeCode = strDocumentTypeCode;
249         }
250         else
251         {
252             strDocumentTypeCode = _strDocumentTypeCode;
253         }
254 
255         DocumentType documentType = DocumentTypeHome.findByPrimaryKey( strDocumentTypeCode );
256 
257         if ( documentType == null )
258         {
259             return getManageDocumentTypes( request );
260         }
261 
262         ReferenceList listAttributeTypes = AttributeTypeHome.getAttributeTypesList( getLocale(  ) );
263         Map<String, Object> model = new HashMap<String, Object>(  );
264         model.put( MARK_DOCUMENT_TYPE, documentType );
265         model.put( MARK_THUMBNAIL_ATTRIBUTES_LIST, getThumbnailAttributesList( documentType ) );
266         model.put( MARK_METADATA_HANDLERS_LIST, MetadataService.getMetadataHandlersList(  ) );
267         model.put( MARK_ATTRIBUTE_TYPES_LIST, listAttributeTypes );
268 
269         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_MODIFY_DOCUMENT_TYPE, getLocale(  ), model );
270 
271         return getAdminPage( template.getHtml(  ) );
272     }
273 
274     /**
275      * Perform document type modification creation
276      * @param request The HTTP request
277      * @return The URL to go after performing the action
278      */
279     public String doModifyDocumentType( HttpServletRequest request )
280     {
281         String strOldCode = request.getParameter( PARAMETER_OLD_CODE );
282         String strCode = request.getParameter( PARAMETER_CODE );
283         String strName = request.getParameter( PARAMETER_NAME );
284         String strDescription = request.getParameter( PARAMETER_DESCRIPTION );
285         String strIconUrl = request.getParameter( PARAMETER_ICON_URL );
286         String strThumbnailAttribute = request.getParameter( PARAMETER_THUMBNAIL_ATTRIBUTE );
287         int nThumbnailAttribute = IntegerUtils.convert( strThumbnailAttribute );
288         String strMetadata = request.getParameter( PARAMETER_METADATA );
289 
290         // Check Accentuated Character
291         if ( !checkDocumentTypeCodePattern( strCode ) )
292         {
293             return AdminMessageService.getMessageUrl( request, Messages.MESSAGE_STRING_FORMAT, AdminMessage.TYPE_STOP );
294         }
295 
296         // Mandatory fields
297         if ( StringUtils.isBlank( strName ) || StringUtils.isBlank( strDescription ) || StringUtils.isBlank( strCode ) )
298         {
299             return AdminMessageService.getMessageUrl( request, Messages.MANDATORY_FIELDS, AdminMessage.TYPE_STOP );
300         }
301 
302         DocumentType documentType = DocumentTypeHome.findByPrimaryKey( strOldCode );
303         documentType.setOldCode( strOldCode );
304         documentType.setCode( strCode );
305         documentType.setName( strName );
306         documentType.setDefaultThumbnailUrl( strIconUrl );
307         documentType.setThumbnailAttributeId( nThumbnailAttribute );
308         documentType.setDescription( strDescription );
309         documentType.setMetadataHandler( strMetadata );
310         DocumentTypeHome.update( documentType );
311 
312         return getHomeUrl( request );
313     }
314 
315     /**
316      * Gets ttribute creation page
317      * @param request The HTTP request
318      * @return the html template
319      */
320     public String getAddAttribute( HttpServletRequest request )
321     {
322         setPageTitleProperty( PROPERTY_PAGE_TITLE_ADD_ATTRIBUTE );
323 
324         String strAttributeTypeCode = request.getParameter( PARAMETER_ATTRIBUTE_TYPE_CODE );
325         AttributeManager manager = AttributeService.getInstance(  ).getManager( strAttributeTypeCode );
326         _strDocumentTypeCode = request.getParameter( PARAMETER_DOCUMENT_TYPE_CODE );
327 
328         Map<String, Object> model = new HashMap<String, Object>(  );
329         model.put( MARK_ATTRIBUTE_TYPE_CODE, strAttributeTypeCode );
330 
331         //        model.put( MARK_ATTRIBUTE_EXTRAS_PARAMETERS , manager.getExtraParameters(  getLocale() ) );
332         String strSession = request.getParameter( PARAMETER_SESSION );
333 
334         if ( StringUtils.isNotBlank( strSession ) )
335         {
336             model.put( MARK_ATTRIBUTE, _attribute );
337             model.put( MARK_ATTRIBUTE_EXTRAS_PARAMETERS,
338                 manager.getCreateParametersFormHtml( _attribute.getParameters(  ), getLocale(  ) ) );
339         }
340         else
341         {
342             _attribute = new DocumentAttribute(  );
343             model.put( MARK_ATTRIBUTE_EXTRAS_PARAMETERS, manager.getCreateParametersFormHtml( getLocale(  ) ) );
344         }
345 
346         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_ADD_ATTRIBUTE, getLocale(  ), model );
347 
348         return getAdminPage( template.getHtml(  ) );
349     }
350 
351     /**
352      * Perform attribute creation
353      * @param request The HTTP request
354      * @return The URL to go after performing the action
355      */
356     public String doAddAttribute( HttpServletRequest request )
357     {
358         _attribute = new DocumentAttribute(  );
359 
360         boolean bIsValid = validateCodeAttribute( request );
361 
362         if ( !bIsValid )
363         {
364             return AdminMessageService.getMessageUrl( request, PROPERTY_CODE_ATTRIBUTE_BAD_FORMAT_CREATE,
365                 AdminMessage.TYPE_STOP );
366         }
367 
368         getAttributeData( request, _attribute );
369 
370         // The user has not clicked on "save", then there are some operations to proceed
371         String strSave = request.getParameter( PARAMETER_SAVE );
372 
373         if ( StringUtils.isBlank( strSave ) )
374         {
375             String strAttributeTypeCode = request.getParameter( PARAMETER_ATTRIBUTE_TYPE_CODE );
376             UrlItem url = new UrlItem( JSP_ADD_DOCUMENT_TYPE_ATTRIBUTE );
377             url.addParameter( PARAMETER_SESSION, PARAMETER_SESSION );
378             url.addParameter( PARAMETER_ATTRIBUTE_TYPE_CODE, strAttributeTypeCode );
379             url.addParameter( PARAMETER_DOCUMENT_TYPE_CODE, _strDocumentTypeCode );
380 
381             return url.getUrl(  );
382         }
383 
384         String strValidateMessage = getAttributeValidationMessage( _attribute );
385 
386         if ( strValidateMessage != null )
387         {
388             return AdminMessageService.getMessageUrl( request, strValidateMessage, AdminMessage.TYPE_STOP );
389         }
390 
391         DocumentAttributeHome.create( _attribute );
392 
393         if ( request.getParameter( PARAMETER_APPLY ) != null )
394         {
395             UrlItem url = new UrlItem( JSP_MODIFY_DOCUMENT_TYPE_ATTRIBUTE );
396             url.addParameter( PARAMETER_ATTRIBUTE_ID, _attribute.getId(  ) );
397 
398             return url.getUrl(  );
399         }
400 
401         return JSP_MODIFY_DOCUMENT_TYPE;
402     }
403 
404     /**
405      * Perform attribute modification
406      * @param request The HTTP request
407      * @return The URL to go after performing the action
408      */
409     public String doModifyAttribute( HttpServletRequest request )
410     {
411         if ( request.getParameter( PARAMETER_CANCEL ) != null )
412         {
413             UrlItem url = new UrlItem( JSP_MODIFY_DOCUMENT_TYPE );
414 
415             return url.getUrl(  );
416         }
417 
418         String strAttributeId = request.getParameter( PARAMETER_ATTRIBUTE_ID );
419         int nAttributeId = IntegerUtils.convert( strAttributeId );
420         _attribute = DocumentAttributeHome.findByPrimaryKey( nAttributeId );
421 
422         boolean bIsValid = validateCodeAttribute( request );
423 
424         if ( !bIsValid )
425         {
426             return AdminMessageService.getMessageUrl( request, PROPERTY_CODE_ATTRIBUTE_BAD_FORMAT_MODIFY,
427                 AdminMessage.TYPE_STOP );
428         }
429 
430         getAttributeData( request, _attribute );
431 
432         // The user has not clicked on "save", then there are some operations to proceed
433         String strSave = request.getParameter( PARAMETER_SAVE );
434 
435         if ( StringUtils.isBlank( strSave ) )
436         {
437             UrlItem url = new UrlItem( JSP_MODIFY_DOCUMENT_TYPE_ATTRIBUTE );
438             url.addParameter( PARAMETER_SESSION, PARAMETER_SESSION );
439             url.addParameter( PARAMETER_ATTRIBUTE_ID, nAttributeId );
440 
441             return url.getUrl(  );
442         }
443 
444         String strValidateMessage = getAttributeValidationMessage( _attribute );
445 
446         if ( strValidateMessage != null )
447         {
448             return AdminMessageService.getMessageUrl( request, strValidateMessage, AdminMessage.TYPE_STOP );
449         }
450 
451         DocumentAttributeHome.update( _attribute );
452 
453         return JSP_MODIFY_DOCUMENT_TYPE;
454     }
455 
456     private void getAttributeData( HttpServletRequest request, DocumentAttribute attribute )
457     {
458         String strName = request.getParameter( PARAMETER_NAME );
459         String strCode = request.getParameter( PARAMETER_CODE ).trim(  ).toLowerCase(  );
460         String strDescription = request.getParameter( PARAMETER_DESCRIPTION );
461         String strRequired = request.getParameter( PARAMETER_REQUIRED );
462         String strSearchable = request.getParameter( PARAMETER_SEARCHABLE );
463         String strAttributeTypeCode = request.getParameter( PARAMETER_ATTRIBUTE_TYPE_CODE );
464         String[] arrayStrValues;
465         List<String> listValues = new ArrayList<String>(  );
466         List<AttributeTypeParameter> listParameters;
467         AttributeManager manager = AttributeService.getInstance(  ).getManager( strAttributeTypeCode );
468 
469         String strSave = request.getParameter( PARAMETER_SAVE );
470 
471         if ( StringUtils.isBlank( strSave ) )
472         {
473             listParameters = manager.getValueParameters( request, getLocale(  ) );
474         }
475         else
476         {
477             listParameters = manager.getExtraParameters( getLocale(  ) );
478 
479             for ( AttributeTypeParameter parameter : listParameters )
480             {
481                 arrayStrValues = request.getParameterValues( parameter.getName(  ) );
482 
483                 if ( arrayStrValues != null )
484                 {
485                     listValues.addAll( Arrays.asList( arrayStrValues ) );
486                 }
487 
488                 parameter.setValueList( listValues );
489                 listValues.clear(  );
490             }
491         }
492 
493         attribute.setName( strName );
494         attribute.setCode( strCode );
495         attribute.setDescription( strDescription );
496         attribute.setRequired( ( strRequired != null ) && ( strRequired.equals( CHECK_ON ) ) );
497         attribute.setSearchable( ( strSearchable != null ) && ( strSearchable.equals( CHECK_ON ) ) );
498         attribute.setCodeDocumentType( _strDocumentTypeCode );
499         attribute.setCodeAttributeType( strAttributeTypeCode );
500 
501         if ( attribute.getAttributeOrder(  ) == 0 )
502         {
503             // Order is not defined (creation). Put this attribute at the end of the list
504             DocumentType documentType = DocumentTypeHome.findByPrimaryKey( _strDocumentTypeCode );
505             attribute.setAttributeOrder( documentType.getAttributes(  ).size(  ) + 1 );
506         }
507 
508         attribute.setParameters( listParameters );
509     }
510 
511     /**
512      * Validate if the code has no spaces and no caps
513      * @param request the HTTPrequest
514      * @return true if the codeAttribute is valid, false otherwise
515      */
516     private boolean validateCodeAttribute( HttpServletRequest request )
517     {
518         String strCode = request.getParameter( PARAMETER_CODE ).trim(  ).toLowerCase(  );
519 
520         if ( ( strCode != null ) && ( strCode.length(  ) == 0 ) )
521         {
522             return true;
523         }
524 
525         boolean isOK = false;
526 
527         if ( ( strCode != null ) && ( strCode.length(  ) > 0 ) )
528         {
529             isOK = StringUtil.checkCodeKey( strCode );
530         }
531 
532         return isOK;
533     }
534 
535     private String getAttributeValidationMessage( DocumentAttribute attribute )
536     {
537         String strMessage = null;
538 
539         // Mandatory fields
540         if ( StringUtils.isBlank( attribute.getName(  ) ) || StringUtils.isBlank( attribute.getDescription(  ) ) ||
541                 StringUtils.isBlank( attribute.getCode(  ) ) )
542         {
543             return Messages.MANDATORY_FIELDS;
544         }
545 
546         AttributeManager manager = AttributeService.getInstance(  ).getManager( attribute.getCodeAttributeType(  ) );
547         String strValidationErrorMessageKey = manager.validateValueParameters( attribute.getParameters(  ),
548                 getLocale(  ) );
549 
550         if ( strValidationErrorMessageKey != null )
551         {
552             return strValidationErrorMessageKey;
553         }
554 
555         return strMessage;
556     }
557 
558     /**
559      * Gets the modification page
560      * @param request The HTTP request
561      * @return The modification page
562      */
563     public String getModifyAttribute( HttpServletRequest request )
564     {
565         setPageTitleProperty( PROPERTY_PAGE_TITLE_MODIFY_ATTRIBUTE );
566 
567         String strAttributeId = request.getParameter( PARAMETER_ATTRIBUTE_ID );
568         int nAttributeId = IntegerUtils.convert( strAttributeId );
569         DocumentAttribute attribute = DocumentAttributeHome.findByPrimaryKey( nAttributeId );
570 
571         if ( attribute == null )
572         {
573             return getManageDocumentTypes( request );
574         }
575 
576         AttributeManager manager = AttributeService.getInstance(  ).getManager( attribute.getCodeAttributeType(  ) );
577 
578         UrlItem url = new UrlItem( request.getRequestURI(  ) );
579         url.addParameter( PARAMETER_ATTRIBUTE_ID, nAttributeId );
580 
581         ReferenceList refListRegularExpressionToAdd = new ReferenceList(  );
582         List<RegularExpression> listRegularExpressionAdded = new ArrayList<RegularExpression>(  );
583 
584         // Checks if the regularexpression plugin is enabled
585         if ( RegularExpressionService.getInstance(  ).isAvailable(  ) )
586         {
587             // Gets the list of regular expressions already added
588             for ( Integer nExpressionId : DocumentAttributeHome.getListRegularExpressionKeyByIdAttribute( nAttributeId ) )
589             {
590                 listRegularExpressionAdded.add( RegularExpressionService.getInstance(  )
591                                                                         .getRegularExpressionByKey( nExpressionId ) );
592             }
593 
594             // Defines the reference list of regular expressions which could be added
595             for ( RegularExpression regularExpression : RegularExpressionService.getInstance(  )
596                                                                                 .getAllRegularExpression(  ) )
597             {
598                 if ( !listRegularExpressionAdded.contains( regularExpression ) )
599                 {
600                     refListRegularExpressionToAdd.addItem( regularExpression.getIdExpression(  ),
601                         regularExpression.getTitle(  ) );
602                 }
603             }
604         }
605 
606         // Paginator
607         _strCurrentPageIndex = Paginator.getPageIndex( request, Paginator.PARAMETER_PAGE_INDEX, _strCurrentPageIndex );
608         _nDefaultItemsPerPage = AppPropertiesService.getPropertyInt( PROPERTY_REGULAR_EXPRESSION_PER_PAGE, 10 );
609         _nItemsPerPage = Paginator.getItemsPerPage( request, Paginator.PARAMETER_ITEMS_PER_PAGE, _nItemsPerPage,
610                 _nDefaultItemsPerPage );
611 
612         LocalizedPaginator<RegularExpression> paginator = new LocalizedPaginator<RegularExpression>( listRegularExpressionAdded,
613                 _nItemsPerPage, url.getUrl(  ), Paginator.PARAMETER_PAGE_INDEX, _strCurrentPageIndex, getLocale(  ) );
614 
615         Map<String, Object> model = new HashMap<String, Object>(  );
616 
617         model.put( MARK_DOCUMENT_TYPE_CODE, _strDocumentTypeCode );
618         model.put( MARK_ATTRIBUTE_TYPE_CODE, attribute.getCodeAttributeType(  ) );
619 
620         //        model.put( MARK_ATTRIBUTE_EXTRAS_PARAMETERS , listParameters );
621         String strSession = request.getParameter( PARAMETER_SESSION );
622 
623         if ( StringUtils.isNotBlank( strSession ) )
624         {
625             model.put( MARK_ATTRIBUTE, _attribute );
626             model.put( MARK_ATTRIBUTE_EXTRAS_PARAMETERS,
627                 manager.getCreateParametersFormHtml( _attribute.getParameters(  ), getLocale(  ) ) );
628         }
629         else
630         {
631             _attribute = new DocumentAttribute(  );
632             model.put( MARK_ATTRIBUTE, attribute );
633             model.put( MARK_ATTRIBUTE_EXTRAS_PARAMETERS,
634                 manager.getModifyParametersFormHtml( getLocale(  ), nAttributeId ) );
635         }
636 
637         // Regular expressions
638         model.put( MARK_REGULAR_EXPRESSION_TO_ADD_LIST, refListRegularExpressionToAdd );
639         model.put( MARK_PAGINATOR, paginator );
640         model.put( MARK_REGULAR_EXPRESSION_ADDED_LIST, paginator.getPageItems(  ) );
641         model.put( MARK_NB_ITEMS_PER_PAGE, "" + _nItemsPerPage );
642         model.put( MARK_NB_REGULAR_EXPRESSION, paginator.getItemsCount(  ) );
643 
644         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_MODIFY_ATTRIBUTE, getLocale(  ), model );
645 
646         return getAdminPage( template.getHtml(  ) );
647     }
648 
649     /**
650      * Confirm the deletion of a document type
651      * @param request The HTTP request
652      * @return The URL to go after performing the action
653      */
654     public String doConfirmDelete( HttpServletRequest request )
655     {
656         String strCode = request.getParameter( PARAMETER_DOCUMENT_TYPE_CODE );
657         String strDeleteUrl = JSP_DELETE_DOCUMENT_TYPE + "?" + PARAMETER_DOCUMENT_TYPE_CODE + "=" + strCode;
658         String strUrl = AdminMessageService.getMessageUrl( request, PROPERTY_CONFIRM_DELETE_TYPE, strDeleteUrl,
659                 AdminMessage.TYPE_CONFIRMATION );
660 
661         // Check if this type has documents
662         if ( DocumentTypeHome.checkDocuments( strCode ) )
663         {
664             strUrl = AdminMessageService.getMessageUrl( request, PROPERTY_CANNOT_DELETE_DOCUMENTS,
665                     AdminMessage.TYPE_STOP );
666         }
667 
668         return strUrl;
669     }
670 
671     /**
672      * Perform the deletion of a document type
673      * @param request The HTTP request
674      * @return The URL to go after performing the action
675      */
676     public String doDeleteDocumentType( HttpServletRequest request )
677     {
678         String strCode = request.getParameter( PARAMETER_DOCUMENT_TYPE_CODE );
679 
680         if ( strCode != null )
681         {
682             DocumentType documentType = DocumentTypeHome.findByPrimaryKey( strCode );
683 
684             List<DocumentAttribute> listDocumentAttributes = documentType.getAttributes(  );
685 
686             if ( listDocumentAttributes != null )
687             {
688                 for ( DocumentAttribute docAttribute : listDocumentAttributes )
689                 {
690                     DocumentAttributeHome.remove( docAttribute.getId(  ) );
691                 }
692             }
693 
694             DocumentTypeHome.remove( strCode );
695         }
696 
697         return getHomeUrl( request );
698     }
699 
700     /**
701      * Confirm the deletion of an attribute
702      * @param request The HTTP request
703      * @return The URL to go after performing the action
704      */
705     public String doConfirmDeleteAttribute( HttpServletRequest request )
706     {
707         String strId = request.getParameter( PARAMETER_ATTRIBUTE_ID );
708         String strDeleteUrl = JSP_DELETE_ATTRIBUTE + "?" + PARAMETER_ATTRIBUTE_ID + "=" + strId;
709         String strUrl = AdminMessageService.getMessageUrl( request, PROPERTY_CONFIRM_DELETE_ATTRIBUTE, strDeleteUrl,
710                 AdminMessage.TYPE_CONFIRMATION );
711 
712         return strUrl;
713     }
714 
715     /**
716      * Perform the attribute deletion
717      * @param request The HTTP request
718      * @return The URL to go after performing the action
719      */
720     public String doDeleteAttribute( HttpServletRequest request )
721     {
722         String strId = request.getParameter( PARAMETER_ATTRIBUTE_ID );
723         int nId = IntegerUtils.convert( strId );
724         DocumentAttributeHome.remove( nId );
725 
726         return JSP_MODIFY_DOCUMENT_TYPE;
727     }
728 
729     /**
730      * Perform the move up action
731      * @param request The HTTP request
732      * @return The URL to go after performing the action
733      */
734     public String doAttributeMoveUp( HttpServletRequest request )
735     {
736         String strIndex = request.getParameter( PARAMETER_INDEX );
737         int nIndex = IntegerUtils.convert( strIndex );
738 
739         if ( nIndex > 1 )
740         {
741             DocumentType documentType = DocumentTypeHome.findByPrimaryKey( _strDocumentTypeCode );
742             List<DocumentAttribute> list = documentType.getAttributes(  );
743             DocumentAttribute attribute1 = list.get( nIndex - 1 );
744             DocumentAttribute attribute2 = list.get( nIndex - 2 );
745             DocumentTypeHome.reorderAttributes( attribute1.getId(  ), nIndex - 1, attribute2.getId(  ), nIndex );
746         }
747 
748         return JSP_MODIFY_DOCUMENT_TYPE;
749     }
750 
751     /**
752      * Perform the move down action
753      * @param request The HTTP request
754      * @return The URL to go after performing the action
755      */
756     public String doAttributeMoveDown( HttpServletRequest request )
757     {
758         String strIndex = request.getParameter( PARAMETER_INDEX );
759         int nIndex = IntegerUtils.convert( strIndex );
760         DocumentType documentType = DocumentTypeHome.findByPrimaryKey( _strDocumentTypeCode );
761         List<DocumentAttribute> list = documentType.getAttributes(  );
762 
763         if ( nIndex < list.size(  ) )
764         {
765             DocumentAttribute attribute1 = list.get( nIndex - 1 );
766             DocumentAttribute attribute2 = list.get( nIndex );
767             DocumentTypeHome.reorderAttributes( attribute1.getId(  ), nIndex + 1, attribute2.getId(  ), nIndex );
768         }
769 
770         return JSP_MODIFY_DOCUMENT_TYPE;
771     }
772 
773     /**
774      * Save the uploaded Sytlesheets
775      * @param request The {@link HttpServletRequest}
776      * @return the home url
777      */
778     public String doLoadStyleSheets( HttpServletRequest request )
779     {
780         MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
781         String strErrorUrl = getStyleSheets( multipartRequest );
782 
783         if ( strErrorUrl != null )
784         {
785             return strErrorUrl;
786         }
787 
788         //Displays the list of the stylesheet files
789         return getHomeUrl( request );
790     }
791 
792     private ReferenceList getThumbnailAttributesList( DocumentType documentType )
793     {
794         ReferenceList list = new ReferenceList(  );
795 
796         String strNoAttribute = I18nService.getLocalizedString( PROPERTY_NO_THUMBNAIL_ATTRIBUTE, getLocale(  ) );
797         list.addItem( NO_THUMBNAIL_ATTRIBUTE, strNoAttribute );
798 
799         for ( DocumentAttribute attribute : documentType.getAttributes(  ) )
800         {
801             AttributeManager manager = AttributeService.getInstance(  ).getManager( attribute.getCodeAttributeType(  ) );
802 
803             if ( manager.canBeUsedAsThumbnail(  ) )
804             {
805                 list.addItem( attribute.getId(  ), attribute.getName(  ) );
806             }
807         }
808 
809         return list;
810     }
811 
812     /**
813      * Reads stylesheet's data
814      * @param multipartRequest The request
815      * @return An error message URL or null if no error
816      */
817     private String getStyleSheets( MultipartHttpServletRequest multipartRequest )
818     {
819         String strErrorUrl = null;
820 
821         String strCode = multipartRequest.getParameter( PARAMETER_DOCUMENT_TYPE_CODE );
822         String strUpdateStylesheetAdmin = multipartRequest.getParameter( PARAMETER_UPDATE_STYLESHEET_ADMIN );
823         String strUpdateStylesheetContent = multipartRequest.getParameter( PARAMETER_UPDATE_STYLESHEET_CONTENT );
824 
825         // Gets XSL for the back office if defined
826         FileItem fileXslAdmin = multipartRequest.getFile( PARAMETER_STYLESHEET_ADMIN );
827         String strFilename = FileUploadService.getFileNameOnly( fileXslAdmin );
828 
829         if ( ( strUpdateStylesheetAdmin != null ) && strUpdateStylesheetAdmin.equals( UPDATE_VALUE ) &&
830                 ( strFilename != null ) && ( !strFilename.equals( "" ) ) )
831         {
832             byte[] baXslAdmin = fileXslAdmin.get(  );
833 
834             // Check the XML validity of the XSL stylesheet
835             if ( isValid( baXslAdmin ) != null )
836             {
837                 Object[] args = { isValid( baXslAdmin ) };
838 
839                 return AdminMessageService.getMessageUrl( multipartRequest, MESSAGE_STYLESHEET_NOT_VALID, args,
840                     AdminMessage.TYPE_STOP );
841             }
842 
843             DocumentTypeHome.setAdminStyleSheet( baXslAdmin, strCode );
844         }
845 
846         // Gets XSL for the back office if defined
847         FileItem fileXslContent = multipartRequest.getFile( PARAMETER_STYLESHEET_CONTENT );
848         strFilename = FileUploadService.getFileNameOnly( fileXslContent );
849 
850         if ( ( strUpdateStylesheetContent != null ) && strUpdateStylesheetContent.equals( UPDATE_VALUE ) &&
851                 ( strFilename != null ) && ( !strFilename.equals( "" ) ) )
852         {
853             byte[] baXslContent = fileXslContent.get(  );
854 
855             // Check the XML validity of the XSL stylesheet
856             if ( isValid( baXslContent ) != null )
857             {
858                 Object[] args = { isValid( baXslContent ) };
859 
860                 return AdminMessageService.getMessageUrl( multipartRequest, MESSAGE_STYLESHEET_NOT_VALID, args,
861                     AdminMessage.TYPE_STOP );
862             }
863 
864             DocumentTypeHome.setContentStyleSheet( baXslContent, strCode );
865         }
866 
867         //clear the cache
868         CacheService.resetCaches(  );
869 
870         return strErrorUrl;
871     }
872 
873     /**
874      * Get the XSL specified in parameters
875      * @param request The {@link HttpServletRequest}
876      * @return A {@link DocumentResource} (name, content and contentType)
877      */
878     public DocumentResource getStyleSheetFile( HttpServletRequest request )
879     {
880         String strDocumentTypeCode = request.getParameter( PARAMETER_DOCUMENT_TYPE_CODE );
881         String strStylesheetType = request.getParameter( PARAMETER_STYLESHEET_TYPE );
882         DocumentResourceDocumentResource.html#DocumentResource">DocumentResource documentResource = new DocumentResource(  );
883         documentResource.setContentType( STYLESHEET_CONTENT_TYPE );
884         documentResource.setName( strDocumentTypeCode + SEPARATOR + strStylesheetType + FILE_EXTENSION );
885 
886         if ( strDocumentTypeCode != null )
887         {
888             _strDocumentTypeCode = strDocumentTypeCode;
889         }
890         else
891         {
892             strDocumentTypeCode = _strDocumentTypeCode;
893         }
894 
895         DocumentType documentType = DocumentTypeHome.findByPrimaryKey( strDocumentTypeCode );
896 
897         if ( strStylesheetType.equals( PARAMETER_STYLESHEET_ADMIN ) )
898         {
899             documentResource.setContent( documentType.getAdminXsl(  ) );
900         }
901 
902         if ( strStylesheetType.equals( PARAMETER_STYLESHEET_CONTENT ) )
903         {
904             documentResource.setContent( documentType.getContentServiceXsl(  ) );
905         }
906 
907         return documentResource;
908     }
909 
910     /**
911      * Use parsing for validate the modify xsl file
912      *
913      * @param baXslSource The XSL source
914      * @return the message exception when the validation is false
915      */
916     private String isValid( byte[] baXslSource )
917     {
918         String strError = null;
919 
920         try
921         {
922             SAXParserFactory factory = SAXParserFactory.newInstance(  );
923             SAXParser analyzer = factory.newSAXParser(  );
924             InputSource is = new InputSource( new ByteArrayInputStream( baXslSource ) );
925             analyzer.getXMLReader(  ).parse( is );
926         }
927         catch ( Exception e )
928         {
929             strError = e.getMessage(  );
930         }
931 
932         return strError;
933     }
934 
935     /**
936      * Inserts a regular expression in the attribute
937      *
938      * @param request The HTTP request
939      * @return The URL to go after performing the action
940      */
941     public String doInsertRegularExpression( HttpServletRequest request )
942     {
943         // Gets the document attribute identifier
944         String strAttributeId = request.getParameter( PARAMETER_ATTRIBUTE_ID );
945         int nAttributeId = IntegerUtils.convert( strAttributeId );
946 
947         // Gets the selected regular expression
948         String strExpressionId = request.getParameter( PARAMETER_EXPRESSION_ID );
949 
950         if ( IntegerUtils.isNumeric( strExpressionId ) )
951         {
952             int nExpressionId = IntegerUtils.convert( strExpressionId );
953 
954             boolean bIsDuplicated = false;
955 
956             for ( Integer nCurrentExpression : DocumentAttributeHome.getListRegularExpressionKeyByIdAttribute( 
957                     nAttributeId ) )
958             {
959                 if ( nExpressionId == nCurrentExpression )
960                 {
961                     bIsDuplicated = true;
962 
963                     break;
964                 }
965             }
966 
967             if ( !bIsDuplicated )
968             {
969                 // Inserts a regular expression in the attribute
970                 DocumentAttributeHome.insertRegularExpression( nAttributeId, nExpressionId );
971             }
972         }
973 
974         UrlItem url = new UrlItem( JSP_MODIFY_DOCUMENT_TYPE_ATTRIBUTE );
975         url.addParameter( PARAMETER_ATTRIBUTE_ID, nAttributeId );
976 
977         return url.getUrl(  );
978     }
979 
980     /**
981      * Deletes a regular expression in the attribute
982      *
983      * @param request The HTTP request
984      * @return The URL to go after performing the action
985      */
986     public String doDeleteRegularExpression( HttpServletRequest request )
987     {
988         // Gets the document attribute identifier
989         String strAttributeId = request.getParameter( PARAMETER_ATTRIBUTE_ID );
990         int nAttributeId = IntegerUtils.convert( strAttributeId );
991 
992         // Gets the selected regular expression
993         String strExpressionId = request.getParameter( PARAMETER_EXPRESSION_ID );
994         int nExpressionId = IntegerUtils.convert( strExpressionId );
995 
996         // Deletes a regular expression in the attribute
997         DocumentAttributeHome.deleteRegularExpression( nAttributeId, nExpressionId );
998 
999         UrlItem url = new UrlItem( JSP_MODIFY_DOCUMENT_TYPE_ATTRIBUTE );
1000         url.addParameter( PARAMETER_ATTRIBUTE_ID, nAttributeId );
1001 
1002         return url.getUrl(  );
1003     }
1004 
1005     /**
1006      * Check if there is no diacritics character
1007      * @param strInput The input string
1008      * @return
1009      */
1010     private boolean checkDocumentTypeCodePattern( String strInput )
1011     {
1012         return strInput.matches( PATTERN_CODE );
1013     }
1014 }