Skip to content

Commit 408e050

Browse files
mp911dechristophstrobl
authored andcommitted
DATAREDIS-425 - Add converters for JSR-310 types.
We ship converters for JSR-310 types (LocalDate/Time, ZonedDateTime, Period, Duration and ZoneId) to map between UTF-8-encoded byte[] and JDK 8 date/time types. This change requires to build the project on Java 8.
1 parent a03d77c commit 408e050

File tree

6 files changed

+542
-29
lines changed

6 files changed

+542
-29
lines changed

.travis.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
language: java
22
jdk:
3-
- oraclejdk7
43
- oraclejdk8
54
env:
65
matrix:

src/main/java/org/springframework/data/redis/core/convert/BinaryConverters.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ private BinaryConverters() {}
4545
* @author Christoph Strobl
4646
* @since 1.7
4747
*/
48-
private static class StringBasedConverter {
48+
static class StringBasedConverter {
4949

5050
byte[] fromString(String source) {
5151

@@ -166,7 +166,7 @@ public T convert(byte[] source) {
166166
if (value == null || value.length() == 0) {
167167
return null;
168168
}
169-
return (T) Enum.valueOf(this.enumType, value.trim());
169+
return Enum.valueOf(this.enumType, value.trim());
170170
}
171171
}
172172
}
@@ -183,8 +183,8 @@ public <T extends Number> Converter<byte[], T> getConverter(Class<T> targetType)
183183
return new BytesToNumberConverter<T>(targetType);
184184
}
185185

