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.ArrayList;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.LinkedHashMap;
17 import java.util.List;
19 import java.util.Properties;
22 import javax.xml.parsers.DocumentBuilder;
23 import javax.xml.parsers.DocumentBuilderFactory;
25 import org.apache.log4j.Logger;
26 import org.splat.dal.bo.som.Document;
27 import org.splat.dal.bo.som.DocumentType;
28 import org.splat.dal.bo.som.KnowledgeElement;
29 import org.splat.dal.bo.som.KnowledgeElementType;
30 import org.splat.dal.bo.som.ProjectElement;
31 import org.splat.dal.bo.som.Scenario;
32 import org.splat.dal.bo.som.SimulationContextType;
33 import org.splat.dal.bo.som.Study;
34 import org.splat.dal.bo.som.ValidationCycle.Actor;
35 import org.splat.dal.dao.som.Database;
36 import org.splat.manox.XDOM;
37 import org.splat.service.DocumentTypeService;
38 import org.splat.service.KnowledgeElementTypeService;
39 import org.splat.service.SimulationContextTypeService;
40 import org.springframework.context.ResourceLoaderAware;
41 import org.springframework.core.io.Resource;
42 import org.springframework.core.io.ResourceLoader;
43 import org.springframework.transaction.annotation.Transactional;
44 import org.w3c.dom.Element;
45 import org.w3c.dom.NamedNodeMap;
46 import org.w3c.dom.Node;
47 import org.w3c.dom.NodeList;
50 * SIMAN workflow configuration data service.
52 public class ProjectSettingsServiceImpl implements ProjectSettingsService,
56 * The logger for the service.
58 protected final static Logger LOG = Logger
59 .getLogger(ProjectSettingsServiceImpl.class);
62 * Type attribute name.
64 private final static String TYPE_ATTR = "type";
67 * Steps configuration storage.
69 private StepsConfigService _stepsConfigService;
71 * Resource loader injected by Spring.
73 private ResourceLoader _resourceLoader;
76 * Configuration resource injected by Spring.
78 private Resource _config;
80 // Non persistent configuration information
82 * Repository settings.
84 private transient final Properties _reprop = new Properties();
86 * Pattern of study references.
88 private transient String _pattern;
90 * Scheme of file names stored into the repository.
92 private transient FileNaming _naming;
94 * Pattern of the presentation of version numbers.
96 private transient String _versioning;
98 * Configuration document validation cycles.
100 private transient final List<ProjectSettingsValidationCycle> _concycles = new ArrayList<ProjectSettingsValidationCycle>();
102 * Document type mappings to file formats which should be imported into SALOME during check-out.
104 private transient final Map<String, List<String>> _mapimport = new HashMap<String, List<String>>();
106 * Default document types structured by step.formats.
108 private transient final Map<String, DocumentType> _defdoctype = new LinkedHashMap<String, DocumentType>();
110 // Temporary attributes initialized from the configuration file for populating the database with object types
112 * Step.format keys structured by Default document types names. This map is used for loading config before document types are created in
113 * the database. When document types are created then _defdoctype is filled.
115 private transient final Map<String, List<String>> _defdoctypeKeys = new HashMap<String, List<String>>();
118 * Document type names and uses mapping.
120 private transient Map<String, String> _mapuse;
122 * Simulation Context type names.
124 private transient List<String> _context;
126 * Knowledge Element type names.
128 private transient List<String> _kname;
132 private transient List<NamedNodeMap> _flows;
134 * Study classifications.
136 private transient List<NamedNodeMap> _sclass;
140 * Database service to check its version, etc.
142 private Database _database;
144 * Injected simulation context type service.
146 private SimulationContextTypeService _simulationContextTypeService;
148 * Injected knowledge element type service.
150 private KnowledgeElementTypeService _knowledgeElementTypeService;
152 * Injected document type service.
154 private DocumentTypeService _documentTypeService;
157 * File naming strategy enumeration.
159 public enum FileNaming {
161 * Name by document title.
165 * Generate encoded name.
169 * Keep original file name.
175 * Validation cycle defined in the XML configuration.
177 public static class ProjectSettingsValidationCycle {
179 * Cycle (document) type name.
181 private transient final String _name;
183 * Array of cycle actors positions in the organization. TODO: Must be replaced by Roles.
185 private transient final Actor[] _actor;
188 * Default constructor.
190 private ProjectSettingsValidationCycle() {
191 this._name = "built-in";
192 this._actor = new Actor[] { null, null, null };
196 * Create a validation cycle definition for the given document type name and actors positions.
199 * the document type name
201 * the array of actors positions
203 private ProjectSettingsValidationCycle(final String name,
204 final Actor[] actor) {
210 * The processed document type name.
212 * @return the document type name
214 public String getName() {
219 * Get an array of cycle actors positions.
221 * @return the array of actors positions
222 * @see org.splat.dal.bo.som.ValidationCycle.Actor
224 public Actor[] getActorTypes() {
229 // ==============================================================================================================================
231 // ==============================================================================================================================
234 * Load workflow configuration from the file defined by config property. <BR>
235 * Create necessary default staff in the database if it is not initialized yet.
237 * @throws IOException
238 * if there is a file reading or index creation problem
239 * @throws SQLException
240 * if there is a database population problem
243 public void configure() throws IOException, SQLException {
244 if (getConfig() != null) {
245 configure("file:" + getConfig().getFile().getAbsolutePath());
250 * Load workflow configuration from the given file. <BR>
251 * Create necessary default staff in the database if it is not initialized yet.
254 * the workflow configuration file
255 * @throws IOException
256 * if there is a file reading or index creation problem
257 * @throws SQLException
258 * if there is a database population problem
261 public void configure(final String filename) throws IOException,
263 if (!getStepsConfigService().getSteps().isEmpty()) {
264 return; // Project already configured
267 Database base = getDatabase().getCheckedDB();
268 if (LOG.isInfoEnabled()) {
269 LOG.info("Loading configuration from: "
270 + getResource(filename).getFile().getAbsolutePath());
271 LOG.info("Root: " + getResource("/").getURI());
273 File config = getResource(filename).getFile();
274 if (config.exists()) {
275 loadCustomization(config);
277 LOG.fatal("Could not find the database configuration file \""
278 + config.getAbsolutePath() + "\"");
279 throw new FileNotFoundException();
281 base.configure(_reprop);
282 if (!base.isInitialized()) {
284 initialize(); // Populates the database with all necessary stuff
289 * Get ordered list of (transient) study steps.
291 * @return the list of steps from project settings
293 public List<ProjectSettingsService.Step> getAllSteps() {
294 return getStepsConfigService().getSteps();
298 * Return the validation cycles of result documents defined in the workflow, ordered by study activities and ending by the default
299 * validation cycle, if defined.
301 * @return the validation cycles of the workflow
303 public List<ProjectSettingsValidationCycle> getAllValidationCycles() {
308 * Get file naming scheme setting.
310 * @return file naming scheme
311 * @see org.splat.service.technical.ProjectSettingsServiceImpl.FileNaming
313 public FileNaming getFileNamingScheme() {
318 * Get a pattern of study references.
320 * @return the reference pattern
322 public String getReferencePattern() {
327 * Get a pattern of the presentation of version numbers.
329 * @return the version numbers presentation pattern
331 public String getRevisionPattern() {
336 * Get a study step by its sequential number.
342 public ProjectSettingsService.Step getStep(final int number) {
343 ProjectSettingsService.Step res = null;
344 for (int i = 0; i < getStepsConfigService().getSteps().size(); i++) {
345 ProjectSettingsService.Step step = getStepsConfigService()
347 if (step.getNumber() == number) {
356 * Check if a file of the given format should be imported during check-out of a document of the given type.
362 * @return true if file should be imported
364 public boolean doImport(final String type, final String format) {
365 if (LOG.isDebugEnabled()) {
366 LOG.debug("Do import for ("
371 + (_mapimport.containsKey(type) && _mapimport.get(type)
374 return (_mapimport.containsKey(type) && _mapimport.get(type).contains(
379 * Get default document type for the given file format on the given study step.
384 * the file format (extension)
385 * @return document type
387 public DocumentType getDefaultDocumentType(final Step step,
388 final String format) {
389 String[] table = format.split("\\x2E");
390 if (LOG.isDebugEnabled()) {
391 LOG.debug("Trying to get default type: " + step.getNumber() + "."
392 + table[table.length - 1]);
395 .get(step.getNumber() + "." + table[table.length - 1]); // May be null
399 * Get the list of default formats for the given study step.
403 * @return list of formats (file extensions)
405 public List<String> getDefaultFormats(final Step step) {
406 Integer stepNumber = step.getNumber();
407 List<String> result = new ArrayList<String>();
409 for (String i : _defdoctype.keySet()) {
410 String[] key = i.split("\\x2E");
411 // PDF is not an authoring format
412 if (stepNumber.equals(Integer.valueOf(key[0]))
413 && (!key[1].equals("pdf"))) {
414 result.add(key[1]); // Formats are unique
421 * Initialize the database: create all necessary default staff defined in the configuration file.
424 protected void initialize() {
425 createDocumentTypes();
426 createSimulationContextTypes();
427 createKnowledgeElementTypes();
430 // ==============================================================================================================================
431 // Private member function
432 // ==============================================================================================================================
435 * Read the configuration file and fill transient project settings fields.
438 * the configuration XML file
440 private void loadCustomization(final File config) {
442 DocumentBuilderFactory dfactory = javax.xml.parsers.DocumentBuilderFactory
444 DocumentBuilder dBuilder = dfactory.newDocumentBuilder();
446 org.w3c.dom.Document conf = dBuilder.parse(config.getPath());
447 HashMap<String, Node> children = XDOM.getNamedChildNodes(conf
448 .getDocumentElement());
450 // Repository tag initializing the reprop attribute
451 Node child = children.get("database");
452 HashMap<String, Node> datag = XDOM.getNamedChildNodes(child);
454 String disk = datag.get("repository").getAttributes().getNamedItem(
455 "disk").getNodeValue();
456 if (!disk.endsWith("/")) {
459 LOG.info("Database root set to " + disk);
460 _reprop.setProperty("repository", disk);
462 // Formats tag initializing the reference pattern and date attributes
463 child = children.get("formats");
464 datag = XDOM.getNamedChildNodes(child);
466 NamedNodeMap natr = datag.get("references").getAttributes();
467 _pattern = natr.getNamedItem("study").getNodeValue();
469 natr = datag.get("files").getAttributes();
470 _naming = FileNaming.valueOf(natr.getNamedItem("name")
473 natr = datag.get("versions").getAttributes();
474 _versioning = natr.getNamedItem("pattern").getNodeValue();
476 // Activities tag initializing the steps and rex attributes
477 child = children.get("activities");
478 NodeList nlist = child.getChildNodes();
479 List<NamedNodeMap> flist = new ArrayList<NamedNodeMap>();
480 List<String> resultype = new ArrayList<String>();
481 List<NamedNodeMap> clist = new ArrayList<NamedNodeMap>();
483 int snum = 1; // Base number of steps
484 for (int i = 0; i < nlist.getLength(); i++) {
485 child = nlist.item(i);
486 if ("scenario".equals(child.getNodeName())) {
487 NodeList slist = child.getChildNodes();
488 for (int j = 0; j < slist.getLength(); j++) {
489 snum = loadStep(slist.item(j), Scenario.class, snum,
490 flist, clist, resultype);
493 snum = loadStep(child, Study.class, snum, flist, clist,
499 loadValidationCycles(children, resultype);
500 // Load steps result document types mapped to file formats
501 loadFormatMappings(children);
502 // Load default mapping of file formats to document types for each step
503 loadDefaultDocTypes(children);
505 if (!getDatabase().getCheckedDB().isInitialized()) {
506 // Load object type definitions
508 child = children.get("documents");
509 nlist = child.getChildNodes();
511 _flows = flist; // Kept for later use in document type definition
512 _sclass = clist; // Kept for later use in simulation context type definition
513 _mapuse = new LinkedHashMap<String, String>();
514 for (int i = 0; i < nlist.getLength(); i++) {
515 child = nlist.item(i);
516 if ("article".equals(child.getNodeName())) {
517 natr = child.getAttributes();
518 String type = natr.getNamedItem(TYPE_ATTR)
521 child = natr.getNamedItem("uses");
523 uses = child.getNodeValue();
525 _mapuse.put(type, uses); // Must be added to the map even if no (null) uses
528 // Simulation Contexts tag
529 _context = loadArticles(children, "contexts");
530 // Knowledge Elements tag
531 _kname = loadArticles(children, "knowledges");
533 } catch (Exception error) {
534 LOG.info("Error in customization", error);
539 * Load mappings of document types to lists of importable file formats.
544 private void loadFormatMappings(final Map<String, Node> children) {
546 Element maps = (Element) children.get("mappings");
549 List<String> formats;
550 NodeList docs, imports;
552 // Read document types
553 docs = maps.getElementsByTagName("document");
554 for (int i = 0; i < docs.getLength(); i++) {
555 doc = (Element) docs.item(i);
556 type = doc.getAttribute(TYPE_ATTR);
557 if (!type.isEmpty()) {
558 // Read file formats for the document type
559 imports = doc.getElementsByTagName("import");
560 formats = new ArrayList<String>();
561 for (int j = 0; j < imports.getLength(); j++) {
562 imp = (Element) imports.item(j);
563 format = imp.getAttribute("format");
564 if (!format.isEmpty()) {
568 if (!formats.isEmpty()) {
569 _mapimport.put(type, formats);
577 * Load default document types from XML configuration.
582 private void loadDefaultDocTypes(final Map<String, Node> children) {
584 _defdoctypeKeys.clear();
585 Node child = children.get("default-doctypes");
587 NodeList nlist = child.getChildNodes();
589 List<DocumentType> listype = getDocumentTypeService()
591 Map<String, DocumentType> maptype = new HashMap<String, DocumentType>();
592 for (Iterator<DocumentType> i = listype.iterator(); i.hasNext();) {
593 DocumentType type = i.next();
594 maptype.put(type.getName(), type);
596 for (int i = 0; i < nlist.getLength(); i++) {
597 child = nlist.item(i);
598 if (!child.getNodeName().equals("step")) {
602 String nstep = child.getAttributes().getNamedItem("number")
604 NodeList map = child.getChildNodes();
605 for (int j = 0; j < map.getLength(); j++) {
607 if (!child.getNodeName().equals("mapping")) {
610 NamedNodeMap natr = child.getAttributes();
611 String dext = natr.getNamedItem("extension").getNodeValue();
612 String type = natr.getNamedItem(TYPE_ATTR).getNodeValue();
613 if (LOG.isDebugEnabled()) {
614 LOG.debug("Map default type: " + nstep + "." + dext
615 + ": (type name = " + type + ")"
616 + maptype.get(type));
618 _defdoctype.put(nstep + "." + dext, maptype.get(type));
619 // Remember the key if type is not created yet
620 if (maptype.get(type) == null) {
622 if (_defdoctypeKeys.containsKey(type)) {
623 keys = _defdoctypeKeys.get(type);
625 keys = new ArrayList<String>();
626 _defdoctypeKeys.put(type, keys);
628 keys.add(nstep + "." + dext);
636 * Load a step from the given XML node. Return the next step's number.
641 * the class of a step's owner project element - study or scenario
647 * list of classifications
649 * list of flow results
650 * @return the next step's number
652 private int loadStep(final Node node,
653 final Class<? extends ProjectElement> ownerClass, final int snum,
654 final List<NamedNodeMap> flist, final List<NamedNodeMap> clist,
655 final List<String> resultype) {
657 if ("step".equals(node.getNodeName())) {
659 String name = ((Element) node).getAttribute("name");
660 HashMap<String, Node> tags = XDOM.getNamedChildNodes(node);
662 NamedNodeMap natr = tags.get("storage").getAttributes();
663 ProjectSettingsService.Step step = new ProjectSettingsService.Step(
664 snum, ownerClass, natr.getNamedItem("path").getNodeValue());
667 // Keeping flow and classification information for eventual later use
668 natr = tags.get("flow").getAttributes();
670 Node child = natr.getNamedItem("result");
672 resultype.add(child.getNodeValue());
675 child = tags.get("classification");
679 clist.add(child.getAttributes());
682 if (natr.getNamedItem("contents").getNodeValue()
683 .equals("knowledge")) {
684 if (Study.class.equals(ownerClass)) {
686 .error("Error: knowledges must be attached to scenarios.");
688 // TODO In a given scenario, only one step must contain knowledges
689 step._contents.add(KnowledgeElement.class);
692 step._contents.add(Document.class);
695 Element module = (Element) tags.get("module");
696 if (module != null) {
697 step.setModule(module.getAttribute("name"));
700 getStepsConfigService().getSteps().add(step);
707 * Get custom validation cycles.
712 * list of result types
714 private void loadValidationCycles(final Map<String, Node> children,
715 final List<String> resultype) {
717 Node child = children.get("validations");
718 Map<String, Node> datag = XDOM.getNamedChildNodes(child);
721 String[] step = { "review", "approval", "acceptance" };
722 resultype.add("default");
723 for (Iterator<String> i = resultype.iterator(); i.hasNext();) {
724 Actor[] actor = { null, null, null };
725 String name = i.next();
726 child = datag.get(name);
728 // Document type is the subject of a validation
729 natr = child.getAttributes();
730 for (int j = 0; j < step.length; j++) {
731 child = natr.getNamedItem(step[j]);
733 actor[j] = Actor.valueOf(child.getNodeValue()); // Validation step is required
736 _concycles.add(new ProjectSettingsValidationCycle(name, actor));
739 _concycles.add(new ProjectSettingsValidationCycle()); // Adds the built-in validation cycle
743 * Read list of articles types.
746 * XML nodes containing articles
748 * the name of the list of articles
749 * @return list of articles types
751 private List<String> loadArticles(final Map<String, Node> children,
752 final String listName) {
753 Node child = children.get(listName);
754 NodeList nlist = child.getChildNodes();
756 List<String> articles = new ArrayList<String>();
757 for (int i = 0; i < nlist.getLength(); i++) {
758 child = nlist.item(i);
759 if (child.getNodeName().equals("article")) {
760 articles.add(child.getAttributes().getNamedItem(TYPE_ATTR)
768 * Create in the database document types defined in the custom configuration.
770 private void createDocumentTypes() {
771 if (LOG.isDebugEnabled()) {
772 LOG.debug("Creating documents types...");
774 DocumentType.Properties tprop = new DocumentType.Properties();
775 Map<String, List<ProjectSettingsService.Step>> mapsteps = new HashMap<String, List<ProjectSettingsService.Step>>();
776 Map<String, ProjectSettingsService.Step> mapresult = new HashMap<String, ProjectSettingsService.Step>();
777 Map<String, DocumentType> maptype = new HashMap<String, DocumentType>();
779 List<ProjectSettingsService.Step> slist = null; // List of Steps to which each document type is valid
780 int snum = 0; // Step number
783 for (Iterator<NamedNodeMap> i = _flows.iterator(); i.hasNext(); snum++) {
784 NamedNodeMap flow = i.next();
785 ProjectSettingsService.Step step = getStepsConfigService()
786 .getSteps().get(snum);
787 String[] contents = flow.getNamedItem("contents").getNodeValue()
789 for (int j = 0; j < contents.length; j++) {
791 if (!_mapuse.containsKey(type)) {
792 LOG.warn("Undefined \"" + type + "\" document type.");
795 slist = mapsteps.get(type);
797 slist = new ArrayList<ProjectSettingsService.Step>();
800 mapsteps.put(type, slist);
802 Node result = flow.getNamedItem("result");
803 if (result != null) {
804 mapresult.put(result.getNodeValue(), step);
808 DocumentType tdoc = null;
809 Set<String> tset = _mapuse.keySet();
810 ProjectSettingsService.Step step;
811 for (Iterator<String> i = tset.iterator(); i.hasNext();) {
813 slist = mapsteps.get(type);
815 uses = _mapuse.get(type);
816 step = mapresult.get(type);
819 tprop.setName(type).setStep(
820 slist.toArray(new ProjectSettingsService.Step[slist
823 // Parse uses attribute
824 String[] usesArr = uses.split(",");
825 List<DocumentType> usesTypesList = new ArrayList<DocumentType>();
826 for (String usesType : usesArr) {
827 tdoc = maptype.get(usesType.trim());
829 LOG.warn("Undefined \"" + usesType.trim()
830 + "\" document type.");
832 if (!usesTypesList.contains(tdoc)) {
833 usesTypesList.add(tdoc);
837 tprop.setUses(usesTypesList
838 .toArray(new DocumentType[] {}));
841 tprop.setResult(step);
844 tprop.disableCheck();
845 tdoc = getDocumentTypeService().createType(tprop); // Creation of Document Types
846 getDocumentTypeService().approve(tdoc);
847 maptype.put(type, tdoc);
848 // Remember default type if it is
849 if (_defdoctypeKeys.containsKey(type)) {
850 for (String key : _defdoctypeKeys.get(type)) {
851 if (LOG.isDebugEnabled()) {
852 LOG.debug("Put mapping for default type: "
853 + key + ": " + tdoc);
855 _defdoctype.put(key, tdoc);
860 } catch (Exception error) {
861 LOG.warn("Error creating document types, reason:", error); // Should not happen
863 if (LOG.isDebugEnabled()) {
864 LOG.debug("Documents types are created: " + maptype.size());
869 * Create in the database knowledge types defined in the custom configuration.
872 private void createKnowledgeElementTypes() {
874 KnowledgeElementType ktype = getKnowledgeElementTypeService()
875 .createType("usecase"); // Internal reserved knowledge element type
876 getKnowledgeElementTypeService().reserve(ktype);
877 for (Iterator<String> i = _kname.iterator(); i.hasNext();) {
878 String type = i.next();
880 ktype = getKnowledgeElementTypeService().createType(type); // Knowledge Elements Types defined in the configuration
881 getKnowledgeElementTypeService().approve(ktype);
883 } catch (Exception error) {
884 LOG.warn("Error creating knowledge types, reason:", error); // Should not happen
889 * Create in the database simulation contexts types defined in the custom configuration.
891 private void createSimulationContextTypes() {
892 Map<String, ProjectSettingsService.Step> mapstep = new HashMap<String, ProjectSettingsService.Step>();
894 for (Iterator<NamedNodeMap> i = _sclass.iterator(); i.hasNext(); snum++) {
895 NamedNodeMap clatr = i.next();
897 String[] clist = clatr.getNamedItem("context").getNodeValue()
899 for (int j = 0; j < clist.length; j++) {
900 mapstep.put(clist[j], getStepsConfigService().getSteps()
906 SimulationContextType tctex = null;
907 for (Iterator<String> i = _context.iterator(); i.hasNext();) {
908 String type = i.next();
909 if (mapstep.containsKey(type)) {
910 tctex = getSimulationContextTypeService().createType(type,
911 mapstep.get(type)); // Creation of Simulation Context Types
912 getSimulationContextTypeService().approve(tctex);
915 .warn("Could not find \""
917 + "\" classification. Simulation Context type ignored.");
920 } catch (Exception error) {
921 LOG.warn("Error creating context types, reason:", error); // Should not happen
928 * @return the database
930 public Database getDatabase() {
938 * the database to set
940 public void setDatabase(final Database database) {
941 _database = database;
945 * Get the simulationContextTypeService.
947 * @return the simulationContextTypeService
949 public SimulationContextTypeService getSimulationContextTypeService() {
950 return _simulationContextTypeService;
954 * Set the simulationContextTypeService.
956 * @param simulationContextTypeService
957 * the simulationContextTypeService to set
959 public void setSimulationContextTypeService(
960 final SimulationContextTypeService simulationContextTypeService) {
961 _simulationContextTypeService = simulationContextTypeService;
965 * Get the knowledgeElementTypeService.
967 * @return the knowledgeElementTypeService
969 public KnowledgeElementTypeService getKnowledgeElementTypeService() {
970 return _knowledgeElementTypeService;
974 * Set the knowledgeElementTypeService.
976 * @param knowledgeElementTypeService
977 * the knowledgeElementTypeService to set
979 public void setKnowledgeElementTypeService(
980 final KnowledgeElementTypeService knowledgeElementTypeService) {
981 _knowledgeElementTypeService = knowledgeElementTypeService;
985 * Get the documentTypeService.
987 * @return the documentTypeService
989 public DocumentTypeService getDocumentTypeService() {
990 return _documentTypeService;
994 * Set the documentTypeService.
996 * @param documentTypeService
997 * the documentTypeService to set
999 public void setDocumentTypeService(
1000 final DocumentTypeService documentTypeService) {
1001 _documentTypeService = documentTypeService;
1007 * @see org.springframework.context.ResourceLoaderAware#setResourceLoader(org.springframework.core.io.ResourceLoader)
1010 public void setResourceLoader(final ResourceLoader resourceLoader) {
1011 this._resourceLoader = resourceLoader;
1015 * Get resource by means of Spring resource loader.
1018 * the resource location
1019 * @return the resource
1021 public Resource getResource(final String location) {
1022 return _resourceLoader.getResource(location);
1028 * @return the config
1030 public Resource getConfig() {
1040 public void setConfig(final Resource config) {
1045 * Get the stepsConfigService.
1047 * @return the stepsConfigService
1049 public StepsConfigService getStepsConfigService() {
1050 return _stepsConfigService;
1054 * Set the stepsConfigService.
1056 * @param stepsConfigService
1057 * the stepsConfigService to set
1059 public void setStepsConfigService(
1060 final StepsConfigService stepsConfigService) {
1061 _stepsConfigService = stepsConfigService;