Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

draft implementation for supporting java.util.Currency as StandardType #576

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,12 @@ object AvroCodec {
.toEither
.left
.map(e => DecodeError.MalformedFieldWithPath(Chunk.empty, e.getMessage))
case StandardType.CurrencyType =>
Try(value.asInstanceOf[Utf8])
.flatMap(c => Try(java.util.Currency.getInstance(c.toString)))
.toEither
.left
.map(e => DecodeError.MalformedFieldWithPath(Chunk.empty, e.getMessage))
}

private def decodeMap(value: Any, schema: Schema.Map[Any, Any]) = {
Expand Down Expand Up @@ -893,6 +899,8 @@ object AvroCodec {
case StandardType.ZonedDateTimeType =>
val zonedDateTime = a.asInstanceOf[java.time.ZonedDateTime]
zonedDateTime.toString
case StandardType.CurrencyType =>
a.asInstanceOf[java.util.Currency].getCurrencyCode
}

private def encodeSequence[A](schema: Schema[A], v: Chunk[A]): Any = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ object AvroPropMarker {
override def propName: String = "zio.schema.codec.avro.either"
}

case object CurrencyWrapper extends AvroPropMarker {
override def propName: String = "zio.schema.codec.avro.currency"
}

final case class DurationChronoUnit(chronoUnit: ChronoUnit) extends AvroPropMarker {
override def propName: String = DurationChronoUnit.propName
override def value: Any = chronoUnit.name()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,12 @@ object AvroSchemaCodec extends AvroSchemaCodec {
.create(SchemaAvro.Type.STRING)
.addMarkerProp(StringDiscriminator(StringType.ZoneDateTime))
)
case StandardType.CurrencyType =>
Right(
SchemaAvro
.create(SchemaAvro.Type.STRING)
.addMarkerProp(CurrencyWrapper)
)
}
case Optional(codec, _) =>
for {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ object BsonSchemaCodec {
case StandardType.ZoneIdType => BsonCodec.zoneId.asInstanceOf[BsonCodec[A]] //BsonCodec[java.time.ZoneId]
case StandardType.ZoneOffsetType =>
BsonCodec.zoneOffset.asInstanceOf[BsonCodec[A]] //BsonCodec[java.time.ZoneOffset]
// case StandardType.CurrencyType => BsonCodec.currency.asInstanceOf[BsonCodec[A]] //BsonCodec[java.util.Currency] // TODO: needs implementation in zio-bson
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,8 @@ private[codec] class MessagePackDecoder(bytes: Chunk[Byte]) {
decodeString(path).map(OffsetDateTime.parse(_))
case StandardType.ZonedDateTimeType =>
decodeString(path).map(ZonedDateTime.parse(_))
case _ => fail(path, s"Unsupported primitive type $standardType")
case StandardType.CurrencyType => decodeString(path).map(java.util.Currency.getInstance(_))
case _ => fail(path, s"Unsupported primitive type $standardType")
}

private def decodeOptional[A](path: Path, schema: Schema.Optional[A]): Result[Option[A]] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,9 @@ private[codec] class MessagePackEncoder {
case (StandardType.ZonedDateTimeType, v: ZonedDateTime) =>
packer.packString(v.toString)
()
case (StandardType.CurrencyType, v: java.util.Currency) =>
packer.packString(v.getCurrencyCode)
()
case (_, _) =>
throw new NotImplementedError(s"No encoder for $standardType")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ object ProtobufCodec {
case StandardType.OffsetTimeType => false
case StandardType.OffsetDateTimeType => false
case StandardType.ZonedDateTimeType => false
case StandardType.CurrencyType => false
}
}

Expand Down Expand Up @@ -400,6 +401,8 @@ object ProtobufCodec {
encodePrimitive(fieldNumber, StandardType.StringType, v.toString)
case (StandardType.ZonedDateTimeType, v: ZonedDateTime) =>
encodePrimitive(fieldNumber, StandardType.StringType, v.format(DateTimeFormatter.ISO_ZONED_DATE_TIME))
case (StandardType.CurrencyType, v: java.util.Currency) =>
encodePrimitive(fieldNumber, StandardType.StringType, v.getCurrencyCode)
case (_, _) =>
throw new NotImplementedError(s"No encoder for $standardType")
}
Expand Down Expand Up @@ -585,7 +588,8 @@ object ProtobufCodec {
OffsetDateTime.parse(stringDecoder(context))
case StandardType.ZonedDateTimeType =>
ZonedDateTime.parse(stringDecoder(context))
case st => fail(context, s"Unsupported primitive type $st")
case StandardType.CurrencyType => java.util.Currency.getInstance(stringDecoder(context))
case st => fail(context, s"Unsupported primitive type $st")
}

override protected def startCreatingRecord(context: DecoderContext, record: Schema.Record[_]): DecoderContext =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,8 @@ object ThriftCodec {
p.writeString(v.toString)
case (StandardType.ZonedDateTimeType, v: ZonedDateTime) =>
p.writeString(v.toString)
case (StandardType.CurrencyType, v: java.util.Currency) =>
p.writeString(v.getCurrencyCode)
case (_, _) =>
fail(s"No encoder for $standardType")
}
Expand Down Expand Up @@ -408,6 +410,7 @@ object ThriftCodec {
case StandardType.OffsetTimeType => TType.STRING
case StandardType.OffsetDateTimeType => TType.STRING
case StandardType.ZonedDateTimeType => TType.STRING
case StandardType.CurrencyType => TType.STRING
case _ => TType.VOID
}

Expand Down Expand Up @@ -572,6 +575,8 @@ object ThriftCodec {
OffsetDateTime.parse(decodeString(context.path))
case StandardType.ZonedDateTimeType =>
ZonedDateTime.parse(decodeString(context.path))
case StandardType.CurrencyType =>
java.util.Currency.getInstance(decodeString(context.path))
case _ => fail(context, s"Unsupported primitive type $typ")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,7 @@ object DeriveGen {
case StandardType.OffsetTimeType => Gen.offsetTime
case StandardType.OffsetDateTimeType => Gen.offsetDateTime
case StandardType.ZonedDateTimeType => Gen.zonedDateTime
// case StandardType.CurrencyType => Gen.currency // TODO: needs implementation in zio-test
}

gen.map(_.asInstanceOf[A])
Expand Down
16 changes: 11 additions & 5 deletions zio-schema/shared/src/main/scala/zio/schema/Differ.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ import java.math.{ BigInteger, MathContext }
import java.time.temporal.{ ChronoField, ChronoUnit }
import java.time.{
DayOfWeek,
Duration => JDuration,
Instant,
LocalDate,
LocalDateTime,
LocalTime,
Month => JMonth,
MonthDay,
OffsetDateTime,
OffsetTime,
Expand All @@ -18,13 +16,13 @@ import java.time.{
YearMonth,
ZoneId,
ZoneOffset,
Duration => JDuration,
Month => JMonth,
ZonedDateTime => JZonedDateTime
}
import java.util.UUID

import java.util.{ Currency, UUID }
import scala.annotation.nowarn
import scala.collection.immutable.ListMap

import zio.schema.diff.Edit
import zio.{ Chunk, ChunkBuilder }

Expand Down Expand Up @@ -255,6 +253,7 @@ object Differ {
case Schema.Primitive(StandardType.OffsetDateTimeType, _) => offsetDateTime
case Schema.Primitive(StandardType.ZonedDateTimeType, _) => zonedDateTime
case Schema.Primitive(StandardType.ZoneOffsetType, _) => zoneOffset
case Schema.Primitive(StandardType.CurrencyType, _) => currency
case Schema.Tuple2(leftSchema, rightSchema, _) => fromSchema(leftSchema) <*> fromSchema(rightSchema)
case Schema.Optional(schema, _) => fromSchema(schema).optional
case Schema.Sequence(schema, g, f, _, _) =>
Expand Down Expand Up @@ -522,6 +521,13 @@ object Differ {
}
}

val currency: Differ[Currency] =
(thisValue: Currency, thatValue: Currency) =>
if (thisValue == thatValue)
Patch.identical
else
Patch.Currency(thatValue)

def tuple[A, B](left: Differ[A], right: Differ[B]): Differ[(A, B)] =
(thisValue: (A, B), thatValue: (A, B)) =>
(thisValue, thatValue) match {
Expand Down
7 changes: 7 additions & 0 deletions zio-schema/shared/src/main/scala/zio/schema/Patch.scala
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,13 @@ object Patch {
override def invert: Patch[JZonedDateTime] = ZonedDateTime(localDateTimeDiff.invert, zoneIdDiff.invert)
}

final case class Currency(currencyCodeDiff: java.util.Currency) extends Patch[java.util.Currency] {
override def patch(input: java.util.Currency): scala.Either[String, java.util.Currency] =
Right(input)

override def invert: Patch[java.util.Currency] = Currency(currencyCodeDiff)
}

final case class Tuple[A, B](leftDifference: Patch[A], rightDifference: Patch[B]) extends Patch[(A, B)] {

override def isIdentical: Boolean = leftDifference.isIdentical && rightDifference.isIdentical
Expand Down
16 changes: 15 additions & 1 deletion zio-schema/shared/src/main/scala/zio/schema/StandardType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ package zio.schema
import java.math.BigInteger
import java.time
import java.time._

import zio.Chunk

import java.util.Currency

sealed trait StandardType[A] extends Ordering[A] { self =>
def tag: String
def defaultValue: Either[String, A]
Expand Down Expand Up @@ -51,6 +52,7 @@ object StandardType {
final val OFFSET_DATE_TIME = "offsetDateTime"
final val ZONED_DATE_TIME = "zonedDateTime"
final val UUID = "uuid"
final val CURRENCY = "currency"
}

def fromString(tag: String): Option[StandardType[_]] =
Expand Down Expand Up @@ -85,6 +87,7 @@ object StandardType {
case Tags.OFFSET_DATE_TIME => Some(OffsetDateTimeType)
case Tags.ZONED_DATE_TIME => Some(ZonedDateTimeType)
case Tags.UUID => Some(UUIDType)
case Tags.CURRENCY => Some(CurrencyType)
}

def apply[A](implicit standardType: StandardType[A]): StandardType[A] = standardType
Expand Down Expand Up @@ -290,4 +293,15 @@ object StandardType {

override def compare(x: ZonedDateTime, y: ZonedDateTime): Int = x.compareTo(y)
}

implicit object CurrencyType extends StandardType[java.util.Currency] {

override def tag: String = Tags.CURRENCY

override def defaultValue: Either[String, Currency] =
Right(java.util.Currency.getInstance(java.util.Locale.getDefault))

override def compare(x: Currency, y: Currency): Int = x.getCurrencyCode.compareTo(y.getCurrencyCode)
}

}
Loading