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