2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
9 package eu
.etaxonomy
.cdm
.hibernate
;
11 import java
.sql
.PreparedStatement
;
12 import java
.sql
.ResultSet
;
13 import java
.sql
.SQLException
;
14 import java
.sql
.Types
;
16 import org
.apache
.logging
.log4j
.LogManager
;
17 import org
.apache
.logging
.log4j
.Logger
;
18 import org
.hibernate
.HibernateException
;
19 import org
.hibernate
.engine
.spi
.SharedSessionContractImplementor
;
20 import org
.hibernate
.type
.StandardBasicTypes
;
21 import org
.hibernate
.usertype
.UserType
;
22 import org
.jadira
.usertype
.spi
.shared
.AbstractUserType
;
23 import org
.joda
.time
.DateTimeFieldType
;
24 import org
.joda
.time
.Partial
;
27 * Persist {@link org.joda.time.Partial} via hibernate.
28 * This is a preliminary implementation that fulfills the needs of CDM but does not fully store a Partial.
29 * Only year, month and day is stored. Since 5.0 also hour and minute is supported.
34 public class PartialUserType
extends AbstractUserType
implements UserType
/* extends AbstractSingleColumnUserType<Partial, String, ColumnMapper<Partial,String>> implements UserType */ {
35 private static final long serialVersionUID
= -5323104403077597869L;
37 private static final Logger logger
= LogManager
.getLogger();
40 public final static PartialUserType INSTANCE
= new PartialUserType();
42 private static final int[] SQL_TYPES
= new int[]{
48 public Partial
nullSafeGet(ResultSet rs
, String
[] names
, SharedSessionContractImplementor session
, Object owner
)
49 throws HibernateException
, SQLException
{
50 String partial
= (String
)StandardBasicTypes
.STRING
.nullSafeGet(rs
, names
, session
, owner
);
51 Partial result
= new Partial();
52 if (partial
== null || "00000000".equals(partial
) || "0000000000000".equals(partial
)) {
54 }else if (partial
.length() != 8 && partial
.length() != 13){
55 throw new HibernateException("Format for Partial not supported. Length mus be 8 or 13: " + partial
);
57 Integer year
= Integer
.valueOf(partial
.substring(0,4));
58 Integer month
= Integer
.valueOf(partial
.substring(4,6));
59 Integer day
= Integer
.valueOf(partial
.substring(6,8));
61 Integer minute
= null;
62 if (partial
.length() == 13){
63 hour
= Integer
.valueOf(partial
.substring(9,11));
64 minute
= Integer
.valueOf(partial
.substring(11,13));
68 result
= result
.with(DateTimeFieldType
.year(), year
);
71 result
= result
.with(DateTimeFieldType
.monthOfYear(), month
);
74 result
= result
.with(DateTimeFieldType
.dayOfMonth(), day
);
77 result
= result
.with(DateTimeFieldType
.hourOfDay(), hour
);
80 result
= result
.with(DateTimeFieldType
.minuteOfHour(), minute
);
82 return isEmptyOrNull(result
)?
null:result
;
85 private boolean isEmptyOrNull(Partial partial
) {
86 return partial
== null ?
true : partial
.getValues().length
== 0;
90 public void nullSafeSet(PreparedStatement preparedStatement
, Object value
, int index
,
91 SharedSessionContractImplementor session
) throws HibernateException
, SQLException
{
92 if (isEmptyOrNull((Partial
)value
)){
93 StandardBasicTypes
.STRING
.nullSafeSet(preparedStatement
, null, index
, session
);
95 Partial p
= ((Partial
) value
);
96 StandardBasicTypes
.STRING
.nullSafeSet(preparedStatement
, partialToString(p
), index
, session
);
102 * @return an ISO 8601 like time representations of the form yyyyMMdd
104 public static String
partialToString(Partial p
) {
105 //FIXME reduce code by use org.joda.time.format.ISODateTimeFormat.basicDate() instead ?
106 // for a date with unknown day this will produce e.g. 195712??
108 String strYear
= getNullFilledString(p
, DateTimeFieldType
.year(),4);
109 String strMonth
= getNullFilledString(p
, DateTimeFieldType
.monthOfYear(),2);
110 String strDay
= getNullFilledString(p
, DateTimeFieldType
.dayOfMonth(),2);
111 String strHour
= getNullFilledString(p
, DateTimeFieldType
.hourOfDay(),2);
112 String strMinute
= getNullFilledString(p
, DateTimeFieldType
.minuteOfHour(),2);
113 boolean timeExists
= timeExists(p
);
114 String result
= strYear
+ strMonth
+ strDay
;
116 result
= result
+ "_" + strHour
+ strMinute
;
121 private static boolean timeExists(Partial partial
) {
122 return partial
.isSupported(DateTimeFieldType
.hourOfDay()) ||
123 partial
.isSupported(DateTimeFieldType
.minuteOfHour());
126 private static String
getNullFilledString(Partial partial
, DateTimeFieldType type
, int count
){
127 String nul
= "0000000000";
128 if (! partial
.isSupported(type
)){
129 return nul
.substring(0, count
);
131 int value
= partial
.get(type
);
132 String result
= String
.valueOf(value
);
133 if (result
.length() > count
){
134 logger
.error("value to long");
135 result
= result
.substring(0, count
);
136 }else if (result
.length() < count
){
137 result
= nul
.substring(0, count
- result
.length()) + result
;
144 public Object
deepCopy(Object value
) throws HibernateException
{
153 public int[] sqlTypes() {
158 public Class
<?
> returnedClass() {
159 return Partial
.class;