186-
private static final class BytesToNumberConverter<T extends Number> extends StringBasedConverter implements
187-
Converter<byte[], T> {
186+
private static final class BytesToNumberConverter<T extends Number> extends StringBasedConverter
187+
implements Converter<byte[], T> {
188188

189189
private final Class<T> targetType;
190190

src/main/java/org/springframework/data/redis/core/convert/CustomConversions.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ public CustomConversions(List<?> converters) {
103103
toRegister.add(new BinaryConverters.DateToBytesConverter());
104104
toRegister.add(new BinaryConverters.BytesToDateConverter());
105105

106+
toRegister.addAll(Jsr310Converters.getConvertersToRegister());
107+
106108
for (Object c : toRegister) {
107109
registerConversion(c);
108110
}
@@ -161,7 +163,8 @@ public void registerConvertersIn(GenericConversionService conversionService) {
161163
}
162164

163165
if (!added) {
164-
throw new IllegalArgumentException("Given set contains element that is neither Converter nor ConverterFactory!");
166+
throw new IllegalArgumentException(
167+
"Given set contains element that is neither Converter nor ConverterFactory!");
165168
}
166169
}
167170
}
Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
/*
2+
* Copyright 2016 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+
17+
package org.springframework.data.redis.core.convert;
18+
19+
import java.time.Duration;
20+
import java.time.Instant;
21+
import java.time.LocalDate;
22+
import java.time.LocalDateTime;
23+
import java.time.LocalTime;
24+
import java.time.Period;
25+
import java.time.ZoneId;
26+
import java.time.ZonedDateTime;
27+
import java.util.ArrayList;
28+
import java.util.Arrays;
29+
import java.util.Collection;
30+
import java.util.Collections;
31+
import java.util.List;
32+
33+
import org.springframework.core.convert.converter.Converter;
34+
import org.springframework.data.convert.ReadingConverter;
35+
import org.springframework.data.convert.WritingConverter;
36+
import org.springframework.data.redis.core.convert.BinaryConverters.StringBasedConverter;
37+
import org.springframework.util.ClassUtils;
38+
39+
/**
40+
* Helper class to register JSR-310 specific {@link Converter} implementations in case the we're running on Java 8.
41+
*
42+
* @author Mark Paluch
43+
*/
44+
public abstract class Jsr310Converters {
45+
46+
private static final boolean JAVA_8_IS_PRESENT = ClassUtils.isPresent("java.time.LocalDateTime",
47+
Jsr310Converters.class.getClassLoader());
48+
49+
/**
50+
* Returns the converters to be registered. Will only return converters in case we're running on Java 8.
51+
*
52+
* @return
53+
*/
54+
public static Collection<Converter<?, ?>> getConvertersToRegister() {
55+
56+
if (!JAVA_8_IS_PRESENT) {
57+
return Collections.emptySet();
58+
}
59+
60+
List<Converter<?, ?>> converters = new ArrayList<Converter<?, ?>>();
61+
converters.add(new LocalDateTimeToBytesConverter());
62+
converters.add(new BytesToLocalDateTimeConverter());
63+
converters.add(new LocalDateToBytesConverter());
64+
converters.add(new BytesToLocalDateConverter());
65+
converters.add(new LocalTimeToBytesConverter());
66+
converters.add(new BytesToLocalTimeConverter());
67+
converters.add(new ZonedDateTimeToBytesConverter());
68+
converters.add(new BytesToZonedDateTimeConverter());
69+
converters.add(new InstantToBytesConverter());
70+
converters.add(new BytesToInstantConverter());
71+
converters.add(new ZoneIdToBytesConverter());
72+
converters.add(new BytesToZoneIdConverter());
73+
converters.add(new PeriodToBytesConverter());
74+
converters.add(new BytesToPeriodConverter());
75+
converters.add(new DurationToBytesConverter());
76+
converters.add(new BytesToDurationConverter());
77+
78+
return converters;
79+
}
80+
81+
public static boolean supports(Class<?> type) {
82+
83+
if (!JAVA_8_IS_PRESENT) {
84+
return false;
85+
}
86+
87+
return Arrays.<Class<?>> asList(LocalDateTime.class, LocalDate.class, LocalTime.class, Instant.class,
88+
ZonedDateTime.class, ZoneId.class, Period.class, Duration.class).contains(type);
89+
}
90+
91+
/**
92+
* @author Mark Paluch
93+
* @since 1.7
94+
*/
95+
@WritingConverter
96+
static class LocalDateTimeToBytesConverter extends StringBasedConverter implements Converter<LocalDateTime, byte[]> {
97+
98+
@Override
99+
public byte[] convert(LocalDateTime source) {
100+
return fromString(source.toString());
101+
}
102+
}
103+
104+
/**
105+
* @author Mark Paluch
106+
* @since 1.7
107+
*/
108+
@ReadingConverter
109+
static class BytesToLocalDateTimeConverter extends StringBasedConverter implements Converter<byte[], LocalDateTime> {
110+
111+
@Override
112+
public LocalDateTime convert(byte[] source) {
113+
return LocalDateTime.parse(toString(source));
114+
}
115+
}
116+
117+
/**
118+
* @author Mark Paluch
119+
* @since 1.7
120+
*/
121+
@WritingConverter
122+
static class LocalDateToBytesConverter extends StringBasedConverter implements Converter<LocalDate, byte[]> {
123+
124+
@Override
125+
public byte[] convert(LocalDate source) {
126+
return fromString(source.toString());
127+
}
128+
}
129+
130+
/**
131+
* @author Mark Paluch
132+
* @since 1.7
133+
*/
134+
@ReadingConverter
135+
static class BytesToLocalDateConverter extends StringBasedConverter implements Converter<byte[], LocalDate> {
136+
137+
@Override
138+
public LocalDate convert(byte[] source) {
139+
return LocalDate.parse(toString(source));
140+
}
141+
}
142+
143+
/**
144+
* @author Mark Paluch
145+
* @since 1.7
146+
*/
147+
@WritingConverter
148+
static class LocalTimeToBytesConverter extends StringBasedConverter implements Converter<LocalTime, byte[]> {
149+
150+
@Override
151+
public byte[] convert(LocalTime source) {
152+
return fromString(source.toString());
153+
}
154+
}
155+
156+
/**
157+
* @author Mark Paluch
158+
* @since 1.7
159+
*/
160+
@ReadingConverter
161+
static class BytesToLocalTimeConverter extends StringBasedConverter implements Converter<byte[], LocalTime> {
162+
163+
@Override
164+
public LocalTime convert(byte[] source) {
165+
return LocalTime.parse(toString(source));
166+
}
167+
}
168+
169+
/**
170+
* @author Mark Paluch
171+
* @since 1.7
172+
*/
173+
@WritingConverter
174+
static class ZonedDateTimeToBytesConverter extends StringBasedConverter implements Converter<ZonedDateTime, byte[]> {
175+
176+
@Override
177+
public byte[] convert(ZonedDateTime source) {
178+
return fromString(source.toString());
179+
}
180+
}
181+
182+
/**
183+
* @author Mark Paluch
184+
* @since 1.7
185+
*/
186+
@ReadingConverter
187+
static class BytesToZonedDateTimeConverter extends StringBasedConverter implements Converter<byte[], ZonedDateTime> {
188+
189+
@Override
190+
public ZonedDateTime convert(byte[] source) {
191+
return ZonedDateTime.parse(toString(source));
192+
}
193+
}
194+
195+
/**
196+
* @author Mark Paluch
197+
* @since 1.7
198+
*/
199+
@WritingConverter
200+
static class InstantToBytesConverter extends StringBasedConverter implements Converter<Instant, byte[]> {
201+
202+
@Override
203+
public byte[] convert(Instant source) {
204+
return fromString(source.toString());
205+
}
206+
}
207+
208+
/**
209+
* @author Mark Paluch
210+
* @since 1.7
211+
*/
212+
@ReadingConverter
213+
static class BytesToInstantConverter extends StringBasedConverter implements Converter<byte[], Instant> {
214+
215+
@Override
216+
public Instant convert(byte[] source) {
217+
return Instant.parse(toString(source));
218+
}
219+
}
220+
221+
/**
222+
* @author Mark Paluch
223+
* @since 1.7
224+
*/
225+
@WritingConverter
226+
static class ZoneIdToBytesConverter extends StringBasedConverter implements Converter<ZoneId, byte[]> {
227+
228+
@Override
229+
public byte[] convert(ZoneId source) {
230+
return fromString(source.toString());
231+
}
232+
}
233+
234+
/**
235+
* @author Mark Paluch
236+
* @since 1.7
237+
*/
238+
@ReadingConverter
239+
static class BytesToZoneIdConverter extends StringBasedConverter implements Converter<byte[], ZoneId> {
240+
241+
@Override
242+
public ZoneId convert(byte[] source) {
243+
return ZoneId.of(toString(source));
244+
}
245+
}
246+
247+
/**
248+
* @author Mark Paluch
249+
* @since 1.7
250+
*/
251+
@WritingConverter
252+
static class PeriodToBytesConverter extends StringBasedConverter implements Converter<Period, byte[]> {
253+
254+
@Override
255+
public byte[] convert(Period source) {
256+
return fromString(source.toString());
257+
}
258+
}
259+
260+
/**
261+
* @author Mark Paluch
262+
* @since 1.7
263+
*/
264+
@ReadingConverter
265+
static class BytesToPeriodConverter extends StringBasedConverter implements Converter<byte[], Period> {
266+
267+
@Override
268+
public Period convert(byte[] source) {
269+
return Period.parse(toString(source));
270+
}
271+
}
272+
273+
/**
274+
* @author Mark Paluch
275+
* @since 1.7
276+
*/
277+
@WritingConverter
278+
static class DurationToBytesConverter extends StringBasedConverter implements Converter<Duration, byte[]> {
279+
280+
@Override
281+
public byte[] convert(Duration source) {
282+
return fromString(source.toString());
283+
}
284+
}
285+
286+
/**
287+
* @author Mark Paluch
288+
* @since 1.7
289+
*/
290+
@ReadingConverter
291+
static class BytesToDurationConverter extends StringBasedConverter implements Converter<byte[], Duration> {
292+
293+
@Override
294+
public Duration convert(byte[] source) {
295+
return Duration.parse(toString(source));
296+
}
297+
}
298+
299+
}

src/test/java/org/springframework/data/redis/core/convert/ConversionTestEntities.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@
1515
*/
1616
package org.springframework.data.redis.core.convert;
1717

18+
import java.time.Duration;
19+
import java.time.Instant;
20+
import java.time.LocalDate;
21+
import java.time.LocalDateTime;
22+
import java.time.LocalTime;
23+
import java.time.Period;
24+
import java.time.ZoneId;
25+
import java.time.ZonedDateTime;
1826
import java.util.Date;
1927
import java.util.List;
2028
import java.util.Map;
@@ -48,6 +56,15 @@ public static class Person {
4856
Boolean alive;
4957
Date birthdate;
5058

59+
LocalDate localDate;
60+
LocalDateTime localDateTime;
61+
LocalTime localTime;
62+
Instant instant;
63+
ZonedDateTime zonedDateTime;
64+
ZoneId zoneId;
65+
Duration duration;
66+
Period period;
67+
5168
Address address;
5269

5370
Map<String, String> physicalAttributes;

0 commit comments

Comments
 (0)