[LIB-2] Add snooker-score-api source files
[snooker-score-api.git] / src / main / java / org / hedgecode / snooker / gson / EmptyDateTypeAdapter.java
diff --git a/src/main/java/org/hedgecode/snooker/gson/EmptyDateTypeAdapter.java b/src/main/java/org/hedgecode/snooker/gson/EmptyDateTypeAdapter.java
new file mode 100644 (file)
index 0000000..5c625c5
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.gson;
+
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.util.Date;
+import java.util.Locale;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.TypeAdapter;
+import com.google.gson.TypeAdapterFactory;
+import com.google.gson.internal.bind.util.ISO8601Utils;
+import com.google.gson.reflect.TypeToken;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import com.google.gson.stream.JsonWriter;
+
+/**
+ * GSON Adapter for Date including a check for an empty string.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public final class EmptyDateTypeAdapter extends TypeAdapter<Date> {
+
+    public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
+        @SuppressWarnings("unchecked")
+        @Override
+        public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
+            return typeToken.getRawType() == Date.class
+                    ? (TypeAdapter<T>) new EmptyDateTypeAdapter()
+                    : null;
+        }
+    };
+
+    private final DateFormat enUsFormat =
+            DateFormat.getDateTimeInstance(
+                    DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US
+            );
+    private final DateFormat localFormat =
+            DateFormat.getDateTimeInstance(
+                    DateFormat.DEFAULT, DateFormat.DEFAULT
+            );
+
+    @Override
+    public Date read(JsonReader in) throws IOException {
+        if (in.peek() == JsonToken.NULL) {
+            in.nextNull();
+            return null;
+        }
+        return deserializeToDate(in.nextString());
+    }
+
+    private synchronized Date deserializeToDate(String json) {
+        if (json.isEmpty())
+            return null;
+        try {
+            return localFormat.parse(json);
+        } catch (ParseException ignored) {
+        }
+        try {
+            return enUsFormat.parse(json);
+        } catch (ParseException ignored) {
+        }
+        try {
+            return ISO8601Utils.parse(json, new ParsePosition(0));
+        } catch (ParseException ignored) {
+        }
+        try {
+            return new Date(Long.parseLong(json));
+        } catch (Exception e) {
+            throw new JsonSyntaxException(json, e);
+        }
+    }
+
+    @Override
+    public synchronized void write(JsonWriter out, Date value) throws IOException {
+        if (value == null) {
+            out.nullValue();
+        } else {
+            String dateFormatAsString = enUsFormat.format(value);
+            out.value(dateFormatAsString);
+        }
+    }
+
+}