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