Salome HOME
Wrong logger creation is fixed.
[tools/siman.git] / Workspace / Siman-Common / src / org / splat / service / technical / ProjectSettingsServiceImpl.java
1 package org.splat.service.technical;
2 /**
3  * 
4  * @author    Daniel Brunier-Coulin
5  * @copyright OPEN CASCADE 2012
6  */
7
8 import java.io.File;
9 import java.io.FileNotFoundException;
10 import java.io.IOException;
11 import java.sql.SQLException;
12 import java.util.HashMap;
13 import java.util.Iterator;
14 import java.util.LinkedHashMap;
15 import java.util.List;
16 import java.util.Properties;
17 import java.util.Set;
18 import java.util.Vector;
19
20 import javax.xml.parsers.DocumentBuilder;
21 import javax.xml.parsers.DocumentBuilderFactory;
22
23 import org.apache.log4j.Logger;
24 import org.w3c.dom.NamedNodeMap;
25 import org.w3c.dom.Node;
26 import org.w3c.dom.NodeList;
27
28 import org.splat.dal.bo.som.Document;
29 import org.splat.dal.bo.som.DocumentType;
30 import org.splat.dal.bo.som.KnowledgeElement;
31 import org.splat.dal.bo.som.KnowledgeElementType;
32 import org.splat.dal.bo.som.ProjectElement;
33 import org.splat.dal.bo.som.Scenario;
34 import org.splat.dal.bo.som.SimulationContext;
35 import org.splat.dal.bo.som.SimulationContextType;
36 import org.splat.dal.bo.som.Study;
37 import org.splat.dal.bo.som.ValidationCycle.Actor;
38 import org.splat.dal.dao.som.Database;
39 import org.splat.manox.XDOM;
40
41
42 public class ProjectSettingsServiceImpl implements ProjectSettingsService {
43
44 //  Non persistent configuration information
45         private  Properties                            reprop;       // Repository settings
46         private  String                                pattern;      // Pattern of study references
47         private  FileNaming                            naming;       // Scheme of file names stored into the repository
48         private  String                                versioning;   // Pattern of the presentation of version numbers 
49         private  Vector<ProjectSettingsService.Step>                          steps;        // Ordered list of (transient) study steps
50         private  Vector<ProjectSettingsValidationCycle>               concycles;    // Configuration document validation cycles
51
52 //  Temporary attributes initialized from the configuration file for populating the database with object types
53     private  LinkedHashMap<String,String>          mapuse;       // Document type names and uses mapping
54     private  Vector<String>                        context;      // Simulation Context type names
55     private  Vector<String>                        kname;        // Knowledge Element type names
56     private  Vector<NamedNodeMap>                  flows;        // Document flows
57     private  Vector<NamedNodeMap>                  sclass;       // Study classifications
58
59 //  Other resources
60         private         static ProjectSettingsServiceImpl  my     = null;       // Singleton instance
61         private Database _database;
62     protected final static Logger           logger = Logger.getLogger(ProjectSettingsServiceImpl.class);
63
64     public enum FileNaming { title, encoded, asis }
65         public static class ProjectSettingsValidationCycle {
66 //  -----------------------------------
67       private String  name;
68       private Actor[] actor;
69
70       private ProjectSettingsValidationCycle () {
71         this.name  = "built-in";
72         this.actor = new Actor[] { null, null, null };
73       }
74       private ProjectSettingsValidationCycle (String name, Actor[] actor) {
75         this.name  = name;
76         this.actor = actor;
77       }
78       public String getName () {
79         return name;
80       }
81       public Actor[] getActorTypes () {
82         return actor;
83       }
84     }
85
86 //  ==============================================================================================================================
87 //  Construction
88 //  ==============================================================================================================================
89
90     public static ProjectSettingsServiceImpl getMe () {
91 //  --------------------------------------
92       if (my == null) my = new ProjectSettingsServiceImpl();
93       return my;
94     }
95         protected ProjectSettingsServiceImpl () {
96 //  ----------------------------
97           reprop = new Properties();
98       steps  = new Vector<ProjectSettingsService.Step>();
99         }       
100     
101 //  ==============================================================================================================================
102 //  Public functions
103 //  ==============================================================================================================================
104
105         public void configure (String filename) throws IOException, SQLException {
106 //  ---------------------------------------
107       if (!steps.isEmpty()) return;       // Project already configured
108
109       Database base   = getDatabase().getMe();
110           File     config = new File(filename);
111           if  (config.exists()) {
112         loadCustomization(config);
113           } else {
114         logger.fatal("Could not find the database configuration file \"" + config.getAbsolutePath() + "\"");
115         throw new FileNotFoundException();
116           }
117           base.configure(reprop);
118       if (!base.isInitialized()) {
119         base.initialize();
120         initialize();   // Populates the database with all necessary stuff
121       }
122         }
123
124     public List<ProjectSettingsService.Step> getAllSteps () {
125 //  ---------------------------------------
126       return steps;
127     }
128
129 /**
130  * Return the validation cycles of result documents defined in the workflow, ordered by study activities
131  * and ending by the default validation cycle, if defined.
132  * 
133  * @return the validation cycles of the workflow
134  */
135     public static List<ProjectSettingsValidationCycle> getAllValidationCycles () {
136 //  -------------------------------------------------------------
137       return my.concycles;
138     }
139
140     public FileNaming getFileNamingScheme () {
141 //  -----------------------------------------------
142       return naming;
143     }
144
145     public static ProjectSettingsValidationCycle getNewValidationCycle () {
146 //  ------------------------------------------------------
147       return  new ProjectSettingsValidationCycle();
148     }
149
150     public String getReferencePattern () {
151       return pattern;
152     }
153
154     public String getRevisionPattern () {
155 //  ------------------------------------------
156       return versioning;
157     }
158
159     public static ProjectSettingsService.Step getStep (int number) {
160 //  ---------------------------------------
161       for (int i=0; i<my.steps.size(); i++) {
162         ProjectSettingsService.Step step = my.steps.get(i);
163         if  (step.number == number)  return step;
164       }
165       return null;
166     }
167
168         public List<ProjectSettingsService.Step> getStepsOf (Class<? extends ProjectElement> level) {
169 //  ---------------------------------------------------------------------------
170       Vector<ProjectSettingsService.Step> result = new Vector<ProjectSettingsService.Step>();
171       
172       for (int i=0; i<steps.size(); i++) {
173         ProjectSettingsService.Step step = steps.get(i);
174         if  (step.appliesTo(level)) result.add(step);         
175       }
176       return result;
177     }
178
179 //  ==============================================================================================================================
180 //  Protected member function
181 //  ==============================================================================================================================
182
183     public void initialize () {
184 //  ----------------------------
185       createDocumentTypes();
186       createSimulationContextTypes();
187       createKnowledgeElementTypes();
188     }
189
190 //  ==============================================================================================================================
191 //  Private member function
192 //  ==============================================================================================================================
193     
194     private void loadCustomization (File config) {
195 //  --------------------------------------------
196       try {
197         DocumentBuilderFactory dfactory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
198         DocumentBuilder        dBuilder = dfactory.newDocumentBuilder();
199         
200         org.w3c.dom.Document   conf     = dBuilder.parse(config.getPath());
201         HashMap<String, Node>  children = XDOM.getNamedChildNodes(conf.getDocumentElement());
202
203 //      Repository tag initializing the reprop attribute
204         Node                   child = children.get("database");
205         HashMap<String, Node>  datag = XDOM.getNamedChildNodes(child);
206
207         String disk = datag.get("repository").getAttributes().getNamedItem("disk").getNodeValue();
208         if (!disk.endsWith("/")) disk = disk + "/";
209         logger.info("Database root set to " + disk);
210         reprop.setProperty("repository", disk);
211
212 //      Formats tag initializing the reference pattern and date attributes
213         child = children.get("formats");
214         datag = XDOM.getNamedChildNodes(child);
215
216         NamedNodeMap natr = datag.get("references").getAttributes();
217         pattern    = natr.getNamedItem("study").getNodeValue();
218         
219         natr       = datag.get("files").getAttributes();
220         naming     = FileNaming.valueOf(natr.getNamedItem("name").getNodeValue());
221         
222         natr       = datag.get("versions").getAttributes();
223         versioning = natr.getNamedItem("pattern").getNodeValue();
224
225 //      Activities tag initializing the steps and rex attributes
226                                child     = children.get("activities");
227         NodeList               nlist     = child.getChildNodes();
228         Vector<NamedNodeMap>   flist     = new Vector<NamedNodeMap>();
229         Vector<String>         resultype = new Vector<String>();
230         Vector<NamedNodeMap>   clist     = new Vector<NamedNodeMap>();
231
232         int snum = 1;                                        // Base number of steps
233         for (int i=0; i<nlist.getLength(); i++) {
234           child = nlist.item(i);
235           if (child.getNodeName().equals("scenario")) {
236                 NodeList slist = child.getChildNodes();
237             for (int j=0; j<slist.getLength(); j++) {
238               child = slist.item(j);
239               if (!child.getNodeName().equals("step")) continue;
240               HashMap<String, Node>  tags = XDOM.getNamedChildNodes(child);
241
242               natr = tags.get("storage").getAttributes();
243               ProjectSettingsService.Step step = new ProjectSettingsService.Step(snum, Scenario.class, natr.getNamedItem("path").getNodeValue());
244
245 //            Keeping flow and classification information for eventual later use
246               natr = tags.get("flow").getAttributes();
247               flist.add(natr);              
248               child = natr.getNamedItem("result");
249               if (child != null) resultype.add(child.getNodeValue());
250
251               child = tags.get("classification");
252               if (child != null) clist.add( child.getAttributes() );
253               else               clist.add( null );
254
255               if (natr.getNamedItem("contents").getNodeValue().equals("knowledge")) {
256 //TODO            In a given scenario, only one step must contain knowledges
257                   step.contents.add(KnowledgeElement.class);
258               } else {
259                 step.contents.add(Document.class);
260               }
261               steps.add(step);
262               snum += 1;
263             }
264           } else {
265             if (!child.getNodeName().equals("step")) continue;
266             HashMap<String, Node>  tags = XDOM.getNamedChildNodes(child);
267
268             natr = tags.get("storage").getAttributes();      // Mandatory information
269             ProjectSettingsService.Step step = new ProjectSettingsService.Step(snum, Study.class, natr.getNamedItem("path").getNodeValue());
270
271 //          Keeping flow and classification information for eventual later use
272             natr = tags.get("flow").getAttributes();
273             flist.add(natr);              
274             child = natr.getNamedItem("result");
275             if (child != null) resultype.add(child.getNodeValue());
276
277             child = tags.get("classification");              // Optional information
278             if (child != null) clist.add( child.getAttributes() );
279             else               clist.add( null );
280
281             if (natr.getNamedItem("contents").getNodeValue().equals("knowledge")) {
282 //TODO        Error: knowledges must be attached to scenarios
283             } else {
284               step.contents.add(Document.class);
285             }
286             steps.add(step);
287             snum += 1;
288           }
289         }
290 //      Validations tag
291         child     = children.get("validations");
292         concycles = new Vector<ProjectSettingsValidationCycle>();
293         datag     = XDOM.getNamedChildNodes(child);
294
295         String[]  step   = { "review", "approval", "acceptance" };
296         resultype.add("default");
297         for (Iterator<String> i=resultype.iterator(); i.hasNext(); ) {
298           Actor[] actor = {  null,     null,       null        };
299           String  name  = i.next();
300           child = datag.get(name);
301           if (child == null) continue;                        // Document type not subject of any validation
302           natr = child.getAttributes();
303           for (int j=0; j<step.length; j++) {
304             child = natr.getNamedItem(step[j]);
305             if (child == null) continue;                      // Validation step not required
306             actor[j] = Actor.valueOf(child.getNodeValue());
307           }
308           concycles.add( new ProjectSettingsValidationCycle(name, actor) );
309         }
310         concycles.add( new ProjectSettingsValidationCycle() );               // Adds the built-in validation cycle
311
312         if (getDatabase().getMe().isInitialized()) return;         // No need to load object type definitions as they are already stored
313
314 //      Documents tag
315         child  = children.get("documents");
316             nlist  = child.getChildNodes();
317
318             flows  = flist;             // Kept for later use in document type definition
319             sclass = clist;             // Kept for later use in simulation context type definition
320         mapuse = new LinkedHashMap<String,String>();
321         for (int i=0; i<nlist.getLength(); i++) {
322           child = nlist.item(i);
323           if (!child.getNodeName().equals("article")) continue;
324
325                        natr = child.getAttributes();
326           String       type = natr.getNamedItem("type").getNodeValue();
327           String       uses = null;
328           child = natr.getNamedItem("uses");
329           if (child != null) uses = child.getNodeValue();
330           mapuse.put(type, uses);   // Must be added to the map even if no (null) uses
331         }
332 //      Simulation Contexts tag
333         child  = children.get("contexts");
334             nlist  = child.getChildNodes();
335
336             context  = new Vector<String>();
337         for (int i=0; i<nlist.getLength(); i++) {
338           child = nlist.item(i);
339           if (!child.getNodeName().equals("article")) continue;
340           
341           context.add(child.getAttributes().getNamedItem("type").getNodeValue());
342         }
343 //      Knowledge Elements tag
344         child  = children.get("knowledges");
345             nlist  = child.getChildNodes();
346
347             kname  = new Vector<String>();
348         for (int i=0; i<nlist.getLength(); i++) {
349           child = nlist.item(i);
350           if (!child.getNodeName().equals("article")) continue;
351           
352           kname.add(child.getAttributes().getNamedItem("type").getNodeValue());
353         }
354       }
355       catch (Exception error) {
356                 logger.info("Error in customization", error);
357       }
358     }
359
360     private void createDocumentTypes () {
361 //  -----------------------------------
362       DocumentType.Properties       tprop     = new DocumentType.Properties();
363       HashMap<String,Vector<ProjectSettingsService.Step>>  mapsteps  = new HashMap<String,Vector<ProjectSettingsService.Step>>();
364       HashMap<String,ProjectSettingsService.Step>          mapresult = new HashMap<String,ProjectSettingsService.Step>();
365       HashMap<String,DocumentType>  maptype   = new HashMap<String,DocumentType>();
366         
367       Vector<ProjectSettingsService.Step> slist = null;     // List of Steps to which each document type is valid
368       int          snum  = 0;        // Step number
369       String       type  = null;
370       String       uses  = null;
371       for (Iterator<NamedNodeMap> i=flows.iterator(); i.hasNext(); snum++) {
372             NamedNodeMap    flow     = i.next();
373             ProjectSettingsService.Step            step     = steps.get(snum);
374         String[]        contents = flow.getNamedItem("contents").getNodeValue().split(",");
375         for (int j=0; j<contents.length; j++) {
376               type = contents[j];
377           if (!mapuse.containsKey(type)) {
378             logger.warn("Undefined \"" + type + "\" document type.");
379             continue;
380           }                  slist = mapsteps.get(type);
381           if (slist == null) slist = new Vector<ProjectSettingsService.Step>();
382           slist.add(step);
383           mapsteps.put(type, slist);
384         }
385         Node result = flow.getNamedItem("result");
386         if  (result != null)  mapresult.put(result.getNodeValue(), step);
387       }
388       try {
389         DocumentType tdoc = null;
390         Set<String>  tset = mapuse.keySet();
391         ProjectSettingsService.Step         step;
392         for (Iterator<String> i=tset.iterator(); i.hasNext(); ) {
393           type  = i.next();
394           slist = mapsteps.get(type);
395           uses  = mapuse.get(type);
396           step  = mapresult.get(type);
397
398           tprop.clear();
399           tprop.setName(type).setStep(slist.toArray(new ProjectSettingsService.Step[slist.size()]));
400           if (uses != null) {
401                 tdoc = maptype.get(uses);
402                 if (tdoc == null) logger.warn("Undefined \"" + uses + "\" document type.");
403                 else              tprop.setUses(tdoc);
404           }
405           if (step != null)   tprop.setResult(step);
406
407           tprop.disableCheck();
408           tdoc = Document.createType(tprop);                                  // Creation of Document Types
409           tdoc.approve();
410           maptype.put(type, tdoc);
411         }
412       } catch (Exception error) {
413         logger.warn("Error creating document types, reason:", error);         // Should not happen
414       }
415     }
416
417     private void createKnowledgeElementTypes () {
418 //  -------------------------------------------
419       try {
420         KnowledgeElementType ktype = KnowledgeElement.createType("usecase");  // Internal reserved knowledge element type
421         ktype.reserve();
422         for (Iterator<String> i=kname.iterator(); i.hasNext(); ) {
423           String  type = i.next();
424
425           ktype = KnowledgeElement.createType(type);                          // Knowledge Elements Types defined in the configuration
426           ktype.approve();
427         }
428       } catch (Exception error) {
429         logger.warn("Error creating knowledge types, reason:", error);        // Should not happen
430       }
431     }
432
433     private void createSimulationContextTypes () {
434 //  --------------------------------------------
435       HashMap<String,ProjectSettingsService.Step>  mapstep = new HashMap<String,ProjectSettingsService.Step>();
436       int snum = 0;
437       for (Iterator<NamedNodeMap> i=sclass.iterator(); i.hasNext(); snum++) {
438         NamedNodeMap clatr = i.next();
439         if (clatr == null) continue;
440
441         String[]        clist = clatr.getNamedItem("context").getNodeValue().split(",");
442         for (int j=0; j<clist.length; j++) {
443           mapstep.put(clist[j], steps.get(snum));
444         }
445       }
446       try {
447         SimulationContextType tctex = null;
448         for (Iterator<String> i=context.iterator(); i.hasNext(); ) {
449           String type = i.next();
450               if (!mapstep.containsKey(type)) {
451             logger.warn("Could not find \"" + type + "\" classification. Simulation Context type ignored.");
452             continue;
453               }
454               tctex = SimulationContext.createType(type, mapstep.get(type));   // Creation of Simulation Context Types
455               tctex.approve();
456         }
457       } catch (Exception error) {
458         logger.warn("Error creating context types, reason:", error);       // Should not happen
459       }
460     }
461         /**
462          * Get the database.
463          * @return the database
464          */
465         public Database getDatabase() {
466                 return _database;
467         }
468         /**
469          * Set the database.
470          * @param database the database to set
471          */
472         public void setDatabase(Database database) {
473                 _database = database;
474         }
475 }