Salome HOME
Copyrights update 2015.
[tools/siman.git] / Workspace / Siman-Common / src / org / splat / service / technical / ProjectSettingsServiceImpl.java
1 package org.splat.service.technical;
2
3 /**
4  * 
5  * @author    Daniel Brunier-Coulin
6  * @copyright OPEN CASCADE 2012-2015
7  */
8
9 import java.io.File;
10 import java.io.FileNotFoundException;
11 import java.io.IOException;
12 import java.sql.SQLException;
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.LinkedHashMap;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Properties;
20 import java.util.Set;
21
22 import javax.xml.parsers.DocumentBuilder;
23 import javax.xml.parsers.DocumentBuilderFactory;
24
25 import org.apache.log4j.Logger;
26 import org.splat.dal.bo.som.Document;
27 import org.splat.dal.bo.som.DocumentType;
28 import org.splat.dal.bo.som.KnowledgeElement;
29 import org.splat.dal.bo.som.KnowledgeElementType;
30 import org.splat.dal.bo.som.ProjectElement;
31 import org.splat.dal.bo.som.Scenario;
32 import org.splat.dal.bo.som.SimulationContextType;
33 import org.splat.dal.bo.som.Study;
34 import org.splat.dal.bo.som.ValidationCycle.Actor;
35 import org.splat.dal.dao.som.Database;
36 import org.splat.manox.XDOM;
37 import org.splat.service.DocumentTypeService;
38 import org.splat.service.KnowledgeElementTypeService;
39 import org.splat.service.SimulationContextTypeService;
40 import org.springframework.context.ResourceLoaderAware;
41 import org.springframework.core.io.Resource;
42 import org.springframework.core.io.ResourceLoader;
43 import org.springframework.transaction.annotation.Transactional;
44 import org.w3c.dom.Element;
45 import org.w3c.dom.NamedNodeMap;
46 import org.w3c.dom.Node;
47 import org.w3c.dom.NodeList;
48
49 /**
50  * SIMAN workflow configuration data service.
51  */
52 public class ProjectSettingsServiceImpl implements ProjectSettingsService,
53                 ResourceLoaderAware {
54
55         /**
56          * The logger for the service.
57          */
58         protected final static Logger LOG = Logger
59                         .getLogger(ProjectSettingsServiceImpl.class);
60
61         /**
62          * Type attribute name.
63          */
64         private final static String TYPE_ATTR = "type";
65
66         /**
67          * Steps configuration storage.
68          */
69         private StepsConfigService _stepsConfigService;
70         /**
71          * Resource loader injected by Spring.
72          */
73         private ResourceLoader _resourceLoader;
74
75         /**
76          * Configuration resource injected by Spring.
77          */
78         private Resource _config;
79
80         // Non persistent configuration information
81         /**
82          * Repository settings.
83          */
84         private transient final Properties _reprop = new Properties();
85         /**
86          * Pattern of study references.
87          */
88         private transient String _pattern;
89         /**
90          * Scheme of file names stored into the repository.
91          */
92         private transient FileNaming _naming;
93         /**
94          * Pattern of the presentation of version numbers.
95          */
96         private transient String _versioning;
97         /**
98          * Configuration document validation cycles.
99          */
100         private transient final List<ProjectSettingsValidationCycle> _concycles = new ArrayList<ProjectSettingsValidationCycle>();
101         /**
102          * Document type mappings to file formats which should be imported into SALOME during check-out.
103          */
104         private transient final Map<String, List<String>> _mapimport = new HashMap<String, List<String>>();
105         /**
106          * Default document types structured by step.formats.
107          */
108         private transient final Map<String, DocumentType> _defdoctype = new LinkedHashMap<String, DocumentType>();
109
110         // Temporary attributes initialized from the configuration file for populating the database with object types
111         /**
112          * Step.format keys structured by Default document types names. This map is used for loading config before document types are created in
113          * the database. When document types are created then _defdoctype is filled.
114          */
115         private transient final Map<String, List<String>> _defdoctypeKeys = new HashMap<String, List<String>>();
116
117         /**
118          * Document type names and uses mapping.
119          */
120         private transient Map<String, String> _mapuse;
121         /**
122          * Simulation Context type names.
123          */
124         private transient List<String> _context;
125         /**
126          * Knowledge Element type names.
127          */
128         private transient List<String> _kname;
129         /**
130          * Document flows.
131          */
132         private transient List<NamedNodeMap> _flows;
133         /**
134          * Study classifications.
135          */
136         private transient List<NamedNodeMap> _sclass;
137
138         // Other resources
139         /**
140          * Database service to check its version, etc.
141          */
142         private Database _database;
143         /**
144          * Injected simulation context type service.
145          */
146         private SimulationContextTypeService _simulationContextTypeService;
147         /**
148          * Injected knowledge element type service.
149          */
150         private KnowledgeElementTypeService _knowledgeElementTypeService;
151         /**
152          * Injected document type service.
153          */
154         private DocumentTypeService _documentTypeService;
155
156         /**
157          * File naming strategy enumeration.
158          */
159         public enum FileNaming {
160                 /**
161                  * Name by document title.
162                  */
163                 title,
164                 /**
165                  * Generate encoded name.
166                  */
167                 encoded,
168                 /**
169                  * Keep original file name.
170                  */
171                 asis
172         }
173
174         /**
175          * Validation cycle defined in the XML configuration.
176          */
177         public static class ProjectSettingsValidationCycle {
178                 /**
179                  * Cycle (document) type name.
180                  */
181                 private transient final String _name;
182                 /**
183                  * Array of cycle actors positions in the organization. TODO: Must be replaced by Roles.
184                  */
185                 private transient final Actor[] _actor;
186
187                 /**
188                  * Default constructor.
189                  */
190                 private ProjectSettingsValidationCycle() {
191                         this._name = "built-in";
192                         this._actor = new Actor[] { null, null, null };
193                 }
194
195                 /**
196                  * Create a validation cycle definition for the given document type name and actors positions.
197                  * 
198                  * @param name
199                  *            the document type name
200                  * @param actor
201                  *            the array of actors positions
202                  */
203                 private ProjectSettingsValidationCycle(final String name,
204                                 final Actor[] actor) {
205                         this._name = name;
206                         this._actor = actor;
207                 }
208
209                 /**
210                  * The processed document type name.
211                  * 
212                  * @return the document type name
213                  */
214                 public String getName() {
215                         return _name;
216                 }
217
218                 /**
219                  * Get an array of cycle actors positions.
220                  * 
221                  * @return the array of actors positions
222                  * @see org.splat.dal.bo.som.ValidationCycle.Actor
223                  */
224                 public Actor[] getActorTypes() {
225                         return _actor;
226                 }
227         }
228
229         // ==============================================================================================================================
230         // Public functions
231         // ==============================================================================================================================
232
233         /**
234          * Load workflow configuration from the file defined by config property. <BR>
235          * Create necessary default staff in the database if it is not initialized yet.
236          * 
237          * @throws IOException
238          *             if there is a file reading or index creation problem
239          * @throws SQLException
240          *             if there is a database population problem
241          */
242         @Transactional
243         public void configure() throws IOException, SQLException {
244                 if (getConfig() != null) {
245                         configure("file:" + getConfig().getFile().getAbsolutePath());
246                 }
247         }
248
249         /**
250          * Load workflow configuration from the given file. <BR>
251          * Create necessary default staff in the database if it is not initialized yet.
252          * 
253          * @param filename
254          *            the workflow configuration file
255          * @throws IOException
256          *             if there is a file reading or index creation problem
257          * @throws SQLException
258          *             if there is a database population problem
259          */
260         @Transactional
261         public void configure(final String filename) throws IOException,
262                         SQLException {
263                 if (!getStepsConfigService().getSteps().isEmpty()) {
264                         return; // Project already configured
265                 }
266
267                 Database base = getDatabase().getCheckedDB();
268                 if (LOG.isInfoEnabled()) {
269                         LOG.info("Loading configuration from: "
270                                         + getResource(filename).getFile().getAbsolutePath());
271                         LOG.info("Root: " + getResource("/").getURI());
272                 }
273                 File config = getResource(filename).getFile();
274                 if (config.exists()) {
275                         loadCustomization(config);
276                 } else {
277                         LOG.fatal("Could not find the database configuration file \""
278                                         + config.getAbsolutePath() + "\"");
279                         throw new FileNotFoundException();
280                 }
281                 base.configure(_reprop);
282                 if (!base.isInitialized()) {
283                         base.initialize();
284                         initialize(); // Populates the database with all necessary stuff
285                 }
286         }
287
288         /**
289          * Get ordered list of (transient) study steps.
290          * 
291          * @return the list of steps from project settings
292          */
293         public List<ProjectSettingsService.Step> getAllSteps() {
294                 return getStepsConfigService().getSteps();
295         }
296
297         /**
298          * Return the validation cycles of result documents defined in the workflow, ordered by study activities and ending by the default
299          * validation cycle, if defined.
300          * 
301          * @return the validation cycles of the workflow
302          */
303         public List<ProjectSettingsValidationCycle> getAllValidationCycles() {
304                 return _concycles;
305         }
306
307         /**
308          * Get file naming scheme setting.
309          * 
310          * @return file naming scheme
311          * @see org.splat.service.technical.ProjectSettingsServiceImpl.FileNaming
312          */
313         public FileNaming getFileNamingScheme() {
314                 return _naming;
315         }
316
317         /**
318          * Get a pattern of study references.
319          * 
320          * @return the reference pattern
321          */
322         public String getReferencePattern() {
323                 return _pattern;
324         }
325
326         /**
327          * Get a pattern of the presentation of version numbers.
328          * 
329          * @return the version numbers presentation pattern
330          */
331         public String getRevisionPattern() {
332                 return _versioning;
333         }
334
335         /**
336          * Get a study step by its sequential number.
337          * 
338          * @param number
339          *            the step number
340          * @return the step
341          */
342         public ProjectSettingsService.Step getStep(final int number) {
343                 ProjectSettingsService.Step res = null;
344                 for (int i = 0; i < getStepsConfigService().getSteps().size(); i++) {
345                         ProjectSettingsService.Step step = getStepsConfigService()
346                                         .getSteps().get(i);
347                         if (step.getNumber() == number) {
348                                 res = step;
349                                 break;
350                         }
351                 }
352                 return res;
353         }
354
355         /**
356          * Check if a file of the given format should be imported during check-out of a document of the given type.
357          * 
358          * @param type
359          *            document type
360          * @param format
361          *            file format
362          * @return true if file should be imported
363          */
364         public boolean doImport(final String type, final String format) {
365                 if (LOG.isDebugEnabled()) {
366                         LOG.debug("Do import for ("
367                                         + type
368                                         + ", "
369                                         + format
370                                         + "): "
371                                         + (_mapimport.containsKey(type) && _mapimport.get(type)
372                                                         .contains(format)));
373                 }
374                 return (_mapimport.containsKey(type) && _mapimport.get(type).contains(
375                                 format));
376         }
377
378         /**
379          * Get default document type for the given file format on the given study step.
380          * 
381          * @param step
382          *            the study step
383          * @param format
384          *            the file format (extension)
385          * @return document type
386          */
387         public DocumentType getDefaultDocumentType(final Step step,
388                         final String format) {
389                 String[] table = format.split("\\x2E");
390                 if (LOG.isDebugEnabled()) {
391                         LOG.debug("Trying to get default type: " + step.getNumber() + "."
392                                         + table[table.length - 1]);
393                 }
394                 return _defdoctype
395                                 .get(step.getNumber() + "." + table[table.length - 1]); // May be null
396         }
397
398         /**
399          * Get the list of default formats for the given study step.
400          * 
401          * @param step
402          *            the study step
403          * @return list of formats (file extensions)
404          */
405         public List<String> getDefaultFormats(final Step step) {
406                 Integer stepNumber = step.getNumber();
407                 List<String> result = new ArrayList<String>();
408
409                 for (String i : _defdoctype.keySet()) {
410                         String[] key = i.split("\\x2E");
411                         // PDF is not an authoring format
412                         if (stepNumber.equals(Integer.valueOf(key[0]))
413                                         && (!key[1].equals("pdf"))) {
414                                 result.add(key[1]); // Formats are unique
415                         }
416                 }
417                 return result;
418         }
419
420         /**
421          * Initialize the database: create all necessary default staff defined in the configuration file.
422          */
423         @Transactional
424         protected void initialize() {
425                 createDocumentTypes();
426                 createSimulationContextTypes();
427                 createKnowledgeElementTypes();
428         }
429
430         // ==============================================================================================================================
431         // Private member function
432         // ==============================================================================================================================
433
434         /**
435          * Read the configuration file and fill transient project settings fields.
436          * 
437          * @param config
438          *            the configuration XML file
439          */
440         private void loadCustomization(final File config) {
441                 try {
442                         DocumentBuilderFactory dfactory = javax.xml.parsers.DocumentBuilderFactory
443                                         .newInstance();
444                         DocumentBuilder dBuilder = dfactory.newDocumentBuilder();
445
446                         org.w3c.dom.Document conf = dBuilder.parse(config.getPath());
447                         HashMap<String, Node> children = XDOM.getNamedChildNodes(conf
448                                         .getDocumentElement());
449
450                         // Repository tag initializing the reprop attribute
451                         Node child = children.get("database");
452                         HashMap<String, Node> datag = XDOM.getNamedChildNodes(child);
453
454                         String disk = datag.get("repository").getAttributes().getNamedItem(
455                                         "disk").getNodeValue();
456                         if (!disk.endsWith("/")) {
457                                 disk = disk + "/";
458                         }
459                         LOG.info("Database root set to " + disk);
460                         _reprop.setProperty("repository", disk);
461
462                         // Formats tag initializing the reference pattern and date attributes
463                         child = children.get("formats");
464                         datag = XDOM.getNamedChildNodes(child);
465
466                         NamedNodeMap natr = datag.get("references").getAttributes();
467                         _pattern = natr.getNamedItem("study").getNodeValue();
468
469                         natr = datag.get("files").getAttributes();
470                         _naming = FileNaming.valueOf(natr.getNamedItem("name")
471                                         .getNodeValue());
472
473                         natr = datag.get("versions").getAttributes();
474                         _versioning = natr.getNamedItem("pattern").getNodeValue();
475
476                         // Activities tag initializing the steps and rex attributes
477                         child = children.get("activities");
478                         NodeList nlist = child.getChildNodes();
479                         List<NamedNodeMap> flist = new ArrayList<NamedNodeMap>();
480                         List<String> resultype = new ArrayList<String>();
481                         List<NamedNodeMap> clist = new ArrayList<NamedNodeMap>();
482
483                         int snum = 1; // Base number of steps
484                         for (int i = 0; i < nlist.getLength(); i++) {
485                                 child = nlist.item(i);
486                                 if ("scenario".equals(child.getNodeName())) {
487                                         NodeList slist = child.getChildNodes();
488                                         for (int j = 0; j < slist.getLength(); j++) {
489                                                 snum = loadStep(slist.item(j), Scenario.class, snum,
490                                                                 flist, clist, resultype);
491                                         }
492                                 } else {
493                                         snum = loadStep(child, Study.class, snum, flist, clist,
494                                                         resultype);
495                                 }
496                         }
497
498                         // Validations tag
499                         loadValidationCycles(children, resultype);
500                         // Load steps result document types mapped to file formats
501                         loadFormatMappings(children);
502                         // Load default mapping of file formats to document types for each step
503                         loadDefaultDocTypes(children);
504
505                         if (!getDatabase().getCheckedDB().isInitialized()) {
506                                 // Load object type definitions
507                                 // Documents tag
508                                 child = children.get("documents");
509                                 nlist = child.getChildNodes();
510
511                                 _flows = flist; // Kept for later use in document type definition
512                                 _sclass = clist; // Kept for later use in simulation context type definition
513                                 _mapuse = new LinkedHashMap<String, String>();
514                                 for (int i = 0; i < nlist.getLength(); i++) {
515                                         child = nlist.item(i);
516                                         if ("article".equals(child.getNodeName())) {
517                                                 natr = child.getAttributes();
518                                                 String type = natr.getNamedItem(TYPE_ATTR)
519                                                                 .getNodeValue();
520                                                 String uses = null;
521                                                 child = natr.getNamedItem("uses");
522                                                 if (child != null) {
523                                                         uses = child.getNodeValue();
524                                                 }
525                                                 _mapuse.put(type, uses); // Must be added to the map even if no (null) uses
526                                         }
527                                 }
528                                 // Simulation Contexts tag
529                                 _context = loadArticles(children, "contexts");
530                                 // Knowledge Elements tag
531                                 _kname = loadArticles(children, "knowledges");
532                         }
533                 } catch (Exception error) {
534                         LOG.info("Error in customization", error);
535                 }
536         }
537
538         /**
539          * Load mappings of document types to lists of importable file formats.
540          * 
541          * @param children
542          *            XML nodes
543          */
544         private void loadFormatMappings(final Map<String, Node> children) {
545                 _mapimport.clear();
546                 Element maps = (Element) children.get("mappings");
547                 Element doc, imp;
548                 String type, format;
549                 List<String> formats;
550                 NodeList docs, imports;
551                 if (maps != null) {
552                         // Read document types
553                         docs = maps.getElementsByTagName("document");
554                         for (int i = 0; i < docs.getLength(); i++) {
555                                 doc = (Element) docs.item(i);
556                                 type = doc.getAttribute(TYPE_ATTR);
557                                 if (!type.isEmpty()) {
558                                         // Read file formats for the document type
559                                         imports = doc.getElementsByTagName("import");
560                                         formats = new ArrayList<String>();
561                                         for (int j = 0; j < imports.getLength(); j++) {
562                                                 imp = (Element) imports.item(j);
563                                                 format = imp.getAttribute("format");
564                                                 if (!format.isEmpty()) {
565                                                         formats.add(format);
566                                                 }
567                                         }
568                                         if (!formats.isEmpty()) {
569                                                 _mapimport.put(type, formats);
570                                         }
571                                 }
572                         }
573                 }
574         }
575
576         /**
577          * Load default document types from XML configuration.
578          * 
579          * @param children
580          *            XML nodes
581          */
582         private void loadDefaultDocTypes(final Map<String, Node> children) {
583                 _defdoctype.clear();
584                 _defdoctypeKeys.clear();
585                 Node child = children.get("default-doctypes");
586                 if (child != null) {
587                         NodeList nlist = child.getChildNodes();
588
589                         List<DocumentType> listype = getDocumentTypeService()
590                                         .selectAllTypes();
591                         Map<String, DocumentType> maptype = new HashMap<String, DocumentType>();
592                         for (Iterator<DocumentType> i = listype.iterator(); i.hasNext();) {
593                                 DocumentType type = i.next();
594                                 maptype.put(type.getName(), type);
595                         }
596                         for (int i = 0; i < nlist.getLength(); i++) {
597                                 child = nlist.item(i);
598                                 if (!child.getNodeName().equals("step")) {
599                                         continue;
600                                 }
601
602                                 String nstep = child.getAttributes().getNamedItem("number")
603                                                 .getNodeValue();
604                                 NodeList map = child.getChildNodes();
605                                 for (int j = 0; j < map.getLength(); j++) {
606                                         child = map.item(j);
607                                         if (!child.getNodeName().equals("mapping")) {
608                                                 continue;
609                                         }
610                                         NamedNodeMap natr = child.getAttributes();
611                                         String dext = natr.getNamedItem("extension").getNodeValue();
612                                         String type = natr.getNamedItem(TYPE_ATTR).getNodeValue();
613                                         if (LOG.isDebugEnabled()) {
614                                                 LOG.debug("Map default type: " + nstep + "." + dext
615                                                                 + ": (type name = " + type + ")"
616                                                                 + maptype.get(type));
617                                         }
618                                         _defdoctype.put(nstep + "." + dext, maptype.get(type));
619                                         // Remember the key if type is not created yet
620                                         if (maptype.get(type) == null) {
621                                                 List<String> keys;
622                                                 if (_defdoctypeKeys.containsKey(type)) {
623                                                         keys = _defdoctypeKeys.get(type);
624                                                 } else {
625                                                         keys = new ArrayList<String>();
626                                                         _defdoctypeKeys.put(type, keys);
627                                                 }
628                                                 keys.add(nstep + "." + dext);
629                                         }
630                                 }
631                         }
632                 }
633         }
634
635         /**
636          * Load a step from the given XML node. Return the next step's number.
637          * 
638          * @param node
639          *            XML node to parse
640          * @param ownerClass
641          *            the class of a step's owner project element - study or scenario
642          * @param snum
643          *            step's number
644          * @param flist
645          *            list of flows
646          * @param clist
647          *            list of classifications
648          * @param resultype
649          *            list of flow results
650          * @return the next step's number
651          */
652         private int loadStep(final Node node,
653                         final Class<? extends ProjectElement> ownerClass, final int snum,
654                         final List<NamedNodeMap> flist, final List<NamedNodeMap> clist,
655                         final List<String> resultype) {
656                 int res = snum;
657                 if ("step".equals(node.getNodeName())) {
658
659                         String name = ((Element) node).getAttribute("name");
660                         HashMap<String, Node> tags = XDOM.getNamedChildNodes(node);
661
662                         NamedNodeMap natr = tags.get("storage").getAttributes();
663                         ProjectSettingsService.Step step = new ProjectSettingsService.Step(
664                                         snum, ownerClass, natr.getNamedItem("path").getNodeValue());
665                         step.setKey(name);
666
667                         // Keeping flow and classification information for eventual later use
668                         natr = tags.get("flow").getAttributes();
669                         flist.add(natr);
670                         Node child = natr.getNamedItem("result");
671                         if (child != null) {
672                                 resultype.add(child.getNodeValue());
673                         }
674
675                         child = tags.get("classification");
676                         if (child == null) {
677                                 clist.add(null);
678                         } else {
679                                 clist.add(child.getAttributes());
680                         }
681
682                         if (natr.getNamedItem("contents").getNodeValue()
683                                         .equals("knowledge")) {
684                                 if (Study.class.equals(ownerClass)) {
685                                         LOG
686                                                         .error("Error: knowledges must be attached to scenarios.");
687                                 } else {
688                                         // TODO In a given scenario, only one step must contain knowledges
689                                         step._contents.add(KnowledgeElement.class);
690                                 }
691                         } else {
692                                 step._contents.add(Document.class);
693                         }
694
695                         Element module = (Element) tags.get("module");
696                         if (module != null) {
697                                 step.setModule(module.getAttribute("name"));
698                         }
699
700                         getStepsConfigService().getSteps().add(step);
701                         res += 1;
702                 }
703                 return res;
704         }
705
706         /**
707          * Get custom validation cycles.
708          * 
709          * @param children
710          *            XML nodes
711          * @param resultype
712          *            list of result types
713          */
714         private void loadValidationCycles(final Map<String, Node> children,
715                         final List<String> resultype) {
716                 _concycles.clear();
717                 Node child = children.get("validations");
718                 Map<String, Node> datag = XDOM.getNamedChildNodes(child);
719                 NamedNodeMap natr;
720
721                 String[] step = { "review", "approval", "acceptance" };
722                 resultype.add("default");
723                 for (Iterator<String> i = resultype.iterator(); i.hasNext();) {
724                         Actor[] actor = { null, null, null };
725                         String name = i.next();
726                         child = datag.get(name);
727                         if (child != null) {
728                                 // Document type is the subject of a validation
729                                 natr = child.getAttributes();
730                                 for (int j = 0; j < step.length; j++) {
731                                         child = natr.getNamedItem(step[j]);
732                                         if (child != null) {
733                                                 actor[j] = Actor.valueOf(child.getNodeValue()); // Validation step is required
734                                         }
735                                 }
736                                 _concycles.add(new ProjectSettingsValidationCycle(name, actor));
737                         }
738                 }
739                 _concycles.add(new ProjectSettingsValidationCycle()); // Adds the built-in validation cycle
740         }
741
742         /**
743          * Read list of articles types.
744          * 
745          * @param children
746          *            XML nodes containing articles
747          * @param listName
748          *            the name of the list of articles
749          * @return list of articles types
750          */
751         private List<String> loadArticles(final Map<String, Node> children,
752                         final String listName) {
753                 Node child = children.get(listName);
754                 NodeList nlist = child.getChildNodes();
755
756                 List<String> articles = new ArrayList<String>();
757                 for (int i = 0; i < nlist.getLength(); i++) {
758                         child = nlist.item(i);
759                         if (child.getNodeName().equals("article")) {
760                                 articles.add(child.getAttributes().getNamedItem(TYPE_ATTR)
761                                                 .getNodeValue());
762                         }
763                 }
764                 return articles;
765         }
766
767         /**
768          * Create in the database document types defined in the custom configuration.
769          */
770         private void createDocumentTypes() {
771                 if (LOG.isDebugEnabled()) {
772                         LOG.debug("Creating documents types...");
773                 }
774                 DocumentType.Properties tprop = new DocumentType.Properties();
775                 Map<String, List<ProjectSettingsService.Step>> mapsteps = new HashMap<String, List<ProjectSettingsService.Step>>();
776                 Map<String, ProjectSettingsService.Step> mapresult = new HashMap<String, ProjectSettingsService.Step>();
777                 Map<String, DocumentType> maptype = new HashMap<String, DocumentType>();
778
779                 List<ProjectSettingsService.Step> slist = null; // List of Steps to which each document type is valid
780                 int snum = 0; // Step number
781                 String type = null;
782                 String uses = null;
783                 for (Iterator<NamedNodeMap> i = _flows.iterator(); i.hasNext(); snum++) {
784                         NamedNodeMap flow = i.next();
785                         ProjectSettingsService.Step step = getStepsConfigService()
786                                         .getSteps().get(snum);
787                         String[] contents = flow.getNamedItem("contents").getNodeValue()
788                                         .split(",");
789                         for (int j = 0; j < contents.length; j++) {
790                                 type = contents[j];
791                                 if (!_mapuse.containsKey(type)) {
792                                         LOG.warn("Undefined \"" + type + "\" document type.");
793                                         continue;
794                                 }
795                                 slist = mapsteps.get(type);
796                                 if (slist == null) {
797                                         slist = new ArrayList<ProjectSettingsService.Step>();
798                                 }
799                                 slist.add(step);
800                                 mapsteps.put(type, slist);
801                         }
802                         Node result = flow.getNamedItem("result");
803                         if (result != null) {
804                                 mapresult.put(result.getNodeValue(), step);
805                         }
806                 }
807                 try {
808                         DocumentType tdoc = null;
809                         Set<String> tset = _mapuse.keySet();
810                         ProjectSettingsService.Step step;
811                         for (Iterator<String> i = tset.iterator(); i.hasNext();) {
812                                 type = i.next();
813                                 slist = mapsteps.get(type);
814                                 if (slist != null) {
815                                         uses = _mapuse.get(type);
816                                         step = mapresult.get(type);
817
818                                         tprop.clear();
819                                         tprop.setName(type).setStep(
820                                                         slist.toArray(new ProjectSettingsService.Step[slist
821                                                                         .size()]));
822                                         if (uses != null) {
823                                                 // Parse uses attribute
824                                                 String[] usesArr = uses.split(",");
825                                                 List<DocumentType> usesTypesList = new ArrayList<DocumentType>();
826                                                 for (String usesType : usesArr) {
827                                                         tdoc = maptype.get(usesType.trim());
828                                                         if (tdoc == null) {
829                                                                 LOG.warn("Undefined \"" + usesType.trim()
830                                                                                 + "\" document type.");
831                                                         } else {
832                                                                 if (!usesTypesList.contains(tdoc)) {
833                                                                         usesTypesList.add(tdoc);
834                                                                 }
835                                                         }
836                                                 }
837                                                 tprop.setUses(usesTypesList
838                                                                 .toArray(new DocumentType[] {}));
839                                         }
840                                         if (step != null) {
841                                                 tprop.setResult(step);
842                                         }
843
844                                         tprop.disableCheck();
845                                         tdoc = getDocumentTypeService().createType(tprop); // Creation of Document Types
846                                         getDocumentTypeService().approve(tdoc);
847                                         maptype.put(type, tdoc);
848                                         // Remember default type if it is
849                                         if (_defdoctypeKeys.containsKey(type)) {
850                                                 for (String key : _defdoctypeKeys.get(type)) {
851                                                         if (LOG.isDebugEnabled()) {
852                                                                 LOG.debug("Put mapping for default type: "
853                                                                                 + key + ": " + tdoc);
854                                                         }
855                                                         _defdoctype.put(key, tdoc);
856                                                 }
857                                         }
858                                 }
859                         }
860                 } catch (Exception error) {
861                         LOG.warn("Error creating document types, reason:", error); // Should not happen
862                 }
863                 if (LOG.isDebugEnabled()) {
864                         LOG.debug("Documents types are created: " + maptype.size());
865                 }
866         }
867
868         /**
869          * Create in the database knowledge types defined in the custom configuration.
870          */
871         @Transactional
872         private void createKnowledgeElementTypes() {
873                 try {
874                         KnowledgeElementType ktype = getKnowledgeElementTypeService()
875                                         .createType("usecase"); // Internal reserved knowledge element type
876                         getKnowledgeElementTypeService().reserve(ktype);
877                         for (Iterator<String> i = _kname.iterator(); i.hasNext();) {
878                                 String type = i.next();
879
880                                 ktype = getKnowledgeElementTypeService().createType(type); // Knowledge Elements Types defined in the configuration
881                                 getKnowledgeElementTypeService().approve(ktype);
882                         }
883                 } catch (Exception error) {
884                         LOG.warn("Error creating knowledge types, reason:", error); // Should not happen
885                 }
886         }
887
888         /**
889          * Create in the database simulation contexts types defined in the custom configuration.
890          */
891         private void createSimulationContextTypes() {
892                 Map<String, ProjectSettingsService.Step> mapstep = new HashMap<String, ProjectSettingsService.Step>();
893                 int snum = 0;
894                 for (Iterator<NamedNodeMap> i = _sclass.iterator(); i.hasNext(); snum++) {
895                         NamedNodeMap clatr = i.next();
896                         if (clatr != null) {
897                                 String[] clist = clatr.getNamedItem("context").getNodeValue()
898                                                 .split(",");
899                                 for (int j = 0; j < clist.length; j++) {
900                                         mapstep.put(clist[j], getStepsConfigService().getSteps()
901                                                         .get(snum));
902                                 }
903                         }
904                 }
905                 try {
906                         SimulationContextType tctex = null;
907                         for (Iterator<String> i = _context.iterator(); i.hasNext();) {
908                                 String type = i.next();
909                                 if (mapstep.containsKey(type)) {
910                                         tctex = getSimulationContextTypeService().createType(type,
911                                                         mapstep.get(type)); // Creation of Simulation Context Types
912                                         getSimulationContextTypeService().approve(tctex);
913                                 } else {
914                                         LOG
915                                                         .warn("Could not find \""
916                                                                         + type
917                                                                         + "\" classification. Simulation Context type ignored.");
918                                 }
919                         }
920                 } catch (Exception error) {
921                         LOG.warn("Error creating context types, reason:", error); // Should not happen
922                 }
923         }
924
925         /**
926          * Get the database.
927          * 
928          * @return the database
929          */
930         public Database getDatabase() {
931                 return _database;
932         }
933
934         /**
935          * Set the database.
936          * 
937          * @param database
938          *            the database to set
939          */
940         public void setDatabase(final Database database) {
941                 _database = database;
942         }
943
944         /**
945          * Get the simulationContextTypeService.
946          * 
947          * @return the simulationContextTypeService
948          */
949         public SimulationContextTypeService getSimulationContextTypeService() {
950                 return _simulationContextTypeService;
951         }
952
953         /**
954          * Set the simulationContextTypeService.
955          * 
956          * @param simulationContextTypeService
957          *            the simulationContextTypeService to set
958          */
959         public void setSimulationContextTypeService(
960                         final SimulationContextTypeService simulationContextTypeService) {
961                 _simulationContextTypeService = simulationContextTypeService;
962         }
963
964         /**
965          * Get the knowledgeElementTypeService.
966          * 
967          * @return the knowledgeElementTypeService
968          */
969         public KnowledgeElementTypeService getKnowledgeElementTypeService() {
970                 return _knowledgeElementTypeService;
971         }
972
973         /**
974          * Set the knowledgeElementTypeService.
975          * 
976          * @param knowledgeElementTypeService
977          *            the knowledgeElementTypeService to set
978          */
979         public void setKnowledgeElementTypeService(
980                         final KnowledgeElementTypeService knowledgeElementTypeService) {
981                 _knowledgeElementTypeService = knowledgeElementTypeService;
982         }
983
984         /**
985          * Get the documentTypeService.
986          * 
987          * @return the documentTypeService
988          */
989         public DocumentTypeService getDocumentTypeService() {
990                 return _documentTypeService;
991         }
992
993         /**
994          * Set the documentTypeService.
995          * 
996          * @param documentTypeService
997          *            the documentTypeService to set
998          */
999         public void setDocumentTypeService(
1000                         final DocumentTypeService documentTypeService) {
1001                 _documentTypeService = documentTypeService;
1002         }
1003
1004         /**
1005          * {@inheritDoc}
1006          * 
1007          * @see org.springframework.context.ResourceLoaderAware#setResourceLoader(org.springframework.core.io.ResourceLoader)
1008          */
1009         @Override
1010         public void setResourceLoader(final ResourceLoader resourceLoader) {
1011                 this._resourceLoader = resourceLoader;
1012         }
1013
1014         /**
1015          * Get resource by means of Spring resource loader.
1016          * 
1017          * @param location
1018          *            the resource location
1019          * @return the resource
1020          */
1021         public Resource getResource(final String location) {
1022                 return _resourceLoader.getResource(location);
1023         }
1024
1025         /**
1026          * Get the config.
1027          * 
1028          * @return the config
1029          */
1030         public Resource getConfig() {
1031                 return _config;
1032         }
1033
1034         /**
1035          * Set the config.
1036          * 
1037          * @param config
1038          *            the config to set
1039          */
1040         public void setConfig(final Resource config) {
1041                 _config = config;
1042         }
1043
1044         /**
1045          * Get the stepsConfigService.
1046          * 
1047          * @return the stepsConfigService
1048          */
1049         public StepsConfigService getStepsConfigService() {
1050                 return _stepsConfigService;
1051         }
1052
1053         /**
1054          * Set the stepsConfigService.
1055          * 
1056          * @param stepsConfigService
1057          *            the stepsConfigService to set
1058          */
1059         public void setStepsConfigService(
1060                         final StepsConfigService stepsConfigService) {
1061                 _stepsConfigService = stepsConfigService;
1062         }
1063 }