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