IssueField.java

  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. package org.itracker.model;

  19. import org.apache.commons.lang.builder.ToStringBuilder;
  20. import org.apache.log4j.Logger;
  21. import org.itracker.IssueException;
  22. import org.itracker.core.resources.ITrackerResources;
  23. import org.itracker.model.CustomField.Type;

  24. import java.text.SimpleDateFormat;
  25. import java.util.Date;
  26. import java.util.Locale;
  27. import java.util.ResourceBundle;

  28. /**
  29.  * A CustomField with its value for an Issue.
  30.  * <p/>
  31.  * <p>
  32.  * An IssueField can only belong to 1 Issue (composition).
  33.  * </p>
  34.  *
  35.  * @author ready
  36.  * @see CustomField
  37.  */
  38. public class IssueField extends AbstractEntity {

  39.     /**
  40.      *
  41.      */
  42.     private static final long serialVersionUID = 1L;

  43.     private static transient final Logger log = Logger
  44.             .getLogger(IssueField.class);

  45.     private Issue issue;

  46.     private CustomField customField;

  47.     private String stringValue;

  48.     private Integer intValue;

  49.     private Date dateValue;

  50.     /**
  51.      * Default constructor (required by Hibernate).
  52.      * <p/>
  53.      * <p>
  54.      * PENDING: should be <code>private</code> so that it can only be used by
  55.      * Hibernate, to ensure that the fields which form an instance's identity
  56.      * are always initialized/never <tt>null</tt>.
  57.      * </p>
  58.      */
  59.     public IssueField() {
  60.     }

  61.     public IssueField(Issue issue, CustomField field) {
  62.         setIssue(issue);
  63.         setCustomField(field);
  64.     }

  65.     public Issue getIssue() {
  66.         return issue;
  67.     }

  68.     public void setIssue(Issue issue) {
  69.         if (issue == null) {
  70.             throw new IllegalArgumentException("null issue");
  71.         }
  72.         this.issue = issue;
  73.     }

  74.     public CustomField getCustomField() {
  75.         return customField;
  76.     }

  77.     public void setCustomField(CustomField customField) {
  78.         if (customField == null) {
  79.             throw new IllegalArgumentException("null customField");
  80.         }
  81.         this.customField = customField;
  82.     }

  83.     public String getStringValue() {
  84.         if (null != this.getCustomField() && Type.DATE == this.getCustomField().getFieldType()) {
  85.             this.stringValue = "";
  86.             if (null != this.dateValue) {
  87.                 String stringValue = formatDate(ITrackerResources.getBundle(ITrackerResources.BASE_LOCALE));
  88.                 this.stringValue = stringValue;
  89.             }
  90.         }
  91.         return stringValue;
  92.     }

  93.     public void setStringValue(String stringValue) {
  94.         this.stringValue = stringValue;
  95.     }

  96.     public Integer getIntValue() {
  97.         return intValue;
  98.     }

  99.     public void setIntValue(Integer intValue) {
  100.         this.intValue = intValue;
  101.     }

  102.     public Date getDateValue() {
  103.         if (null == dateValue)
  104.             return null;
  105.         return new Date(dateValue.getTime());
  106.     }

  107.     public void setDateValue(Date dateValue) {
  108.         if (null == dateValue) {
  109.             this.dateValue = null;
  110.         } else {
  111.             this.dateValue = new Date(dateValue.getTime());
  112.             this.stringValue = formatDate(ITrackerResources.getBundle());
  113.         }
  114.     }

  115.     /**
  116.      * Gets the custom field value as a String.
  117.      *
  118.      * @param locale the locale used for any string formatting
  119.      * @return the current value of this field
  120.      */
  121.     public String getValue(Locale locale) {
  122.         // only date fields are currently localizable
  123.         if (getCustomField().getFieldType() == Type.DATE) {
  124.             return getValue(ITrackerResources.getBundle(locale));
  125.         } else if (getCustomField().getFieldType() == Type.INTEGER) {
  126.             return String.valueOf(getIntValue());
  127.         }
  128.         return getStringValue();

  129.     }

  130.     /**
  131.      * Gets the custom field value as a String.
  132.      *
  133.      * @param bundle a resource bundle to use for any string formatting
  134.      * @param locale a locale to use for any string formatting
  135.      * @return the current value of this field
  136.      * @deprecated use getValue(ResourceBundle bundle) instead, locale is taken
  137.      *             from bundle
  138.      */
  139.     public String getValue(ResourceBundle bundle, Locale locale) {
  140.         if (log.isDebugEnabled()) {
  141.             log.debug("getValue: called with bundle: " + bundle + ", locale: "
  142.                     + locale);
  143.         }
  144.         return getValue(bundle);
  145.     }

  146.     /**
  147.      * Gets the custom field value as a String.
  148.      *
  149.      * @param bundle a resource bundle to use for any string formatting
  150.      * @return the current value of this field
  151.      * @deprecated this can not be in the entity, replace by Utility or service.
  152.      */
  153.     public String getValue(ResourceBundle bundle) {

  154.         // skip this code, it's not approved
  155.         Locale locale = bundle.getLocale();

  156.         if (log.isDebugEnabled()) {
  157.             log.debug("getValue: called with bundle: " + bundle + ", locale: "
  158.                     + locale);
  159.         }
  160.         switch (customField.getFieldType()) {

  161.             case INTEGER:
  162.                 if (log.isDebugEnabled()) {
  163.                     log
  164.                             .debug("getValue: type was INTEGER, value: "
  165.                                     + this.intValue);
  166.                 }
  167.                 return String.valueOf(this.intValue);

  168.             case DATE:
  169.                 if (log.isDebugEnabled()) {
  170.                     log.debug("getValue: type was DATE, value: " + this.dateValue);
  171.                 }
  172.                 if (!customField.isRequired() && this.dateValue == null) {

  173.                     if (log.isDebugEnabled()) {
  174.                         log.debug("getValue: value was null and not required");
  175.                     }
  176.                     return null;
  177.                 }
  178.                 if (this.dateValue == null) {
  179.                     this.dateValue = new Date();
  180.                 }
  181.                 return formatDate(bundle);
  182.             default:
  183.                 return this.stringValue;
  184.         }

  185.     }

  186.     private String formatDate(ResourceBundle bundle) {
  187.         assert (dateValue != null) : "dateValue failed";
  188.         try {

  189.             SimpleDateFormat sdf =
  190.                     new SimpleDateFormat(bundle
  191.                             .getString("itracker.dateformat."
  192.                                     + customField.getDateFormat()), bundle.getLocale());

  193.             if (log.isDebugEnabled()) {
  194.                 log.debug("getValue: dateFormat from itracker configuration "
  195.                         + sdf.toPattern());
  196.             }

  197.             // sdf = new SimpleDateFormat(dateFormat, locale);
  198.             String formattedDate = sdf.format(this.dateValue);
  199.             if (log.isDebugEnabled()) {
  200.                 log.debug("getValue: formated date " + this.dateValue
  201.                         + " to " + formattedDate);
  202.             }
  203.             return formattedDate;
  204.         } catch (NullPointerException ne) {
  205.             log.debug("getValue: ", ne);
  206.             if (dateValue == null) {
  207.                 log.warn("getValue: failed to format date, null for "
  208.                         + customField);
  209.             }
  210.             return "";
  211.         }
  212.     }

  213.     /**
  214.      * Sets the custom field value.
  215.      * <p/>
  216.      * <p>
  217.      * Takes a string and then converts the value to the appropriate type based
  218.      * on the defined field type.
  219.      * </p>
  220.      * <p/>
  221.      * TODO : throw IllegalArgumentException instead of IssueException ?
  222.      *
  223.      * @param value  the value to set this field to as a string
  224.      * @param locale the locale used for any string formatting
  225.      * @param bundle the ResourceBundle used for any string formatting
  226.      * @throws org.itracker.IssueException represents an error formatting or parsing the value
  227.      * @deprecated locale is redundant set, in bundle and as separate parameter.
  228.      *             use {@link IssueField#setValue(String, ResourceBundle)}
  229.      *             instead
  230.      */
  231.     public void setValue(String value, Locale locale, ResourceBundle bundle)
  232.             throws IssueException {
  233.         this.stringValue = null;
  234.         this.intValue = 0;
  235.         this.dateValue = null;

  236.         if (value != null && value.trim().length() > 0) {
  237.             switch (customField.getFieldType()) {

  238.                 case INTEGER:
  239.                     setStringValue(value);
  240.                     try {
  241.                         setIntValue(Integer.parseInt(value));
  242.                     } catch (NumberFormatException nfe) {
  243.                         throw new IssueException("Invalid integer.",
  244.                                 IssueException.TYPE_CF_PARSE_NUM);
  245.                     }
  246.                     break;

  247.                 case DATE:
  248.                     setStringValue(value);
  249.                     try {
  250.                         if (null == locale) {
  251.                             locale = bundle.getLocale();
  252.                         }
  253.                         SimpleDateFormat sdf = // CustomField.DEFAULT_DATE_FORMAT;
  254.                                 new SimpleDateFormat(bundle
  255.                                         .getString("itracker.dateformat."
  256.                                                 + customField.getDateFormat()), locale);

  257.                         Date dateValue = sdf.parse(value);
  258.                         if (dateValue != null) {
  259.                             setDateValue(dateValue);
  260.                         } else {
  261.                             log.error("setValue: caught exception for date "
  262.                                     + value);
  263.                             throw new IssueException("Invalid date.",
  264.                                     IssueException.TYPE_CF_PARSE_DATE);
  265.                         }
  266.                     } catch (Exception ex) {
  267.                         log.error("setValue: caught exception for date " + value,
  268.                                 ex);
  269.                         throw new IssueException("Invalid date format.",
  270.                                 IssueException.TYPE_CF_PARSE_DATE);
  271.                     }
  272.                     break;

  273.                 default:
  274.                     setStringValue(value);
  275.             }

  276.         } else {
  277.             // reset value
  278.             setStringValue("");
  279.             setDateValue(null);
  280.             setIntValue(0);
  281.         }
  282.     }

  283.     /**
  284.      * Sets the custom field value.
  285.      * <p/>
  286.      * <p>
  287.      * Takes a string and then converts the value to the appropriate type based
  288.      * on the defined field type.
  289.      * </p>
  290.      * <p/>
  291.      * TODO : throw IllegalArgumentException instead of IssueException ?
  292.      *
  293.      * @param value  the value to set this field to as a string
  294.      * @param bundle the ResourceBundle used for any string formatting
  295.      * @throws IssueException represents an error formatting or parsing the value
  296.      */
  297.     public void setValue(String value, ResourceBundle bundle)
  298.             throws IssueException {
  299.         setValue(value, bundle.getLocale(), bundle);
  300.     }

  301.     @Override
  302.     public String toString() {
  303.         return new ToStringBuilder(this).append("id", getId()).append("issue",
  304.                 getIssue()).append("customField", getCustomField()).toString();
  305.     }

  306. }