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