1 package org.splat.service.technical;
5 * @author Daniel Brunier-Coulin
6 * @copyright OPEN CASCADE 2012
10 import java.io.FileNotFoundException;
11 import java.io.IOException;
12 import java.sql.SQLException;
13 import java.util.HashMap;
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.dal.bo.som.Document;
30 import org.splat.dal.bo.som.DocumentType;
31 import org.splat.dal.bo.som.KnowledgeElement;
32 import org.splat.dal.bo.som.KnowledgeElementType;
33 import org.splat.dal.bo.som.ProjectElement;
34 import org.splat.dal.bo.som.Scenario;
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 import org.splat.service.DocumentTypeService;
41 import org.splat.service.KnowledgeElementTypeService;
42 import org.splat.service.SimulationContextTypeService;
44 public class ProjectSettingsServiceImpl implements ProjectSettingsService {
47 * The logger for the service.
49 protected final static Logger logger = Logger
50 .getLogger(ProjectSettingsServiceImpl.class);
52 // Non persistent configuration information
53 private Properties reprop; // Repository settings
54 private String pattern; // Pattern of study references
55 private FileNaming naming; // Scheme of file names stored into the repository
56 private String versioning; // Pattern of the presentation of version numbers
57 private Vector<ProjectSettingsService.Step> steps; // Ordered list of (transient) study steps
58 private Vector<ProjectSettingsValidationCycle> concycles; // Configuration document validation cycles
60 // Temporary attributes initialized from the configuration file for populating the database with object types
61 private LinkedHashMap<String, String> mapuse; // Document type names and uses mapping
62 private Vector<String> context; // Simulation Context type names
63 private Vector<String> kname; // Knowledge Element type names
64 private Vector<NamedNodeMap> flows; // Document flows
65 private Vector<NamedNodeMap> sclass; // Study classifications
68 private static ProjectSettingsServiceImpl my = null; // Singleton instance
69 private Database _database;
71 * Injected simulation context type service.
73 private SimulationContextTypeService _simulationContextTypeService;
75 * Injected knowledge element type service.
77 private KnowledgeElementTypeService _knowledgeElementTypeService;
79 * Injected document type service.
81 private DocumentTypeService _documentTypeService;
83 public enum FileNaming {
87 public static class ProjectSettingsValidationCycle {
88 // -----------------------------------
90 private Actor[] actor;
92 private ProjectSettingsValidationCycle() {
93 this.name = "built-in";
94 this.actor = new Actor[] { null, null, null };
97 private ProjectSettingsValidationCycle(String name, Actor[] actor) {
102 public String getName() {
106 public Actor[] getActorTypes() {
111 // ==============================================================================================================================
113 // ==============================================================================================================================
114 protected ProjectSettingsServiceImpl() {
115 // ----------------------------
116 reprop = new Properties();
117 steps = new Vector<ProjectSettingsService.Step>();
121 // ==============================================================================================================================
123 // ==============================================================================================================================
125 public void configure(String filename) throws IOException, SQLException {
126 // ---------------------------------------
127 if (!steps.isEmpty())
128 return; // Project already configured
130 Database base = getDatabase().getCheckedDB();
131 File config = new File(filename);
132 if (config.exists()) {
133 loadCustomization(config);
135 logger.fatal("Could not find the database configuration file \""
136 + config.getAbsolutePath() + "\"");
137 throw new FileNotFoundException();
139 base.configure(reprop);
140 if (!base.isInitialized()) {
142 initialize(); // Populates the database with all necessary stuff
146 public List<ProjectSettingsService.Step> getAllSteps() {
147 // ---------------------------------------
152 * Return the validation cycles of result documents defined in the workflow, ordered by study activities and ending by the default
153 * validation cycle, if defined.
155 * @return the validation cycles of the workflow
157 public static List<ProjectSettingsValidationCycle> getAllValidationCycles() {
158 // -------------------------------------------------------------
162 public FileNaming getFileNamingScheme() {
163 // -----------------------------------------------
167 public static ProjectSettingsValidationCycle getNewValidationCycle() {
168 // ------------------------------------------------------
169 return new ProjectSettingsValidationCycle();
172 public String getReferencePattern() {
176 public String getRevisionPattern() {
177 // ------------------------------------------
181 public static ProjectSettingsService.Step getStep(int number) {
182 // ---------------------------------------
183 for (int i = 0; i < my.steps.size(); i++) {
184 ProjectSettingsService.Step step = my.steps.get(i);
185 if (step.number == number)
191 public List<ProjectSettingsService.Step> getStepsOf(
192 Class<? extends ProjectElement> level) {
193 // ---------------------------------------------------------------------------
194 Vector<ProjectSettingsService.Step> result = new Vector<ProjectSettingsService.Step>();
196 for (int i = 0; i < steps.size(); i++) {
197 ProjectSettingsService.Step step = steps.get(i);
198 if (step.appliesTo(level))
204 // ==============================================================================================================================
205 // Protected member function
206 // ==============================================================================================================================
208 public void initialize() {
209 // ----------------------------
210 createDocumentTypes();
211 createSimulationContextTypes();
212 createKnowledgeElementTypes();
215 // ==============================================================================================================================
216 // Private member function
217 // ==============================================================================================================================
219 private void loadCustomization(File config) {
220 // --------------------------------------------
222 DocumentBuilderFactory dfactory = javax.xml.parsers.DocumentBuilderFactory
224 DocumentBuilder dBuilder = dfactory.newDocumentBuilder();
226 org.w3c.dom.Document conf = dBuilder.parse(config.getPath());
227 HashMap<String, Node> children = XDOM.getNamedChildNodes(conf
228 .getDocumentElement());
230 // Repository tag initializing the reprop attribute
231 Node child = children.get("database");
232 HashMap<String, Node> datag = XDOM.getNamedChildNodes(child);
234 String disk = datag.get("repository").getAttributes().getNamedItem(
235 "disk").getNodeValue();
236 if (!disk.endsWith("/"))
238 logger.info("Database root set to " + disk);
239 reprop.setProperty("repository", disk);
241 // Formats tag initializing the reference pattern and date attributes
242 child = children.get("formats");
243 datag = XDOM.getNamedChildNodes(child);
245 NamedNodeMap natr = datag.get("references").getAttributes();
246 pattern = natr.getNamedItem("study").getNodeValue();
248 natr = datag.get("files").getAttributes();
249 naming = FileNaming.valueOf(natr.getNamedItem("name")
252 natr = datag.get("versions").getAttributes();
253 versioning = natr.getNamedItem("pattern").getNodeValue();
255 // Activities tag initializing the steps and rex attributes
256 child = children.get("activities");
257 NodeList nlist = child.getChildNodes();
258 Vector<NamedNodeMap> flist = new Vector<NamedNodeMap>();
259 Vector<String> resultype = new Vector<String>();
260 Vector<NamedNodeMap> clist = new Vector<NamedNodeMap>();
262 int snum = 1; // Base number of steps
263 for (int i = 0; i < nlist.getLength(); i++) {
264 child = nlist.item(i);
265 if (child.getNodeName().equals("scenario")) {
266 NodeList slist = child.getChildNodes();
267 for (int j = 0; j < slist.getLength(); j++) {
268 child = slist.item(j);
269 if (!child.getNodeName().equals("step"))
271 HashMap<String, Node> tags = XDOM
272 .getNamedChildNodes(child);
274 natr = tags.get("storage").getAttributes();
275 ProjectSettingsService.Step step = new ProjectSettingsService.Step(
276 snum, Scenario.class, natr.getNamedItem("path")
279 // Keeping flow and classification information for eventual later use
280 natr = tags.get("flow").getAttributes();
282 child = natr.getNamedItem("result");
284 resultype.add(child.getNodeValue());
286 child = tags.get("classification");
288 clist.add(child.getAttributes());
292 if (natr.getNamedItem("contents").getNodeValue()
293 .equals("knowledge")) {
294 // TODO In a given scenario, only one step must contain knowledges
295 step.contents.add(KnowledgeElement.class);
297 step.contents.add(Document.class);
303 if (!child.getNodeName().equals("step"))
305 HashMap<String, Node> tags = XDOM.getNamedChildNodes(child);
307 natr = tags.get("storage").getAttributes(); // Mandatory information
308 ProjectSettingsService.Step step = new ProjectSettingsService.Step(
309 snum, Study.class, natr.getNamedItem("path")
312 // Keeping flow and classification information for eventual later use
313 natr = tags.get("flow").getAttributes();
315 child = natr.getNamedItem("result");
317 resultype.add(child.getNodeValue());
319 child = tags.get("classification"); // Optional information
321 clist.add(child.getAttributes());
325 if (natr.getNamedItem("contents").getNodeValue().equals(
327 // TODO Error: knowledges must be attached to scenarios
329 step.contents.add(Document.class);
336 child = children.get("validations");
337 concycles = new Vector<ProjectSettingsValidationCycle>();
338 datag = XDOM.getNamedChildNodes(child);
340 String[] step = { "review", "approval", "acceptance" };
341 resultype.add("default");
342 for (Iterator<String> i = resultype.iterator(); i.hasNext();) {
343 Actor[] actor = { null, null, null };
344 String name = i.next();
345 child = datag.get(name);
347 continue; // Document type not subject of any validation
348 natr = child.getAttributes();
349 for (int j = 0; j < step.length; j++) {
350 child = natr.getNamedItem(step[j]);
352 continue; // Validation step not required
353 actor[j] = Actor.valueOf(child.getNodeValue());
355 concycles.add(new ProjectSettingsValidationCycle(name, actor));
357 concycles.add(new ProjectSettingsValidationCycle()); // Adds the built-in validation cycle
359 if (getDatabase().getCheckedDB().isInitialized())
360 return; // No need to load object type definitions as they are already stored
363 child = children.get("documents");
364 nlist = child.getChildNodes();
366 flows = flist; // Kept for later use in document type definition
367 sclass = clist; // Kept for later use in simulation context type definition
368 mapuse = new LinkedHashMap<String, String>();
369 for (int i = 0; i < nlist.getLength(); i++) {
370 child = nlist.item(i);
371 if (!child.getNodeName().equals("article"))
374 natr = child.getAttributes();
375 String type = natr.getNamedItem("type").getNodeValue();
377 child = natr.getNamedItem("uses");
379 uses = child.getNodeValue();
380 mapuse.put(type, uses); // Must be added to the map even if no (null) uses
382 // Simulation Contexts tag
383 child = children.get("contexts");
384 nlist = child.getChildNodes();
386 context = new Vector<String>();
387 for (int i = 0; i < nlist.getLength(); i++) {
388 child = nlist.item(i);
389 if (!child.getNodeName().equals("article"))
392 context.add(child.getAttributes().getNamedItem("type")
395 // Knowledge Elements tag
396 child = children.get("knowledges");
397 nlist = child.getChildNodes();
399 kname = new Vector<String>();
400 for (int i = 0; i < nlist.getLength(); i++) {
401 child = nlist.item(i);
402 if (!child.getNodeName().equals("article"))
405 kname.add(child.getAttributes().getNamedItem("type")
408 } catch (Exception error) {
409 logger.info("Error in customization", error);
413 private void createDocumentTypes() {
414 // -----------------------------------
415 DocumentType.Properties tprop = new DocumentType.Properties();
416 HashMap<String, Vector<ProjectSettingsService.Step>> mapsteps = new HashMap<String, Vector<ProjectSettingsService.Step>>();
417 HashMap<String, ProjectSettingsService.Step> mapresult = new HashMap<String, ProjectSettingsService.Step>();
418 HashMap<String, DocumentType> maptype = new HashMap<String, DocumentType>();
420 Vector<ProjectSettingsService.Step> slist = null; // List of Steps to which each document type is valid
421 int snum = 0; // Step number
424 for (Iterator<NamedNodeMap> i = flows.iterator(); i.hasNext(); snum++) {
425 NamedNodeMap flow = i.next();
426 ProjectSettingsService.Step step = steps.get(snum);
427 String[] contents = flow.getNamedItem("contents").getNodeValue()
429 for (int j = 0; j < contents.length; j++) {
431 if (!mapuse.containsKey(type)) {
432 logger.warn("Undefined \"" + type + "\" document type.");
435 slist = mapsteps.get(type);
437 slist = new Vector<ProjectSettingsService.Step>();
439 mapsteps.put(type, slist);
441 Node result = flow.getNamedItem("result");
443 mapresult.put(result.getNodeValue(), step);
446 DocumentType tdoc = null;
447 Set<String> tset = mapuse.keySet();
448 ProjectSettingsService.Step step;
449 for (Iterator<String> i = tset.iterator(); i.hasNext();) {
451 slist = mapsteps.get(type);
452 uses = mapuse.get(type);
453 step = mapresult.get(type);
456 tprop.setName(type).setStep(
457 slist.toArray(new ProjectSettingsService.Step[slist
460 tdoc = maptype.get(uses);
463 .warn("Undefined \"" + uses
464 + "\" document type.");
469 tprop.setResult(step);
471 tprop.disableCheck();
472 tdoc = getDocumentTypeService().createType(tprop); // Creation of Document Types
473 getDocumentTypeService().approve(tdoc);
474 maptype.put(type, tdoc);
476 } catch (Exception error) {
477 logger.warn("Error creating document types, reason:", error); // Should not happen
481 private void createKnowledgeElementTypes() {
482 // -------------------------------------------
484 KnowledgeElementType ktype = getKnowledgeElementTypeService()
485 .createType("usecase"); // Internal reserved knowledge element type
486 getKnowledgeElementTypeService().reserve(ktype);
487 for (Iterator<String> i = kname.iterator(); i.hasNext();) {
488 String type = i.next();
490 ktype = getKnowledgeElementTypeService().createType(type); // Knowledge Elements Types defined in the configuration
491 getKnowledgeElementTypeService().approve(ktype);
493 } catch (Exception error) {
494 logger.warn("Error creating knowledge types, reason:", error); // Should not happen
498 private void createSimulationContextTypes() {
499 // --------------------------------------------
500 HashMap<String, ProjectSettingsService.Step> mapstep = new HashMap<String, ProjectSettingsService.Step>();
502 for (Iterator<NamedNodeMap> i = sclass.iterator(); i.hasNext(); snum++) {
503 NamedNodeMap clatr = i.next();
507 String[] clist = clatr.getNamedItem("context").getNodeValue()
509 for (int j = 0; j < clist.length; j++) {
510 mapstep.put(clist[j], steps.get(snum));
514 SimulationContextType tctex = null;
515 for (Iterator<String> i = context.iterator(); i.hasNext();) {
516 String type = i.next();
517 if (!mapstep.containsKey(type)) {
519 .warn("Could not find \""
521 + "\" classification. Simulation Context type ignored.");
524 tctex = getSimulationContextTypeService().createType(type,
525 mapstep.get(type)); // Creation of Simulation Context Types
526 getSimulationContextTypeService().approve(tctex);
528 } catch (Exception error) {
529 logger.warn("Error creating context types, reason:", error); // Should not happen
536 * @return the database
538 public Database getDatabase() {
546 * the database to set
548 public void setDatabase(Database database) {
549 _database = database;
553 * Get the simulationContextTypeService.
555 * @return the simulationContextTypeService
557 public SimulationContextTypeService getSimulationContextTypeService() {
558 return _simulationContextTypeService;
562 * Set the simulationContextTypeService.
564 * @param simulationContextTypeService
565 * the simulationContextTypeService to set
567 public void setSimulationContextTypeService(
568 SimulationContextTypeService simulationContextTypeService) {
569 _simulationContextTypeService = simulationContextTypeService;
573 * Get the knowledgeElementTypeService.
575 * @return the knowledgeElementTypeService
577 public KnowledgeElementTypeService getKnowledgeElementTypeService() {
578 return _knowledgeElementTypeService;
582 * Set the knowledgeElementTypeService.
584 * @param knowledgeElementTypeService
585 * the knowledgeElementTypeService to set
587 public void setKnowledgeElementTypeService(
588 KnowledgeElementTypeService knowledgeElementTypeService) {
589 _knowledgeElementTypeService = knowledgeElementTypeService;
593 * Get the documentTypeService.
594 * @return the documentTypeService
596 public DocumentTypeService getDocumentTypeService() {
597 return _documentTypeService;
601 * Set the documentTypeService.
602 * @param documentTypeService the documentTypeService to set
604 public void setDocumentTypeService(DocumentTypeService documentTypeService) {
605 _documentTypeService = documentTypeService;