ConfigurationServiceImpl.java

  1. /*
  2. /*
  3.  * This software was designed and created by Jason Carroll.
  4.  * Copyright (c) 2002, 2003, 2004 Jason Carroll.
  5.  * The author can be reached at jcarroll@cowsultants.com
  6.  * ITracker website: http://www.cowsultants.com
  7.  * ITracker forums: http://www.cowsultants.com/phpBB/index.php
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it only under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  */

  19. package org.itracker.services.implementations;

  20. import org.apache.commons.collections.CollectionUtils;
  21. import org.apache.commons.collections.Transformer;
  22. import org.apache.commons.collections.functors.NotNullPredicate;
  23. import org.apache.commons.lang.StringUtils;
  24. import org.itracker.core.resources.ITrackerResources;
  25. import org.itracker.model.*;
  26. import org.itracker.model.util.CustomFieldUtilities;
  27. import org.itracker.model.util.IssueUtilities;
  28. import org.itracker.model.util.SystemConfigurationUtilities;
  29. import org.itracker.persistence.dao.*;
  30. import org.itracker.services.ConfigurationService;
  31. import org.itracker.util.NamingUtilites;
  32. import org.slf4j.Logger;
  33. import org.slf4j.LoggerFactory;

  34. import javax.naming.InitialContext;
  35. import java.util.*;

  36. /**
  37.  * Implementation of the ConfigurationService Interface.
  38.  *
  39.  * @see ConfigurationService
  40.  */

  41. public class ConfigurationServiceImpl implements ConfigurationService {

  42.     private static final Logger logger = LoggerFactory.getLogger(ConfigurationServiceImpl.class.getName());

  43.     private final Properties props;
  44.     private ConfigurationDAO configurationDAO;
  45.     private CustomFieldDAO customFieldDAO;
  46.     private CustomFieldValueDAO customFieldValueDAO;
  47.     private LanguageDAO languageDAO;
  48.     private ProjectScriptDAO projectScriptDAO;
  49.     private WorkflowScriptDAO workflowScriptDAO;


  50.     private static final Long _START_TIME_MILLIS = System.currentTimeMillis();
  51.     private String jndiPropertiesOverridePrefix;
  52.     private String mailSessionLookupName;

  53.     /**
  54.      * Creates a new instance using the given configuration.
  55.      *
  56.      * @param configurationProperties itracker configuration properties
  57.      *                                (see classpath:configuration.properties)
  58.      */
  59.     public ConfigurationServiceImpl(Properties configurationProperties,
  60.                                     ConfigurationDAO configurationDAO, CustomFieldDAO customFieldDAO,
  61.                                     CustomFieldValueDAO customFieldValueDAO, LanguageDAO languageDAO,
  62.                                     ProjectScriptDAO projectScriptDAO, WorkflowScriptDAO workflowScriptDAO) {
  63.         if (configurationProperties == null) {
  64.             throw new IllegalArgumentException("null configurationProperties");
  65.         }
  66.         this.props = configurationProperties;
  67.         props.setProperty("start_time_millis", String.valueOf(_START_TIME_MILLIS));

  68.         // initialize naming context prefix for properties overrides
  69.         if (StringUtils.isEmpty(jndiPropertiesOverridePrefix)) {
  70.             jndiPropertiesOverridePrefix = props.getProperty("jndi_override_prefix", "java:comp/env/itracker");
  71.         }
  72.         if (StringUtils.isEmpty(mailSessionLookupName)) {
  73.             mailSessionLookupName = configurationProperties.getProperty("mail_session_jndi_lookup", "java:comp/env/itracker/mail/Session");
  74.         }

  75.         this.configurationDAO = configurationDAO;
  76.         this.customFieldDAO = customFieldDAO;
  77.         this.customFieldValueDAO = customFieldValueDAO;
  78.         this.languageDAO = languageDAO;

  79.         this.projectScriptDAO = projectScriptDAO;
  80.         this.workflowScriptDAO = workflowScriptDAO;
  81.     }

  82.     public String getJndiPropertiesOverridePrefix() {
  83.         return jndiPropertiesOverridePrefix;
  84.     }

  85.     public void setJndiPropertiesOverridePrefix(String jndiPropertiesOverridePrefix) {
  86.         if (null != jndiPropertiesOverridePrefix) {
  87.             return;
  88.         }
  89.         this.jndiPropertiesOverridePrefix = jndiPropertiesOverridePrefix;
  90.     }

  91.     public String getMailSessionLookupName() {
  92.         return mailSessionLookupName;
  93.     }

  94.     public void setMailSessionLookupName(String mailSessionLookupName) {
  95.         this.mailSessionLookupName = mailSessionLookupName;
  96.     }

  97.     public String getProperty(String name) {
  98.         String value = null;
  99.         if (null != getJndiPropertiesOverridePrefix()) {

  100.             if (logger.isDebugEnabled()) {

  101.                 logger.debug("getProperty: looking up '" + name
  102.                         + "' from jndi context "
  103.                         + getJndiPropertiesOverridePrefix());


  104.             }
  105.             try {
  106.                 value = NamingUtilites.getStringValue(new InitialContext(),
  107.                         getJndiPropertiesOverridePrefix() + "/" + name, null);
  108.                 if (null == value) {
  109.                     if (logger.isDebugEnabled()) {
  110.                         logger.debug("getProperty: value not found in jndi: " + name);
  111.                     }
  112.                 }
  113.             } catch (Exception e) {
  114.                 logger.debug("getProperty: caught exception looking up value for " + name, e);
  115.             }

  116.         }

  117.         if (null == value) {
  118.             value = props.getProperty(name, null);
  119.         }
  120.         if (logger.isDebugEnabled()) {
  121.             logger.debug("getProperty: returning " + value + " for name: " + name);
  122.         }
  123.         return value;
  124.     }

  125.     public String getProperty(String name, String defaultValue) {
  126.         String val = getProperty(name);
  127.         return (val == null) ? defaultValue : val;
  128.     }

  129.     private String getItrackerVersion() {
  130.         return props.getProperty("version");
  131.     }


  132.     public boolean getBooleanProperty(String name, boolean defaultValue) {
  133.         String value = getProperty(name);

  134.         return (value == null ? defaultValue : Boolean.valueOf(value));
  135.     }

  136.     public int getIntegerProperty(String name, int defaultValue) {
  137.         String value = getProperty(name);

  138.         try {
  139.             return (value == null) ? defaultValue : Integer.parseInt(value);
  140.         } catch (NumberFormatException ex) {
  141.             return defaultValue;
  142.         }

  143.     }

  144.     public long getLongProperty(String name, long defaultValue) {
  145.         String value = getProperty(name);
  146.         try {
  147.             return (value == null) ? defaultValue : Long.parseLong(value);
  148.         } catch (NumberFormatException ex) {
  149.             return defaultValue;
  150.         }

  151.     }

  152.     public Configuration getConfigurationItem(Integer id) {
  153.         Configuration configItem = configurationDAO.findByPrimaryKey(id);
  154.         return configItem;
  155.     }

  156.     @Deprecated
  157.     public List<Configuration> getConfigurationItemsByType(int type) {
  158.         return getConfigurationItemsByType(Configuration.Type.valueOf(type));
  159.     }

  160.     public List<Configuration> getConfigurationItemsByType(Configuration.Type type) {
  161.         List<Configuration> configItems = configurationDAO.findByType(type);
  162.         Collections.sort(configItems, new Configuration.ConfigurationOrderComparator());
  163.         return configItems;
  164.     }

  165.     @Deprecated
  166.     public List<Configuration> getConfigurationItemsByType(int type, Locale locale) {
  167.         return getConfigurationItemsByType(Configuration.Type.valueOf(type), locale);
  168.     }

  169.     public List<Configuration> getConfigurationItemsByType(Configuration.Type type, Locale locale) {
  170.         List<Configuration> items = getConfigurationItemsByType(type);

  171.         for (int i = 0; i < items.size(); i++) {
  172.             if (items.get(i).getType() == Configuration.Type.status) {
  173.                 items.get(i).setName(IssueUtilities.getStatusName(items.get(i).getValue(), locale));
  174.             } else if (items.get(i).getType() == Configuration.Type.severity) {
  175.                 items.get(i).setName(IssueUtilities.getSeverityName(items.get(i).getValue(), locale));
  176.             } else if (items.get(i).getType() == Configuration.Type.resolution) {
  177.                 items.get(i).setName(IssueUtilities.getResolutionName(items.get(i).getValue(), locale));
  178.             }
  179.         }
  180.         return items;
  181.     }

  182.     public Configuration createConfigurationItem(Configuration configuration) {

  183.         Configuration configurationItem = new Configuration();

  184.         configurationItem.setType(configuration.getType());
  185.         configurationItem.setOrder(configuration.getOrder());
  186.         configurationItem.setValue(configuration.getValue());
  187.         configurationItem.setCreateDate(new Date());
  188.         configurationItem.setVersion(getItrackerVersion());
  189.         configurationDAO.saveOrUpdate(configurationItem);

  190.         return configurationItem;

  191.     }


  192.     public Configuration updateConfigurationItem(Configuration configuration) {
  193.         // find item by primary key
  194.         Configuration configurationItem = configurationDAO.findByPrimaryKey(configuration.getId());

  195.         configurationItem.setVersion(getInitializedVersionString());

  196.         // update now
  197.         configurationDAO.saveOrUpdate(configurationItem);
  198.         // get model from saved item
  199.         return configurationItem;
  200.     }

  201.     @Deprecated
  202.     public List<Configuration> updateConfigurationItems(List<Configuration> configurations, Configuration.Type type) {

  203.         List<Configuration> configurationItems = new ArrayList<Configuration>();
  204.         for (Configuration configurationItem : configurations) {
  205.             if (type == configurationItem.getType()) {
  206.                 // create a new item
  207.                 Configuration curConfiguration = configurationDAO.findByPrimaryKey(configurationItem.getId());

  208.                 curConfiguration.setName(configurationItem.getName());
  209.                 curConfiguration.setOrder(configurationItem.getOrder());
  210.                 curConfiguration.setType(configurationItem.getType());
  211.                 curConfiguration.setValue(configurationItem.getValue());
  212.                 curConfiguration.setVersion(getInitializedVersionString());

  213.                 // save or update
  214.                 this.configurationDAO.saveOrUpdate(curConfiguration);
  215.                 configurationItems.add(curConfiguration);
  216.             }
  217.         }
  218.         // sort array
  219.         Collections.sort(configurationItems);

  220.         return configurationItems;
  221.     }

  222.     /**
  223.      * Finds the <code>Configuration</code> by primary key <code>id<code>
  224.      * and deletes it.
  225.      *
  226.      * @param id The id of the <code>COnfigurationBean</code> to remove
  227.      */
  228.     public void removeConfigurationItem(Integer id) {

  229.         Configuration configBean = this.configurationDAO.findByPrimaryKey(id);
  230.         if (configBean != null) {
  231.             this.configurationDAO.delete(configBean);
  232.         }
  233.     }

  234.     /**
  235.      * Removes all <code>Configuration</code>s of the give <code>type</code>
  236.      *
  237.      * @param type the type of <code>Configuration</code> to remove
  238.      * @deprecated
  239.      */
  240.     public void removeConfigurationItems(int type) {
  241.         removeConfigurationItems(Configuration.Type.valueOf(type));
  242.     }

  243.     /**
  244.      * Removes all <code>Configuration</code>s of the give <code>type</code>
  245.      *
  246.      * @param type the type of <code>Configuration</code> to remove
  247.      */
  248.     public void removeConfigurationItems(Configuration.Type type) {

  249.         // find the configuration beans by its type
  250.         Collection<Configuration> currentItems = configurationDAO.findByType(type);

  251.         for (Iterator<Configuration> iter = currentItems.iterator(); iter.hasNext(); ) {
  252.             // get current config bean
  253.             Configuration config = (Configuration) iter.next();
  254.             // delete it
  255.             this.configurationDAO.delete(config);
  256.         }
  257.     }

  258.     public void removeConfigurationItems(Configuration configuration) {
  259.         Collection<Configuration> currentItems = configurationDAO.findByTypeAndValue(configuration.getType(), configuration.getValue());
  260.         for (Iterator<Configuration> iter = currentItems.iterator(); iter.hasNext(); ) {
  261.             Configuration configItem = (Configuration) iter.next();
  262.             configurationDAO.delete(configItem);
  263.         }
  264.     }

  265.     public boolean configurationItemExists(Configuration configuration) {

  266.         if (configuration != null && configuration.getVersion() != null) {

  267.             Collection<Configuration> configItems = configurationDAO.findByTypeAndValue(configuration.getType(), configuration.getValue());

  268.             if (configItems != null && configItems.size() > 0) {

  269.                 return true;

  270.             }

  271.         }

  272.         return false;

  273.     }

  274.     public String getInitializedVersionString() {
  275.         List<Configuration> initialized = getConfigurationItemsByType(Configuration.Type.initialized);
  276.         if (null == initialized || initialized.isEmpty()) {
  277.             return "0";
  278.         }
  279.         Collections.sort(initialized, new Comparator<Configuration>() {
  280.             public int compare(Configuration configuration, Configuration configuration1) {
  281.                 return configuration.getVersion().compareTo(configuration1.getVersion());
  282.             }
  283.         });

  284.         return initialized.get(initialized.size() - 1).getVersion();
  285.     }

  286.     public boolean isConfigurationItemUpToDate(Configuration configuration) {

  287.         if (null == configuration) {
  288.             return false;
  289.         }

  290.         if (StringUtils.endsWith(configuration.getVersion(), "-SNAPSHOT")) {
  291.             return false;
  292.         }

  293.         long currentVersion = SystemConfigurationUtilities.getVersionAsLong(getInitializedVersionString());

  294.         if (configuration != null && configuration.getVersion() != null) {

  295.             Collection<Configuration> configItems = configurationDAO.findByTypeAndValue(configuration.getType(), configuration.getValue());

  296.             for (Iterator<Configuration> iter = configItems.iterator(); iter.hasNext(); ) {

  297.                 Configuration configItem = (Configuration) iter.next();

  298.                 if (null != configItem) {

  299.                     currentVersion = Math.max(SystemConfigurationUtilities.getVersionAsLong(configItem.getVersion()),
  300.                             currentVersion);

  301.                 }

  302.             }

  303.             if (currentVersion >= SystemConfigurationUtilities.getVersionAsLong(configuration.getVersion())) {

  304.                 return true;

  305.             }

  306.         }

  307.         return false;

  308.     }

  309.     public void resetConfigurationCache() {

  310.         IssueUtilities.setResolutions(getConfigurationItemsByType(Configuration.Type.resolution));
  311.         IssueUtilities.setSeverities(getConfigurationItemsByType(Configuration.Type.severity));
  312.         IssueUtilities.setStatuses(getConfigurationItemsByType(Configuration.Type.status));
  313.         IssueUtilities.setCustomFields(getCustomFields());

  314.     }

  315.     public void resetConfigurationCache(Configuration.Type type) {
  316.         switch (type) {
  317.             case resolution:
  318.                 IssueUtilities.setResolutions(getConfigurationItemsByType(type));
  319.                 break;
  320.             case severity:
  321.                 IssueUtilities.setSeverities(getConfigurationItemsByType(Configuration.Type.severity));
  322.                 break;
  323.             case status:
  324.                 IssueUtilities.setStatuses(getConfigurationItemsByType(Configuration.Type.status));
  325.                 break;
  326.             case customfield:
  327.                 IssueUtilities.setCustomFields(getCustomFields());
  328.                 break;
  329.             default:
  330.                 logger.warn("resetConfigurationCache: unsupported type " + type);

  331.         }
  332.     }

  333.     @Deprecated
  334.     public void resetConfigurationCache(int type) {
  335.         logger.warn("resetConfigurationCache: called with deprecated API!");
  336.         resetConfigurationCache(Configuration.Type.valueOf(type));

  337.     }

  338.     public ProjectScript getProjectScript(Integer scriptId) {
  339.         ProjectScript projectScript = this.projectScriptDAO.findByPrimaryKey(scriptId);
  340.         return projectScript;

  341.     }

  342.     public List<ProjectScript> getProjectScripts() {
  343.         List<ProjectScript> projectScripts = this.projectScriptDAO.findAll();
  344.         return projectScripts;
  345.     }


  346.     public ProjectScript createProjectScript(ProjectScript projectScript) {

  347.         // create project script and populate data
  348.         ProjectScript editprojectScript = new ProjectScript();
  349.         editprojectScript.setFieldId(projectScript.getFieldId());
  350.         editprojectScript.setFieldType(projectScript.getFieldType());
  351.         editprojectScript.setPriority(projectScript.getPriority());
  352.         editprojectScript.setProject(projectScript.getProject());
  353.         editprojectScript.setScript(projectScript.getScript());

  354.         // save entity
  355.         this.projectScriptDAO.save(editprojectScript);

  356.         return editprojectScript;
  357.     }

  358.     public ProjectScript updateProjectScript(ProjectScript projectScript) {
  359.         ProjectScript editprojectScript;

  360.         editprojectScript = projectScriptDAO.findByPrimaryKey(projectScript.getId());
  361.         editprojectScript.setFieldId(projectScript.getFieldId());
  362.         editprojectScript.setFieldType(projectScript.getFieldType());
  363.         editprojectScript.setPriority(projectScript.getPriority());
  364.         editprojectScript.setProject(projectScript.getProject());
  365.         editprojectScript.setScript(projectScript.getScript());
  366.         this.projectScriptDAO.saveOrUpdate(editprojectScript);
  367.         return editprojectScript;
  368.     }

  369.     /**
  370.      * remove a project script by its id
  371.      *
  372.      * @param projectScript_id the id of the project script to remove
  373.      */
  374.     public void removeProjectScript(Integer projectScript_id) {
  375.         if (projectScript_id != null) {
  376.             ProjectScript projectScript = this.projectScriptDAO.findByPrimaryKey(projectScript_id);
  377.             if (projectScript != null) {
  378.                 this.projectScriptDAO.delete(projectScript);
  379.             }
  380.         }
  381.     }

  382.     public WorkflowScript getWorkflowScript(Integer id) {

  383.         WorkflowScript workflowScript = workflowScriptDAO.findByPrimaryKey(id);

  384.         return workflowScript;

  385.     }

  386.     public List<WorkflowScript> getWorkflowScripts() {
  387.         List<WorkflowScript> workflowScripts = workflowScriptDAO.findAll();
  388.         return workflowScripts;
  389.     }

  390.     /**
  391.      * Creates a workflow script.
  392.      *
  393.      * @param workflowScript The <code>WorkflowScript</code> carring the data
  394.      * @return The <code>WorkflowScript</code> after inserting
  395.      */
  396.     public WorkflowScript createWorkflowScript(WorkflowScript workflowScript) {

  397.         // create workflow script and populate data
  398.         WorkflowScript editworkflowScript = new WorkflowScript();
  399.         editworkflowScript.setName(workflowScript.getName());
  400.         editworkflowScript.setScript(workflowScript.getScript());
  401.         editworkflowScript.setEvent(workflowScript.getEvent());
  402.         editworkflowScript.setLanguage(workflowScript.getLanguage());
  403.         // save entity
  404.         workflowScriptDAO.save(editworkflowScript);

  405.         return editworkflowScript;
  406.     }

  407.     public WorkflowScript updateWorkflowScript(WorkflowScript workflowScript) {
  408.         WorkflowScript editworkflowScript;

  409.         editworkflowScript = workflowScriptDAO.findByPrimaryKey(workflowScript.getId());
  410.         editworkflowScript.setName(workflowScript.getName());
  411.         editworkflowScript.setScript(workflowScript.getScript());
  412.         editworkflowScript.setEvent(workflowScript.getEvent());
  413.         editworkflowScript.setLanguage(workflowScript.getLanguage());
  414.         workflowScriptDAO.saveOrUpdate(editworkflowScript);
  415.         return editworkflowScript;
  416.     }

  417.     /**
  418.      * remove a workflow script by its id
  419.      *
  420.      * @param workflowScript_id the id of the workflow script to remove
  421.      */
  422.     public void removeWorkflowScript(Integer workflowScript_id) {
  423.         if (workflowScript_id != null) {
  424.             WorkflowScript workflowScript = this.workflowScriptDAO.findByPrimaryKey(workflowScript_id);
  425.             if (workflowScript != null) {
  426.                 this.workflowScriptDAO.delete(workflowScript);
  427.             }
  428.         }
  429.     }

  430.     public CustomField getCustomField(Integer id) {

  431.         CustomField customField = customFieldDAO.findByPrimaryKey(id);

  432.         return customField;

  433.     }

  434.     @Deprecated
  435.     public List<CustomField> getCustomFields() {
  436.         return getCustomFieldsSorted(null);
  437.     }

  438.     public List<CustomField> getCustomFieldsSorted(Locale locale) {
  439.         List<CustomField> customFields = customFieldDAO.findAll();
  440.         Collections.sort(customFields, new CustomFieldUtilities.CustomFieldByNameComparator((null == locale)
  441.                 ? ITrackerResources.getLocale(ITrackerResources.getDefaultLocale())
  442.                 : locale));
  443.         return customFields;
  444.     }

  445.     /**
  446.      * Creates a custom field
  447.      *
  448.      * @param customField The <code>CustomField</code> carrying the data
  449.      * @return the <code>CustomField</code> after saving
  450.      */
  451.     public CustomField createCustomField(CustomField customField) {
  452.         CustomField addcustomField = new CustomField();
  453.         addcustomField.setDateFormat(customField.getDateFormat());
  454.         addcustomField.setFieldType(customField.getFieldType());
  455.         addcustomField.setOptions(customField.getOptions());
  456.         addcustomField.setRequired(customField.isRequired());
  457.         this.customFieldDAO.save(addcustomField);

  458.         return addcustomField;
  459.     }

  460.     public CustomField updateCustomField(CustomField customField) {
  461.         CustomField editcustomField = customFieldDAO.findByPrimaryKey(customField.getId());

  462.         editcustomField.setDateFormat(customField.getDateFormat());
  463.         editcustomField.setFieldType(customField.getFieldType());
  464.         editcustomField.setOptions(customField.getOptions());
  465.         editcustomField.setRequired(customField.isRequired());
  466.         this.customFieldDAO.saveOrUpdate(editcustomField);

  467.         return editcustomField;
  468.     }

  469.     /**
  470.      * searches for a custom field by primary key and removes it
  471.      *
  472.      * @param customFieldId the primary key
  473.      */
  474.     public boolean removeCustomField(Integer customFieldId) {
  475.         boolean status = true;
  476.         boolean del_Status = true;
  477.         CustomField customField = customFieldDAO.findByPrimaryKey(customFieldId);

  478.         if (customField != null) {
  479.             try {
  480.                 if (customField.getFieldType() == CustomField.Type.LIST)
  481.                     status = this.removeCustomFieldValues(customFieldId);
  482.                 String key = CustomFieldUtilities.getCustomFieldLabelKey(customField.getId());
  483.                 this.customFieldDAO.delete(customField);
  484.                 if (key != null)
  485.                     status = this.removeLanguageKey(key);
  486.             } catch (Exception ex) {
  487.                 del_Status = false;
  488.             }
  489.         }
  490.         if (!del_Status)
  491.             status = del_Status;

  492.         return status;
  493.     }


  494.     /**
  495.      * Gets a <code>CustomFieldValue</code> by primary key
  496.      *
  497.      * @param id the primary key
  498.      * @return The <code>CustomFieldValue</code> found or <code>null</code>
  499.      */
  500.     public CustomFieldValue getCustomFieldValue(Integer id) {

  501.         CustomFieldValue cfvBean = (CustomFieldValue)
  502.                 this.customFieldValueDAO.findByPrimaryKey(id);

  503.         return cfvBean;
  504.     }

  505.     public CustomFieldValue createCustomFieldValue(CustomFieldValue customFieldValue) {
  506.         CustomFieldValue addcustomFieldValue = new CustomFieldValue();
  507.         addcustomFieldValue.setCustomField(customFieldValue.getCustomField());
  508.         addcustomFieldValue.setValue(customFieldValue.getValue());
  509.         this.customFieldValueDAO.save(addcustomFieldValue);

  510.         return addcustomFieldValue;
  511.     }


  512.     /**
  513.      * Updates a <code>CustomFieldValue</code>.
  514.      *
  515.      * @param customFieldValue The model to update
  516.      * @return The <code>CustomFieldValue</code> after saving
  517.      */
  518.     public CustomFieldValue updateCustomFieldValue(CustomFieldValue customFieldValue) {
  519.         CustomFieldValue editcustomFieldValue = this.customFieldValueDAO.findByPrimaryKey(customFieldValue.getId());
  520.         editcustomFieldValue.setCustomField(customFieldValue.getCustomField());
  521.         editcustomFieldValue.setValue(customFieldValue.getValue());
  522.         this.customFieldValueDAO.saveOrUpdate(editcustomFieldValue);

  523.         return editcustomFieldValue;
  524.     }

  525.     public List<CustomFieldValue> updateCustomFieldValues(Integer customFieldId, List<CustomFieldValue> customFieldValues) {
  526.         List<CustomFieldValue> customFieldValueItems = new ArrayList<CustomFieldValue>();

  527.         if (customFieldId != null) {
  528.             try {
  529.                 CustomField customField = customFieldDAO.findByPrimaryKey(customFieldId);
  530.                 if (customFieldValues != null && !customFieldValues.isEmpty()) {
  531.                     for (Iterator<CustomFieldValue> iterator = customFieldValues.iterator(); iterator.hasNext(); ) {

  532.                         // create a new item
  533.                         CustomFieldValue customFieldValueItem = (CustomFieldValue) iterator.next();
  534.                         CustomFieldValue curCustomFieldValue = customFieldValueDAO.findByPrimaryKey(customFieldValueItem.getId());

  535.                         curCustomFieldValue.setCreateDate(customFieldValueItem.getCreateDate());
  536.                         curCustomFieldValue.setValue(customFieldValueItem.getValue());
  537.                         curCustomFieldValue.setCustomField(customFieldValueItem.getCustomField());
  538.                         curCustomFieldValue.setSortOrder(customFieldValueItem.getSortOrder());

  539.                         // save or update
  540.                         this.customFieldValueDAO.saveOrUpdate(curCustomFieldValue);
  541.                         customFieldValueItems.add(curCustomFieldValue);

  542.                     }
  543.                     customField.setOptions(customFieldValueItems);
  544.                     return customFieldValueItems;

  545.                 }
  546.             } catch (Exception fe) {
  547.             }
  548.         }

  549.         return customFieldValues;
  550.     }

  551.     /**
  552.      * removes a custom field value by primary key
  553.      *
  554.      * @param customFieldValueId the id of the custoem field
  555.      */
  556.     public boolean removeCustomFieldValue(Integer customFieldValueId) {
  557.         boolean status = true;
  558.         boolean del_Status = true;

  559.         // find custom field value by id
  560.         CustomFieldValue customFieldValue = this.customFieldValueDAO.findByPrimaryKey(customFieldValueId);

  561.         // delete it
  562.         try {
  563.             this.customFieldValueDAO.delete(customFieldValue);
  564.         } catch (Exception ex) {
  565.             del_Status = false;
  566.         }
  567.         if (!del_Status)
  568.             status = del_Status;

  569.         return status;
  570.     }

  571.     /**
  572.      * Removes all field values of a given custom field
  573.      *
  574.      * @param customFieldId The id of the customField
  575.      */
  576.     public boolean removeCustomFieldValues(Integer customFieldId) {
  577.         boolean status = true;
  578.         boolean lp_Status = true;
  579.         CustomField customField = this.customFieldDAO.findByPrimaryKey(customFieldId);
  580.         // get values of the field
  581.         List<CustomFieldValue> customFieldValues = customField.getOptions();
  582.         for (Iterator<CustomFieldValue> iter = customFieldValues.iterator(); iter.hasNext(); ) {
  583.             // get current
  584.             CustomFieldValue customFieldValue = (CustomFieldValue) iter.next();
  585.             String key = CustomFieldUtilities.getCustomFieldOptionLabelKey(customFieldId, customFieldValue.getId());
  586.             // remove from collection
  587.             iter.remove();
  588.             // delete from datasource
  589.             try {
  590.                 this.customFieldValueDAO.delete(customFieldValue);

  591.                 if (key != null)
  592.                     status = this.removeLanguageKey(key);
  593.             } catch (Exception ex) {
  594.                 lp_Status = false;
  595.             }
  596.         }
  597.         if (!lp_Status)
  598.             status = lp_Status;

  599.         return status;
  600.     }

  601.     @Override
  602.     public String getLanguageValue(String key, Locale locale) {
  603.         return getLanguageItemByKey(key, locale).getResourceValue();
  604.     }

  605.     @Override
  606.     public String getLanguageEntry(String key, Locale locale) {
  607.         try {
  608.             Language l = getLanguageItemByKey(key, locale);
  609.             return l.getResourceValue();
  610.         } catch (NoSuchEntityException e) {
  611.             logger.debug("failed to get entry", e);
  612.         }
  613.         throw new MissingResourceException("Entry doesn't exist.", Language.class.getName(), key);
  614.     }

  615.     @Override
  616.     public Language getLanguageItemByKey(String key, Locale locale) {
  617.         String localeString = ITrackerResources.BASE_LOCALE;
  618.         if (null != locale
  619.                 && !locale.equals(ITrackerResources.getLocale(ITrackerResources.BASE_LOCALE))) {
  620.             localeString = locale.toString();
  621.         }
  622.         Language languageItem = languageDAO.findByKeyAndLocale(key, localeString);
  623.         // TODO: obsolete code:
  624. //        try {
  625. //            languageItem = languageDAO.findByKeyAndLocale(key, ITrackerResources.BASE_LOCALE);
  626. //        } catch (RuntimeException e) {
  627. //            logger.debug("could not find {} with BASE", key);
  628. //            languageItem = null;
  629. //        }
  630. //
  631. //        if (null == locale) {
  632. //            logger.debug("locale was null, returning BASE: {}", languageItem);
  633. //            return languageItem;
  634. //        }
  635. //        try {
  636. //            languageItem = languageDAO.findByKeyAndLocale(key, locale.getLanguage());
  637. //        } catch (RuntimeException re) {
  638. //            logger.debug("could not find {} with language {}", key, locale.getLanguage());
  639. //        }
  640. //        if (StringUtils.isNotEmpty(locale.getCountry())) {
  641. //            try {
  642. //                languageItem = languageDAO.findByKeyAndLocale(key, locale.toString());
  643. //            } catch (RuntimeException ex) {
  644. //                logger.debug("could not find {} with locale {}", key, locale);
  645. //            }
  646. //        }

  647.         return languageItem;

  648.     }

  649.     public List<Language> getLanguageItemsByKey(String key) {
  650.             List<Language> languageItems = languageDAO.findByKey(key);

  651.         return languageItems;
  652.     }

  653.     public Language updateLanguageItem(Language language) {
  654.         Language languageItem;

  655.         try {
  656.             languageItem = languageDAO.findByKeyAndLocale(language.getResourceKey(), language.getLocale());
  657.             languageItem.setLocale(language.getLocale());
  658.             languageItem.setResourceKey(language.getResourceKey());
  659.             languageItem.setResourceValue(language.getResourceValue());
  660.         } catch (NoSuchEntityException fe) {
  661.             logger.debug("NoSuchEntityException: Language, now populating Language");
  662.             languageItem = new Language();
  663.             languageItem.setLocale(language.getLocale());
  664.             languageItem.setResourceKey(language.getResourceKey());
  665.             languageItem.setResourceValue(language.getResourceValue());
  666.         }
  667.         logger.debug("Start saveOrUpdate Language");
  668.         languageDAO.saveOrUpdate(languageItem);
  669.         logger.debug("Saved Language");
  670.         return languageItem;
  671.     }

  672.     /**
  673.      * Removes all <code>Language</code>s with the give key
  674.      *
  675.      * @param key The key to be removed
  676.      */
  677.     public boolean removeLanguageKey(String key) {
  678.         boolean status = true;
  679.         boolean lp_Status = true;

  680.         // find all <code>Language</code>s for the given key
  681.         List<Language> languageItems = languageDAO.findByKey(key);

  682.         for (Iterator<Language> iter = languageItems.iterator(); iter.hasNext(); ) {
  683.             // delete current item
  684.             Language language = (Language) iter.next();
  685.             try {
  686.                 this.languageDAO.delete(language);
  687.             } catch (Exception ex) {
  688.                 lp_Status = false;
  689.             }
  690.         }
  691.         if (!lp_Status)
  692.             status = lp_Status;

  693.         return status;
  694.     }

  695.     /**
  696.      * Removes the <code>Language</code> passed as parameter
  697.      *
  698.      * @param language The <code>Language</code> to remove
  699.      */
  700.     public void removeLanguageItem(Language language) {

  701.         Language languageItem = languageDAO.findByKeyAndLocale(language.getResourceKey(), language.getLocale());

  702.         if (languageItem != null) {
  703.             // delete item
  704.             this.languageDAO.delete(languageItem);
  705.         }
  706.     }

  707.     public String[] getSortedKeys() {

  708.         int i = 0;
  709.         Collection<Language> items = languageDAO.findByLocale(ITrackerResources.BASE_LOCALE);
  710.         String[] sortedKeys = new String[items.size()];

  711.         for (Iterator<Language> iter = items.iterator(); iter.hasNext(); i++) {
  712.             Language item = (Language) iter.next();
  713.             sortedKeys[i] = item.getResourceKey();
  714.         }

  715.         // Now sort the list of keys in a logical manner

  716.         Arrays.sort(sortedKeys);
  717.         return sortedKeys;

  718.     }

  719.     public HashMap<String, String> getDefinedKeys(String locale) {

  720.         HashMap<String, String> keys = new HashMap<String, String>();

  721.         if (locale == null || locale.equals("")) {
  722.             locale = ITrackerResources.BASE_LOCALE;
  723.         }


  724.         Collection<Language> items = languageDAO.findByLocale(locale);
  725.         for (Iterator<Language> iter = items.iterator(); iter.hasNext(); ) {
  726.             Language item = iter.next();
  727.             keys.put(item.getResourceKey(), item.getResourceValue());
  728.         }


  729.         return keys;

  730.     }

  731.     public List<NameValuePair> getDefinedKeysAsArray(String locale) {
  732.         NameValuePair[] keys = null;
  733.         if (locale == null || locale.equals("")) {
  734.             locale = ITrackerResources.BASE_LOCALE;
  735.         }

  736.         int i = 0;
  737.         Collection<Language> items = languageDAO.findByLocale(locale);
  738.         keys = new NameValuePair[items.size()];

  739.         for (Iterator<Language> iter = items.iterator(); iter.hasNext(); i++) {
  740.             Language item = (Language) iter.next();
  741.             keys[i] = new NameValuePair(item.getResourceKey(), item.getResourceValue());
  742.         }

  743.         Arrays.sort(keys);
  744.         return Arrays.asList(keys);

  745.     }

  746.     public int getNumberDefinedKeys(String locale) {

  747.         return getDefinedKeys(locale).size();

  748.     }

  749.     private List<Language> getLanguage(Locale locale) {
  750.         Map<String, String> language = new HashMap<String, String>();
  751.         if (locale == null) {
  752.             locale = new Locale("");
  753.         }
  754.         String localeString = (locale.toString().equals("") ? ITrackerResources.BASE_LOCALE : locale.toString());

  755.         Collection<Language> items = languageDAO.findByLocale(localeString);
  756.         for (Language item : items) {
  757.             language.put(item.getResourceKey(), item.getResourceValue());
  758.         }

  759.         Language[] languageArray = new Language[language.size()];
  760.         int i = 0;

  761.         for (String key : language.keySet()) {
  762.             languageArray[i] = new Language(localeString, key, language.get(key));
  763.             i++;
  764.         }
  765.         return Arrays.asList(languageArray);
  766.     }

  767.     public Properties getLanguageProperties(Locale locale) {
  768.         Properties properties = new Properties();
  769.         List<Language> lang = getLanguage(locale);
  770.         for (Language l : lang) {
  771.             properties.put(l.getResourceKey(), l.getResourceValue());
  772.         }
  773.         return properties;
  774.     }

  775.     public Map<String, List<String>> getAvailableLanguages() {

  776.         final TreeMap<String, List<String>> languages = new TreeMap<>();
  777.         final List<Configuration> locales = getConfigurationItemsByType(Configuration.Type.locale);

  778.         for (int i = 0; i < locales.size(); i++) {
  779.             String baselocalestring = locales.get(i).getValue();
  780.             if (baselocalestring.length() == 2) {
  781.                 List<String> languageList = new ArrayList<>();
  782.                 final String l = baselocalestring;

  783.                 languageList.addAll(
  784.                         CollectionUtils.collect(locales, new Transformer() {
  785.                             @Override
  786.                             public Object transform(Object input) {
  787.                                 String val = ((Configuration) input).getValue();
  788.                                 if (val.length() > 2 &&
  789.                                         val.startsWith(l + "_")) {
  790.                                     return val;
  791.                                 }
  792.                                 return null;
  793.                             }
  794.                         }));
  795.                 CollectionUtils.filter(languageList, NotNullPredicate.getInstance());
  796.                 languages.put(baselocalestring, languageList);
  797.             }
  798.         }


  799.         return languages;

  800.     }

  801.     @SuppressWarnings("unchecked")
  802.     public int getNumberAvailableLanguages() {

  803.         int numLanguages = 0;
  804.         Map<String, List<String>> availableLanguages = getAvailableLanguages();

  805.         for (Iterator iter = availableLanguages.keySet().iterator(); iter.hasNext(); ) {
  806.             List<List> languages = new ArrayList<>();
  807.             List list = availableLanguages.get(iter.next());
  808.             languages.add(list);

  809.             if (languages != null && languages.size() > 0) {
  810.                 numLanguages += languages.size();
  811.             } else {
  812.                 numLanguages += 1;
  813.             }

  814.         }

  815.         return numLanguages;

  816.     }

  817.     public void updateLanguage(Locale locale, List<Language> items) {

  818.         if (locale != null && items != null) {
  819.             Configuration configItem = new Configuration(Configuration.Type.locale, locale
  820.                     .toString(), getItrackerVersion());
  821.             updateLanguage(locale, items, configItem);

  822.         }

  823.     }

  824.     public void updateLanguage(Locale locale, List<Language> items, Configuration configItem) {
  825.         for (int i = 0; i < items.size(); i++) {

  826.             if (items.get(i) != null) {
  827.                 updateLanguageItem(items.get(i));
  828.             }
  829.         }
  830.         removeConfigurationItems(configItem);
  831.         createConfigurationItem(configItem);
  832.     }

  833.     public SystemConfiguration getSystemConfiguration(Locale locale) {

  834.         SystemConfiguration config = new SystemConfiguration();

  835.         // Load the basic system configuration

  836.         List<Configuration> resolutions = getConfigurationItemsByType(Configuration.Type.resolution);

  837.         for (int i = 0; i < resolutions.size(); i++) {

  838.             resolutions.get(i).setName(ITrackerResources.getString(SystemConfigurationUtilities
  839.                     .getLanguageKey(resolutions.get(i)), locale));

  840.         }

  841.         config.setResolutions(resolutions);

  842.         List<Configuration> severities = getConfigurationItemsByType(Configuration.Type.severity);

  843.         for (int i = 0; i < severities.size(); i++) {

  844.             severities.get(i).setName(ITrackerResources.getString(SystemConfigurationUtilities
  845.                     .getLanguageKey(severities.get(i)), locale));

  846.         }

  847.         config.setSeverities(severities);

  848.         List<Configuration> statuses = getConfigurationItemsByType(Configuration.Type.status);

  849.         for (int i = 0; i < statuses.size(); i++) {

  850.             statuses.get(i).setName(ITrackerResources.getString(SystemConfigurationUtilities.getLanguageKey(statuses.get(i)),
  851.                     locale));

  852.         }

  853.         config.setStatuses(statuses);

  854.         List<CustomField> customFields = getCustomFields();

  855.         config.setCustomFields(customFields);


  856.         // Now set the system version

  857.         config.setVersion(getItrackerVersion());

  858.         return config;

  859.     }


  860.     public boolean initializeLocale(String locale, boolean forceReload) {
  861.         boolean result = false;

  862.         Configuration localeConfig = new Configuration(Configuration.Type.locale, locale,
  863.                 getItrackerVersion());

  864.         if (!isConfigurationItemUpToDate(localeConfig) || forceReload) {

  865.             logger.debug("Loading database with locale " + locale);

  866.             removeConfigurationItems(localeConfig);
  867. //                
  868.             createConfigurationItem(localeConfig);
  869. //                
  870.             ITrackerResources.clearBundle(ITrackerResources.getLocale(locale));

  871.             result = true;


  872.         }

  873.         return result;

  874.     }

  875.     public void initializeConfiguration() {

  876.         // TODO when current version is outdated?
  877.         long current = SystemConfigurationUtilities.getVersionAsLong(getItrackerVersion());

  878.         long initialized = SystemConfigurationUtilities.getVersionAsLong(getInitializedVersionString());

  879.         if (0 == initialized) {

  880.             logger.info("System does not appear to be initialized, initializing system configuration.");

  881.             ResourceBundle baseLanguage = ITrackerResources.getBundle(ITrackerResources.getLocale(ITrackerResources.BASE_LOCALE));
  882.             getLanguage(ITrackerResources.getLocale(ITrackerResources.BASE_LOCALE));

  883.             if (baseLanguage == null) {

  884.                 throw new IllegalStateException(
  885.                         "Languages must be initialized before the system configuration can be loaded.");

  886.             }

  887.             // Remove any previous configuration information, possibly left
  888.             // over from previous failed initialization

  889.             logger.debug("Removing previous incomplete initialization information.");

  890.             removeConfigurationItems(Configuration.Type.status);

  891.             removeConfigurationItems(Configuration.Type.severity);

  892.             removeConfigurationItems(Configuration.Type.resolution);

  893.             Set<String> keys = baseLanguage.keySet();
  894.             for (final String key : keys) {
  895.                 if (key.startsWith(ITrackerResources.KEY_BASE_RESOLUTION)) {

  896.                     try {

  897.                         String resolutionString = key.substring(20);
  898.                         if (logger.isDebugEnabled()) {
  899.                             logger.debug("Adding new configuration resolution value: " + resolutionString);
  900.                         }
  901.                         int resolutionNumber = Integer.parseInt(resolutionString);

  902.                         createConfigurationItem(new Configuration(
  903.                                 Configuration.Type.resolution, resolutionString, getItrackerVersion(),
  904.                                 resolutionNumber));

  905.                     } catch (RuntimeException e) {

  906.                         logger.error("Unable to load resolution value: " + key, e);
  907.                         throw e;

  908.                     }

  909.                 }

  910.                 if (key.startsWith(ITrackerResources.KEY_BASE_SEVERITY)) {

  911.                     try {

  912.                         String severityString = key.substring(18);

  913.                         logger.debug("Adding new configuration severity value: " + severityString);

  914.                         int severityNumber = Integer.parseInt(severityString);

  915.                         createConfigurationItem(new Configuration(Configuration.Type.severity,
  916.                                 severityString, getItrackerVersion(), severityNumber));

  917.                     } catch (RuntimeException e) {

  918.                         logger.error("Unable to load severity value: " + key, e);
  919.                         throw e;
  920.                     }

  921.                 }

  922.                 if (key.startsWith(ITrackerResources.KEY_BASE_STATUS)) {

  923.                     try {

  924.                         String statusString = key.substring(16);

  925.                         logger.debug("Adding new configuration status value: " + statusString);

  926.                         int statusNumber = Integer.parseInt(statusString);

  927.                         createConfigurationItem(new Configuration(Configuration.Type.status,
  928.                                 statusString, getItrackerVersion(), statusNumber));
  929.                     } catch (RuntimeException e) {
  930.                         logger.error("Unable to load status value: " + key, e);
  931.                         throw e;
  932.                     }
  933.                 }
  934.             }


  935.             createConfigurationItem(new Configuration(Configuration.Type.initialized, "1",
  936.                     getItrackerVersion()));
  937.         }


  938.     }

  939.     public LanguageDAO getLanguageDAO() {
  940.         return languageDAO;
  941.     }

  942.     public ConfigurationDAO getConfigurationDAO() {
  943.         return configurationDAO;
  944.     }

  945.     public CustomFieldDAO getCustomFieldDAO() {
  946.         return customFieldDAO;
  947.     }

  948.     public CustomFieldValueDAO getCustomFieldValueDAO() {
  949.         return customFieldValueDAO;
  950.     }

  951.     public WorkflowScriptDAO getWorkflowScriptDAO() {
  952.         return workflowScriptDAO;
  953.     }

  954.     public String getSystemBaseURL() {
  955.         return getProperty(PNAME_SYSTEM_BASE_URL);
  956.     }


  957.     /**
  958.      * This method will attempt to load all of the locales defined in the
  959.      * ITracker.properties file, and add them to the database if they don't
  960.      * already exist.
  961.      *
  962.      * @param forceReload if true, it will reload the languages from the property files
  963.      *                    even if they are listed as being up to date
  964.      */
  965.     public void initializeAllLanguages(boolean forceReload) {
  966.         Set<String> definedLocales = new LinkedHashSet<>();

  967.         initializeLocale(ITrackerResources.BASE_LOCALE,
  968.                 forceReload);

  969.         String definedLocalesString;
  970.         try {
  971.             definedLocalesString =
  972.                     getProperty("available_locales", ITrackerResources.getDefaultLocale());
  973.         } catch (RuntimeException e) {
  974.             definedLocalesString = ITrackerResources.getString(ITrackerResources.getDefaultLocale());
  975.         }
  976.         if (definedLocalesString != null) {
  977.             StringTokenizer token = new StringTokenizer(definedLocalesString, ",");
  978.             while (token.hasMoreTokens()) {
  979.                 String locale = StringUtils.trim(token.nextToken());
  980.                 if (locale.length() == 5 && locale.indexOf('_') == 2) {
  981.                     definedLocales.add(locale.substring(0, 2));
  982.                 }
  983.                 definedLocales.add(locale);
  984.             }
  985.         }

  986. //        // apply configuration locales
  987. //        for (Configuration c: getConfigurationItemsByType(Configuration.Type.locale)) {
  988. //            if (!definedLocales.contains(c.getValue())) {
  989. //                logger.info("removing language configuration from database: {}, not in: {}", c, definedLocales);
  990. //                removeConfigurationItems(c);
  991. //            }
  992. //        }
  993.         for (String locale : definedLocales) {
  994.             initializeLocale(locale, forceReload);
  995.         }
  996.     }
  997. }