Salome HOME
The draft of the "Copy from existing study" action is added. The YACS step is introdu...
[tools/siman.git] / Workspace / Siman / src / org / splat / simer / ApplicationSettings.java
1 package org.splat.simer;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.util.ArrayList;
6 import java.util.HashMap;
7 import java.util.HashSet;
8 import java.util.Iterator;
9 import java.util.List;
10 import java.util.Locale;
11 import java.util.Map;
12 import java.util.Properties;
13 import java.util.Set;
14
15 import javax.servlet.http.HttpServletRequest;
16 import javax.xml.parsers.DocumentBuilder;
17 import javax.xml.parsers.DocumentBuilderFactory;
18
19 import org.apache.log4j.Logger;
20 import org.splat.dal.bo.kernel.User;
21 import org.splat.dal.bo.som.Document;
22 import org.splat.dal.bo.som.DocumentType;
23 import org.splat.dal.bo.som.KnowledgeElement;
24 import org.splat.dal.bo.som.ProgressState;
25 import org.splat.dal.bo.som.SimulationContext;
26 import org.splat.dal.bo.som.Visibility;
27 import org.splat.manox.XDOM;
28 import org.splat.service.DocumentTypeService;
29 import org.splat.service.technical.ProjectSettingsService;
30 import org.splat.som.DocumentRights;
31 import org.splat.som.Step;
32 import org.splat.som.StudyRights;
33 import org.splat.wapp.MenuItem;
34 import org.splat.wapp.PopupItem;
35 import org.splat.wapp.PopupMenu;
36 import org.splat.wapp.SimpleMenu;
37 import org.splat.wapp.ToolBar;
38 import org.springframework.web.context.request.RequestContextHolder;
39 import org.springframework.web.context.request.ServletRequestAttributes;
40 import org.w3c.dom.NamedNodeMap;
41 import org.w3c.dom.Node;
42 import org.w3c.dom.NodeList;
43
44 /**
45  * SIMAN project settings service. Provides settings according to XML customization.
46  */
47 public class ApplicationSettings {
48
49         /**
50          * Application settings logger.
51          */
52         protected final static Logger LOG = Logger
53                         .getLogger(ApplicationSettings.class);
54         /**
55          * JNDI context for launching converters.
56          */
57         private transient static final Properties _JNDPROPS;
58         /**
59          * Siman web application name.
60          */
61         private transient static String wappname;
62         /**
63          * General properties from the application properties files.
64          */
65         private transient static final Properties _WAPPROPS = new Properties();
66         /**
67          * Siman web application root path on the server.
68          */
69         private transient static String wapproot;
70         /**
71          * Available template files.
72          */
73         private transient static Map<String, String> tempfile;
74         /**
75          * List of file extensions mapped to a viewer.
76          */
77         private transient static String[] viewermap;
78         /**
79          * Available document format converters.
80          */
81         private transient static Map<String, Converter> convertmap;
82
83         static {
84                 synchronized (_WAPPROPS) {
85                         // Do common configuration for all users
86
87                         _JNDPROPS = new Properties();
88                         tempfile = new HashMap<String, String>();
89                         viewermap = new String[0];
90                         convertmap = new HashMap<String, Converter>();
91
92                         ClassLoader cloader = Thread.currentThread()
93                                         .getContextClassLoader();
94                         HttpServletRequest curRequest = ((ServletRequestAttributes) RequestContextHolder
95                                         .currentRequestAttributes()).getRequest();
96                         String appname = curRequest.getContextPath();
97                         if (appname.startsWith("/")) {
98                                 wappname = appname.substring(1);
99                         }
100                         // Set local path on the server to the application root.
101                         wapproot = curRequest.getSession().getServletContext().getRealPath(
102                                         "/");
103
104                         try {
105                                 _JNDPROPS.load(cloader.getResourceAsStream("jndi.properties"));
106                                 _WAPPROPS.load(cloader.getResourceAsStream(wappname
107                                                 + ".properties"));
108                         } catch (IOException e) {
109                                 LOG.info(
110                                                 "Can't load application properties: " + e.getMessage(),
111                                                 e);
112                         }
113
114                         // Configure login security
115                         System.setProperty("java.security.auth.login.config", wapproot
116                                         + ApplicationSettings.getApplicationProperty("wapp.login"));
117
118                         // Customization (must be done after above default settings)
119                         File config = new File(wapproot
120                                         + getApplicationProperty("wapp.customization"));
121                         if (config.exists()) {
122                                 loadCustomization(config); // Sets default document types, installed modules and available templates
123                         } else {
124                                 LOG.info("Could not find the application configuration file \""
125                                                 + config.getAbsolutePath()
126                                                 + "\", using default settings");
127                         }
128                 }
129         }
130
131         /**
132          * All value.
133          */
134         private static final String ALL = "all";
135
136         /**
137          * Hold icon file name.
138          */
139         private static final String IMG_HOLD = "image.hold.gif";
140         /**
141          * Attach icon file name.
142          */
143         private static final String IMG_ATTACH = "image.attach.png";
144         /**
145          * Version icon file name.
146          */
147         private static final String IMG_VERSION = "image.version.png";
148         /**
149          * Delete icon file name.
150          */
151         private static final String IMG_DELETE = "icon.delete.png";
152         /**
153          * Attach menu item name.
154          */
155         private static final String MNU_ATTACH = "attach";
156         /**
157          * Demote menu item name.
158          */
159         private static final String MNU_DEMOTE = "demote";
160         /**
161          * Promote menu item name.
162          */
163         private static final String MNU_PROMOTE = "promote";
164         /**
165          * Publish menu item name.
166          */
167         private static final String MNU_PUBLISH = "publish";
168         /**
169          * Edit menu item name.
170          */
171         private static final String MNU_EDIT = "edit";
172         /**
173          * Script menu item name.
174          */
175         private static final String MNU_SCRIPT = "script";
176         /**
177          * Version menu item name.
178          */
179         private static final String MNU_VERSION = "version";
180         /**
181          * Purge menu item name.
182          */
183         private static final String MNU_PURGE = "purge";
184         /**
185          * Remove menu item name.
186          */
187         private static final String MNU_REMOVE = "remove";
188         /**
189          * Rename menu item name.
190          */
191         private static final String MNU_RENAME = "rename";
192
193         /**
194          * Attach menu item name.
195          */
196         private static final String MNU_NAME_ATTACH = "menu.attach";
197         /**
198          * Demote menu item name.
199          */
200         private static final String MNU_NAME_DEMOTE = "menu.demote";
201         /**
202          * Promote menu item name.
203          */
204         private static final String MNU_NAME_PROMOTE = "menu.promote";
205         /**
206          * Publish menu item name.
207          */
208         private static final String MNU_NAME_PUBLISH = "menu.publish";
209         /**
210          * Protect menu item name.
211          */
212         private static final String MNU_NAME_PROTECT = "menu.protect";
213         /**
214          * Edit menu item name.
215          */
216         private static final String MNU_NAME_EDIT = "menu.edit";
217         /**
218          * Edit menu item name.
219          */
220         private static final String MNU_NAME_REMOVE = "menu.remove";
221         /**
222          * Script menu item name.
223          */
224         private static final String MNU_NAME_SCRIPT = "menu.newscenario";
225         /**
226          * Version menu item name.
227          */
228         private static final String MNU_NAME_VERSION = "menu.version";
229         /**
230          * Purge menu item name.
231          */
232         private static final String MNU_NAME_PURGE = "menu.purge";
233         /**
234          * Remove menu item name.
235          */
236         private static final String MNU_NAME_REMOVE_VERSION = "menu.remove.version";
237         /**
238          * Rename menu item name.
239          */
240         private static final String MNU_NAME_RENAME = "menu.rename";
241         /**
242          * Mark as reference menu item name.
243          */
244         private static final String MNU_MARK_AS_REFERENCE = "markasreference";
245         /**
246          * Mark as reference menu item label key.
247          */
248         private static final String MNU_NAME_MARK_AS_REFERENCE = "menu.markasreference";
249         /**
250          * Remove as reference menu item label key.
251          */
252         private static final String MNU_NAME_REMOVE_AS_REFERENCE = "menu.removeasreference";
253         /**
254          * Not yet implemented action name.
255          */
256         private static final String ACT_NOT_YET_IMPLEMENTED = "notyetimplemented";
257         /**
258          * Attach action name.
259          */
260         private static final String ACT_ATTACH = "select-file?nextAction=attach";
261         /**
262          * Version action name.
263          */
264         private static final String ACT_VERSION = "select-file?nextAction=version";
265         /**
266          * Mark as reference action name.
267          */
268         private static final String ACT_MARK_AS_REFERENCE = "markasref-study";
269         /**
270          * Remove as reference action name.
271          */
272         private static final String ACT_REMOVE_AS_REFERENCE = "removeasref-study";
273
274         /**
275          * Siman application server name.
276          */
277         private transient final String _wappserver;
278         /**
279          * Current user locale.
280          */
281         private transient Locale _locale;
282         /**
283          * Application menus.
284          */
285         private transient final Map<String, SimpleMenu> _menus = new HashMap<String, SimpleMenu>();
286         /**
287          * Study module-bars structured by steps.
288          */
289         private transient Map<Integer, ToolBar> _bars = null;
290         /**
291          * Popup menus.
292          */
293         private transient Map<String, PopupMenu> _popups = null;
294         /**
295          * Named search filters.
296          */
297         private transient Map<String, Map<String, Object>> _filter = null;
298         /**
299          * Injected project settings service.
300          */
301         private ProjectSettingsService _projectSettings;
302         /**
303          * Injected document type service.
304          */
305         private DocumentTypeService _documentTypeService;
306
307         /**
308          * Application settings constructor.
309          */
310         public ApplicationSettings() {
311                 HttpServletRequest curRequest = ((ServletRequestAttributes) RequestContextHolder
312                                 .currentRequestAttributes()).getRequest();
313                 _wappserver = curRequest.getServerName() + ":"
314                                 + curRequest.getServerPort();
315
316                 LOG.info("Application server is set to " + _wappserver);
317                 LOG.info("Application name is set to " + wappname);
318         }
319
320         /**
321          * Get the projectSettingsService.
322          * 
323          * @return the projectSettingsService
324          */
325         public ProjectSettingsService getProjectSettings() {
326                 return _projectSettings;
327         }
328
329         /**
330          * Set the projectSettingsService.
331          * 
332          * @param projectSettingsService
333          *            the projectSettingsService to set
334          */
335         public void setProjectSettings(
336                         final ProjectSettingsService projectSettingsService) {
337                 _projectSettings = projectSettingsService;
338         }
339
340         /**
341          * New study menu.
342          */
343         private static class NewMenu extends SimpleMenu {
344                 /**
345                  * New study menu constructor.
346                  */
347                 private NewMenu() {
348                         super("create");
349                         addItem("new-empty", "menu.new.empty", "image.empty.png",
350                                         "select?menu=create&item=new-empty");
351                         addItem("new-copy", "menu.new.copy", "image.copy.png",
352                                         "select?menu=create&item=new-copy");
353                         /*
354                          * addItem("new-instance", new MenuItem("menu.new.instance") .icon(IMG_HOLD)); addItem("new-import", new
355                          * MenuItem("menu.new.import") .icon("icon.upload.png"));
356                          */
357                         this.selects("new-empty");
358                 }
359         }
360
361         /**
362          * Search menu.
363          */
364         private static class SearchMenu extends SimpleMenu {
365                 /**
366                  * Search menu constructor.
367                  */
368                 private SearchMenu() {
369                         super("search");
370                         addItem("search-study", "menu.search.study", "image.study.png",
371                                         "select?menu=search&item=search-study");
372                         addItem("search-knowledge", "menu.search.idea", "image.idea.png",
373                                         "select?menu=search&item=search-knowledge");
374                         addItem("search-document", new MenuItem("menu.search.document")
375                                         .icon("icon.any.png"));
376                         this.selects("search-study");
377                 }
378         }
379
380         /**
381          * Configuration menu.
382          */
383         private static class PropertiesMenu extends SimpleMenu {
384                 /**
385                  * Configuration menu constructor.
386                  */
387                 private PropertiesMenu() {
388                         super("configuration");
389                         addItem("prop-general", "menu.prop.general", IMG_HOLD,
390                                         "select?menu=configuration&item=prop-general");
391                         addItem("prop-scenario", "menu.prop.scenario", IMG_HOLD,
392                                         "select?menu=configuration&item=prop-scenario");
393                         // These menu items will not be implemented in the current version.
394                         /*
395                          * addItem("prop-timestamp", new MenuItem("menu.prop.timestamp") .icon("image.stamp.png")); addItem("prop-comlog", new
396                          * MenuItem("menu.prop.comlog") .icon(IMG_HOLD)); addItem("prop-version", new MenuItem("menu.prop.version")
397                          * .icon("image.dirclosed.png"));
398                          */
399                 }
400         }
401
402         /**
403          * Data administrator menu.
404          */
405         private static class DatadminMenu extends SimpleMenu {
406                 /**
407                  * Data administrator menu constructor.
408                  */
409                 private DatadminMenu() {
410                         super("datadmin");
411                         addItem("admin-scontext", "menu.admin.context", IMG_HOLD,
412                                         "select?menu=datadmin&item=admin-scontext");
413                         addItem("admin-knowelm", "menu.admin.knowledge", "image.idea.png",
414                                         "select?menu=datadmin&item=admin-knowelm");
415                         addItem("admin-study", new MenuItem("menu.admin.study")
416                                         .icon("image.study.png"));
417                 }
418         }
419
420         /**
421          * System administrator menu.
422          */
423         private static class SysadminMenu extends SimpleMenu {
424                 /**
425                  * System administrator menu constructor.
426                  */
427                 private SysadminMenu() {
428                         super("sysadmin");
429                         addItem("admin-indexing", "menu.admin.indexing", "image.index.png",
430                                         "select?menu=sysadmin&item=admin-indexing");
431                         addItem("admin-importuser", "menu.admin.importuser",
432                                         "image.group.png",
433                                         "select?menu=sysadmin&item=admin-importuser");
434                 }
435         }
436
437         /**
438          * Menu items enumeration.
439          */
440         private enum Item {
441                 /**
442                  * Publish the study.
443                  */
444                 publish,
445                 /**
446                  * Accept the document.
447                  */
448                 accept,
449                 /**
450                  * Approve the document.
451                  */
452                 approve,
453                 /**
454                  * Promote the document.
455                  */
456                 promote,
457                 /**
458                  * Demote the docuemnt.
459                  */
460                 demote,
461                 /**
462                  * Undo the last operation.
463                  */
464                 undo,
465                 /**
466                  * Rename the document.
467                  */
468                 rename,
469                 /**
470                  * Attach a file to the document.
471                  */
472                 attach,
473                 /**
474                  * Edit the document.
475                  */
476                 edit,
477                 /**
478                  * script
479                  */
480                 script,
481                 /**
482                  * Version the document.
483                  */
484                 version,
485                 /**
486                  * replace
487                  */
488                 replace,
489                 /**
490                  * export
491                  */
492                 export,
493                 /**
494                  * Remove the document.
495                  */
496                 remove,
497                 /**
498                  * purge
499                  */
500                 purge,
501                 /**
502                  * Mark the study as reference.
503                  */
504                 markasreference
505         };
506
507         // Resources relative to studies
508         /**
509          * Study popup menu.
510          */
511         private static class EditableMarkedStudyPopup extends PopupMenu {
512                 /**
513                  * User rights for the selected study.
514                  */
515                 private transient StudyRights _user = null;
516
517                 /**
518                  * Study popup menu constructor.
519                  * 
520                  * @param isPublic
521                  *            public study flag
522                  * @param isMarked
523                  *            "marked as reference" study flag
524                  */
525                 private EditableMarkedStudyPopup(final boolean isPublic,
526                                 final boolean isMarked) {
527                         super();
528
529                         if (isMarked) {
530                                 addItem(MNU_MARK_AS_REFERENCE, new PopupItem(
531                                                 MNU_NAME_REMOVE_AS_REFERENCE).action(
532                                                 ACT_REMOVE_AS_REFERENCE).confirmation(
533                                                 "message.removeasreference.study"));
534                         } else {
535                                 addItem(MNU_MARK_AS_REFERENCE, new PopupItem(
536                                                 MNU_NAME_MARK_AS_REFERENCE).action(
537                                                 ACT_MARK_AS_REFERENCE).confirmation(
538                                                 "message.markasreference.study"));
539                         }
540
541                         if (isPublic) {
542                                 addItem(MNU_PUBLISH, new PopupItem(MNU_NAME_PROTECT).icon(
543                                                 "image.publish.png")
544                                                 .action("edit-study?action=protect").confirmation(
545                                                                 "message.protect.study"));
546                         } else {
547                                 addItem(MNU_PUBLISH, new PopupItem(MNU_NAME_PUBLISH).icon(
548                                                 "image.publish.png")
549                                                 .action("edit-study?action=publish").confirmation(
550                                                                 "message.publish.study"));
551                         }
552
553                         /* addItem(MNU_PROMOTE, new PopupItem("menu.archive")); */
554                         addSeparator();
555                         addItem(MNU_EDIT, new PopupItem("menu.properties").icon(
556                                         "icon.ed.png").action(
557                                         "../select?menu=configuration&item=prop-general"));
558                         addSeparator();
559                         addItem(MNU_SCRIPT, new PopupItem(MNU_NAME_SCRIPT)
560                                         .action("add-scenario"));
561                         /*
562                          * addItem(MNU_VERSION, new PopupItem(MNU_NAME_VERSION).icon( IMG_VERSION).action(ACT_NOT_YET_IMPLEMENTED));
563                          */
564                         addSeparator();
565                         /*
566                          * addItem(MNU_PURGE, new PopupItem(MNU_NAME_PURGE) .confirmation("message.purge.study")); addItem("export", new
567                          * PopupItem("menu.export") .icon("image.export.png")); // For future needs
568                          */addItem(MNU_REMOVE, new PopupItem(MNU_NAME_REMOVE_VERSION).icon(
569                                         IMG_DELETE).action("remove-study").confirmation(
570                                         "message.delete.study"));
571                 }
572
573                 /**
574                  * {@inheritDoc}
575                  * 
576                  * @see org.splat.wapp.ContextualMenu#isEnabled(java.lang.String)
577                  */
578                 @Override
579                 public boolean isEnabled(final String name) {
580                         boolean res = (_user != null);
581                         if (res) {
582                                 Item item = Item.valueOf(name);
583                                 switch (item) {
584                                         case publish:
585                                                 if (_user.getOperand().getVisibility() == Visibility.PRIVATE) {
586                                                         res = _user.canPublish();
587                                                 } else {
588                                                         res = _user.canProtect();
589                                                 }
590                                                 break;
591                                         case edit:
592                                                 res = _user.canEditProperties();
593                                                 break;
594                                         case script:
595                                                 res = _user.canAddScenario();
596                                                 break;
597                                         case version:
598                                                 res = _user.canVersion();
599                                                 break;
600                                         case remove:
601                                                 res = _user.canRemove();
602                                                 break;
603                                         case purge:
604                                                 res = _user.canPurge();
605                                                 break;
606                                         case markasreference:
607                                                 if (_user.getOperand().getMarkreference() == 0) {
608                                                         res = _user.canMarkStudyAsReference();
609                                                 } else {
610                                                         res = _user.canRemoveStudyAsReference();
611                                                 }
612                                                 break;
613                                         default:
614                                                 res = false;
615                                 }
616                         }
617                         return res;
618                 }
619
620                 @Override
621                 public void setContext(final String name, final Object context) {
622                         if (context instanceof StudyRights) {
623                                 _user = (StudyRights) context; // Just for optimizing
624                                 boolean history = _user.getOperand().isVersioned();
625                                 PopupItem item = this.item(MNU_REMOVE);
626                                 if (history) {
627                                         item.rename(MNU_NAME_REMOVE_VERSION);
628                                 } else {
629                                         item.rename("menu.remove.study");
630                                 }
631                         }
632                 }
633         }
634
635         // Resources relative to documents
636         /**
637          * Popup of In-Work documents.
638          */
639         private static class EditableDocumentPopup extends PopupMenu {
640                 /**
641                  * User rights for the selected document.
642                  */
643                 private transient DocumentRights _user = null;
644
645                 /**
646                  * Document popup menu constructor.
647                  */
648                 private EditableDocumentPopup() {
649                         super();
650                         addItem("accept", new PopupItem("menu.accept").icon(
651                                         "image.accept.png").action("setDocument?action=accept")
652                                         .confirmation("message.accept.document"));
653                         addItem(MNU_PROMOTE, new PopupItem(MNU_NAME_PROMOTE).icon(
654                                         "image.publish.png").action("setDocument?action=promote")
655                                         .confirmation("message.promote.document"));
656                         addSeparator();
657                         addItem(MNU_RENAME, new PopupItem(MNU_NAME_RENAME)
658                                         .action("edit-document?action=renameDocument"));
659                         addItem(MNU_ATTACH, new PopupItem(MNU_NAME_ATTACH).icon(IMG_ATTACH)
660                                         .action(ACT_ATTACH));
661                         addSeparator();
662                         addItem(MNU_VERSION, new PopupItem(MNU_NAME_VERSION).icon(
663                                         IMG_VERSION).action(ACT_VERSION));
664                         addItem("replace", new PopupItem("menu.replace").icon(
665                                         "image.replace.png").action(
666                                         "select-file?nextAction=replace"));
667                         addSeparator();
668                         addItem(MNU_PURGE, new PopupItem(MNU_NAME_PURGE).action(
669                                         ACT_NOT_YET_IMPLEMENTED).confirmation(
670                                         "message.purge.document"));
671                         addItem(MNU_REMOVE, new PopupItem(MNU_NAME_REMOVE_VERSION).icon(
672                                         IMG_DELETE).action("remove-document").confirmation(
673                                         "message.delete.document"));
674                 }
675
676                 @Override
677                 public boolean isEnabled(final String name) {
678                         boolean res = (_user != null);
679                         if (res) {
680                                 Item item = Item.valueOf(name);
681                                 switch (item) {
682                                         case accept:
683                                                 res = _user.canAccept();
684                                                 break;
685                                         case promote:
686                                                 res = _user.canPromote();
687                                                 break;
688                                         case rename:
689                                                 res = _user.canRename();
690                                                 break;
691                                         case attach:
692                                                 res = _user.canAttach();
693                                                 break;
694                                         case version:
695                                                 res = _user.canVersion();
696                                                 break;
697                                         case replace:
698                                                 res = _user.canReplace();
699                                                 break;
700                                         case purge:
701                                                 res = _user.canPurge();
702                                                 break;
703                                         case remove:
704                                                 res = _user.canRemove();
705                                                 break;
706                                         default:
707                                                 res = false;
708                                 }
709                         }
710                         return res;
711                 }
712
713                 @Override
714                 public void setContext(final String name, final Object context) {
715                         if (context instanceof DocumentRights) {
716                                 _user = (DocumentRights) context; // Just for optimizing
717                                 Document downer = _user.getOperand();
718                                 PopupItem item = this.item(MNU_REMOVE);
719                                 if (downer.isVersioned()) {
720                                         item.rename(MNU_NAME_REMOVE_VERSION);
721                                 } else {
722                                         item.rename("menu.remove.document");
723                                 }
724                         }
725                 }
726         }
727
728         /**
729          * Popup of In-Draft documents.
730          */
731         private static class ReviewableDocumentPopup extends PopupMenu {
732                 /**
733                  * User rights for the selected document.
734                  */
735                 private transient DocumentRights _user = null;
736
737                 /**
738                  * Document popup menu constructor.
739                  */
740                 private ReviewableDocumentPopup() {
741                         super();
742                         addItem(MNU_DEMOTE, new PopupItem(MNU_NAME_DEMOTE).icon(
743                                         "image.demote.png").action("setDocument?action=demote")
744                                         .confirmation("message.demote.document"));
745                         addItem(MNU_PROMOTE, new PopupItem("menu.review").icon(
746                                         "image.review.png").action("setDocument?action=review")
747                                         .confirmation("message.review.document"));
748                         addSeparator();
749                         addItem(MNU_ATTACH, new PopupItem(MNU_NAME_ATTACH).icon(IMG_ATTACH)
750                                         .action(ACT_ATTACH));
751                         addSeparator();
752                         addItem(MNU_VERSION, new PopupItem(MNU_NAME_VERSION).icon(
753                                         IMG_VERSION).action(ACT_VERSION));
754                         addSeparator();
755                         addItem(MNU_PURGE, new PopupItem(MNU_NAME_PURGE).action(
756                                         ACT_NOT_YET_IMPLEMENTED).confirmation(
757                                         "message.purge.document"));
758                 }
759
760                 @Override
761                 public boolean isEnabled(final String name) {
762                         boolean res = (_user != null);
763                         if (res) {
764                                 Item item = Item.valueOf(name);
765                                 switch (item) {
766                                         case demote:
767                                                 res = _user.canDemote();
768                                                 break;
769                                         case promote:
770                                                 res = _user.canReview();
771                                                 break;
772                                         case attach:
773                                                 res = _user.canAttach();
774                                                 break;
775                                         case version:
776                                                 res = _user.canVersion();
777                                                 break;
778                                         case purge:
779                                                 res = _user.canPurge();
780                                                 break;
781                                         default:
782                                                 res = false;
783                                 }
784                         }
785                         return res;
786                 }
787
788                 @Override
789                 public void setContext(final String name, final Object context) {
790                         if (context instanceof DocumentRights) {
791                                 _user = (DocumentRights) context; // Just for optimizing
792                         }
793                 }
794         }
795
796         private static class NotResultDocumentPopup extends PopupMenu {
797                 // private final DocumentRights _user = null;
798
799                 private NotResultDocumentPopup() {
800                         super();
801                         addItem(MNU_DEMOTE, new PopupItem(MNU_NAME_DEMOTE).icon(
802                                         "image.demote.png").action("setDocument?action=demote")
803                                         .confirmation("message.demote.document"));
804                         addSeparator();
805                         addItem(MNU_ATTACH, new PopupItem(MNU_NAME_ATTACH).icon(IMG_ATTACH)
806                                         .action(ACT_ATTACH));
807                         addSeparator();
808                         addItem(MNU_VERSION, new PopupItem(MNU_NAME_VERSION).icon(
809                                         IMG_VERSION).action(ACT_VERSION));
810                         addSeparator();
811                         addItem(MNU_PURGE, new PopupItem(MNU_NAME_PURGE).action(
812                                         ACT_NOT_YET_IMPLEMENTED).confirmation(
813                                         "message.purge.document"));
814                         addItem(MNU_REMOVE, new PopupItem(MNU_NAME_REMOVE_VERSION).icon(
815                                         IMG_DELETE).action("remove-document").confirmation(
816                                         "message.delete.document"));
817                 }
818         }
819
820         /**
821          * Popup of In-Check documents.
822          */
823         private static class ApprovableDocumentPopup extends PopupMenu {
824                 private transient DocumentRights _user = null;
825
826                 private ApprovableDocumentPopup() {
827                         super();
828                         addItem("undo", new PopupItem(MNU_NAME_DEMOTE).icon(
829                                         "image.invalidate.png").action(
830                                         "setDocument?action=invalidate").confirmation(
831                                         "message.demote.document"));
832                         addItem(MNU_DEMOTE, new PopupItem("menu.disapprove").icon(
833                                         "image.demote.png").action("setDocument?action=disapprove")
834                                         .confirmation("message.disapprove.document"));
835                         addItem("approve", new PopupItem("menu.approve").icon(
836                                         "icon.APPROVED.png").action("setDocument?action=approve")
837                                         .confirmation("message.approve.document"));
838                 }
839
840                 @Override
841                 public boolean isEnabled(final String name) {
842                         boolean res = (_user != null);
843                         if (res) {
844                                 Item item = Item.valueOf(name);
845                                 switch (item) {
846                                         case undo:
847                                                 res = _user.canInvalidate();
848                                                 break;
849                                         case demote:
850                                                 res = _user.canDemote();
851                                                 break;
852                                         case approve:
853                                                 res = _user.canApprove();
854                                                 break;
855                                         default:
856                                                 res = false;
857                                 }
858                         }
859                         return res;
860                 }
861
862                 @Override
863                 public void setContext(final String name, final Object context) {
864                         if (context instanceof DocumentRights) {
865                                 _user = (DocumentRights) context; // Just for optimizing
866                         }
867                 }
868         }
869
870         /**
871          * Popup of Approved documents.
872          */
873         private static class ApprovedPopup extends PopupMenu {
874                 private ApprovedPopup() {
875                         super();
876                         addItem(MNU_ATTACH, new PopupItem(MNU_NAME_ATTACH).icon(IMG_ATTACH)
877                                         .action(ACT_ATTACH));
878                         addSeparator();
879                         addItem(MNU_VERSION, new PopupItem(MNU_NAME_VERSION).icon(
880                                         IMG_VERSION).action(ACT_VERSION));
881                 }
882         }
883
884         /**
885          * Popup of Extern documents.
886          */
887         private static class ExternPopup extends PopupMenu {
888                 private transient DocumentRights _user = null;
889
890                 private ExternPopup() {
891                         super();
892                         addItem(MNU_RENAME, new PopupItem(MNU_NAME_RENAME)
893                                         .action("edit-document?action=renameDocument"));
894                         addSeparator();
895                         addItem(MNU_VERSION, new PopupItem(MNU_NAME_VERSION).icon(
896                                         IMG_VERSION).action(ACT_VERSION));
897                         addSeparator();
898                         addItem("replace", new PopupItem("menu.replace").icon(
899                                         "image.replace.png").action(
900                                         "select-file?nextAction=replace"));
901                         addSeparator();
902                         addItem(MNU_REMOVE, new PopupItem("menu.remove.document").icon(
903                                         IMG_DELETE).action("remove-document").confirmation(
904                                         "message.delete.document"));
905                 }
906
907                 @Override
908                 public boolean isEnabled(final String name) {
909                         boolean res = (_user != null);
910                         if (res) {
911                                 Item item = Item.valueOf(name);
912                                 switch (item) {
913                                         case rename:
914                                                 res = _user.canRename();
915                                                 break;
916                                         case version:
917                                                 res = _user.canVersion();
918                                                 break;
919                                         case replace:
920                                                 res = _user.canReplace();
921                                                 break;
922                                         case remove:
923                                                 res = _user.canRemove();
924                                                 break;
925                                         default:
926                                                 res = false;
927                                 }
928                         }
929                         return res;
930                 }
931
932                 @Override
933                 public void setContext(final String name, final Object context) {
934                         if (context instanceof DocumentRights) {
935                                 _user = (DocumentRights) context; // Just for optimizing
936                         }
937                 }
938         }
939
940         // Resources relative to simulation contexts
941         private static class ScontextPopup extends PopupMenu {
942                 private SimulationContextFacade _owner = null; // RKV: NOPMD: TODO: Refine the usage of this field or remove it.
943
944                 private ScontextPopup() {
945                         super();
946                         addItem(MNU_RENAME, new PopupItem(MNU_NAME_RENAME)
947                                         .action("edit-context?action=renameContext"));
948                         addItem(MNU_EDIT, new PopupItem(MNU_NAME_EDIT)
949                                         .action("edit-context?action=editContext"));
950                         addSeparator();
951                         addItem(MNU_REMOVE, new PopupItem(MNU_NAME_REMOVE).icon(IMG_DELETE)
952                                         .action("remove-context").confirmation(
953                                                         "message.delete.context"));
954                 }
955
956                 @Override
957                 public boolean isEnabled(final String name) {
958                         Item item = Item.valueOf(name);
959                         boolean res = true;
960
961                         if (item == Item.rename) {
962                                 res = false;
963                         } else if (item == Item.edit) {
964                                 // if (!owner.isEditable())
965                                 res = false;
966                         }
967                         return res;
968                 }
969
970                 @Override
971                 public void setContext(final String name, final Object context) {
972                         if (context instanceof SimulationContextFacade) {
973                                 _owner = (SimulationContextFacade) context; // Just for optimizing
974                         } else {
975                                 super.setContext(name, context);
976                         }
977                 }
978         }
979
980         // Resources relative to knowledge
981         private static class FeedbexPopup extends PopupMenu {
982                 private transient KnowledgeElement _owner = null;
983
984                 private FeedbexPopup() {
985                         super();
986                         addItem(MNU_PROMOTE, new PopupItem(MNU_NAME_PROMOTE).icon(
987                                         "image.review.png").action("promote-knowledge")
988                                         .confirmation("message.promote.knowledge"));
989                         addItem(MNU_DEMOTE, new PopupItem(MNU_NAME_DEMOTE).icon(
990                                         "image.invalidate.png").action("demote-knowledge")
991                                         .confirmation("message.demote.knowledge"));
992                         addSeparator();
993                         addItem(MNU_RENAME, new PopupItem(MNU_NAME_RENAME)
994                                         .action("edit-knowledge?action=renameKnowledge"));
995                         addItem(MNU_EDIT, new PopupItem(MNU_NAME_EDIT)
996                                         .action("edit-knowledge?action=editKnowledge"));
997                         addSeparator();
998                         addItem(MNU_REMOVE, new PopupItem(MNU_NAME_REMOVE).icon(IMG_DELETE)
999                                         .action("remove-knowledge").confirmation(
1000                                                         "message.delete.knowledge"));
1001                 }
1002
1003                 @Override
1004                 public boolean isEnabled(final String name) {
1005                         Item item = Item.valueOf(name);
1006                         boolean res = true;
1007
1008                         if (item == Item.promote) {
1009                                 if (_owner.getProgressState() != ProgressState.inDRAFT) {
1010                                         res = false;
1011                                 }
1012                         } else if ((item == Item.demote)
1013                                         && (_owner.getProgressState() != ProgressState.inCHECK)) {
1014                                 res = false;
1015                         }
1016                         return res;
1017                 }
1018
1019                 @Override
1020                 public void setContext(final String name, final Object context) {
1021                         if (context instanceof KnowledgeElement) {
1022                                 _owner = (KnowledgeElement) context; // Just for optimizing
1023                         } else {
1024                                 super.setContext(name, context);
1025                         }
1026                 }
1027         }
1028
1029         /**
1030          * Pop-up menu for comments.
1031          */
1032         private static class CommentPopup extends PopupMenu {
1033                 /**
1034                  * Default constructor.
1035                  */
1036                 private CommentPopup() {
1037                         super();
1038                         addItem(MNU_EDIT, new PopupItem(MNU_NAME_EDIT).icon("icon.ed.png")
1039                                         .action("editComment(entity_index)"));
1040                         addItem(MNU_REMOVE, new PopupItem(MNU_NAME_REMOVE).icon(IMG_DELETE)
1041                                         .action("removeComment(entity_index)").confirmation(
1042                                                         "message.delete.comment"));
1043                 }
1044
1045                 /**
1046                  * Is enabled.
1047                  * 
1048                  * @param name
1049                  *            the entry name
1050                  * @return true
1051                  */
1052                 @Override
1053                 public boolean isEnabled(final String name) {
1054                         return true;
1055                 }
1056         }
1057
1058         /**
1059          * Pop-up menu for comments.
1060          */
1061         private static class DescritptionPopup extends PopupMenu {
1062                 /**
1063                  * Default constructor.
1064                  */
1065                 private DescritptionPopup() {
1066                         super();
1067                         addItem(MNU_EDIT, new PopupItem(MNU_NAME_EDIT).icon("icon.ed.png")
1068                                         .action("showDescriptionEditor()"));
1069                         addItem(MNU_REMOVE, new PopupItem(MNU_NAME_REMOVE).icon(IMG_DELETE)
1070                                         .action("removeDescription()").confirmation(
1071                                                         "message.delete.description"));
1072                 }
1073
1074                 /**
1075                  * Is enable.
1076                  * 
1077                  * @param name
1078                  *            the entry name
1079                  * @return true
1080                  */
1081                 @Override
1082                 public boolean isEnabled(final String name) {
1083                         return true;
1084                 }
1085         }
1086
1087         // ==============================================================================================================================
1088         // Construction
1089         // ==============================================================================================================================
1090
1091         // ==============================================================================================================================
1092         // Public member functions
1093         // ==============================================================================================================================
1094
1095         public void configure() {
1096                 // Non customizable settings
1097                 _menus.clear();
1098                 SimpleMenu menu = new NewMenu();
1099                 _menus.put(menu.getName(), menu);
1100                 menu = new SearchMenu();
1101                 _menus.put(menu.getName(), menu);
1102                 menu = new DatadminMenu();
1103                 _menus.put(menu.getName(), menu);
1104                 menu = new SysadminMenu();
1105                 _menus.put(menu.getName(), menu);
1106                 menu = new PropertiesMenu();
1107                 _menus.put(menu.getName(), menu);
1108
1109                 _popups = new HashMap<String, PopupMenu>();
1110                 _popups.put("steditablemarkpublic", new EditableMarkedStudyPopup(false,
1111                                 false));
1112                 _popups.put("steditableunmarkpublic", new EditableMarkedStudyPopup(
1113                                 false, true));
1114                 _popups.put("steditablemarkprivate", new EditableMarkedStudyPopup(true,
1115                                 false));
1116                 _popups.put("steditableunmarkprivate", new EditableMarkedStudyPopup(
1117                                 true, true));
1118                 _popups.put("editable", new EditableDocumentPopup());
1119                 _popups.put("notresult", new NotResultDocumentPopup());
1120                 _popups.put("reviewable", new ReviewableDocumentPopup());
1121                 _popups.put("approvable", new ApprovableDocumentPopup());
1122                 _popups.put("approved", new ApprovedPopup());
1123                 _popups.put("extern", new ExternPopup());
1124                 _popups.put("scontext", new ScontextPopup());
1125                 _popups.put("feedbex", new FeedbexPopup());
1126                 _popups.put("comment", new CommentPopup());
1127                 _popups.put("description", new DescritptionPopup());
1128
1129                 // Default customizable mandatory settings
1130                 Map<String, Object> fprop = new HashMap<String, Object>();
1131                 fprop.put("visibility", "PRIVATE");
1132                 fprop.put("matchamong", ALL);
1133                 fprop.put("matcontext", ALL);
1134                 fprop.put("state", "APPROVED");
1135                 fprop.put("author", "0");
1136                 fprop.put("reference", "");
1137                 fprop.put("title", "");
1138                 fprop.put("context", new ArrayList<SimulationContext>());
1139
1140                 Map<String, Object> gprop = new HashMap<String, Object>();
1141                 gprop.put("visibility", "PUBLIC");
1142                 gprop.put("matchamong", ALL);
1143                 gprop.put("matcontext", ALL);
1144                 gprop.put("type", "2"); // TODO: Get the index from the type name
1145                 gprop.put("author", "0");
1146                 gprop.put("reference", "");
1147                 gprop.put("title", "");
1148                 gprop.put("context", new ArrayList<SimulationContext>());
1149
1150                 _filter = new HashMap<String, Map<String, Object>>();
1151                 _filter.put("study", fprop);
1152                 _filter.put("knowledge", gprop);
1153
1154                 // Settings based on the customization
1155                 configureToolbars();
1156         }
1157
1158         /**
1159          * Configure toolbars for steps.
1160          */
1161         private void configureToolbars() {
1162                 _bars = new HashMap<Integer, ToolBar>(); // May be empty if no module installed
1163
1164                 List<ProjectSettingsService.Step> steps = getProjectSettings()
1165                                 .getAllSteps();
1166                 for (Iterator<ProjectSettingsService.Step> i = steps.iterator(); i
1167                                 .hasNext();) {
1168                         ProjectSettingsService.Step step = i.next();
1169                         List<String> formats = getProjectSettings().getDefaultFormats(step);
1170                         if (formats.isEmpty()) {
1171                                 continue;
1172                         }
1173
1174                         ToolBar bar = new ToolBar(24); // Height of the module-bar
1175                         Set<String> module = new HashSet<String>(); // For not duplicating modules
1176                         for (String format : formats) {
1177                                 String command = getApplicationProperty("executable." + format);
1178                                 if (command == null) {
1179                                         continue; // Module not installed
1180                                 }
1181                                 if (module.contains(command)) {
1182                                         continue;
1183                                 }
1184                                 module.add(command);
1185                                 String[] parsed = command.split("/");
1186                                 String[] name = parsed[parsed.length - 1].split("\\x2E");
1187                                 DocumentType dtype = getProjectSettings()
1188                                                 .getDefaultDocumentType(step, format);
1189                                 String docname = "";
1190                                 if (dtype != null) {
1191                                         docname = dtype.getName();
1192                                 }
1193                                 if (tempfile.get(docname) == null) { // No available template
1194                                         String tool = parsed[parsed.length - 1];
1195                                         String icon = name[0];
1196                                         if ("index".equals(icon)) {
1197                                                 tool = parsed[parsed.length - 2];
1198                                                 icon = "tool." + tool.toLowerCase() + ".png";
1199                                         } else {
1200                                                 icon = "tool." + icon.toLowerCase() + ".png";
1201                                         }
1202                                         File image = new File(ApplicationSettings
1203                                                         .getApplicationSkinPath()
1204                                                         + icon);
1205                                         if (!image.exists()) {
1206                                                 icon = "tool.any.png";
1207                                         }
1208                                         bar.addTool(tool, icon, command);
1209                                 } else {
1210                                         docname = "/jsp/newDocument.jsp?type=" + docname;
1211                                         String icon = "tool." + name[0].toLowerCase() + ".png";
1212                                         File image = new File(ApplicationSettings
1213                                                         .getApplicationSkinPath()
1214                                                         + icon);
1215                                         if (!image.exists()) {
1216                                                 icon = "tool.any.png";
1217                                         }
1218                                         bar.addTool(name[0], icon, command, docname);
1219                                 }
1220                         }
1221                         if (!bar.isEmpty()) {
1222                                 _bars.put(step.getNumber(), bar);
1223                         }
1224                 }
1225         }
1226
1227         public static String getApplicationProperty(final String name) {
1228                 return _WAPPROPS.getProperty(name); // May be null
1229         }
1230
1231         public static String getApplicationRootPath() {
1232                 // The property is supposed including the Web application name
1233                 return wapproot;
1234         }
1235
1236         public String getApplicationURL() {
1237                 StringBuffer url = new StringBuffer("http://").append(_wappserver)
1238                                 .append("/").append(wappname);
1239                 return url.toString();
1240         }
1241
1242         public Map<String, Object> getFilter(final String name) {
1243                 return _filter.get(name);
1244         }
1245
1246         public ToolBar getModuleBar(final Step step) {
1247                 return _bars.get(step.getNumber());
1248         }
1249
1250         static public Properties getNamingProperties() {
1251                 return _JNDPROPS;
1252         }
1253
1254         // ==============================================================================================================================
1255         // Public services
1256         // ==============================================================================================================================
1257
1258         public static String getApplicationPluginPath() {
1259                 return getApplicationRootPath() + "plugin/";
1260         }
1261
1262         public static String getApplicationResourcePath() {
1263                 return getApplicationRootPath() + "WEB-INF/classes/";
1264         }
1265
1266         public static String getApplicationSkinPath() {
1267                 return getApplicationRootPath() + "skin/";
1268         }
1269
1270         public static Converter getConverter(final DocumentType type,
1271                         final String format) {
1272                 return convertmap.get(format + type.getName()); // May be null;
1273         }
1274
1275         /**
1276          * Get default document type for the given format on the given study step.
1277          * 
1278          * @param step
1279          *            the study step
1280          * @param format
1281          *            the file format
1282          * @return default document type or null if not defined in the configuration
1283          */
1284         public DocumentType getDefaultDocumentType(final Step step,
1285                         final String format) {
1286                 return getProjectSettings().getDefaultDocumentType(step.getStep(),
1287                                 format); // May be null
1288         }
1289
1290         public String getDownloadURL(final User user) {
1291                 StringBuffer url = new StringBuffer("http://").append(_wappserver)
1292                                 .append("/download/").append(user.getUsername()).append("/");
1293                 return url.toString(); // The download Tomcat context is supposed being defined
1294         }
1295
1296         public Locale getCurrentLocale() {
1297                 return _locale;
1298         }
1299
1300         public SimpleMenu getMenu(final String name) {
1301                 return _menus.get(name);
1302         }
1303
1304         public PopupMenu getPopupMenu(final String name) {
1305                 return _popups.get(name);
1306         }
1307
1308         public String getRepositoryURL() {
1309                 StringBuffer url = new StringBuffer("http://").append(_wappserver)
1310                                 .append("/repository/");
1311                 return url.toString(); // The repository Tomcat context is supposed being defined
1312         }
1313
1314         public static Locale[] getSupportedLocales() {
1315                 String[] code = _WAPPROPS.getProperty("locale.supported").split(",");
1316                 Locale[] result = new Locale[code.length];
1317                 for (int i = 0; i < code.length; i++) {
1318                         result[i] = new Locale(code[i]);
1319                 }
1320                 return result;
1321         }
1322
1323         public static String[] getViewersMapping() {
1324                 return viewermap;
1325         }
1326
1327         public static String getWebSiteURL() {
1328                 return getApplicationProperty("wapp.website");
1329         }
1330
1331         public static String getHelpURL() {
1332                 return getApplicationProperty("wapp.onlinehelp");
1333         }
1334
1335         // ==============================================================================================================================
1336         // Private services
1337         // ==============================================================================================================================
1338
1339         /**
1340          * Load application custom configuration from the given XML file (see conf/my.xml).
1341          * 
1342          * @param config
1343          *            the XML configuration file
1344          */
1345         private static void loadCustomization(final File config) {
1346                 try {
1347                         DocumentBuilderFactory dfactory = javax.xml.parsers.DocumentBuilderFactory
1348                                         .newInstance();
1349                         DocumentBuilder dBuilder = dfactory.newDocumentBuilder();
1350
1351                         org.w3c.dom.Document conf = dBuilder.parse(config.getPath());
1352                         HashMap<String, Node> children = XDOM.getNamedChildNodes(conf
1353                                         .getDocumentElement());
1354
1355                         // Modules tag
1356                         loadModules(children);
1357
1358                         // Converters tag
1359                         loadConverters(children);
1360
1361                         // Templates tag
1362                         loadTemplates(children);
1363                 } catch (Exception error) {
1364                         LOG.info("Error in customization", error);
1365                 }
1366         }
1367
1368         /**
1369          * Load modules from XML configuration.
1370          * 
1371          * @param children
1372          *            XML nodes
1373          */
1374         private static void loadModules(final Map<String, Node> children) {
1375                 Node child = children.get("modules");
1376                 NodeList nlist = child.getChildNodes();
1377                 for (int i = 0; i < nlist.getLength(); i++) {
1378                         child = nlist.item(i);
1379                         if (!child.getNodeName().equals("mapping")) {
1380                                 continue;
1381                         }
1382
1383                         NamedNodeMap natr = child.getAttributes();
1384                         String dext = natr.getNamedItem("extension").getNodeValue();
1385                         String exec = natr.getNamedItem("executable").getNodeValue();
1386                         _WAPPROPS.put("executable." + dext, exec);
1387                 }
1388                 // Viewer mappings tag
1389                 child = children.get("viewers");
1390                 viewermap = child.getAttributes().getNamedItem("extension")
1391                                 .getNodeValue().split(",");
1392         }
1393
1394         /**
1395          * Load converters from XML configuration.
1396          * 
1397          * @param children
1398          *            XML nodes
1399          */
1400         private static void loadConverters(final Map<String, Node> children) {
1401                 Node child = children.get("converters");
1402                 NodeList nlist = child.getChildNodes();
1403                 for (int i = 0; i < nlist.getLength(); i++) {
1404                         child = nlist.item(i);
1405
1406                         if (child.getNodeName().equals("geometry")) {
1407                                 NamedNodeMap natr = child.getAttributes();
1408                                 String from = natr.getNamedItem("from").getNodeValue();
1409                                 String to = natr.getNamedItem("to").getNodeValue();
1410                                 String exec = natr.getNamedItem("executable").getNodeValue();
1411                                 convertmap.put(from + "geometry", new Converter("geometry",
1412                                                 from, to, exec));
1413                         }
1414                 }
1415         }
1416
1417         /**
1418          * Load templates from XML configuration.
1419          * 
1420          * @param children
1421          *            XML nodes
1422          */
1423         private static void loadTemplates(final Map<String, Node> children) {
1424                 Node child = children.get("templates");
1425                 NodeList nlist = child.getChildNodes();
1426                 for (int i = 0; i < nlist.getLength(); i++) {
1427                         child = nlist.item(i);
1428                         if (!child.getNodeName().equals("document")) {
1429                                 continue;
1430                         }
1431
1432                         NamedNodeMap natr = child.getAttributes();
1433                         String type = natr.getNamedItem("type").getNodeValue();
1434                         String file = natr.getNamedItem("file").getNodeValue();
1435                         tempfile.put(type, file);
1436                 }
1437         }
1438
1439         /**
1440          * Get the documentTypeService.
1441          * 
1442          * @return the documentTypeService
1443          */
1444         public DocumentTypeService getDocumentTypeService() {
1445                 return _documentTypeService;
1446         }
1447
1448         /**
1449          * Set the documentTypeService.
1450          * 
1451          * @param documentTypeService
1452          *            the documentTypeService to set
1453          */
1454         public void setDocumentTypeService(
1455                         final DocumentTypeService documentTypeService) {
1456                 _documentTypeService = documentTypeService;
1457         }
1458
1459         /**
1460          * Get the locale.
1461          * 
1462          * @return the locale
1463          */
1464         public Locale getLocale() {
1465                 return _locale;
1466         }
1467
1468         /**
1469          * Set the locale.
1470          * 
1471          * @param locale
1472          *            the locale to set
1473          */
1474         public void setLocale(final Locale locale) {
1475                 _locale = locale;
1476         }
1477
1478 }