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