From 93995f8ce17b950d668c3a59fe50ff1a42f60c3c Mon Sep 17 00:00:00 2001 From: Malik Date: Thu, 1 Aug 2019 14:46:31 +0300 Subject: [PATCH 1/5] Add adapters, annotation and a factory to process date patterns --- KotlinOutputFiles/AbstractDateJsonAdapter.kt | 45 ++++++++++++++++++++ KotlinOutputFiles/DateFactory.kt | 26 +++++++++++ KotlinOutputFiles/DateTimeJsonAdapter.kt | 16 +++++++ KotlinOutputFiles/Format.kt | 5 +++ KotlinOutputFiles/LocalDataJsonAdapter.kt | 16 +++++++ 5 files changed, 108 insertions(+) create mode 100644 KotlinOutputFiles/AbstractDateJsonAdapter.kt create mode 100644 KotlinOutputFiles/DateFactory.kt create mode 100644 KotlinOutputFiles/DateTimeJsonAdapter.kt create mode 100644 KotlinOutputFiles/Format.kt create mode 100644 KotlinOutputFiles/LocalDataJsonAdapter.kt diff --git a/KotlinOutputFiles/AbstractDateJsonAdapter.kt b/KotlinOutputFiles/AbstractDateJsonAdapter.kt new file mode 100644 index 0000000..0c843f9 --- /dev/null +++ b/KotlinOutputFiles/AbstractDateJsonAdapter.kt @@ -0,0 +1,45 @@ +import com.squareup.moshi.JsonAdapter +import com.squareup.moshi.JsonEncodingException +import com.squareup.moshi.JsonReader +import com.squareup.moshi.JsonWriter +import org.joda.time.format.DateTimeFormat +import org.joda.time.format.DateTimeFormatter +import java.util.Arrays + +abstract class AbstractDateJsonAdapter( + private val formats: Array +) : JsonAdapter() { + + companion object { + const val CANT_FIND_ANY_FORMATTERS = "Can't find any DateTimeFormatter" + const val LOCAL_DATE_CANNOT_BE_NULL = "LocalDate value can't be null" + } + + private val formatters = formats.map(DateTimeFormat::forPattern) + + override fun fromJson(reader: JsonReader): T? { + val dateTimeString = reader.nextString() + formatters.forEachIndexed { index, dateTimeFormatter -> + try { + return fromJsonInner(dateTimeString, dateTimeFormatter) + } catch (e: IllegalArgumentException) { + if (index == formatters.lastIndex) { + throw JsonEncodingException("$dateTimeString doesn't fit any of the formats ${Arrays.toString(formats)}") + } + } + } + throw IllegalArgumentException(CANT_FIND_ANY_FORMATTERS) + } + + override fun toJson(writer: JsonWriter, value: T?) { + if (formatters.isEmpty()) throw IllegalArgumentException(CANT_FIND_ANY_FORMATTERS) + value?.let { + writer.value(toJsonInner(value, formatters.first())) + } ?: throw JsonEncodingException(LOCAL_DATE_CANNOT_BE_NULL) + } + + abstract fun fromJsonInner(value: String, dateTimeFormatter: DateTimeFormatter): T + + abstract fun toJsonInner(value: T?, dateTimeFormatter: DateTimeFormatter) : String? + +} diff --git a/KotlinOutputFiles/DateFactory.kt b/KotlinOutputFiles/DateFactory.kt new file mode 100644 index 0000000..0ffdbfd --- /dev/null +++ b/KotlinOutputFiles/DateFactory.kt @@ -0,0 +1,26 @@ +import com.squareup.moshi.JsonAdapter +import com.squareup.moshi.Moshi +import org.joda.time.DateTime +import org.joda.time.LocalDate +import java.lang.reflect.Type + +class DateFactory : JsonAdapter.Factory { + + override fun create(type: Type, annotations: MutableSet, moshi: Moshi): JsonAdapter<*>? { + val dateTimeName = DateTime::class.java.typeName + val localDateName = LocalDate::class.java.typeName + val typeName = type.typeName + + return if (typeName == dateTimeName || typeName == localDateName) { + val formatAnnotation = annotations + .map { it as? Format } + .firstOrNull() + ?: throw IllegalArgumentException("You should use Format annotation for DateTime and LocalDate fields") + + if (typeName == dateTimeName) DateTimeJsonAdapter(formatAnnotation.patterns) + else LocalDataJsonAdapter(formatAnnotation.patterns) + + } else null + } + +} diff --git a/KotlinOutputFiles/DateTimeJsonAdapter.kt b/KotlinOutputFiles/DateTimeJsonAdapter.kt new file mode 100644 index 0000000..b384e83 --- /dev/null +++ b/KotlinOutputFiles/DateTimeJsonAdapter.kt @@ -0,0 +1,16 @@ +import org.joda.time.DateTime +import org.joda.time.format.DateTimeFormatter + +class DateTimeJsonAdapter( + formats: Array +) : AbstractDateJsonAdapter(formats) { + + override fun fromJsonInner(value: String, dateTimeFormatter: DateTimeFormatter): DateTime { + return DateTime.parse(value, dateTimeFormatter) + } + + override fun toJsonInner(value: DateTime?, dateTimeFormatter: DateTimeFormatter): String? { + return value?.toString(dateTimeFormatter) + } + +} \ No newline at end of file diff --git a/KotlinOutputFiles/Format.kt b/KotlinOutputFiles/Format.kt new file mode 100644 index 0000000..07e39ce --- /dev/null +++ b/KotlinOutputFiles/Format.kt @@ -0,0 +1,5 @@ +import com.squareup.moshi.JsonQualifier + +@JsonQualifier +@Target(AnnotationTarget.FIELD) +annotation class Format(val patterns: Array) diff --git a/KotlinOutputFiles/LocalDataJsonAdapter.kt b/KotlinOutputFiles/LocalDataJsonAdapter.kt new file mode 100644 index 0000000..93a248d --- /dev/null +++ b/KotlinOutputFiles/LocalDataJsonAdapter.kt @@ -0,0 +1,16 @@ +import org.joda.time.LocalDate +import org.joda.time.format.DateTimeFormatter + +class LocalDataJsonAdapter( + formats: Array +) : AbstractDateJsonAdapter(formats) { + + override fun fromJsonInner(value: String, dateTimeFormatter: DateTimeFormatter): LocalDate { + return LocalDate.parse(value, dateTimeFormatter) + } + + override fun toJsonInner(value: LocalDate?, dateTimeFormatter: DateTimeFormatter): String? { + return value?.toString(dateTimeFormatter) + } + +} From 04cf0d7c52c37af4152788c9faf393fde62ac396 Mon Sep 17 00:00:00 2001 From: Malik Date: Thu, 1 Aug 2019 18:02:15 +0300 Subject: [PATCH 2/5] Fix a type --- KotlinOutputFiles/DateFactory.kt | 2 +- .../{LocalDataJsonAdapter.kt => LocalDateJsonAdapter.kt} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename KotlinOutputFiles/{LocalDataJsonAdapter.kt => LocalDateJsonAdapter.kt} (94%) diff --git a/KotlinOutputFiles/DateFactory.kt b/KotlinOutputFiles/DateFactory.kt index 0ffdbfd..3a64437 100644 --- a/KotlinOutputFiles/DateFactory.kt +++ b/KotlinOutputFiles/DateFactory.kt @@ -18,7 +18,7 @@ class DateFactory : JsonAdapter.Factory { ?: throw IllegalArgumentException("You should use Format annotation for DateTime and LocalDate fields") if (typeName == dateTimeName) DateTimeJsonAdapter(formatAnnotation.patterns) - else LocalDataJsonAdapter(formatAnnotation.patterns) + else LocalDateJsonAdapter(formatAnnotation.patterns) } else null } diff --git a/KotlinOutputFiles/LocalDataJsonAdapter.kt b/KotlinOutputFiles/LocalDateJsonAdapter.kt similarity index 94% rename from KotlinOutputFiles/LocalDataJsonAdapter.kt rename to KotlinOutputFiles/LocalDateJsonAdapter.kt index 93a248d..2aec04a 100644 --- a/KotlinOutputFiles/LocalDataJsonAdapter.kt +++ b/KotlinOutputFiles/LocalDateJsonAdapter.kt @@ -1,7 +1,7 @@ import org.joda.time.LocalDate import org.joda.time.format.DateTimeFormatter -class LocalDataJsonAdapter( +class LocalDateJsonAdapter( formats: Array ) : AbstractDateJsonAdapter(formats) { From fd24198675766231491f5475b5096771a9980955 Mon Sep 17 00:00:00 2001 From: Malik Date: Wed, 7 Aug 2019 18:00:17 +0300 Subject: [PATCH 3/5] Review --- KotlinOutputFiles/AbstractDateJsonAdapter.kt | 4 ++-- KotlinOutputFiles/DateFactory.kt | 25 +++++++++----------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/KotlinOutputFiles/AbstractDateJsonAdapter.kt b/KotlinOutputFiles/AbstractDateJsonAdapter.kt index 0c843f9..166d395 100644 --- a/KotlinOutputFiles/AbstractDateJsonAdapter.kt +++ b/KotlinOutputFiles/AbstractDateJsonAdapter.kt @@ -11,8 +11,8 @@ abstract class AbstractDateJsonAdapter( ) : JsonAdapter() { companion object { - const val CANT_FIND_ANY_FORMATTERS = "Can't find any DateTimeFormatter" - const val LOCAL_DATE_CANNOT_BE_NULL = "LocalDate value can't be null" + private const val CANT_FIND_ANY_FORMATTERS = "Can't find any DateTimeFormatter" + private const val LOCAL_DATE_CANNOT_BE_NULL = "LocalDate value can't be null" } private val formatters = formats.map(DateTimeFormat::forPattern) diff --git a/KotlinOutputFiles/DateFactory.kt b/KotlinOutputFiles/DateFactory.kt index 3a64437..165eca2 100644 --- a/KotlinOutputFiles/DateFactory.kt +++ b/KotlinOutputFiles/DateFactory.kt @@ -7,20 +7,17 @@ import java.lang.reflect.Type class DateFactory : JsonAdapter.Factory { override fun create(type: Type, annotations: MutableSet, moshi: Moshi): JsonAdapter<*>? { - val dateTimeName = DateTime::class.java.typeName - val localDateName = LocalDate::class.java.typeName - val typeName = type.typeName - - return if (typeName == dateTimeName || typeName == localDateName) { - val formatAnnotation = annotations - .map { it as? Format } - .firstOrNull() - ?: throw IllegalArgumentException("You should use Format annotation for DateTime and LocalDate fields") - - if (typeName == dateTimeName) DateTimeJsonAdapter(formatAnnotation.patterns) - else LocalDateJsonAdapter(formatAnnotation.patterns) - - } else null + return when (type.typeName) { + DateTime::class.java.typeName -> DateTimeJsonAdapter(getPatterns(annotations)) + LocalDate::class.java.typeName -> LocalDateJsonAdapter(getPatterns(annotations)) + else -> null + } } + private fun getPatterns(annotations: MutableSet) = annotations + .map { it as? Format } + .firstOrNull() + ?.patterns + ?: throw IllegalArgumentException("You should use Format annotation for DateTime and LocalDate fields") + } From d7a1aad6726a2635dd47696ba59da86c684912cf Mon Sep 17 00:00:00 2001 From: Malik Date: Wed, 7 Aug 2019 18:02:09 +0300 Subject: [PATCH 4/5] New line --- KotlinOutputFiles/DateTimeJsonAdapter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/KotlinOutputFiles/DateTimeJsonAdapter.kt b/KotlinOutputFiles/DateTimeJsonAdapter.kt index b384e83..b383822 100644 --- a/KotlinOutputFiles/DateTimeJsonAdapter.kt +++ b/KotlinOutputFiles/DateTimeJsonAdapter.kt @@ -13,4 +13,4 @@ class DateTimeJsonAdapter( return value?.toString(dateTimeFormatter) } -} \ No newline at end of file +} From 06783d2ad380cd7e72970e0a94f130b2e7bcfb99 Mon Sep 17 00:00:00 2001 From: Malik Date: Wed, 7 Aug 2019 18:07:13 +0300 Subject: [PATCH 5/5] Fix error message --- KotlinOutputFiles/AbstractDateJsonAdapter.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/KotlinOutputFiles/AbstractDateJsonAdapter.kt b/KotlinOutputFiles/AbstractDateJsonAdapter.kt index 166d395..4b00431 100644 --- a/KotlinOutputFiles/AbstractDateJsonAdapter.kt +++ b/KotlinOutputFiles/AbstractDateJsonAdapter.kt @@ -12,7 +12,6 @@ abstract class AbstractDateJsonAdapter( companion object { private const val CANT_FIND_ANY_FORMATTERS = "Can't find any DateTimeFormatter" - private const val LOCAL_DATE_CANNOT_BE_NULL = "LocalDate value can't be null" } private val formatters = formats.map(DateTimeFormat::forPattern) @@ -35,7 +34,7 @@ abstract class AbstractDateJsonAdapter( if (formatters.isEmpty()) throw IllegalArgumentException(CANT_FIND_ANY_FORMATTERS) value?.let { writer.value(toJsonInner(value, formatters.first())) - } ?: throw JsonEncodingException(LOCAL_DATE_CANNOT_BE_NULL) + } ?: throw JsonEncodingException("Value can't be null") } abstract fun fromJsonInner(value: String, dateTimeFormatter: DateTimeFormatter): T