1 /*
2  * Copyright 2011 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.modelmapper.internal.converter;
17
18 import java.sql.Time;
19 import java.sql.Timestamp;
20 import java.text.ParseException;
21 import java.text.SimpleDateFormat;
22 import java.util.Calendar;
23 import java.util.Date;
24
25 import javax.xml.datatype.XMLGregorianCalendar;
26
27 import org.modelmapper.internal.Errors;
28 import org.modelmapper.spi.ConditionalConverter;
29 import org.modelmapper.spi.MappingContext;
30
31 /**
32  * Converts:
33  * 
34  * <ul>
35  * <li>Date (and subclasses)</li>
36  * <li>Calendar (and subclasses)</li>
37  * <li>XMLGregorianCalendar</li>
38  * <li>Long</li>
39  * <li>String</li>
40  * </ul>
41  * 
42  * instances to destination instances of:
43  * 
44  * <ul>
45  * <li>java.util.Date</li>
46  * <li>java.sql.Date</li>
47  * <li>java.sql.Time</li>
48  * <li>java.sql.Timestamp</li>
49  * </ul>
50  * 
51  * @author Jonathan Halterman
52  */

53 class DateConverter implements ConditionalConverter<Object, Date> {
54   public Date convert(MappingContext<Object, Date> context) {
55     Object source = context.getSource();
56     if (source == null)
57       return null;
58
59     Class<?> destinationType = context.getDestinationType();
60
61     if (source instanceof Date)
62       return dateFor(((Date) source).getTime(), destinationType);
63     if (source instanceof Calendar)
64       return dateFor(((Calendar) source).getTimeInMillis(), destinationType);
65     if (source instanceof XMLGregorianCalendar)
66       return dateFor(((XMLGregorianCalendar) source).toGregorianCalendar().getTimeInMillis(),
67           destinationType);
68     if (source instanceof Long)
69       return dateFor(((Long) source).longValue(), destinationType);
70     return dateFor(source.toString(), context.getDestinationType());
71   }
72
73   public MatchResult match(Class<?> sourceType, Class<?> destinationType) {
74     return Date.class.isAssignableFrom(destinationType)
75         && (Date.class.isAssignableFrom(sourceType) || Calendar.class.isAssignableFrom(sourceType)
76             || sourceType == XMLGregorianCalendar.class || sourceType == Long.class
77             || sourceType == Long.TYPE || sourceType == String.class) ? MatchResult.FULL
78         : MatchResult.NONE;
79   }
80
81   Date dateFor(long source, Class<?> destinationType) {
82     if (destinationType.equals(Date.class))
83       return new Date(source);
84     if (destinationType.equals(java.sql.Date.class))
85       return new java.sql.Date(source);
86     if (destinationType.equals(Time.class))
87       return new Time(source);
88     if (destinationType.equals(Timestamp.class))
89       return new Timestamp(source);
90
91     throw new Errors().errorMapping(source, destinationType).toMappingException();
92   }
93
94   Date dateFor(String source, Class<?> destinationType) {
95     String sourceString = toString().trim();
96     if (sourceString.length() == 0)
97       throw new Errors().errorMapping(source, destinationType).toMappingException();
98
99     if (destinationType.equals(java.sql.Date.class)) {
100       try {
101         return java.sql.Date.valueOf(source);
102       } catch (IllegalArgumentException e) {
103         throw new Errors().addMessage(
104             "String must be in JDBC format [yyyy-MM-dd] to create a java.sql.Date")
105             .toMappingException();
106       }
107     }
108     
109     if (destinationType.equals(Time.class)) {
110       try {
111         return Time.valueOf(source);
112       } catch (IllegalArgumentException e) {
113         throw new Errors().addMessage(
114             "String must be in JDBC format [HH:mm:ss] to create a java.sql.Time")
115             .toMappingException();
116       }
117     }
118
119     if (destinationType.equals(Timestamp.class)) {
120       try {
121         return Timestamp.valueOf(source);
122       } catch (IllegalArgumentException e) {
123         throw new Errors().addMessage(
124             "String must be in JDBC format [yyyy-MM-dd HH:mm:ss.fffffffff] "
125                 + "to create a java.sql.Timestamp").toMappingException();
126       }
127     }
128     
129     if (destinationType.equals(java.util.Date.class)) {
130       try {
131           SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
132         return simpleDateFormat.parse(source);
133       } catch (ParseException e) {
134         throw new Errors().addMessage(
135             "String must be in DATE format [yyyy-MM-dd] to create a java.util.Date")
136             .toMappingException();
137       }
138     }
139
140     throw new Errors().errorMapping(source, destinationType).toMappingException();
141   }
142 }
143