1 package org.splat.service.technical;
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.Iterator;
14 import java.util.LinkedHashMap;
15 import java.util.List;
16 import java.util.Properties;
18 import java.util.Vector;
20 import javax.xml.parsers.DocumentBuilder;
21 import javax.xml.parsers.DocumentBuilderFactory;
23 import org.apache.log4j.Logger;
24 import org.w3c.dom.NamedNodeMap;
25 import org.w3c.dom.Node;
26 import org.w3c.dom.NodeList;
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;
42 public class ProjectSettingsServiceImpl implements ProjectSettingsService {
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
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
60 private static ProjectSettingsServiceImpl my = null; // Singleton instance
61 private Database _database;
62 protected final static Logger logger = Logger.getLogger(ProjectSettingsServiceImpl.class);
64 public enum FileNaming { title, encoded, asis }
65 public static class ProjectSettingsValidationCycle {
66 // -----------------------------------
68 private Actor[] actor;
70 private ProjectSettingsValidationCycle () {
71 this.name = "built-in";
72 this.actor = new Actor[] { null, null, null };
74 private ProjectSettingsValidationCycle (String name, Actor[] actor) {
78 public String getName () {
81 public Actor[] getActorTypes () {
86 // ==============================================================================================================================
88 // ==============================================================================================================================
89 protected ProjectSettingsServiceImpl () {
90 // ----------------------------
91 reprop = new Properties();
92 steps = new Vector<ProjectSettingsService.Step>();
96 // ==============================================================================================================================
98 // ==============================================================================================================================
100 public void configure (String filename) throws IOException, SQLException {
101 // ---------------------------------------
102 if (!steps.isEmpty()) return; // Project already configured
104 Database base = getDatabase().getMe();
105 File config = new File(filename);
106 if (config.exists()) {
107 loadCustomization(config);
109 logger.fatal("Could not find the database configuration file \"" + config.getAbsolutePath() + "\"");
110 throw new FileNotFoundException();
112 base.configure(reprop);
113 if (!base.isInitialized()) {
115 initialize(); // Populates the database with all necessary stuff
119 public List<ProjectSettingsService.Step> getAllSteps () {
120 // ---------------------------------------
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.
128 * @return the validation cycles of the workflow
130 public static List<ProjectSettingsValidationCycle> getAllValidationCycles () {
131 // -------------------------------------------------------------
135 public FileNaming getFileNamingScheme () {
136 // -----------------------------------------------
140 public static ProjectSettingsValidationCycle getNewValidationCycle () {
141 // ------------------------------------------------------
142 return new ProjectSettingsValidationCycle();
145 public String getReferencePattern () {
149 public String getRevisionPattern () {
150 // ------------------------------------------
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;
163 public List<ProjectSettingsService.Step> getStepsOf (Class<? extends ProjectElement> level) {
164 // ---------------------------------------------------------------------------
165 Vector<ProjectSettingsService.Step> result = new Vector<ProjectSettingsService.Step>();
167 for (int i=0; i<steps.size(); i++) {
168 ProjectSettingsService.Step step = steps.get(i);
169 if (step.appliesTo(level)) result.add(step);
174 // ==============================================================================================================================
175 // Protected member function
176 // ==============================================================================================================================
178 public void initialize () {
179 // ----------------------------
180 createDocumentTypes();
181 createSimulationContextTypes();
182 createKnowledgeElementTypes();
185 // ==============================================================================================================================
186 // Private member function
187 // ==============================================================================================================================
189 private void loadCustomization (File config) {
190 // --------------------------------------------
192 DocumentBuilderFactory dfactory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
193 DocumentBuilder dBuilder = dfactory.newDocumentBuilder();
195 org.w3c.dom.Document conf = dBuilder.parse(config.getPath());
196 HashMap<String, Node> children = XDOM.getNamedChildNodes(conf.getDocumentElement());
198 // Repository tag initializing the reprop attribute
199 Node child = children.get("database");
200 HashMap<String, Node> datag = XDOM.getNamedChildNodes(child);
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);
207 // Formats tag initializing the reference pattern and date attributes
208 child = children.get("formats");
209 datag = XDOM.getNamedChildNodes(child);
211 NamedNodeMap natr = datag.get("references").getAttributes();
212 pattern = natr.getNamedItem("study").getNodeValue();
214 natr = datag.get("files").getAttributes();
215 naming = FileNaming.valueOf(natr.getNamedItem("name").getNodeValue());
217 natr = datag.get("versions").getAttributes();
218 versioning = natr.getNamedItem("pattern").getNodeValue();
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>();
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);
237 natr = tags.get("storage").getAttributes();
238 ProjectSettingsService.Step step = new ProjectSettingsService.Step(snum, Scenario.class, natr.getNamedItem("path").getNodeValue());
240 // Keeping flow and classification information for eventual later use
241 natr = tags.get("flow").getAttributes();
243 child = natr.getNamedItem("result");
244 if (child != null) resultype.add(child.getNodeValue());
246 child = tags.get("classification");
247 if (child != null) clist.add( child.getAttributes() );
248 else clist.add( null );
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);
254 step.contents.add(Document.class);
260 if (!child.getNodeName().equals("step")) continue;
261 HashMap<String, Node> tags = XDOM.getNamedChildNodes(child);
263 natr = tags.get("storage").getAttributes(); // Mandatory information
264 ProjectSettingsService.Step step = new ProjectSettingsService.Step(snum, Study.class, natr.getNamedItem("path").getNodeValue());
266 // Keeping flow and classification information for eventual later use
267 natr = tags.get("flow").getAttributes();
269 child = natr.getNamedItem("result");
270 if (child != null) resultype.add(child.getNodeValue());
272 child = tags.get("classification"); // Optional information
273 if (child != null) clist.add( child.getAttributes() );
274 else clist.add( null );
276 if (natr.getNamedItem("contents").getNodeValue().equals("knowledge")) {
277 //TODO Error: knowledges must be attached to scenarios
279 step.contents.add(Document.class);
286 child = children.get("validations");
287 concycles = new Vector<ProjectSettingsValidationCycle>();
288 datag = XDOM.getNamedChildNodes(child);
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());
303 concycles.add( new ProjectSettingsValidationCycle(name, actor) );
305 concycles.add( new ProjectSettingsValidationCycle() ); // Adds the built-in validation cycle
307 if (getDatabase().getMe().isInitialized()) return; // No need to load object type definitions as they are already stored
310 child = children.get("documents");
311 nlist = child.getChildNodes();
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;
320 natr = child.getAttributes();
321 String type = natr.getNamedItem("type").getNodeValue();
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
327 // Simulation Contexts tag
328 child = children.get("contexts");
329 nlist = child.getChildNodes();
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;
336 context.add(child.getAttributes().getNamedItem("type").getNodeValue());
338 // Knowledge Elements tag
339 child = children.get("knowledges");
340 nlist = child.getChildNodes();
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;
347 kname.add(child.getAttributes().getNamedItem("type").getNodeValue());
350 catch (Exception error) {
351 logger.info("Error in customization", error);
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>();
362 Vector<ProjectSettingsService.Step> slist = null; // List of Steps to which each document type is valid
363 int snum = 0; // Step number
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++) {
372 if (!mapuse.containsKey(type)) {
373 logger.warn("Undefined \"" + type + "\" document type.");
375 } slist = mapsteps.get(type);
376 if (slist == null) slist = new Vector<ProjectSettingsService.Step>();
378 mapsteps.put(type, slist);
380 Node result = flow.getNamedItem("result");
381 if (result != null) mapresult.put(result.getNodeValue(), step);
384 DocumentType tdoc = null;
385 Set<String> tset = mapuse.keySet();
386 ProjectSettingsService.Step step;
387 for (Iterator<String> i=tset.iterator(); i.hasNext(); ) {
389 slist = mapsteps.get(type);
390 uses = mapuse.get(type);
391 step = mapresult.get(type);
394 tprop.setName(type).setStep(slist.toArray(new ProjectSettingsService.Step[slist.size()]));
396 tdoc = maptype.get(uses);
397 if (tdoc == null) logger.warn("Undefined \"" + uses + "\" document type.");
398 else tprop.setUses(tdoc);
400 if (step != null) tprop.setResult(step);
402 tprop.disableCheck();
403 tdoc = Document.createType(tprop); // Creation of Document Types
405 maptype.put(type, tdoc);
407 } catch (Exception error) {
408 logger.warn("Error creating document types, reason:", error); // Should not happen
412 private void createKnowledgeElementTypes () {
413 // -------------------------------------------
415 KnowledgeElementType ktype = KnowledgeElement.createType("usecase"); // Internal reserved knowledge element type
417 for (Iterator<String> i=kname.iterator(); i.hasNext(); ) {
418 String type = i.next();
420 ktype = KnowledgeElement.createType(type); // Knowledge Elements Types defined in the configuration
423 } catch (Exception error) {
424 logger.warn("Error creating knowledge types, reason:", error); // Should not happen
428 private void createSimulationContextTypes () {
429 // --------------------------------------------
430 HashMap<String,ProjectSettingsService.Step> mapstep = new HashMap<String,ProjectSettingsService.Step>();
432 for (Iterator<NamedNodeMap> i=sclass.iterator(); i.hasNext(); snum++) {
433 NamedNodeMap clatr = i.next();
434 if (clatr == null) continue;
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));
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.");
449 tctex = SimulationContext.createType(type, mapstep.get(type)); // Creation of Simulation Context Types
452 } catch (Exception error) {
453 logger.warn("Error creating context types, reason:", error); // Should not happen
458 * @return the database
460 public Database getDatabase() {
465 * @param database the database to set
467 public void setDatabase(Database database) {
468 _database = database;