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 // ==============================================================================================================================
90 public static ProjectSettingsServiceImpl getMe () {
91 // --------------------------------------
92 if (my == null) my = new ProjectSettingsServiceImpl();
95 protected ProjectSettingsServiceImpl () {
96 // ----------------------------
97 reprop = new Properties();
98 steps = new Vector<ProjectSettingsService.Step>();
101 // ==============================================================================================================================
103 // ==============================================================================================================================
105 public void configure (String filename) throws IOException, SQLException {
106 // ---------------------------------------
107 if (!steps.isEmpty()) return; // Project already configured
109 Database base = getDatabase().getMe();
110 File config = new File(filename);
111 if (config.exists()) {
112 loadCustomization(config);
114 logger.fatal("Could not find the database configuration file \"" + config.getAbsolutePath() + "\"");
115 throw new FileNotFoundException();
117 base.configure(reprop);
118 if (!base.isInitialized()) {
120 initialize(); // Populates the database with all necessary stuff
124 public List<ProjectSettingsService.Step> getAllSteps () {
125 // ---------------------------------------
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.
133 * @return the validation cycles of the workflow
135 public static List<ProjectSettingsValidationCycle> getAllValidationCycles () {
136 // -------------------------------------------------------------
140 public FileNaming getFileNamingScheme () {
141 // -----------------------------------------------
145 public static ProjectSettingsValidationCycle getNewValidationCycle () {
146 // ------------------------------------------------------
147 return new ProjectSettingsValidationCycle();
150 public String getReferencePattern () {
154 public String getRevisionPattern () {
155 // ------------------------------------------
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;
168 public List<ProjectSettingsService.Step> getStepsOf (Class<? extends ProjectElement> level) {
169 // ---------------------------------------------------------------------------
170 Vector<ProjectSettingsService.Step> result = new Vector<ProjectSettingsService.Step>();
172 for (int i=0; i<steps.size(); i++) {
173 ProjectSettingsService.Step step = steps.get(i);
174 if (step.appliesTo(level)) result.add(step);
179 // ==============================================================================================================================
180 // Protected member function
181 // ==============================================================================================================================
183 public void initialize () {
184 // ----------------------------
185 createDocumentTypes();
186 createSimulationContextTypes();
187 createKnowledgeElementTypes();
190 // ==============================================================================================================================
191 // Private member function
192 // ==============================================================================================================================
194 private void loadCustomization (File config) {
195 // --------------------------------------------
197 DocumentBuilderFactory dfactory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
198 DocumentBuilder dBuilder = dfactory.newDocumentBuilder();
200 org.w3c.dom.Document conf = dBuilder.parse(config.getPath());
201 HashMap<String, Node> children = XDOM.getNamedChildNodes(conf.getDocumentElement());
203 // Repository tag initializing the reprop attribute
204 Node child = children.get("database");
205 HashMap<String, Node> datag = XDOM.getNamedChildNodes(child);
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);
212 // Formats tag initializing the reference pattern and date attributes
213 child = children.get("formats");
214 datag = XDOM.getNamedChildNodes(child);
216 NamedNodeMap natr = datag.get("references").getAttributes();
217 pattern = natr.getNamedItem("study").getNodeValue();
219 natr = datag.get("files").getAttributes();
220 naming = FileNaming.valueOf(natr.getNamedItem("name").getNodeValue());
222 natr = datag.get("versions").getAttributes();
223 versioning = natr.getNamedItem("pattern").getNodeValue();
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>();
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);
242 natr = tags.get("storage").getAttributes();
243 ProjectSettingsService.Step step = new ProjectSettingsService.Step(snum, Scenario.class, natr.getNamedItem("path").getNodeValue());
245 // Keeping flow and classification information for eventual later use
246 natr = tags.get("flow").getAttributes();
248 child = natr.getNamedItem("result");
249 if (child != null) resultype.add(child.getNodeValue());
251 child = tags.get("classification");
252 if (child != null) clist.add( child.getAttributes() );
253 else clist.add( null );
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);
259 step.contents.add(Document.class);
265 if (!child.getNodeName().equals("step")) continue;
266 HashMap<String, Node> tags = XDOM.getNamedChildNodes(child);
268 natr = tags.get("storage").getAttributes(); // Mandatory information
269 ProjectSettingsService.Step step = new ProjectSettingsService.Step(snum, Study.class, natr.getNamedItem("path").getNodeValue());
271 // Keeping flow and classification information for eventual later use
272 natr = tags.get("flow").getAttributes();
274 child = natr.getNamedItem("result");
275 if (child != null) resultype.add(child.getNodeValue());
277 child = tags.get("classification"); // Optional information
278 if (child != null) clist.add( child.getAttributes() );
279 else clist.add( null );
281 if (natr.getNamedItem("contents").getNodeValue().equals("knowledge")) {
282 //TODO Error: knowledges must be attached to scenarios
284 step.contents.add(Document.class);
291 child = children.get("validations");
292 concycles = new Vector<ProjectSettingsValidationCycle>();
293 datag = XDOM.getNamedChildNodes(child);
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());
308 concycles.add( new ProjectSettingsValidationCycle(name, actor) );
310 concycles.add( new ProjectSettingsValidationCycle() ); // Adds the built-in validation cycle
312 if (getDatabase().getMe().isInitialized()) return; // No need to load object type definitions as they are already stored
315 child = children.get("documents");
316 nlist = child.getChildNodes();
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;
325 natr = child.getAttributes();
326 String type = natr.getNamedItem("type").getNodeValue();
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
332 // Simulation Contexts tag
333 child = children.get("contexts");
334 nlist = child.getChildNodes();
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;
341 context.add(child.getAttributes().getNamedItem("type").getNodeValue());
343 // Knowledge Elements tag
344 child = children.get("knowledges");
345 nlist = child.getChildNodes();
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;
352 kname.add(child.getAttributes().getNamedItem("type").getNodeValue());
355 catch (Exception error) {
356 logger.info("Error in customization", error);
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>();
367 Vector<ProjectSettingsService.Step> slist = null; // List of Steps to which each document type is valid
368 int snum = 0; // Step number
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++) {
377 if (!mapuse.containsKey(type)) {
378 logger.warn("Undefined \"" + type + "\" document type.");
380 } slist = mapsteps.get(type);
381 if (slist == null) slist = new Vector<ProjectSettingsService.Step>();
383 mapsteps.put(type, slist);
385 Node result = flow.getNamedItem("result");
386 if (result != null) mapresult.put(result.getNodeValue(), step);
389 DocumentType tdoc = null;
390 Set<String> tset = mapuse.keySet();
391 ProjectSettingsService.Step step;
392 for (Iterator<String> i=tset.iterator(); i.hasNext(); ) {
394 slist = mapsteps.get(type);
395 uses = mapuse.get(type);
396 step = mapresult.get(type);
399 tprop.setName(type).setStep(slist.toArray(new ProjectSettingsService.Step[slist.size()]));
401 tdoc = maptype.get(uses);
402 if (tdoc == null) logger.warn("Undefined \"" + uses + "\" document type.");
403 else tprop.setUses(tdoc);
405 if (step != null) tprop.setResult(step);
407 tprop.disableCheck();
408 tdoc = Document.createType(tprop); // Creation of Document Types
410 maptype.put(type, tdoc);
412 } catch (Exception error) {
413 logger.warn("Error creating document types, reason:", error); // Should not happen
417 private void createKnowledgeElementTypes () {
418 // -------------------------------------------
420 KnowledgeElementType ktype = KnowledgeElement.createType("usecase"); // Internal reserved knowledge element type
422 for (Iterator<String> i=kname.iterator(); i.hasNext(); ) {
423 String type = i.next();
425 ktype = KnowledgeElement.createType(type); // Knowledge Elements Types defined in the configuration
428 } catch (Exception error) {
429 logger.warn("Error creating knowledge types, reason:", error); // Should not happen
433 private void createSimulationContextTypes () {
434 // --------------------------------------------
435 HashMap<String,ProjectSettingsService.Step> mapstep = new HashMap<String,ProjectSettingsService.Step>();
437 for (Iterator<NamedNodeMap> i=sclass.iterator(); i.hasNext(); snum++) {
438 NamedNodeMap clatr = i.next();
439 if (clatr == null) continue;
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));
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.");
454 tctex = SimulationContext.createType(type, mapstep.get(type)); // Creation of Simulation Context Types
457 } catch (Exception error) {
458 logger.warn("Error creating context types, reason:", error); // Should not happen
463 * @return the database
465 public Database getDatabase() {
470 * @param database the database to set
472 public void setDatabase(Database database) {
473 _database = database;