]> SALOME platform Git repositories - tools/siman.git/blob - Workspace/Siman-Common/src/org/splat/service/technical/ProjectSettingsServiceImpl.java
Salome HOME
14e6e66d58e7a01d791636fe656a70450573b36e
[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
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.w3c.dom.NamedNodeMap;
41 import org.w3c.dom.Node;
42 import org.w3c.dom.NodeList;
43
44 /**
45  * SIMAN configuration data service.
46  */
47 public class ProjectSettingsServiceImpl implements ProjectSettingsService {
48
49         /**
50          * The logger for the service.
51          */
52         protected final static Logger LOG = Logger
53                         .getLogger(ProjectSettingsServiceImpl.class);
54
55         // Non persistent configuration information
56         /**
57          * Repository settings.
58          */
59         private transient final Properties _reprop = new Properties();
60         /**
61          * Pattern of study references.
62          */
63         private transient String _pattern;
64         /**
65          * Scheme of file names stored into the repository.
66          */
67         private transient FileNaming _naming;
68         /**
69          * Pattern of the presentation of version numbers.
70          */
71         private transient String _versioning;
72         /**
73          * Ordered list of (transient) study steps.
74          */
75         private transient final List<ProjectSettingsService.Step> _steps = new ArrayList<ProjectSettingsService.Step>();
76         /**
77          * Configuration document validation cycles.
78          */
79         private transient List<ProjectSettingsValidationCycle> _concycles;
80
81         // Temporary attributes initialized from the configuration file for populating the database with object types
82         /**
83          * Document type names and uses mapping.
84          */
85         private transient Map<String, String> _mapuse;
86         /**
87          * Simulation Context type names.
88          */
89         private transient List<String> _context;
90         /**
91          * Knowledge Element type names.
92          */
93         private transient List<String> _kname;
94         /**
95          * Document flows.
96          */
97         private transient List<NamedNodeMap> _flows;
98         /**
99          * Study classifications.
100          */
101         private transient List<NamedNodeMap> _sclass;
102
103         // Other resources
104         /**
105          * Database service to check its version, etc.
106          */
107         private Database _database;
108         /**
109          * Injected simulation context type service.
110          */
111         private SimulationContextTypeService _simulationContextTypeService;
112         /**
113          * Injected knowledge element type service.
114          */
115         private KnowledgeElementTypeService _knowledgeElementTypeService;
116         /**
117          * Injected document type service.
118          */
119         private DocumentTypeService _documentTypeService;
120
121         public enum FileNaming {
122                 title, encoded, asis
123         }
124
125         /**
126          * Validation cycle defined in the XML configuration.
127          */
128         public static class ProjectSettingsValidationCycle {
129                 /**
130                  * Cycle (document) type name.
131                  */
132                 private final String _name;
133                 /**
134                  * Array of cycle actors positions in the organization. TODO: Must be replaced by Roles.
135                  */
136                 private final Actor[] _actor;
137
138                 /**
139                  * Default constructor.
140                  */
141                 private ProjectSettingsValidationCycle() {
142                         this._name = "built-in";
143                         this._actor = new Actor[] { null, null, null };
144                 }
145
146                 /**
147                  * Create a validation cycle definition for the given document type name and actors positions.
148                  * 
149                  * @param name
150                  *            the document type name
151                  * @param actor
152                  *            the array of actors positions
153                  */
154                 private ProjectSettingsValidationCycle(final String name,
155                                 final Actor[] actor) {
156                         this._name = name;
157                         this._actor = actor;
158                 }
159
160                 /**
161                  * The processed document type name.
162                  * 
163                  * @return the document type name
164                  */
165                 public String getName() {
166                         return _name;
167                 }
168
169                 /**
170                  * Get an array of cycle actors positions.
171                  * 
172                  * @return the array of actors positions
173                  * @see org.splat.dal.bo.som.ValidationCycle.Actor
174                  */
175                 public Actor[] getActorTypes() {
176                         return _actor;
177                 }
178         }
179
180         // ==============================================================================================================================
181         // Public functions
182         // ==============================================================================================================================
183
184         /**
185          * Load workflow configuration from the given file. <br/> Create necessary default staff in the database if it is not initialized yet.
186          * 
187          * @param filename
188          *            the workflow configuration file
189          * @throws IOException
190          *             if there is a file reading or index creation problem
191          * @throws SQLException
192          *             if there is a database population problem
193          */
194         public void configure(final String filename) throws IOException,
195                         SQLException {
196                 if (!_steps.isEmpty()) {
197                         return; // Project already configured
198                 }
199
200                 Database base = getDatabase().getCheckedDB();
201                 File config = new File(filename);
202                 if (config.exists()) {
203                         loadCustomization(config);
204                 } else {
205                         LOG.fatal("Could not find the database configuration file \""
206                                         + config.getAbsolutePath() + "\"");
207                         throw new FileNotFoundException();
208                 }
209                 base.configure(_reprop);
210                 if (!base.isInitialized()) {
211                         base.initialize();
212                         initialize(); // Populates the database with all necessary stuff
213                 }
214         }
215
216         /**
217          * Get ordered list of (transient) study steps.
218          * 
219          * @return the list of steps from project settings
220          */
221         public List<ProjectSettingsService.Step> getAllSteps() {
222                 return _steps;
223         }
224
225         /**
226          * Return the validation cycles of result documents defined in the workflow, ordered by study activities and ending by the default
227          * validation cycle, if defined.
228          * 
229          * @return the validation cycles of the workflow
230          */
231         public List<ProjectSettingsValidationCycle> getAllValidationCycles() {
232                 return _concycles;
233         }
234
235         /**
236          * Get file naming scheme setting.
237          * 
238          * @return file naming scheme
239          * @see org.splat.service.technical.ProjectSettingsServiceImpl.FileNaming
240          */
241         public FileNaming getFileNamingScheme() {
242                 return _naming;
243         }
244
245         /**
246          * Get a pattern of study references.
247          * 
248          * @return the reference pattern
249          */
250         public String getReferencePattern() {
251                 return _pattern;
252         }
253
254         /**
255          * Get a pattern of the presentation of version numbers.
256          * 
257          * @return the version numbers presentation pattern
258          */
259         public String getRevisionPattern() {
260                 return _versioning;
261         }
262
263         /**
264          * Get a study step by its sequential number.
265          * 
266          * @param number
267          *            the step number
268          * @return the step
269          */
270         public ProjectSettingsService.Step getStep(final int number) {
271                 ProjectSettingsService.Step res = null;
272                 for (int i = 0; i < _steps.size(); i++) {
273                         ProjectSettingsService.Step step = _steps.get(i);
274                         if (step.getNumber() == number) {
275                                 res = step;
276                                 break;
277                         }
278                 }
279                 return res;
280         }
281
282         /**
283          * Get steps of the given project element (study or scenario).
284          * 
285          * @param level
286          *            the project element (study or scenario)
287          * @return the list of steps
288          */
289         public List<ProjectSettingsService.Step> getStepsOf(
290                         final Class<? extends ProjectElement> level) {
291                 List<ProjectSettingsService.Step> result = new ArrayList<ProjectSettingsService.Step>();
292
293                 for (int i = 0; i < _steps.size(); i++) {
294                         ProjectSettingsService.Step step = _steps.get(i);
295                         if (step.appliesTo(level)) {
296                                 result.add(step);
297                         }
298                 }
299                 return result;
300         }
301
302         /**
303          * Initialize the database: create all necessary default staff defined in the configuration file.
304          */
305         protected void initialize() {
306                 createDocumentTypes();
307                 createSimulationContextTypes();
308                 createKnowledgeElementTypes();
309         }
310
311         // ==============================================================================================================================
312         // Private member function
313         // ==============================================================================================================================
314
315         /**
316          * Read the configuration file and fill transient project settings fields.
317          * 
318          * @param config
319          *            the configuration XML file
320          */
321         private void loadCustomization(final File config) {
322                 try {
323                         DocumentBuilderFactory dfactory = javax.xml.parsers.DocumentBuilderFactory
324                                         .newInstance();
325                         DocumentBuilder dBuilder = dfactory.newDocumentBuilder();
326
327                         org.w3c.dom.Document conf = dBuilder.parse(config.getPath());
328                         HashMap<String, Node> children = XDOM.getNamedChildNodes(conf
329                                         .getDocumentElement());
330
331                         // Repository tag initializing the reprop attribute
332                         Node child = children.get("database");
333                         HashMap<String, Node> datag = XDOM.getNamedChildNodes(child);
334
335                         String disk = datag.get("repository").getAttributes().getNamedItem(
336                                         "disk").getNodeValue();
337                         if (!disk.endsWith("/")) {
338                                 disk = disk + "/";
339                         }
340                         LOG.info("Database root set to " + disk);
341                         _reprop.setProperty("repository", disk);
342
343                         // Formats tag initializing the reference pattern and date attributes
344                         child = children.get("formats");
345                         datag = XDOM.getNamedChildNodes(child);
346
347                         NamedNodeMap natr = datag.get("references").getAttributes();
348                         _pattern = natr.getNamedItem("study").getNodeValue();
349
350                         natr = datag.get("files").getAttributes();
351                         _naming = FileNaming.valueOf(natr.getNamedItem("name")
352                                         .getNodeValue());
353
354                         natr = datag.get("versions").getAttributes();
355                         _versioning = natr.getNamedItem("pattern").getNodeValue();
356
357                         // Activities tag initializing the steps and rex attributes
358                         child = children.get("activities");
359                         NodeList nlist = child.getChildNodes();
360                         List<NamedNodeMap> flist = new ArrayList<NamedNodeMap>();
361                         List<String> resultype = new ArrayList<String>();
362                         List<NamedNodeMap> clist = new ArrayList<NamedNodeMap>();
363
364                         int snum = 1; // Base number of steps
365                         for (int i = 0; i < nlist.getLength(); i++) {
366                                 child = nlist.item(i);
367                                 if (child.getNodeName().equals("scenario")) {
368                                         NodeList slist = child.getChildNodes();
369                                         for (int j = 0; j < slist.getLength(); j++) {
370                                                 child = slist.item(j);
371                                                 if (!child.getNodeName().equals("step")) {
372                                                         continue;
373                                                 }
374                                                 HashMap<String, Node> tags = XDOM
375                                                                 .getNamedChildNodes(child);
376
377                                                 natr = tags.get("storage").getAttributes();
378                                                 ProjectSettingsService.Step step = new ProjectSettingsService.Step(
379                                                                 snum, Scenario.class, natr.getNamedItem("path")
380                                                                                 .getNodeValue());
381
382                                                 // Keeping flow and classification information for eventual later use
383                                                 natr = tags.get("flow").getAttributes();
384                                                 flist.add(natr);
385                                                 child = natr.getNamedItem("result");
386                                                 if (child != null) {
387                                                         resultype.add(child.getNodeValue());
388                                                 }
389
390                                                 child = tags.get("classification");
391                                                 if (child == null) {
392                                                         clist.add(null);
393                                                 } else {
394                                                         clist.add(child.getAttributes());
395                                                 }
396
397                                                 if (natr.getNamedItem("contents").getNodeValue()
398                                                                 .equals("knowledge")) {
399                                                         // TODO In a given scenario, only one step must contain knowledges
400                                                         step._contents.add(KnowledgeElement.class);
401                                                 } else {
402                                                         step._contents.add(Document.class);
403                                                 }
404                                                 _steps.add(step);
405                                                 snum += 1;
406                                         }
407                                 } else {
408                                         if (!child.getNodeName().equals("step")) {
409                                                 continue;
410                                         }
411                                         HashMap<String, Node> tags = XDOM.getNamedChildNodes(child);
412
413                                         natr = tags.get("storage").getAttributes(); // Mandatory information
414                                         ProjectSettingsService.Step step = new ProjectSettingsService.Step(
415                                                         snum, Study.class, natr.getNamedItem("path")
416                                                                         .getNodeValue());
417
418                                         // Keeping flow and classification information for eventual later use
419                                         natr = tags.get("flow").getAttributes();
420                                         flist.add(natr);
421                                         child = natr.getNamedItem("result");
422                                         if (child != null) {
423                                                 resultype.add(child.getNodeValue());
424                                         }
425
426                                         child = tags.get("classification"); // Optional information
427                                         if (child == null) {
428                                                 clist.add(null);
429                                         } else {
430                                                 clist.add(child.getAttributes());
431                                         }
432
433                                         if (natr.getNamedItem("contents").getNodeValue().equals(
434                                                         "knowledge")) {
435                                                 // TODO Error: knowledges must be attached to scenarios
436                                                 LOG.error("Error: knowledges must be attached to scenarios.");
437                                         } else {
438                                                 step._contents.add(Document.class);
439                                         }
440                                         _steps.add(step);
441                                         snum += 1;
442                                 }
443                         }
444                         // Validations tag
445                         child = children.get("validations");
446                         _concycles = new ArrayList<ProjectSettingsValidationCycle>();
447                         datag = XDOM.getNamedChildNodes(child);
448
449                         String[] step = { "review", "approval", "acceptance" };
450                         resultype.add("default");
451                         for (Iterator<String> i = resultype.iterator(); i.hasNext();) {
452                                 Actor[] actor = { null, null, null };
453                                 String name = i.next();
454                                 child = datag.get(name);
455                                 if (child == null) {
456                                         continue; // Document type not subject of any validation
457                                 }
458                                 natr = child.getAttributes();
459                                 for (int j = 0; j < step.length; j++) {
460                                         child = natr.getNamedItem(step[j]);
461                                         if (child == null) {
462                                                 continue; // Validation step not required
463                                         }
464                                         actor[j] = Actor.valueOf(child.getNodeValue());
465                                 }
466                                 _concycles.add(new ProjectSettingsValidationCycle(name, actor));
467                         }
468                         _concycles.add(new ProjectSettingsValidationCycle()); // Adds the built-in validation cycle
469
470                         if (getDatabase().getCheckedDB().isInitialized()) {
471                                 return; // No need to load object type definitions as they are already stored
472                         }
473
474                         // Documents tag
475                         child = children.get("documents");
476                         nlist = child.getChildNodes();
477
478                         _flows = flist; // Kept for later use in document type definition
479                         _sclass = clist; // Kept for later use in simulation context type definition
480                         _mapuse = new LinkedHashMap<String, String>();
481                         for (int i = 0; i < nlist.getLength(); i++) {
482                                 child = nlist.item(i);
483                                 if (!child.getNodeName().equals("article")) {
484                                         continue;
485                                 }
486
487                                 natr = child.getAttributes();
488                                 String type = natr.getNamedItem("type").getNodeValue();
489                                 String uses = null;
490                                 child = natr.getNamedItem("uses");
491                                 if (child != null) {
492                                         uses = child.getNodeValue();
493                                 }
494                                 _mapuse.put(type, uses); // Must be added to the map even if no (null) uses
495                         }
496                         // Simulation Contexts tag
497                         child = children.get("contexts");
498                         nlist = child.getChildNodes();
499
500                         _context = new ArrayList<String>();
501                         for (int i = 0; i < nlist.getLength(); i++) {
502                                 child = nlist.item(i);
503                                 if (!child.getNodeName().equals("article")) {
504                                         continue;
505                                 }
506
507                                 _context.add(child.getAttributes().getNamedItem("type")
508                                                 .getNodeValue());
509                         }
510                         // Knowledge Elements tag
511                         child = children.get("knowledges");
512                         nlist = child.getChildNodes();
513
514                         _kname = new ArrayList<String>();
515                         for (int i = 0; i < nlist.getLength(); i++) {
516                                 child = nlist.item(i);
517                                 if (!child.getNodeName().equals("article")) {
518                                         continue;
519                                 }
520
521                                 _kname.add(child.getAttributes().getNamedItem("type")
522                                                 .getNodeValue());
523                         }
524                 } catch (Exception error) {
525                         LOG.info("Error in customization", error);
526                 }
527         }
528
529         /**
530          * Create in the database document types defined in the custom configuration.
531          */
532         private void createDocumentTypes() {
533                 DocumentType.Properties tprop = new DocumentType.Properties();
534                 Map<String, List<ProjectSettingsService.Step>> mapsteps = new HashMap<String, List<ProjectSettingsService.Step>>();
535                 Map<String, ProjectSettingsService.Step> mapresult = new HashMap<String, ProjectSettingsService.Step>();
536                 Map<String, DocumentType> maptype = new HashMap<String, DocumentType>();
537
538                 List<ProjectSettingsService.Step> slist = null; // List of Steps to which each document type is valid
539                 int snum = 0; // Step number
540                 String type = null;
541                 String uses = null;
542                 for (Iterator<NamedNodeMap> i = _flows.iterator(); i.hasNext(); snum++) {
543                         NamedNodeMap flow = i.next();
544                         ProjectSettingsService.Step step = _steps.get(snum);
545                         String[] contents = flow.getNamedItem("contents").getNodeValue()
546                                         .split(",");
547                         for (int j = 0; j < contents.length; j++) {
548                                 type = contents[j];
549                                 if (!_mapuse.containsKey(type)) {
550                                         LOG.warn("Undefined \"" + type + "\" document type.");
551                                         continue;
552                                 }
553                                 slist = mapsteps.get(type);
554                                 if (slist == null) {
555                                         slist = new ArrayList<ProjectSettingsService.Step>();
556                                 }
557                                 slist.add(step);
558                                 mapsteps.put(type, slist);
559                         }
560                         Node result = flow.getNamedItem("result");
561                         if (result != null) {
562                                 mapresult.put(result.getNodeValue(), step);
563                         }
564                 }
565                 try {
566                         DocumentType tdoc = null;
567                         Set<String> tset = _mapuse.keySet();
568                         ProjectSettingsService.Step step;
569                         for (Iterator<String> i = tset.iterator(); i.hasNext();) {
570                                 type = i.next();
571                                 slist = mapsteps.get(type);
572                                 uses = _mapuse.get(type);
573                                 step = mapresult.get(type);
574
575                                 tprop.clear();
576                                 tprop.setName(type).setStep(
577                                                 slist.toArray(new ProjectSettingsService.Step[slist
578                                                                 .size()]));
579                                 if (uses != null) {
580                                         tdoc = maptype.get(uses);
581                                         if (tdoc == null) {
582                                                 LOG
583                                                                 .warn("Undefined \"" + uses
584                                                                                 + "\" document type.");
585                                         } else {
586                                                 tprop.setUses(tdoc);
587                                         }
588                                 }
589                                 if (step != null) {
590                                         tprop.setResult(step);
591                                 }
592
593                                 tprop.disableCheck();
594                                 tdoc = getDocumentTypeService().createType(tprop); // Creation of Document Types
595                                 getDocumentTypeService().approve(tdoc);
596                                 maptype.put(type, tdoc);
597                         }
598                 } catch (Exception error) {
599                         LOG.warn("Error creating document types, reason:", error); // Should not happen
600                 }
601         }
602
603         /**
604          * Create in the database knowledge types defined in the custom configuration.
605          */
606         private void createKnowledgeElementTypes() {
607                 try {
608                         KnowledgeElementType ktype = getKnowledgeElementTypeService()
609                                         .createType("usecase"); // Internal reserved knowledge element type
610                         getKnowledgeElementTypeService().reserve(ktype);
611                         for (Iterator<String> i = _kname.iterator(); i.hasNext();) {
612                                 String type = i.next();
613
614                                 ktype = getKnowledgeElementTypeService().createType(type); // Knowledge Elements Types defined in the configuration
615                                 getKnowledgeElementTypeService().approve(ktype);
616                         }
617                 } catch (Exception error) {
618                         LOG.warn("Error creating knowledge types, reason:", error); // Should not happen
619                 }
620         }
621
622         /**
623          * Create in the database simulation contexts types defined in the custom configuration.
624          */
625         private void createSimulationContextTypes() {
626                 Map<String, ProjectSettingsService.Step> mapstep = new HashMap<String, ProjectSettingsService.Step>();
627                 int snum = 0;
628                 for (Iterator<NamedNodeMap> i = _sclass.iterator(); i.hasNext(); snum++) {
629                         NamedNodeMap clatr = i.next();
630                         if (clatr == null) {
631                                 continue;
632                         }
633
634                         String[] clist = clatr.getNamedItem("context").getNodeValue()
635                                         .split(",");
636                         for (int j = 0; j < clist.length; j++) {
637                                 mapstep.put(clist[j], _steps.get(snum));
638                         }
639                 }
640                 try {
641                         SimulationContextType tctex = null;
642                         for (Iterator<String> i = _context.iterator(); i.hasNext();) {
643                                 String type = i.next();
644                                 if (!mapstep.containsKey(type)) {
645                                         LOG
646                                                         .warn("Could not find \""
647                                                                         + type
648                                                                         + "\" classification. Simulation Context type ignored.");
649                                         continue;
650                                 }
651                                 tctex = getSimulationContextTypeService().createType(type,
652                                                 mapstep.get(type)); // Creation of Simulation Context Types
653                                 getSimulationContextTypeService().approve(tctex);
654                         }
655                 } catch (Exception error) {
656                         LOG.warn("Error creating context types, reason:", error); // Should not happen
657                 }
658         }
659
660         /**
661          * Get the database.
662          * 
663          * @return the database
664          */
665         public Database getDatabase() {
666                 return _database;
667         }
668
669         /**
670          * Set the database.
671          * 
672          * @param database
673          *            the database to set
674          */
675         public void setDatabase(final Database database) {
676                 _database = database;
677         }
678
679         /**
680          * Get the simulationContextTypeService.
681          * 
682          * @return the simulationContextTypeService
683          */
684         public SimulationContextTypeService getSimulationContextTypeService() {
685                 return _simulationContextTypeService;
686         }
687
688         /**
689          * Set the simulationContextTypeService.
690          * 
691          * @param simulationContextTypeService
692          *            the simulationContextTypeService to set
693          */
694         public void setSimulationContextTypeService(
695                         final SimulationContextTypeService simulationContextTypeService) {
696                 _simulationContextTypeService = simulationContextTypeService;
697         }
698
699         /**
700          * Get the knowledgeElementTypeService.
701          * 
702          * @return the knowledgeElementTypeService
703          */
704         public KnowledgeElementTypeService getKnowledgeElementTypeService() {
705                 return _knowledgeElementTypeService;
706         }
707
708         /**
709          * Set the knowledgeElementTypeService.
710          * 
711          * @param knowledgeElementTypeService
712          *            the knowledgeElementTypeService to set
713          */
714         public void setKnowledgeElementTypeService(
715                         final KnowledgeElementTypeService knowledgeElementTypeService) {
716                 _knowledgeElementTypeService = knowledgeElementTypeService;
717         }
718
719         /**
720          * Get the documentTypeService.
721          * 
722          * @return the documentTypeService
723          */
724         public DocumentTypeService getDocumentTypeService() {
725                 return _documentTypeService;
726         }
727
728         /**
729          * Set the documentTypeService.
730          * 
731          * @param documentTypeService
732          *            the documentTypeService to set
733          */
734         public void setDocumentTypeService(
735                         final DocumentTypeService documentTypeService) {
736                 _documentTypeService = documentTypeService;
737         }
738 }