[LIB-2] Add snooker-score-api source files
[snooker-score-api.git] / src / main / java / org / hedgecode / snooker / gson / EmptyDateTypeAdapter.java
1 /*
2  * Copyright (c) 2017. Developed by Hedgecode.
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.hedgecode.snooker.gson;
18
19 import java.io.IOException;
20 import java.text.DateFormat;
21 import java.text.ParseException;
22 import java.text.ParsePosition;
23 import java.util.Date;
24 import java.util.Locale;
25
26 import com.google.gson.Gson;
27 import com.google.gson.JsonSyntaxException;
28 import com.google.gson.TypeAdapter;
29 import com.google.gson.TypeAdapterFactory;
30 import com.google.gson.internal.bind.util.ISO8601Utils;
31 import com.google.gson.reflect.TypeToken;
32 import com.google.gson.stream.JsonReader;
33 import com.google.gson.stream.JsonToken;
34 import com.google.gson.stream.JsonWriter;
35
36 /**
37  * GSON Adapter for Date including a check for an empty string.
38  *
39  * @author Dmitry Samoshin aka gotty
40  */
41 public final class EmptyDateTypeAdapter extends TypeAdapter<Date> {
42
43     public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
44         @SuppressWarnings("unchecked")
45         @Override
46         public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
47             return typeToken.getRawType() == Date.class
48                     ? (TypeAdapter<T>) new EmptyDateTypeAdapter()
49                     : null;
50         }
51     };
52
53     private final DateFormat enUsFormat =
54             DateFormat.getDateTimeInstance(
55                     DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US
56             );
57     private final DateFormat localFormat =
58             DateFormat.getDateTimeInstance(
59                     DateFormat.DEFAULT, DateFormat.DEFAULT
60             );
61
62     @Override
63     public Date read(JsonReader in) throws IOException {
64         if (in.peek() == JsonToken.NULL) {
65             in.nextNull();
66             return null;
67         }
68         return deserializeToDate(in.nextString());
69     }
70
71     private synchronized Date deserializeToDate(String json) {
72         if (json.isEmpty())
73             return null;
74         try {
75             return localFormat.parse(json);
76         } catch (ParseException ignored) {
77         }
78         try {
79             return enUsFormat.parse(json);
80         } catch (ParseException ignored) {
81         }
82         try {
83             return ISO8601Utils.parse(json, new ParsePosition(0));
84         } catch (ParseException ignored) {
85         }
86         try {
87             return new Date(Long.parseLong(json));
88         } catch (Exception e) {
89             throw new JsonSyntaxException(json, e);
90         }
91     }
92
93     @Override
94     public synchronized void write(JsonWriter out, Date value) throws IOException {
95         if (value == null) {
96             out.nullValue();
97         } else {
98             String dateFormatAsString = enUsFormat.format(value);
99             out.value(dateFormatAsString);
100         }
101     }
102
103 }