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