View Javadoc
1   package org.itracker.persistence.dao;
2   
3   import org.apache.log4j.Logger;
4   import org.hibernate.HibernateException;
5   import org.itracker.model.IntCodeEnum;
6   
7   import java.sql.PreparedStatement;
8   import java.sql.ResultSet;
9   import java.sql.SQLException;
10  import java.sql.Types;
11  import java.util.Properties;
12  
13  /**
14   * Custom Hibernate UserType to persist a Java 5 enum constant
15   * that implement {@link org.itracker.model.IntCodeEnum } as an INTEGER
16   * using its integer code.
17   * <p/>
18   * <p>This should be preferred to using the enum.ordinal() or enum.name(). </p>
19   *
20   * @author johnny
21   */
22  public class EnumCodeUserType extends AbstractEnumUserType {
23  
24      private static final int[] SQL_TYPES = {Types.SMALLINT};
25      private static final Logger log = Logger.getLogger(EnumCodeUserType.class);
26      /**
27       * Enum members, in the order they where declared.
28       */
29      @SuppressWarnings("unchecked")
30      private IntCodeEnum[] enumValues;
31  
32      /**
33       * Default constructor, required by Hibernate.
34       */
35      public EnumCodeUserType() {
36      }
37  
38      public void setParameterValues(Properties parameters) {
39          super.setParameterValues(parameters);
40          this.enumValues = (IntCodeEnum[]) this.enumClass.getEnumConstants();
41      }
42  
43      public Object nullSafeGet(ResultSet rs, String[] names,
44                                Object owner) throws HibernateException, SQLException {
45          final int code = rs.getInt(names[0]);
46  
47          /* It is safe to assume there's always at least 1 enum constant
48          * because the compiler ensures that enums are never empty.
49          *
50          * Note : fromCode cannot be static in IntEnumCode !
51          */
52          try {
53              return rs.wasNull() ? null : this.enumValues[0].fromCode(code);
54          } catch (Exception e) {
55              log.info("nullSafeGet: failed to get default code enum, trying DEFAULT-code " + IntCodeEnum.DEFAULT_CODE, e);
56              return this.enumValues[0].fromCode(IntCodeEnum.DEFAULT_CODE);
57          }
58      }
59  
60      public void nullSafeSet(PreparedStatement stmt, Object value,
61                              int index) throws HibernateException, SQLException {
62          if (value == null) {
63              stmt.setNull(index, Types.INTEGER);
64          } else {
65              stmt.setInt(index, ((IntCodeEnum<?>) value).getCode());
66          }
67      }
68  
69      public int[] sqlTypes() {
70          return SQL_TYPES;
71      }
72  
73      public String objectToSQLString(Object value) {
74          return Integer.toString(((IntCodeEnum<?>) value).getCode());
75      }
76  
77      public String toXMLString(Object value) {
78          return objectToSQLString(value);
79      }
80  
81      public Object fromXMLString(String xmlValue) {
82          final int code;
83  
84          try {
85              code = Integer.parseInt(xmlValue);
86          } catch (NumberFormatException ex) {
87              throw new HibernateException(ex);
88          }
89  
90          /* It is safe to assume there's always at least 1 enum constant
91          * because the compiler ensures that enums are never empty.
92          *
93          * Note : fromCode cannot be static in IntEnumCode !
94          */
95          return this.enumValues[0].fromCode(code);
96      }
97  
98  }