4 * @author Daniel Brunier-Coulin
5 * @copyright OPEN CASCADE 2012
9 import java.io.FileNotFoundException;
10 import java.io.IOException;
11 import java.sql.SQLException;
12 import java.util.HashMap;
13 import java.util.HashSet;
14 import java.util.Iterator;
15 import java.util.LinkedHashMap;
16 import java.util.List;
17 import java.util.Properties;
19 import java.util.Vector;
21 import javax.xml.parsers.DocumentBuilder;
22 import javax.xml.parsers.DocumentBuilderFactory;
24 import org.apache.log4j.Logger;
25 import org.w3c.dom.NamedNodeMap;
26 import org.w3c.dom.Node;
27 import org.w3c.dom.NodeList;
29 import org.splat.kernel.XDOM;
30 import org.splat.som.ValidationCycle.Actor;
33 public class ProjectSettings {
35 // Non persistent configuration information
36 private Properties reprop; // Repository settings
37 private String pattern; // Pattern of study references
38 private FileNaming naming; // Scheme of file names stored into the repository
39 private String versioning; // Pattern of the presentation of version numbers
40 private Vector<Step> steps; // Ordered list of (transient) study steps
41 private Vector<ValidationCycle> concycles; // Configuration document validation cycles
43 // Temporary attributes initialized from the configuration file for populating the database with object types
44 private LinkedHashMap<String,String> mapuse; // Document type names and uses mapping
45 private Vector<String> context; // Simulation Context type names
46 private Vector<String> kname; // Knowledge Element type names
47 private Vector<NamedNodeMap> flows; // Document flows
48 private Vector<NamedNodeMap> sclass; // Study classifications
51 private static ProjectSettings my = null; // Singleton instance
52 protected final static Logger logger = Logger.getLogger(ProjectSettings.class);
54 protected enum FileNaming { title, encoded, asis }
55 public static class Step {
56 // ------------------------
58 private Class<? extends ProjectElement> level; // Study or Scenario
59 private Set<Class<?>> contents; // Set of Document and/or Knowledge
62 private Step (int number, Class<? extends ProjectElement> level, String path) {
63 this.initialize(number, level, path);
65 private Step (int number, Class<? extends ProjectElement> level, Class<?> contents, String path) {
66 this.initialize(number, level, path);
67 this.contents.add(contents);
69 private void initialize (int number, Class<? extends ProjectElement> level, String path) {
72 this.path = path + "/";
73 this.contents = new HashSet<Class<?>>();
75 public boolean appliesTo (Class<? extends ProjectElement> level) {
76 return (level == this.level);
78 public boolean mayContain (Class<?> type) {
79 return contents.contains(type);
81 public int getNumber () {
84 public String getPath () {
88 public static class ValidationCycle {
89 // -----------------------------------
91 private Actor[] actor;
93 private ValidationCycle () {
94 this.name = "built-in";
95 this.actor = new Actor[] { null, null, null };
97 private ValidationCycle (String name, Actor[] actor) {
101 public String getName () {
104 public Actor[] getActorTypes () {
109 // ==============================================================================================================================
111 // ==============================================================================================================================
113 public static ProjectSettings getMe () {
114 // --------------------------------------
115 if (my == null) my = new ProjectSettings();
118 protected ProjectSettings () {
119 // ----------------------------
120 reprop = new Properties();
121 steps = new Vector<Step>();
124 // ==============================================================================================================================
126 // ==============================================================================================================================
128 public void configure (String filename) throws IOException, SQLException {
129 // ---------------------------------------
130 if (!steps.isEmpty()) return; // Project already configured
132 Database base = Database.getMe();
133 File config = new File(filename);
134 if (config.exists()) {
135 loadCustomization(config);
137 logger.fatal("Could not find the database configuration file \"" + config.getAbsolutePath() + "\"");
138 throw new FileNotFoundException();
140 base.configure(reprop);
141 if (!base.isInitialized()) {
143 //TODO: Move the second part of loadCustomization here
147 public static List<Step> getAllSteps () {
148 // ---------------------------------------
153 * Return the validation cycles of result documents defined in the workflow, ordered by study activities
154 * and ending by the default validation cycle, if defined.
156 * @return the validation cycles of the workflow
158 public static List<ValidationCycle> getAllValidationCycles () {
159 // -------------------------------------------------------------
163 public static FileNaming getFileNamingScheme () {
164 // -----------------------------------------------
168 public static ValidationCycle getNewValidationCycle () {
169 // ------------------------------------------------------
170 return new ValidationCycle();
173 public static String getReferencePattern () {
174 // -------------------------------------------
178 public static String getRevisionPattern () {
179 // ------------------------------------------
180 return my.versioning;
183 public static Step getStep (int number) {
184 // ---------------------------------------
185 for (int i=0; i<my.steps.size(); i++) {
186 Step step = my.steps.get(i);
187 if (step.number == number) return step;
192 public static List<Step> getStepsOf (Class<? extends ProjectElement> level) {
193 // ---------------------------------------------------------------------------
194 Vector<Step> result = new Vector<Step>();
196 for (int i=0; i<my.steps.size(); i++) {
197 Step step = my.steps.get(i);
198 if (step.appliesTo(level)) result.add(step);
203 // ==============================================================================================================================
204 // Protected member function
205 // ==============================================================================================================================
207 protected void initialize () {
208 // ----------------------------
209 createDocumentTypes();
210 createSimulationContextTypes();
211 createKnowledgeElementTypes();
214 // ==============================================================================================================================
215 // Private member function
216 // ==============================================================================================================================
218 private void loadCustomization (File config) {
219 // --------------------------------------------
221 DocumentBuilderFactory dfactory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
222 DocumentBuilder dBuilder = dfactory.newDocumentBuilder();
224 org.w3c.dom.Document conf = dBuilder.parse(config.getPath());
225 HashMap<String, Node> children = XDOM.getNamedChildNodes(conf.getDocumentElement());
227 // Repository tag initializing the reprop attribute
228 Node child = children.get("database");
229 HashMap<String, Node> datag = XDOM.getNamedChildNodes(child);
231 String disk = datag.get("repository").getAttributes().getNamedItem("disk").getNodeValue();
232 if (!disk.endsWith("/")) disk = disk + "/";
233 logger.info("Database root set to " + disk);
234 reprop.setProperty("repository", disk);
236 // Formats tag initializing the reference pattern and date attributes
237 child = children.get("formats");
238 datag = XDOM.getNamedChildNodes(child);
240 NamedNodeMap natr = datag.get("references").getAttributes();
241 pattern = natr.getNamedItem("study").getNodeValue();
243 natr = datag.get("files").getAttributes();
244 naming = FileNaming.valueOf(natr.getNamedItem("name").getNodeValue());
246 natr = datag.get("versions").getAttributes();
247 versioning = natr.getNamedItem("pattern").getNodeValue();
249 // Activities tag initializing the steps and rex attributes
250 child = children.get("activities");
251 NodeList nlist = child.getChildNodes();
252 Vector<NamedNodeMap> flist = new Vector<NamedNodeMap>();
253 Vector<String> resultype = new Vector<String>();
254 Vector<NamedNodeMap> clist = new Vector<NamedNodeMap>();
256 int snum = 1; // Base number of steps
257 for (int i=0; i<nlist.getLength(); i++) {
258 child = nlist.item(i);
259 if (child.getNodeName().equals("scenario")) {
260 NodeList slist = child.getChildNodes();
261 for (int j=0; j<slist.getLength(); j++) {
262 child = slist.item(j);
263 if (!child.getNodeName().equals("step")) continue;
264 HashMap<String, Node> tags = XDOM.getNamedChildNodes(child);
266 natr = tags.get("storage").getAttributes();
267 Step step = new Step(snum, Scenario.class, natr.getNamedItem("path").getNodeValue());
269 // Keeping flow and classification information for eventual later use
270 natr = tags.get("flow").getAttributes();
272 child = natr.getNamedItem("result");
273 if (child != null) resultype.add(child.getNodeValue());
275 child = tags.get("classification");
276 if (child != null) clist.add( child.getAttributes() );
277 else clist.add( null );
279 if (natr.getNamedItem("contents").getNodeValue().equals("knowledge")) {
280 //TODO In a given scenario, only one step must contain knowledges
281 step.contents.add(KnowledgeElement.class);
283 step.contents.add(Document.class);
289 if (!child.getNodeName().equals("step")) continue;
290 HashMap<String, Node> tags = XDOM.getNamedChildNodes(child);
292 natr = tags.get("storage").getAttributes(); // Mandatory information
293 Step step = new Step(snum, Study.class, natr.getNamedItem("path").getNodeValue());
295 // Keeping flow and classification information for eventual later use
296 natr = tags.get("flow").getAttributes();
298 child = natr.getNamedItem("result");
299 if (child != null) resultype.add(child.getNodeValue());
301 child = tags.get("classification"); // Optional information
302 if (child != null) clist.add( child.getAttributes() );
303 else clist.add( null );
305 if (natr.getNamedItem("contents").getNodeValue().equals("knowledge")) {
306 //TODO Error: knowledges must be attached to scenarios
308 step.contents.add(Document.class);
315 child = children.get("validations");
316 concycles = new Vector<ValidationCycle>();
317 datag = XDOM.getNamedChildNodes(child);
319 String[] step = { "review", "approval", "acceptance" };
320 resultype.add("default");
321 for (Iterator<String> i=resultype.iterator(); i.hasNext(); ) {
322 Actor[] actor = { null, null, null };
323 String name = i.next();
324 child = datag.get(name);
325 if (child == null) continue; // Document type not subject of any validation
326 natr = child.getAttributes();
327 for (int j=0; j<step.length; j++) {
328 child = natr.getNamedItem(step[j]);
329 if (child == null) continue; // Validation step not required
330 actor[j] = Actor.valueOf(child.getNodeValue());
332 concycles.add( new ValidationCycle(name, actor) );
334 concycles.add( new ValidationCycle() ); // Adds the built-in validation cycle
336 if (Database.getMe().isInitialized()) return; // No need to load object type definitions as they are already stored
339 child = children.get("documents");
340 nlist = child.getChildNodes();
342 flows = flist; // Kept for later use in document type definition
343 sclass = clist; // Kept for later use in simulation context type definition
344 mapuse = new LinkedHashMap<String,String>();
345 for (int i=0; i<nlist.getLength(); i++) {
346 child = nlist.item(i);
347 if (!child.getNodeName().equals("article")) continue;
349 natr = child.getAttributes();
350 String type = natr.getNamedItem("type").getNodeValue();
352 child = natr.getNamedItem("uses");
353 if (child != null) uses = child.getNodeValue();
354 mapuse.put(type, uses); // Must be added to the map even if no (null) uses
356 // Simulation Contexts tag
357 child = children.get("contexts");
358 nlist = child.getChildNodes();
360 context = new Vector<String>();
361 for (int i=0; i<nlist.getLength(); i++) {
362 child = nlist.item(i);
363 if (!child.getNodeName().equals("article")) continue;
365 context.add(child.getAttributes().getNamedItem("type").getNodeValue());
367 // Knowledge Elements tag
368 child = children.get("knowledges");
369 nlist = child.getChildNodes();
371 kname = new Vector<String>();
372 for (int i=0; i<nlist.getLength(); i++) {
373 child = nlist.item(i);
374 if (!child.getNodeName().equals("article")) continue;
376 kname.add(child.getAttributes().getNamedItem("type").getNodeValue());
379 catch (Exception error) {
380 logger.info("Error in customization", error);
384 private void createDocumentTypes () {
385 // -----------------------------------
386 DocumentType.Properties tprop = new DocumentType.Properties();
387 HashMap<String,Vector<Step>> mapsteps = new HashMap<String,Vector<Step>>();
388 HashMap<String,Step> mapresult = new HashMap<String,Step>();
389 HashMap<String,DocumentType> maptype = new HashMap<String,DocumentType>();
391 Vector<Step> slist = null; // List of Steps to which each document type is valid
392 int snum = 0; // Step number
395 for (Iterator<NamedNodeMap> i=flows.iterator(); i.hasNext(); snum++) {
396 NamedNodeMap flow = i.next();
397 Step step = steps.get(snum);
398 String[] contents = flow.getNamedItem("contents").getNodeValue().split(",");
399 for (int j=0; j<contents.length; j++) {
401 if (!mapuse.containsKey(type)) {
402 logger.warn("Undefined \"" + type + "\" document type.");
404 } slist = mapsteps.get(type);
405 if (slist == null) slist = new Vector<Step>();
407 mapsteps.put(type, slist);
409 Node result = flow.getNamedItem("result");
410 if (result != null) mapresult.put(result.getNodeValue(), step);
413 DocumentType tdoc = null;
414 Set<String> tset = mapuse.keySet();
416 for (Iterator<String> i=tset.iterator(); i.hasNext(); ) {
418 slist = mapsteps.get(type);
419 uses = mapuse.get(type);
420 step = mapresult.get(type);
423 tprop.setName(type).setStep(slist.toArray(new Step[slist.size()]));
425 tdoc = maptype.get(uses);
426 if (tdoc == null) logger.warn("Undefined \"" + uses + "\" document type.");
427 else tprop.setUses(tdoc);
429 if (step != null) tprop.setResult(step);
431 tprop.disableCheck();
432 tdoc = Document.createType(tprop); // Creation of Document Types
434 maptype.put(type, tdoc);
436 } catch (Exception error) {
437 logger.warn("Error creating document types, reason:", error); // Should not happen
441 private void createKnowledgeElementTypes () {
442 // -------------------------------------------
444 KnowledgeElementType ktype = KnowledgeElement.createType("usecase"); // Internal reserved knowledge element type
446 for (Iterator<String> i=kname.iterator(); i.hasNext(); ) {
447 String type = i.next();
449 ktype = KnowledgeElement.createType(type); // Knowledge Elements Types defined in the configuration
452 } catch (Exception error) {
453 logger.warn("Error creating knowledge types, reason:", error); // Should not happen
457 private void createSimulationContextTypes () {
458 // --------------------------------------------
459 HashMap<String,Step> mapstep = new HashMap<String,Step>();
461 for (Iterator<NamedNodeMap> i=sclass.iterator(); i.hasNext(); snum++) {
462 NamedNodeMap clatr = i.next();
463 if (clatr == null) continue;
465 String[] clist = clatr.getNamedItem("context").getNodeValue().split(",");
466 for (int j=0; j<clist.length; j++) {
467 mapstep.put(clist[j], steps.get(snum));
471 SimulationContextType tctex = null;
472 for (Iterator<String> i=context.iterator(); i.hasNext(); ) {
473 String type = i.next();
474 if (!mapstep.containsKey(type)) {
475 logger.warn("Could not find \"" + type + "\" classification. Simulation Context type ignored.");
478 tctex = SimulationContext.createType(type, mapstep.get(type)); // Creation of Simulation Context Types
481 } catch (Exception error) {
482 logger.warn("Error creating context types, reason:", error); // Should not happen