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