fix #7074 Change Media.mediaCreated to TimePeriod and make let PartialUserType suppor...
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / hibernate / PartialUserType.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
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.
8 */
9
10 package eu.etaxonomy.cdm.hibernate;
11
12 import java.sql.PreparedStatement;
13 import java.sql.ResultSet;
14 import java.sql.SQLException;
15 import java.sql.Types;
16
17 import org.apache.log4j.Logger;
18 import org.hibernate.HibernateException;
19 import org.hibernate.engine.spi.SessionImplementor;
20 import org.hibernate.type.StandardBasicTypes;
21 import org.hibernate.usertype.UserType;
22 import org.jadira.usertype.dateandtime.shared.spi.AbstractUserType;
23 import org.joda.time.DateTimeFieldType;
24 import org.joda.time.Partial;
25
26 /**
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.
30 *
31 * @author a.mueller
32 * @since 11.11.2008
33 */
34 public class PartialUserType extends AbstractUserType implements UserType /* extends AbstractSingleColumnUserType<Partial, String, ColumnMapper<Partial,String>> implements UserType */ {
35 private static final long serialVersionUID = -5323104403077597869L;
36
37 private static final Logger logger = Logger.getLogger(PartialUserType.class);
38
39 //not required
40 public final static PartialUserType INSTANCE = new PartialUserType();
41
42 private static final int[] SQL_TYPES = new int[]{
43 Types.VARCHAR,
44 };
45
46
47 @Override
48 public Partial nullSafeGet(ResultSet rs, String[] names, SessionImplementor 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) {
53 return null;
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);
56 }
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));
60 Integer hour = null;
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));
65 }
66
67 if (year != 0){
68 result = result.with(DateTimeFieldType.year(), year);
69 }
70 if (month != 0){
71 result = result.with(DateTimeFieldType.monthOfYear(), month);
72 }
73 if (day != 0){
74 result = result.with(DateTimeFieldType.dayOfMonth(), day);
75 }
76 if (hour != null){
77 result = result.with(DateTimeFieldType.hourOfDay(), hour);
78 }
79 if (minute != null){
80 result = result.with(DateTimeFieldType.minuteOfHour(), minute);
81 }
82 return result;
83 }
84
85 @Override
86 public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index,
87 SessionImplementor session) throws HibernateException, SQLException {
88 if (value == null){
89 StandardBasicTypes.STRING.nullSafeSet(preparedStatement, null, index, session);
90 }else {
91 Partial p = ((Partial) value);
92 StandardBasicTypes.STRING.nullSafeSet(preparedStatement, partialToString(p), index, session);
93 }
94 }
95
96 /**
97 * @param p
98 * @return an ISO 8601 like time representations of the form yyyyMMdd
99 */
100 public static String partialToString(Partial p) {
101 //FIXME reduce code by use org.joda.time.format.ISODateTimeFormat.basicDate() instead ?
102 // for a date with unknown day this will produce e.g. 195712??
103 //
104 String strYear = getNullFilledString(p, DateTimeFieldType.year(),4);
105 String strMonth = getNullFilledString(p, DateTimeFieldType.monthOfYear(),2);
106 String strDay = getNullFilledString(p, DateTimeFieldType.dayOfMonth(),2);
107 String strHour = getNullFilledString(p, DateTimeFieldType.hourOfDay(),2);
108 String strMinute = getNullFilledString(p, DateTimeFieldType.minuteOfHour(),2);
109 boolean timeExists = timeExists(p);
110 String result = strYear + strMonth + strDay;
111 if (timeExists) {
112 result = result + "_" + strHour + strMinute;
113 }
114 return result;
115 }
116
117 /**
118 * @param p
119 * @return
120 */
121 private static boolean timeExists(Partial partial) {
122 return partial.isSupported(DateTimeFieldType.hourOfDay()) ||
123 partial.isSupported(DateTimeFieldType.minuteOfHour());
124 }
125
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);
130 }else{
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;
138 }
139 return result;
140 }
141 }
142
143 @Override
144 public Object deepCopy(Object value) throws HibernateException {
145 if (value == null) {
146 return null;
147 }
148
149 return value;
150 }
151
152 @Override
153 public int[] sqlTypes() {
154 return SQL_TYPES;
155 }
156
157 @Override
158 public Class returnedClass() {
159 return Partial.class;
160 }
161
162 }
163