View Javadoc

1   /*
2    * This software was designed and created by Jason Carroll.
3    * Copyright (c) 2002, 2003, 2004 Jason Carroll.
4    * The author can be reached at jcarroll@cowsultants.com
5    * ITracker website: http://www.cowsultants.com
6    * ITracker forums: http://www.cowsultants.com/phpBB/index.php
7    *
8    * This program is free software; you can redistribute it and/or modify
9    * it only under the terms of the GNU General Public License as published by
10   * the Free Software Foundation; either version 2 of the License, or
11   * (at your option) any later version.
12   *
13   * This program is distributed in the hope that it will be useful,
14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   * GNU General Public License for more details.
17   */
18  
19  package org.itracker.services.implementations;
20  
21  import java.util.ArrayList;
22  import java.util.Arrays;
23  import java.util.Collection;
24  import java.util.Collections;
25  import java.util.Date;
26  import java.util.Enumeration;
27  import java.util.HashMap;
28  import java.util.Iterator;
29  import java.util.List;
30  import java.util.Locale;
31  import java.util.Map;
32  import java.util.Properties;
33  import java.util.ResourceBundle;
34  
35  import javax.naming.InitialContext;
36  import javax.naming.NamingException;
37  
38  import org.apache.log4j.Logger;
39  import org.itracker.core.resources.ITrackerResources;
40  import org.itracker.model.Configuration;
41  import org.itracker.model.CustomField;
42  import org.itracker.model.CustomFieldValue;
43  import org.itracker.model.Language;
44  import org.itracker.model.NameValuePair;
45  import org.itracker.model.ProjectScript;
46  import org.itracker.model.SystemConfiguration;
47  import org.itracker.model.WorkflowScript;
48  import org.itracker.model.util.PropertiesFileHandler;
49  import org.itracker.persistence.dao.ConfigurationDAO;
50  import org.itracker.persistence.dao.CustomFieldDAO;
51  import org.itracker.persistence.dao.CustomFieldValueDAO;
52  import org.itracker.persistence.dao.LanguageDAO;
53  import org.itracker.persistence.dao.NoSuchEntityException;
54  import org.itracker.persistence.dao.ProjectScriptDAO;
55  import org.itracker.persistence.dao.WorkflowScriptDAO;
56  import org.itracker.services.ConfigurationService;
57  import org.itracker.services.util.CustomFieldUtilities;
58  import org.itracker.services.util.IssueUtilities;
59  import org.itracker.services.util.NamingUtilites;
60  import org.itracker.services.util.SystemConfigurationUtilities;
61  import org.jfree.util.Log;
62  
63  /**
64   * Implementation of the ConfigurationService Interface.
65   *
66   * @see ConfigurationService
67   */
68  
69  // TODO: Cleanup this file, go through all issues, todos, etc.
70  
71  public class ConfigurationServiceImpl implements ConfigurationService {
72      
73      private static final Logger logger = Logger.getLogger(ConfigurationServiceImpl.class.getName());
74      // TODO make final static?
75      private final Properties props;
76      private ConfigurationDAO configurationDAO;
77      private CustomFieldDAO customFieldDAO;
78      private CustomFieldValueDAO customFieldValueDAO;
79      private LanguageDAO languageDAO;
80      private ProjectScriptDAO projectScriptDAO;
81      private WorkflowScriptDAO workflowScriptDAO;
82  
83      
84      private static final Long _START_TIME_MILLIS = System.currentTimeMillis();
85      private String jndiPropertiesOverridePrefix;
86      
87      /**
88       * Creates a new instance using the given configuration.
89       *
90       * @param configurationProperties itracker configuration properties
91       *        (see /WEB-INF/configuration.properties)
92       */
93      public ConfigurationServiceImpl(Properties configurationProperties, 
94      		ConfigurationDAO configurationDAO, CustomFieldDAO customFieldDAO,
95      		CustomFieldValueDAO customFieldValueDAO, LanguageDAO languageDAO, 
96      		ProjectScriptDAO projectScriptDAO, WorkflowScriptDAO workflowScriptDAO) {
97          if (configurationProperties == null) {
98              throw new IllegalArgumentException("null configurationProperties");
99          }
100         this.props = configurationProperties;
101         props.setProperty("start_time_millis", String.valueOf(_START_TIME_MILLIS));
102         
103         // initialize naming context prefix for properties overrides
104         this.jndiPropertiesOverridePrefix = props.getProperty(
105 				"jndi_override_prefix", null);
106         
107         this.configurationDAO = configurationDAO;
108         this.customFieldDAO = customFieldDAO;
109         this.customFieldValueDAO = customFieldValueDAO;
110         this.languageDAO = languageDAO;
111         
112         this.projectScriptDAO = projectScriptDAO;
113         this.workflowScriptDAO = workflowScriptDAO;
114     }
115     
116     public String getProperty(String name) {
117     	String value = null;
118     	if (null != jndiPropertiesOverridePrefix) {
119 
120 			if (logger.isDebugEnabled()) {
121 
122 				logger.debug("getProperty: looking up '" + name
123 						+ "' from jndi context "
124 						+ jndiPropertiesOverridePrefix);
125 				
126 
127 			}
128 			try {
129 				value = NamingUtilites.getStringValue(new InitialContext(),
130 						jndiPropertiesOverridePrefix + "/" + name, null);
131 		    	if (null == value) {
132 		    		if (logger.isDebugEnabled()) {
133 		    			logger.debug("getProperty: value not found in jndi: " + name);
134 		    		}	
135 		    	}
136 			} catch (Exception e) {
137 				logger.error("getProperty: exception looking up value for " + name, e);
138 			}
139 
140     	}
141     	
142     	if (null == value) {
143     		value = props.getProperty(name, null);
144     	}
145     	if (logger.isDebugEnabled()) {
146     		logger.debug("getProperty: returning " + value + " for name: " + name);
147     	}
148     	return value;
149     }
150     
151     public String getProperty(String name, String defaultValue) {
152         String val = getProperty(name);
153     	return (val == null) ? defaultValue : val;
154     }
155     
156     public boolean getBooleanProperty(String name, boolean defaultValue) {
157         String value = getProperty(name);
158         
159         return (value == null ? defaultValue : Boolean.valueOf(value));
160     }
161     
162     public int getIntegerProperty(String name, int defaultValue) {
163         String value = getProperty(name);
164         
165         try {
166             return (value == null) ? defaultValue : Integer.parseInt(value);
167         } catch (NumberFormatException ex) {
168             return defaultValue;
169         }
170         
171     }
172     
173     public long getLongProperty(String name, long defaultValue) {
174         String value = getProperty(name);
175         try {
176             return (value == null) ? defaultValue : Long.parseLong(value);
177         } catch (NumberFormatException ex) {
178             return defaultValue;
179         }
180         
181     }
182     /**
183      * returns a proxy to the properties, supplying jndi awareness
184      */
185     public Properties getProperties() {
186     	Properties p = new Properties(props) {
187     		
188     		/**
189 			 * 
190 			 */
191 			private static final long serialVersionUID = -9126991683132905153L;
192 
193 			@Override
194     		public synchronized Object get(Object key) {
195     			if (null != super.getProperty(
196     					"jndi_override_prefix", null)) {
197     				if (logger.isInfoEnabled()) {
198 						logger.info("get: looking for override for " + key
199 								+ " in jndi properties override: "
200 								+ super.getProperty(
201 				    					"jndi_override_prefix", null));
202     				}
203 					Object val = null;
204 					try {
205 						val = NamingUtilites.lookup(new InitialContext(),
206 								super.getProperty(
207 				    					"jndi_override_prefix", null) + "/" + String.valueOf(key));
208 					} catch (NamingException e) {
209 						if (logger.isDebugEnabled()) {
210 							logger.debug("get: failed to create initial context", e);
211 						}
212 					}
213 					if (null != val) {
214 						if (logger.isDebugEnabled()) {
215 							logger.debug("get: returning " + val);
216 						}
217 						return val;
218 					}
219 
220 				}
221     			if (logger.isDebugEnabled()) {
222     				logger.debug("get: get value of " + key + " from super");
223     			}
224     			return super.get(key);
225     		}
226     	};
227         return p;
228     }
229     
230     public Configuration getConfigurationItem(Integer id) {
231         Configuration configItem = configurationDAO.findByPrimaryKey(id);
232         return configItem;
233     }
234     
235     public List<Configuration> getConfigurationItemsByType(int type) {
236         List<Configuration> configItems = configurationDAO.findByType(type);
237         Collections.sort(configItems, new Configuration.ConfigurationOrderComparator());
238         return configItems;
239     }
240     
241     public List<Configuration> getConfigurationItemsByType(int type, Locale locale) {
242         List<Configuration> items = getConfigurationItemsByType(type);
243         
244         for (int i = 0; i < items.size(); i++) {
245             if (items.get(i).getType() == SystemConfigurationUtilities.TYPE_STATUS) {
246                 items.get(i).setName(IssueUtilities.getStatusName(items.get(i).getValue(), locale));
247             } else if (items.get(i).getType() == SystemConfigurationUtilities.TYPE_SEVERITY) {
248                 items.get(i).setName(IssueUtilities.getSeverityName(items.get(i).getValue(), locale));
249             } else if (items.get(i).getType() == SystemConfigurationUtilities.TYPE_RESOLUTION) {
250                 items.get(i).setName(IssueUtilities.getResolutionName(items.get(i).getValue(), locale));
251             }
252         }
253         return items;
254     }
255     
256     /**
257      * Creates a <code>Configuration</code>.
258      *
259      * @param model The <code>Configuration</code> to store
260      * @return the <code>Configuration</code> after saving
261      * @todo replace hardcoded version by a resource
262      */
263     public Configuration createConfigurationItem(Configuration configuration) {
264         
265         Configuration configurationItem = new Configuration();
266         
267         configurationItem.setType( configuration.getType() );
268         configurationItem.setOrder( configuration.getOrder() );
269         configurationItem.setValue( configuration.getValue() );
270         configurationItem.setCreateDate(new Date());
271         configurationItem.setVersion( this.getProperty("version") );
272         configurationDAO.saveOrUpdate(configurationItem);
273         
274         return configurationItem;
275         
276     }
277     
278     /**
279      * Updates a <code>ConfigurationItem</code>
280      *
281      * @param model The model containing the data
282      * @return the <code>Configuration</code> after save
283      */
284     public Configuration updateConfigurationItem(Configuration configuration) {
285         // find item by primary key
286         Configuration configurationItem = configurationDAO.findByPrimaryKey(configuration.getId());
287         
288         // update now
289         configurationDAO.saveOrUpdate( configurationItem );
290         // get model from saved item
291         return configurationItem;
292     }
293     
294     /**
295      * Updates the configuration items
296      *
297      * @param models the <code>ConfigurationModels</code> to update
298      * @param  type The type of the <code>ConfigurationItem</code>s to update
299      * @return an array with the saved models
300      */
301     public List<Configuration> updateConfigurationItems(List<Configuration> configurations, int type) {
302         
303         // remove all items
304 //        removeConfigurationItems(type);
305         List<Configuration> configurationItems = new ArrayList<Configuration>();
306         for (Iterator<Configuration> iterator = configurations.iterator(); iterator.hasNext();) {
307             
308             // create a new item
309             Configuration configurationItem = (Configuration) iterator.next();
310             Configuration curConfiguration = configurationDAO.findByPrimaryKey(configurationItem.getId());
311             
312 //            curConfiguration.setCreateDate(configurationItem.getCreateDate());
313 //            curConfiguration.setLastModifiedDate(configurationItem.getLastModifiedDate());
314             curConfiguration.setName(configurationItem.getName());
315             curConfiguration.setOrder(configurationItem.getOrder());
316             curConfiguration.setType(configurationItem.getType());
317             curConfiguration.setValue(configurationItem.getValue());
318             curConfiguration.setVersion(configurationItem.getVersion());
319             
320             // set Modified date
321 //            curConfiguration.setLastModifiedDate(new Date());
322             // save or update
323             this.configurationDAO.saveOrUpdate( curConfiguration );
324             configurationItems.add(curConfiguration);
325         }
326         // sort array
327         Collections.sort(configurationItems);
328         
329         return configurationItems;
330     }
331     
332     /**
333      * Finds the <code>Configuration</code> by primary key <code>id<code>
334      * and deletes it.
335      *
336      * @param id The id of the <code>COnfigurationBean</code> to remove
337      */
338     public void removeConfigurationItem(Integer id) {
339         
340         Configuration configBean = this.configurationDAO.findByPrimaryKey(id);
341         if ( configBean != null ) {
342             this.configurationDAO.delete( configBean );
343         }
344     }
345     
346     /**
347      * Removes all <code>Configuration</code>s of the give <code>type</code>
348      *
349      * @param type the type of <code>Configuration</code> to remove
350      */
351     public void removeConfigurationItems(int type) {
352         
353         // find the configuration beans by its type
354         Collection<Configuration> currentItems = configurationDAO.findByType(type);
355         
356         for (Iterator<Configuration> iter = currentItems.iterator(); iter.hasNext();) {
357             // get current config bean
358             Configuration config = (Configuration) iter.next();
359             // delete it
360             this.configurationDAO.delete( config );
361         }
362     }
363     
364     public void removeConfigurationItems(Configuration configuration) {
365         // TODO: never used, therefore commented, task added:
366         // Vector currentIds = new Vector();
367         Collection<Configuration> currentItems = configurationDAO.findByTypeAndValue(configuration.getType(), configuration.getValue());
368         for (Iterator<Configuration> iter = currentItems.iterator(); iter.hasNext();) {
369             Configuration configItem = (Configuration) iter.next();
370             configurationDAO.delete(configItem);
371         }
372     }
373     
374     public boolean configurationItemExists(Configuration configuration) {
375         
376         if (configuration != null && configuration.getVersion() != null) {
377             
378             Collection<Configuration> configItems = configurationDAO.findByTypeAndValue(configuration.getType(), configuration.getValue());
379             
380             if (configItems != null && configItems.size() > 0) {
381                 
382                 return true;
383                 
384             }
385             
386         }
387         
388         return false;
389         
390     }
391     
392     public boolean configurationItemUpToDate(Configuration configuration) {
393         
394         long currentVersion = 0;
395         
396         if (configuration != null && configuration.getVersion() != null) {
397             
398             Collection<Configuration> configItems = configurationDAO.findByTypeAndValue(configuration.getType(), configuration.getValue());
399             
400             for (Iterator<Configuration> iter = configItems.iterator(); iter.hasNext();) {
401                 
402                 Configuration configItem = (Configuration) iter.next();
403                 
404                 if (configItem != null) {
405                     
406                     currentVersion = Math.max(SystemConfigurationUtilities.getVersionAsLong(configItem.getVersion()),
407                             currentVersion);
408                     
409                 }
410                 
411             }
412             
413             if (currentVersion >= SystemConfigurationUtilities.getVersionAsLong(configuration.getVersion())) {
414                 
415                 return true;
416                 
417             }
418             
419         }
420         
421         return false;
422         
423     }
424     
425     public void resetConfigurationCache() {
426         
427         IssueUtilities.setResolutions(getConfigurationItemsByType(SystemConfigurationUtilities.TYPE_RESOLUTION));
428         
429         IssueUtilities.setSeverities(getConfigurationItemsByType(SystemConfigurationUtilities.TYPE_SEVERITY));
430         
431         IssueUtilities.setStatuses(getConfigurationItemsByType(SystemConfigurationUtilities.TYPE_STATUS));
432         
433         IssueUtilities.setCustomFields(getCustomFields());
434         
435     }
436     
437     public void resetConfigurationCache(int type) {
438         
439         if (type == SystemConfigurationUtilities.TYPE_RESOLUTION) {
440             
441             IssueUtilities.setResolutions(getConfigurationItemsByType(SystemConfigurationUtilities.TYPE_RESOLUTION));
442             
443         } else if (type == SystemConfigurationUtilities.TYPE_SEVERITY) {
444             
445             IssueUtilities.setSeverities(getConfigurationItemsByType(SystemConfigurationUtilities.TYPE_SEVERITY));
446             
447         } else if (type == SystemConfigurationUtilities.TYPE_STATUS) {
448             
449             IssueUtilities.setStatuses(getConfigurationItemsByType(SystemConfigurationUtilities.TYPE_STATUS));
450             
451         } else if (type == SystemConfigurationUtilities.TYPE_CUSTOMFIELD) {
452             
453             IssueUtilities.setCustomFields(getCustomFields());
454             
455         }
456         
457     }
458     
459     public ProjectScript getProjectScript(Integer scriptId) {
460         
461         ProjectScript projectScript = this.projectScriptDAO.findByPrimaryKey(scriptId);
462         return projectScript;
463         
464     }
465     
466     public List<ProjectScript> getProjectScripts() {
467         List<ProjectScript> projectScripts = this.projectScriptDAO.findAll();
468         return projectScripts;
469     }
470     
471     
472     public ProjectScript createProjectScript(ProjectScript projectScript) {
473         
474         // create project script and populate data
475         ProjectScript editprojectScript = new ProjectScript();
476         editprojectScript.setFieldId(projectScript.getFieldId());
477         editprojectScript.setPriority(projectScript.getPriority());
478         editprojectScript.setProject(projectScript.getProject());
479         editprojectScript.setScript(projectScript.getScript());
480 //        moved date stuff to BaseHibernateDAO
481 //        editprojectScript.setCreateDate(new Date());
482 //        editprojectScript.setLastModifiedDate(editprojectScript.getCreateDate());
483         
484         // save entity
485         this.projectScriptDAO.save(editprojectScript);
486         
487         return editprojectScript;
488     }
489     
490     public ProjectScript updateProjectScript(ProjectScript projectScript) {
491         ProjectScript editprojectScript;
492         
493         editprojectScript = projectScriptDAO.findByPrimaryKey(projectScript.getId());
494         editprojectScript.setFieldId(projectScript.getFieldId());
495         editprojectScript.setPriority(projectScript.getPriority());
496         editprojectScript.setProject(projectScript.getProject());
497         editprojectScript.setScript(projectScript.getScript());
498 //      moved date stuff to BaseHibernateDAO
499 //        editprojectScript.setLastModifiedDate(new Date());
500         this.projectScriptDAO.saveOrUpdate(editprojectScript);
501         return editprojectScript;
502     }
503     
504     /**
505      * remove a project script by its id
506      *
507      * @todo get all ProjectScriptBeans with that script attached and delete the ProjectScriptBean
508      * @param id the id of the project script to remove
509      */
510     public void removeProjectScript( Integer projectScript_id ) {
511         if ( projectScript_id != null ) {
512             ProjectScript projectScript = this.projectScriptDAO.findByPrimaryKey(projectScript_id);
513             if ( projectScript != null ) {
514                 this.projectScriptDAO.delete(projectScript);
515             }
516         }
517     }
518     
519     public WorkflowScript getWorkflowScript(Integer id) {
520         
521         WorkflowScript workflowScript = workflowScriptDAO.findByPrimaryKey(id);
522         
523         return workflowScript;
524         
525     }
526     
527     public List<WorkflowScript> getWorkflowScripts() {
528         List<WorkflowScript> workflowScripts = workflowScriptDAO.findAll();
529         return workflowScripts;
530     }
531     
532     /**
533      * Creates a workflow script.
534      *
535      * @param model The <code>WorkflowScript</code> carring the data
536      * @return The <code>WorkflowScript</code> after inserting
537      */
538     public WorkflowScript createWorkflowScript(WorkflowScript workflowScript) {
539         
540         // create workflow script and populate data
541         WorkflowScript editworkflowScript = new WorkflowScript();
542         editworkflowScript.setName(workflowScript.getName());
543         editworkflowScript.setScript(workflowScript.getScript());
544         editworkflowScript.setEvent(workflowScript.getEvent());
545 //      moved date stuff to BaseHibernateDAO
546 //        editworkflowScript.setLastModifiedDate(new Date());
547 //        editworkflowScript.setCreateDate(new Date());
548 //        editworkflowScript.setLastModifiedDate(editworkflowScript.getCreateDate());
549         
550         // save entity
551         workflowScriptDAO.save(editworkflowScript);
552         
553         return editworkflowScript;
554     }
555     
556     public WorkflowScript updateWorkflowScript(WorkflowScript workflowScript) {
557         WorkflowScript editworkflowScript;
558         
559         editworkflowScript = workflowScriptDAO.findByPrimaryKey(workflowScript.getId());
560         editworkflowScript.setName(workflowScript.getName());
561         editworkflowScript.setScript(workflowScript.getScript());
562         editworkflowScript.setEvent(workflowScript.getEvent());
563 //      moved date stuff to BaseHibernateDAO
564 //        editworkflowScript.setLastModifiedDate(new Date());
565         workflowScriptDAO.saveOrUpdate(editworkflowScript);
566         return editworkflowScript;
567     }
568     
569     /**
570      * remove a workflow script by its id
571      *
572      * @todo get all ProjectScriptBeans with that script attached and delete the ProjectScriptBean
573      * @param id the id of the workflow script to remove
574      */
575     public void removeWorkflowScript( Integer workflowScript_id ) {
576         if ( workflowScript_id != null ) {
577             WorkflowScript workflowScript = this.workflowScriptDAO.findByPrimaryKey(workflowScript_id);
578             if ( workflowScript != null ) {
579                 this.workflowScriptDAO.delete(workflowScript);
580             }
581         }
582     }
583     
584     public CustomField getCustomField(Integer id) {
585         
586         CustomField customField = customFieldDAO.findByPrimaryKey(id);
587         
588         return customField;
589         
590     }
591     
592     public List<CustomField> getCustomFields() {
593         List<CustomField> customFields = customFieldDAO.findAll();
594         Collections.sort(customFields, new CustomField.NameComparator());
595         return customFields;
596         
597     }
598     
599     public List<CustomField> getCustomFields(Locale locale) {
600         
601     	if (true)
602     		return null;
603     	// skip this code.
604         List<CustomField> fields = getCustomFields();
605         
606         for (int i = 0; i < fields.size(); i++) {
607             
608 //            fields.get(i).setLabels(locale);
609             
610         }
611         Collections.sort(fields,  new CustomField.NameComparator());
612         
613         return fields;
614         
615     }
616     
617     /**
618      * Creates a custom field
619      *
620      * @param customField The <code>CustomField</code> carrying the data
621      * @return  the <code>CustomField</code> after saving
622      */
623     public CustomField createCustomField(CustomField customField) {
624         CustomField addcustomField = new CustomField();
625         addcustomField.setDateFormat(customField.getDateFormat());
626         addcustomField.setFieldType(customField.getFieldType());
627         addcustomField.setOptions(customField.getOptions());
628 //        addcustomField.setName(customField.getName());
629         addcustomField.setRequired(customField.isRequired());
630         this.customFieldDAO.save( addcustomField );
631         
632 /*        if (addcustomField.getOptions() !=  null && addcustomField.getOptions().size() > 0) {
633             removeCustomFieldValues(addcustomField.getId());
634             List<CustomFieldValue> newOptions = addcustomField.getOptions();
635  
636             for (int i = 0; i < newOptions.size(); i++) {
637                 newOptions.get(i).getCustomField().setId(addcustomField.getId());
638                 createCustomFieldValue(newOptions.get(i));
639             }
640         }
641  */
642         return addcustomField;
643     }
644     
645     public CustomField updateCustomField(CustomField customField) {
646         CustomField editcustomField = customFieldDAO.findByPrimaryKey(customField.getId());
647         
648         editcustomField.setDateFormat(customField.getDateFormat());
649         editcustomField.setFieldType(customField.getFieldType());
650         editcustomField.setOptions(customField.getOptions());
651 //        editcustomField.setName(customField.getName());
652         editcustomField.setRequired(customField.isRequired());
653 //      moved date stuff to BaseHibernateDAO
654 //        editcustomField.setLastModifiedDate(new Date());
655         
656         this.customFieldDAO.saveOrUpdate( editcustomField );
657         
658 /*        if (editcustomField.getOptions() != null && editcustomField.getOptions().size() > 0) {
659             removeCustomFieldValues(editcustomField.getId());
660             List<CustomFieldValue> newOptions = editcustomField.getOptions();
661  
662             for (int i = 0; i < newOptions.size(); i++) {
663                 createCustomFieldValue(newOptions.get(i));
664             }
665         }
666  */
667         return editcustomField;
668     }
669     
670     /**
671      * searches for a custom field by primary key and removes it
672      *
673      * @param customFieldId the primary key
674      */
675     public boolean removeCustomField(Integer customFieldId) {
676         boolean status = true;
677         boolean del_Status = true;
678         CustomField customField = customFieldDAO.findByPrimaryKey(customFieldId);
679         
680         if ( customField != null ) {
681             try {
682                 if(customField.getFieldType() == CustomField.Type.LIST)
683                     status = this.removeCustomFieldValues(customFieldId);
684                 String key = CustomFieldUtilities.getCustomFieldLabelKey(customField.getId());
685                 this.customFieldDAO.delete(customField);
686                 if(key != null)
687                     status = this.removeLanguageKey(key);
688             } catch (Exception ex) {
689                 del_Status = false;
690             }
691         }
692         if ( ! del_Status )
693             status = del_Status;
694         
695         return status;
696     }
697     
698     
699     /**
700      * Gets a <code>CustomFieldValue</code> by primary key
701      *
702      * @param id the primary key
703      * @return The <code>CustomFieldValue</code> found or <code>null</code>
704      */
705     public CustomFieldValue getCustomFieldValue(Integer id) {
706         
707         CustomFieldValue cfvBean = (CustomFieldValue)
708         this.customFieldValueDAO.findByPrimaryKey(id);
709         
710         return cfvBean;
711     }
712     
713     public CustomFieldValue createCustomFieldValue(CustomFieldValue customFieldValue) {
714         CustomFieldValue addcustomFieldValue = new CustomFieldValue();
715         addcustomFieldValue.setCustomField(customFieldValue.getCustomField());
716         addcustomFieldValue.setValue(customFieldValue.getValue());
717 //        addcustomFieldValue.setName(customFieldValue.getName());
718         this.customFieldValueDAO.save(addcustomFieldValue);
719         
720         return addcustomFieldValue;
721     }
722     
723     
724     /**
725      * Updates a <code>CustomFieldValue</code>.
726      *
727      * @param model The model to update
728      * @return The <code>CustomFieldValue</code> after saving
729      */
730     public CustomFieldValue updateCustomFieldValue(CustomFieldValue customFieldValue) {
731         CustomFieldValue editcustomFieldValue = this.customFieldValueDAO.findByPrimaryKey( customFieldValue.getId() );
732 //      moved date stuff to BaseHibernateDAO
733 //        editcustomFieldValue.setCreateDate(customFieldValue.getCreateDate());
734         editcustomFieldValue.setCustomField(customFieldValue.getCustomField());
735         editcustomFieldValue.setValue(customFieldValue.getValue());
736 //      moved date stuff to BaseHibernateDAO
737 //        editcustomFieldValue.setLastModifiedDate(new Date());
738 //        editcustomFieldValue.setName(customFieldValue.getName());
739         this.customFieldValueDAO.saveOrUpdate( editcustomFieldValue );
740         return editcustomFieldValue;
741     }
742     
743     public List<CustomFieldValue> updateCustomFieldValues(Integer customFieldId, List<CustomFieldValue> customFieldValues) {
744         List<CustomFieldValue> customFieldValueItems = new ArrayList<CustomFieldValue>();
745         
746         if(customFieldId != null) {
747             try {
748                 CustomField customField = customFieldDAO.findByPrimaryKey(customFieldId);
749                 if(customFieldValues == null || customFieldValues.size() == 0) {
750                     // Collection<CustomFieldValue> currValues = customField.getOptions();
751                     // boolean status = currValues.removeAll(currValues);
752                 } else {
753                     for (Iterator<CustomFieldValue> iterator = customFieldValues.iterator(); iterator.hasNext();) {
754                         
755                         // create a new item
756                         CustomFieldValue customFieldValueItem = (CustomFieldValue) iterator.next();
757                         CustomFieldValue curCustomFieldValue = customFieldValueDAO.findByPrimaryKey(customFieldValueItem.getId());
758                         
759                         curCustomFieldValue.setCreateDate(customFieldValueItem.getCreateDate());
760 //                      moved date stuff to BaseHibernateDAO
761 //                        curCustomFieldValue.setLastModifiedDate(customFieldValueItem.getLastModifiedDate());
762 //                        curCustomFieldValue.setName(customFieldValueItem.getName());
763                         curCustomFieldValue.setValue(customFieldValueItem.getValue());
764                         curCustomFieldValue.setCustomField(customFieldValueItem.getCustomField());
765                         curCustomFieldValue.setSortOrder(customFieldValueItem.getSortOrder());
766                         
767                         // set Modified date
768 //                        curCustomFieldValue.setLastModifiedDate(new Date());
769                         // save or update
770                         this.customFieldValueDAO.saveOrUpdate( curCustomFieldValue );
771                         customFieldValueItems.add(curCustomFieldValue);
772                         
773                     }
774                     // sort array
775 //                    Collections.sort(customFieldValueItems);
776                     customField.setOptions(customFieldValueItems);
777                     return customFieldValueItems;
778                     
779                 }
780             } catch(Exception fe) {
781             }
782         }
783         
784 //        Arrays.sort(customFieldValues, new CustomFieldValue());
785         return customFieldValues;
786     }
787     
788     /**
789      * removes a custom field value by primary key
790      *
791      * @param customFieldValueId the id of the custoem field
792      */
793     public boolean removeCustomFieldValue(Integer customFieldValueId) {
794         boolean status = true;
795         boolean del_Status = true;
796         
797         // find custom field value by id
798         CustomFieldValue customFieldValue = this.customFieldValueDAO.findByPrimaryKey(customFieldValueId);
799         
800         // remove from parent field
801 //        customFieldValue.getCustomField().getOptions().remove(customFieldValue);
802         // delete it
803         try {
804             this.customFieldValueDAO.delete(customFieldValue);
805         } catch (Exception ex) {
806             del_Status = false;
807         }
808         if ( ! del_Status )
809             status = del_Status;
810         
811         return status;
812     }
813     
814     /**
815      * Removes all field values of a given custom field
816      *
817      * @param customFieldId The id of the customField
818      */
819     public boolean removeCustomFieldValues(Integer customFieldId) {
820         boolean status = true;
821         boolean lp_Status = true;
822         CustomField customField = this.customFieldDAO.findByPrimaryKey( customFieldId );
823         // get values of the field
824         List<CustomFieldValue> customFieldValues = customField.getOptions();
825         for ( Iterator<CustomFieldValue> iter = customFieldValues.iterator(); iter.hasNext();) {
826             // get current
827             CustomFieldValue customFieldValue = (CustomFieldValue)iter.next();
828             String key = CustomFieldUtilities.getCustomFieldOptionLabelKey(customFieldId, customFieldValue.getId());
829             // remove from collection
830             iter.remove();
831             // delete from datasource
832             try {
833                 this.customFieldValueDAO.delete( customFieldValue );
834                 
835                 if(key != null)
836                     status = this.removeLanguageKey(key);
837             } catch (Exception ex) {
838                 lp_Status = false;
839             }
840         }
841         if (! lp_Status )
842             status = lp_Status;
843         
844         return status;
845     }
846     
847     public Language getLanguageItemByKey(String key, Locale locale) {
848         Language languageItem;
849         try {
850         	languageItem = languageDAO.findByKeyAndLocale(key, ITrackerResources.BASE_LOCALE);
851         } catch (RuntimeException e) {
852         	languageItem = null;
853         }
854         
855         if (null == locale){  
856 
857         	locale = ITrackerResources.getLocale(ITrackerResources.BASE_LOCALE);
858         	
859         }
860         try {
861         	return languageDAO.findByKeyAndLocale(key, locale.getLanguage());
862         } catch (RuntimeException re) {
863         	if (null == languageItem) {
864         		languageItem = new Language(locale.getDisplayName(), key, ITrackerResources.getBundle(locale.getLanguage()).getString(key));
865         	}
866         }
867         if (!"".equals(locale.getCountry())) {
868             try {
869                 return languageDAO.findByKeyAndLocale(key, locale.toString());
870             } catch (RuntimeException ex){
871             	if (null == languageItem){
872             		return new Language(locale.getDisplayName(), key, ITrackerResources.getBundle(locale).getString(key));
873             	}
874             }
875         }
876         
877         return languageItem;
878         
879     }
880     
881     public List<Language> getLanguageItemsByKey(String key) {
882         List<Language> languageItems = languageDAO.findByKey(key);
883         
884         return languageItems;
885     }
886     
887     public Language updateLanguageItem(Language language) {
888         Language languageItem;
889         
890         try {
891             languageItem = languageDAO.findByKeyAndLocale(language.getResourceKey(), language.getLocale());
892             languageItem.setLocale(language.getLocale());
893             languageItem.setResourceKey(language.getResourceKey());
894             languageItem.setResourceValue(language.getResourceValue());
895 //          moved date stuff to BaseHibernateDAO
896 //            languageItem.setLastModifiedDate(new Timestamp(new Date().getTime()));
897         } catch (NoSuchEntityException fe) {
898             logger.debug("NoSuchEntityException: Language, now populating Language");
899             languageItem = new Language();
900             languageItem.setLocale(language.getLocale());
901             languageItem.setResourceKey(language.getResourceKey());
902             languageItem.setResourceValue(language.getResourceValue());
903 //          moved date stuff to BaseHibernateDAO
904 //            languageItem.setCreateDate(new Timestamp(new Date().getTime()));
905 //            languageItem.setLastModifiedDate(languageItem.getCreateDate());
906         }
907         logger.debug("Start saveOrUpdate Language");
908         languageDAO.saveOrUpdate(languageItem);
909         logger.debug("Saved Language");
910         return languageItem;
911     }
912     
913     /**
914      * Removes all <code>Language</code>s with the give key
915      *
916      * @param key The key to be removed
917      */
918     public boolean removeLanguageKey(String key) {
919         boolean status = true;
920         boolean lp_Status = true;
921         
922         // find all <code>Language</code>s for the given key
923         List<Language> languageItems = languageDAO.findByKey(key);
924         
925         for (Iterator<Language> iter = languageItems.iterator(); iter.hasNext();) {
926             // delete current item
927             Language language = (Language) iter.next();
928             try {
929                 this.languageDAO.delete(language);
930             } catch (Exception ex) {
931                 lp_Status = false;
932             }
933         }
934         if ( ! lp_Status )
935             status = lp_Status;
936         
937         return status;
938     }
939     /**
940      * Removes the <code>Language</code> passed as parameter
941      *
942      * @param model The <code>Language</code> to remove
943      */
944     public void removeLanguageItem(Language language) {
945         
946         Language languageItem = languageDAO.findByKeyAndLocale(language.getResourceKey(), language.getLocale());
947         
948         if ( languageItem != null ) {
949             // delete item
950             this.languageDAO.delete( languageItem );
951         }
952     }
953     
954     public String[] getSortedKeys() {
955         
956         int i = 0;
957         Collection<Language> items = languageDAO.findByLocale(ITrackerResources.BASE_LOCALE);
958         String[] sortedKeys = new String[items.size()];
959         
960         for (Iterator<Language> iter = items.iterator(); iter.hasNext(); i++) {
961             Language item = (Language) iter.next();
962             sortedKeys[i] = item.getResourceKey();
963         }
964         
965         // Now sort the list of keys in a logical manner
966         
967         Arrays.sort(sortedKeys);
968         return sortedKeys;
969         
970     }
971     
972     public HashMap<String,String> getDefinedKeys(String locale) {
973         
974         HashMap<String,String> keys = new HashMap<String,String>();
975         
976         if (locale == null || locale.equals("")) {
977             locale = ITrackerResources.BASE_LOCALE;
978         }
979 
980         
981         Collection<Language> items = languageDAO.findByLocale(locale);
982         for (Iterator<Language> iter = items.iterator(); iter.hasNext();) {
983             Language item = (Language) iter.next();
984             keys.put(item.getResourceKey(), item.getResourceValue());
985         }
986 
987         
988         return keys;
989         
990     }
991     
992     public List<NameValuePair> getDefinedKeysAsArray(String locale) {
993         NameValuePair[] keys = null;
994         if (locale == null || locale.equals("")) {
995             locale = ITrackerResources.BASE_LOCALE;
996         }
997         
998         int i = 0;
999         Collection<Language> items = languageDAO.findByLocale(locale);
1000         keys = new NameValuePair[items.size()];
1001         
1002         for (Iterator<Language> iter = items.iterator(); iter.hasNext(); i++) {
1003             Language item = (Language) iter.next();
1004             keys[i] = new NameValuePair(item.getResourceKey(), item.getResourceValue());
1005         }
1006         
1007         Arrays.sort(keys);
1008         return Arrays.asList(keys);
1009         
1010     }
1011     
1012     public int getNumberDefinedKeys(String locale) {
1013         
1014         return getDefinedKeys(locale).size();
1015         
1016     }
1017     
1018     public List<Language> getLanguage(Locale locale) {
1019         
1020         
1021         Map<String,String> language = new HashMap<String,String>();
1022 
1023         if (locale == null) {
1024      	   locale = new Locale("");
1025         }
1026 
1027         String localeString = (locale.toString().equals("") ? ITrackerResources.BASE_LOCALE : locale.toString());
1028         
1029         Collection<Language> items = languageDAO.findByLocale(localeString);
1030 
1031         for (Iterator<Language> iterator = items.iterator(); iterator.hasNext();) {
1032             
1033             Language item = (Language) iterator.next();
1034             
1035             language.put(item.getResourceKey(), item.getResourceValue());
1036             
1037         }
1038 //        if (locale != null && !"".equals(locale.getLanguage())) {
1039 //            
1040 //            Collection<Language> languageItems = languageDAO.findByLocale(locale.getLanguage());
1041 //            
1042 //            for (Iterator<Language> iterator = languageItems.iterator(); iterator.hasNext();) {
1043 //                
1044 //                Language item = (Language) iterator.next();
1045 //                
1046 //                language.put(item.getResourceKey(), item.getResourceValue());
1047 //                
1048 //            }
1049 //            
1050 //            if (!"".equals(locale.getCountry())) {
1051 //                
1052 //                Collection<Language> countryItems = languageDAO.findByLocale(locale.toString());
1053 //                
1054 //                for (Iterator<Language> iterator = countryItems.iterator(); iterator.hasNext();) {
1055 //                    
1056 //                    Language item = (Language) iterator.next();
1057 //                    
1058 //                    language.put(item.getResourceKey(), item.getResourceValue());
1059 //                    
1060 //                }
1061 //                
1062 //            }
1063 //            
1064 //        }
1065         
1066         Language[] languageArray = new Language[language.size()];
1067         
1068         int i = 0;
1069         
1070         
1071         for (Iterator<String> iterator = language.keySet().iterator(); iterator.hasNext(); i++) {
1072             
1073             String key = (String) iterator.next();
1074 
1075             languageArray[i] = new Language(localeString, key, (String) language.get(key));
1076             
1077         }
1078         
1079         return Arrays.asList(languageArray);
1080         
1081     }
1082     
1083     public HashMap<String,List<String>> getAvailableLanguages() {
1084         
1085         HashMap<String,List<String>> languages = new HashMap<String,List<String>>();
1086         List<Configuration> locales = getConfigurationItemsByType(SystemConfigurationUtilities.TYPE_LOCALE);
1087         
1088         for (int i = 0; i < locales.size(); i++) {
1089             String Baselocalestring = locales.get(i).getValue();
1090             if (! ITrackerResources.BASE_LOCALE.equalsIgnoreCase(Baselocalestring)) {
1091                 
1092                 if (Baselocalestring.length() == 2) {
1093 //                languages.put(Baselocalestring, new ArrayList());
1094                     List<String> languageList = new ArrayList<String>();
1095                     for (int j = 0; j < locales.size(); j++) {
1096                         String localestring = locales.get(j).getValue();
1097                         if (!ITrackerResources.BASE_LOCALE.equalsIgnoreCase(localestring) && localestring.length() > 2 ) {
1098                             String baseLanguage = localestring.substring(0, 2);
1099                             if (baseLanguage.equals(Baselocalestring) && localestring.length() == 5 && localestring.indexOf('_') == 2) {
1100                                 languageList.add(localestring);
1101                             }
1102                         }
1103                     }
1104                     languages.put(Baselocalestring,languageList);
1105                 }
1106             }
1107         }
1108         
1109         return languages;
1110         
1111     }
1112     
1113     @SuppressWarnings("unchecked")
1114     public int getNumberAvailableLanguages() {
1115         
1116         int numLanguages = 0;
1117         HashMap<String,List<String>> availableLanguages = getAvailableLanguages();
1118         
1119         for (Iterator iter = availableLanguages.keySet().iterator(); iter.hasNext();) {
1120             List<List> languages = new ArrayList<List>();
1121             List list = availableLanguages.get((String)iter.next());
1122             languages.add(list);
1123             
1124             if (languages != null && languages.size() > 0) {
1125                 numLanguages += languages.size();
1126             } else {
1127                 numLanguages += 1;
1128             }
1129             
1130         }
1131         
1132         return numLanguages;
1133         
1134     }
1135     
1136     public void updateLanguage(Locale locale, List<Language> items) {
1137         
1138         if (locale != null && items != null) {
1139             Configuration configItem = new Configuration(SystemConfigurationUtilities.TYPE_LOCALE, locale
1140                     .toString(), props.getProperty("version"));
1141             updateLanguage(locale, items, configItem);
1142             
1143         }
1144         
1145     }
1146     
1147     public void updateLanguage(Locale locale, List<Language> items, Configuration configItem) {
1148         for (int i = 0; i < items.size(); i++) {
1149             
1150             if (items.get(i) != null) {
1151                 updateLanguageItem(items.get(i));
1152             }
1153         }
1154         removeConfigurationItems(configItem);
1155         createConfigurationItem(configItem);
1156     }
1157     
1158     public SystemConfiguration getSystemConfiguration(Locale locale) {
1159         
1160         SystemConfiguration config = new SystemConfiguration();
1161         
1162         // Load the basic system configuration
1163         
1164         List<Configuration> resolutions = getConfigurationItemsByType(SystemConfigurationUtilities.TYPE_RESOLUTION);
1165         
1166         for (int i = 0; i < resolutions.size(); i++) {
1167             
1168             resolutions.get(i).setName(ITrackerResources.getString(SystemConfigurationUtilities
1169                     .getLanguageKey(resolutions.get(i)), locale));
1170             
1171         }
1172         
1173         config.setResolutions(resolutions);
1174         
1175         List<Configuration> severities = getConfigurationItemsByType(SystemConfigurationUtilities.TYPE_SEVERITY);
1176         
1177         for (int i = 0; i < severities.size(); i++) {
1178             
1179             severities.get(i).setName(ITrackerResources.getString(SystemConfigurationUtilities
1180                     .getLanguageKey(severities.get(i)), locale));
1181             
1182         }
1183         
1184         config.setSeverities(severities);
1185         
1186         List<Configuration> statuses = getConfigurationItemsByType(SystemConfigurationUtilities.TYPE_STATUS);
1187         
1188         for (int i = 0; i < statuses.size(); i++) {
1189             
1190             statuses.get(i).setName(ITrackerResources.getString(SystemConfigurationUtilities.getLanguageKey(statuses.get(i)),
1191                     locale));
1192             
1193         }
1194         
1195         config.setStatuses(statuses);
1196         
1197         // Now load the CustomFields
1198         
1199 //        config.setCustomFields(IssueUtilities.getCustomFields(locale));
1200         
1201         // Now set the system version
1202         
1203         config.setVersion(props.getProperty("version"));
1204         
1205         return config;
1206         
1207     }
1208     
1209     
1210     
1211     public boolean initializeLocale(String locale, boolean forceReload) {
1212         boolean result = false;
1213         
1214         Configuration localeConfig = new Configuration(SystemConfigurationUtilities.TYPE_LOCALE, locale,
1215                 props.getProperty("version"));
1216         
1217         if (!configurationItemUpToDate(localeConfig) || forceReload) {
1218             
1219             logger.debug("Loading database with locale " + locale);
1220             
1221 //            PropertiesFileHandler localePropertiesHandler = new PropertiesFileHandler(
1222 //                    "/org/itracker/core/resources/ITracker"
1223 //                    + (ITrackerResources.BASE_LOCALE.equals(locale) ? "" : "_" + locale) + ".properties");
1224             
1225 //            if (localePropertiesHandler.hasProperties()) {
1226                 
1227 //                Properties localeProperties = localePropertiesHandler.getProperties();
1228                 
1229 //                logger.debug("Locale " + locale + " contains " + localeProperties.size() + " properties.");
1230                 
1231 //                for (Enumeration<?> propertiesEnumeration = localeProperties.propertyNames();
1232 //                propertiesEnumeration.hasMoreElements();) {
1233 //                    String key = (String) propertiesEnumeration.nextElement();
1234 //                    String value = localeProperties.getProperty(key);
1235 //                    updateLanguageItem(new Language(locale, key, value));
1236 //                }
1237                 
1238                 removeConfigurationItems(localeConfig);
1239 //                
1240                 createConfigurationItem(localeConfig);
1241 //                
1242                 ITrackerResources.clearBundle(ITrackerResources.getLocale(locale));
1243                 
1244                 result = true;
1245                 
1246             
1247         }
1248         
1249         return result;
1250         
1251     }
1252     
1253     public void initializeConfiguration() {
1254         
1255         // Need to eventually add in code that detects the current version of
1256         // the config and update
1257         
1258         // if necessary
1259 
1260             
1261             List<Configuration> initialized = getConfigurationItemsByType(SystemConfigurationUtilities.TYPE_INITIALIZED);
1262             
1263             if (initialized == null || initialized.size() != 1) {
1264                 
1265                 logger.debug("System does not appear to be initialized, initializing system configuration.");
1266                 
1267                 ResourceBundle baseLanguage = ITrackerResources.getBundle(ITrackerResources.getLocale(ITrackerResources.BASE_LOCALE));
1268                  getLanguage(ITrackerResources.getLocale(ITrackerResources.BASE_LOCALE));
1269                 
1270                 if (baseLanguage == null) {
1271                     
1272                     throw new IllegalStateException (
1273                             "Languages must be initialized before the system configuration can be loaded.");
1274                     
1275                 }
1276                 
1277                 // Remove any previous configuration information, possibly left
1278                 // over from previous failed initialization
1279                 
1280                 logger.debug("Removing previous incomplete initialization information.");
1281                 
1282                 removeConfigurationItems(SystemConfigurationUtilities.TYPE_STATUS);
1283                 
1284                 removeConfigurationItems(SystemConfigurationUtilities.TYPE_SEVERITY);
1285                 
1286                 removeConfigurationItems(SystemConfigurationUtilities.TYPE_RESOLUTION);
1287                 Enumeration<String> keys = baseLanguage.getKeys();
1288                 while (keys.hasMoreElements()) {
1289                     String key = keys.nextElement();
1290                     if (key.startsWith(ITrackerResources.KEY_BASE_RESOLUTION)) {
1291                         
1292                         try {
1293                             
1294                             String resolutionString = key.substring(20);
1295                             if (Log.isDebugEnabled()) {
1296                             	logger.debug("Adding new configuration resolution value: " + resolutionString);
1297                             }
1298                             int resolutionNumber = Integer.parseInt(resolutionString);
1299                             
1300                             createConfigurationItem(new Configuration(
1301                                     SystemConfigurationUtilities.TYPE_RESOLUTION, resolutionString, props
1302                                     .getProperty("version"), resolutionNumber));
1303                             
1304                         } catch (RuntimeException e) {
1305                             
1306                             logger.error("Unable to load resolution value: " + key, e);
1307                             throw e;
1308                             
1309                         }
1310                         
1311                     }
1312                     
1313                     if (key.startsWith(ITrackerResources.KEY_BASE_SEVERITY)) {
1314                         
1315                         try {
1316                             
1317                             String severityString = key.substring(18);
1318                             
1319                             logger.debug("Adding new configuration severity value: " + severityString);
1320                             
1321                             int severityNumber = Integer.parseInt(severityString);
1322                             
1323                             createConfigurationItem(new Configuration(SystemConfigurationUtilities.TYPE_SEVERITY,
1324                                     severityString, props.getProperty("version"), severityNumber));
1325                             
1326                         } catch (RuntimeException e) {
1327                             
1328                             logger.error("Unable to load severity value: " + key, e);
1329                             throw e;
1330                         }
1331                         
1332                     }
1333                     
1334                     if (key.startsWith(ITrackerResources.KEY_BASE_STATUS)) {
1335                         
1336                         try {
1337                             
1338                             String statusString = key.substring(16);
1339                             
1340                             logger.debug("Adding new configuration status value: " + statusString);
1341                             
1342                             int statusNumber = Integer.parseInt(statusString);
1343                             
1344                             createConfigurationItem(new Configuration(SystemConfigurationUtilities.TYPE_STATUS,
1345                                     statusString, props.getProperty("version"), statusNumber));
1346                         } catch (RuntimeException e) {
1347                             logger.error("Unable to load status value: " + key, e);
1348                             throw e;
1349                         }
1350                     }
1351                 }
1352                 createConfigurationItem(new Configuration(SystemConfigurationUtilities.TYPE_INITIALIZED, "1",
1353                         props.getProperty("version")));
1354             }
1355         
1356         
1357     }
1358     
1359     public LanguageDAO getLanguageDAO() {
1360         return languageDAO;
1361     }
1362     
1363     public ConfigurationDAO getConfigurationDAO() {
1364         return configurationDAO;
1365     }
1366     
1367     public CustomFieldDAO getCustomFieldDAO() {
1368         return customFieldDAO;
1369     }
1370     
1371     public CustomFieldValueDAO getCustomFieldValueDAO() {
1372         return customFieldValueDAO;
1373     }
1374     
1375     public WorkflowScriptDAO getWorkflowScriptDAO() {
1376         return workflowScriptDAO;
1377     }
1378     
1379     public String getSystemBaseURL() {
1380 	    return getProperty(PNAME_SYSTEM_BASE_URL);
1381     }
1382 }