366 lines
15 KiB
Scala
366 lines
15 KiB
Scala
package gs.predicate.v0.serde.json
|
|
|
|
import gs.predicate.v0.api.And
|
|
import gs.predicate.v0.api.False
|
|
import gs.predicate.v0.api.Messages
|
|
import gs.predicate.v0.api.Or
|
|
import gs.predicate.v0.api.Predicate
|
|
import gs.predicate.v0.api.True
|
|
import gs.predicate.v0.json.JsonComparison
|
|
import gs.predicate.v0.json.JsonComparisonPredicate
|
|
import gs.predicate.v0.string.StringComparison
|
|
import gs.predicate.v0.string.StringComparisonPredicate
|
|
import io.circe.*
|
|
import io.circe.syntax.*
|
|
|
|
/** Given some [[And]] predicate, encode it as a JSON blob.
|
|
*
|
|
* @param and
|
|
* The [[And]] predicate.
|
|
* @return
|
|
* The JSON blob representing the [[And]].
|
|
*/
|
|
def encodeAnd(and: And): Json =
|
|
Json.obj(
|
|
(JsonKeys.predicateType, Json.fromString(And.PredicateType)),
|
|
(JsonKeys.predicates, and.ps.asJson)
|
|
)
|
|
|
|
def encodeJsonComparisonAnd(and: JsonComparison.And): Json =
|
|
Json.obj(
|
|
(JsonKeys.name, Json.fromString(JsonComparison.And.Name)),
|
|
(JsonKeys.comparisons, and.cs.asJson)
|
|
)
|
|
|
|
def encodeStringComparisonAnd(and: StringComparison.And): Json =
|
|
Json.obj(
|
|
(JsonKeys.name, Json.fromString(StringComparison.And.Name)),
|
|
(JsonKeys.comparisons, and.cs.asJson)
|
|
)
|
|
|
|
/** Given some [[Or]] predicate, encode it as a JSON blob.
|
|
*
|
|
* @param and
|
|
* The [[Or]] predicate.
|
|
* @return
|
|
* The JSON blob representing the [[Or]].
|
|
*/
|
|
def encodeOr(and: Or): Json =
|
|
Json.obj(
|
|
(JsonKeys.predicateType, Json.fromString(Or.PredicateType)),
|
|
(JsonKeys.predicates, and.ps.asJson)
|
|
)
|
|
|
|
def encodeJsonComparisonOr(or: JsonComparison.Or): Json =
|
|
Json.obj(
|
|
(JsonKeys.name, Json.fromString(JsonComparison.Or.Name)),
|
|
(JsonKeys.comparisons, or.cs.asJson)
|
|
)
|
|
|
|
def encodeStringComparisonOr(or: StringComparison.Or): Json =
|
|
Json.obj(
|
|
(JsonKeys.name, Json.fromString(StringComparison.Or.Name)),
|
|
(JsonKeys.comparisons, or.cs.asJson)
|
|
)
|
|
|
|
/** @return
|
|
* Generic encoder for any [[Predicate]].
|
|
*/
|
|
given predicateEncoder: Encoder[Predicate] =
|
|
Encoder.instance {
|
|
case p: True.type => Encoder[True.type].apply(p)
|
|
case p: False.type => Encoder[False.type].apply(p)
|
|
case p: And => encodeAnd(p)
|
|
case p: Or => encodeOr(p)
|
|
case p: StringComparisonPredicate =>
|
|
Encoder[StringComparisonPredicate].apply(p)
|
|
case p: JsonComparisonPredicate => Encoder[JsonComparisonPredicate].apply(p)
|
|
case p =>
|
|
throw new IllegalArgumentException(
|
|
s"Unsupported predicate type: '${p.predicateType}'"
|
|
)
|
|
}
|
|
|
|
given jsonComparisonEncoder: Encoder[JsonComparison] =
|
|
Encoder.instance[JsonComparison] {
|
|
case jc: JsonComparison.And => encodeJsonComparisonAnd(jc)
|
|
case jc: JsonComparison.Or => encodeJsonComparisonOr(jc)
|
|
case jc: JsonComparison.True.type =>
|
|
Encoder[JsonComparison.True.type].apply(jc)
|
|
case jc: JsonComparison.False.type =>
|
|
Encoder[JsonComparison.False.type].apply(jc)
|
|
case jc: JsonComparison.Eq => Encoder[JsonComparison.Eq].apply(jc)
|
|
case jc: JsonComparison.Neq => Encoder[JsonComparison.Neq].apply(jc)
|
|
case jc: JsonComparison.StringContains =>
|
|
Encoder[JsonComparison.StringContains].apply(jc)
|
|
case jc: JsonComparison.StringPrefix =>
|
|
Encoder[JsonComparison.StringPrefix].apply(jc)
|
|
case jc: JsonComparison.StringSuffix =>
|
|
Encoder[JsonComparison.StringSuffix].apply(jc)
|
|
case jc: JsonComparison.IntLessThan =>
|
|
Encoder[JsonComparison.IntLessThan].apply(jc)
|
|
case jc: JsonComparison.IntLessThanOrEqualTo =>
|
|
Encoder[JsonComparison.IntLessThanOrEqualTo].apply(jc)
|
|
case jc: JsonComparison.IntGreaterThan =>
|
|
Encoder[JsonComparison.IntGreaterThan].apply(jc)
|
|
case jc: JsonComparison.IntGreaterThanOrEqualTo =>
|
|
Encoder[JsonComparison.IntGreaterThanOrEqualTo].apply(jc)
|
|
case jc: JsonComparison.IntBetweenInclusive =>
|
|
Encoder[JsonComparison.IntBetweenInclusive].apply(jc)
|
|
case jc: JsonComparison.IntBetweenExclusive =>
|
|
Encoder[JsonComparison.IntBetweenExclusive].apply(jc)
|
|
case jc: JsonComparison.DateEq => Encoder[JsonComparison.DateEq].apply(jc)
|
|
case jc: JsonComparison.DateBefore =>
|
|
Encoder[JsonComparison.DateBefore].apply(jc)
|
|
case jc: JsonComparison.DateAfter =>
|
|
Encoder[JsonComparison.DateAfter].apply(jc)
|
|
case jc: JsonComparison.DateBetweenInclusive =>
|
|
Encoder[JsonComparison.DateBetweenInclusive].apply(jc)
|
|
case jc: JsonComparison.DateBetweenExclusive =>
|
|
Encoder[JsonComparison.DateBetweenExclusive].apply(jc)
|
|
case jc =>
|
|
throw new IllegalArgumentException(
|
|
s"Unsupported JSON comparison: '${jc.name}'"
|
|
)
|
|
}
|
|
|
|
given stringComparisonEncoder: Encoder[StringComparison] =
|
|
Encoder.instance[StringComparison] {
|
|
case jc: StringComparison.And => encodeStringComparisonAnd(jc)
|
|
case jc: StringComparison.Or => encodeStringComparisonOr(jc)
|
|
case jc: StringComparison.True.type =>
|
|
Encoder[StringComparison.True.type].apply(jc)
|
|
case jc: StringComparison.False.type =>
|
|
Encoder[StringComparison.False.type].apply(jc)
|
|
case jc: StringComparison.Eq => Encoder[StringComparison.Eq].apply(jc)
|
|
case jc: StringComparison.Neq => Encoder[StringComparison.Neq].apply(jc)
|
|
case jc: StringComparison.StringContains =>
|
|
Encoder[StringComparison.StringContains].apply(jc)
|
|
case jc: StringComparison.StringPrefix =>
|
|
Encoder[StringComparison.StringPrefix].apply(jc)
|
|
case jc: StringComparison.StringSuffix =>
|
|
Encoder[StringComparison.StringSuffix].apply(jc)
|
|
case jc: StringComparison.IntLessThan =>
|
|
Encoder[StringComparison.IntLessThan].apply(jc)
|
|
case jc: StringComparison.IntLessThanOrEqualTo =>
|
|
Encoder[StringComparison.IntLessThanOrEqualTo].apply(jc)
|
|
case jc: StringComparison.IntGreaterThan =>
|
|
Encoder[StringComparison.IntGreaterThan].apply(jc)
|
|
case jc: StringComparison.IntGreaterThanOrEqualTo =>
|
|
Encoder[StringComparison.IntGreaterThanOrEqualTo].apply(jc)
|
|
case jc: StringComparison.IntBetweenInclusive =>
|
|
Encoder[StringComparison.IntBetweenInclusive].apply(jc)
|
|
case jc: StringComparison.IntBetweenExclusive =>
|
|
Encoder[StringComparison.IntBetweenExclusive].apply(jc)
|
|
case jc: StringComparison.DateEq =>
|
|
Encoder[StringComparison.DateEq].apply(jc)
|
|
case jc: StringComparison.DateBefore =>
|
|
Encoder[StringComparison.DateBefore].apply(jc)
|
|
case jc: StringComparison.DateAfter =>
|
|
Encoder[StringComparison.DateAfter].apply(jc)
|
|
case jc: StringComparison.DateBetweenInclusive =>
|
|
Encoder[StringComparison.DateBetweenInclusive].apply(jc)
|
|
case jc: StringComparison.DateBetweenExclusive =>
|
|
Encoder[StringComparison.DateBetweenExclusive].apply(jc)
|
|
case jc =>
|
|
throw new IllegalArgumentException(
|
|
s"Unsupported string comparison: '${jc.name}'"
|
|
)
|
|
}
|
|
|
|
/** Given some JSON cursor, decode a logical [[And]] predicate.
|
|
*
|
|
* @param cursor
|
|
* The cursor that points to some JSON value.
|
|
* @return
|
|
* The [[And]] predicate or a decoding failure.
|
|
*/
|
|
def decodeAnd(
|
|
cursor: HCursor
|
|
): Either[DecodingFailure, And] =
|
|
for ps <- cursor.downField(JsonKeys.predicates).as[List[Predicate]]
|
|
yield new And(ps)
|
|
|
|
def decodeJsonComparisonAnd(
|
|
cursor: HCursor
|
|
): Either[DecodingFailure, JsonComparison.And] =
|
|
for cs <- cursor.downField(JsonKeys.comparisons).as[List[JsonComparison]]
|
|
yield new JsonComparison.And(cs)
|
|
|
|
def decodeStringComparisonAnd(
|
|
cursor: HCursor
|
|
): Either[DecodingFailure, StringComparison.And] =
|
|
for cs <- cursor.downField(JsonKeys.comparisons).as[List[StringComparison]]
|
|
yield new StringComparison.And(cs)
|
|
|
|
/** Given some JSON cursor, decode a logical [[Or]] predicate.
|
|
*
|
|
* @param cursor
|
|
* The cursor that points to some JSON value.
|
|
* @return
|
|
* The [[Or]] predicate or a decoding failure.
|
|
*/
|
|
def decodeOr(cursor: HCursor): Either[DecodingFailure, Or] =
|
|
for ps <- cursor.downField(JsonKeys.predicates).as[List[Predicate]]
|
|
yield new Or(ps)
|
|
|
|
def decodeJsonComparisonOr(
|
|
cursor: HCursor
|
|
): Either[DecodingFailure, JsonComparison.Or] =
|
|
for cs <- cursor.downField(JsonKeys.comparisons).as[List[JsonComparison]]
|
|
yield new JsonComparison.Or(cs)
|
|
|
|
def decodeStringComparisonOr(
|
|
cursor: HCursor
|
|
): Either[DecodingFailure, StringComparison.Or] =
|
|
for cs <- cursor.downField(JsonKeys.comparisons).as[List[StringComparison]]
|
|
yield new StringComparison.Or(cs)
|
|
|
|
/** Given some JSON cursor, decode any known [[Predicate]].
|
|
*
|
|
* @param cursor
|
|
* The cursor that points to some JSON value.
|
|
* @return
|
|
* The decoded [[Predicate]] or some decoding failure.
|
|
*/
|
|
def decodePredicate(
|
|
cursor: HCursor
|
|
): Either[DecodingFailure, Predicate] =
|
|
for
|
|
predicateType <- cursor.downField(JsonKeys.predicateType).as[String]
|
|
predicate <- predicateType match
|
|
case True.PredicateType => Right(True)
|
|
case False.PredicateType => Right(False)
|
|
case And.PredicateType => decodeAnd(cursor)
|
|
case Or.PredicateType => decodeOr(cursor)
|
|
case StringComparisonPredicate.PredicateType =>
|
|
Decoder[StringComparisonPredicate].apply(cursor)
|
|
case JsonComparisonPredicate.PredicateType =>
|
|
Decoder[JsonComparisonPredicate].apply(cursor)
|
|
case _ =>
|
|
Left(
|
|
DecodingFailure(
|
|
Messages.unrecognizedPredicateType(predicateType),
|
|
Nil
|
|
)
|
|
)
|
|
yield predicate
|
|
|
|
/** @return
|
|
* Generic decoder for any [[Predicate]].
|
|
*/
|
|
given predicateDecoder: Decoder[Predicate] =
|
|
Decoder.instance[Predicate](cursor => decodePredicate(cursor))
|
|
|
|
/** Given some JSON cursor, decode any known JSON comparison.
|
|
*
|
|
* @param cursor
|
|
* The cursor.
|
|
* @return
|
|
* The decoded [[JsonComparison]] or a decoding failure.
|
|
*/
|
|
def decodeJsonComparison(cursor: HCursor)
|
|
: Either[DecodingFailure, JsonComparison] =
|
|
for
|
|
name <- cursor.downField(JsonKeys.name).as[String]
|
|
comparison <- name match
|
|
case JsonComparison.And.Name => decodeJsonComparisonAnd(cursor)
|
|
case JsonComparison.Or.Name => decodeJsonComparisonOr(cursor)
|
|
case JsonComparison.True.Name =>
|
|
Decoder[JsonComparison.True.type].apply(cursor)
|
|
case JsonComparison.False.Name =>
|
|
Decoder[JsonComparison.False.type].apply(cursor)
|
|
case JsonComparison.Eq.Name => Decoder[JsonComparison.Eq].apply(cursor)
|
|
case JsonComparison.Neq.Name => Decoder[JsonComparison.Neq].apply(cursor)
|
|
case JsonComparison.StringContains.Name =>
|
|
Decoder[JsonComparison.StringContains].apply(cursor)
|
|
case JsonComparison.StringPrefix.Name =>
|
|
Decoder[JsonComparison.StringPrefix].apply(cursor)
|
|
case JsonComparison.StringSuffix.Name =>
|
|
Decoder[JsonComparison.StringSuffix].apply(cursor)
|
|
case JsonComparison.IntLessThan.Name =>
|
|
Decoder[JsonComparison.IntLessThan].apply(cursor)
|
|
case JsonComparison.IntLessThanOrEqualTo.Name =>
|
|
Decoder[JsonComparison.IntLessThanOrEqualTo].apply(cursor)
|
|
case JsonComparison.IntGreaterThan.Name =>
|
|
Decoder[JsonComparison.IntGreaterThan].apply(cursor)
|
|
case JsonComparison.IntGreaterThanOrEqualTo.Name =>
|
|
Decoder[JsonComparison.IntGreaterThanOrEqualTo].apply(cursor)
|
|
case JsonComparison.IntBetweenInclusive.Name =>
|
|
Decoder[JsonComparison.IntBetweenInclusive].apply(cursor)
|
|
case JsonComparison.IntBetweenExclusive.Name =>
|
|
Decoder[JsonComparison.IntBetweenExclusive].apply(cursor)
|
|
case JsonComparison.DateEq.Name =>
|
|
Decoder[JsonComparison.DateEq].apply(cursor)
|
|
case JsonComparison.DateBefore.Name =>
|
|
Decoder[JsonComparison.DateBefore].apply(cursor)
|
|
case JsonComparison.DateAfter.Name =>
|
|
Decoder[JsonComparison.DateAfter].apply(cursor)
|
|
case JsonComparison.DateBetweenInclusive.Name =>
|
|
Decoder[JsonComparison.DateBetweenInclusive].apply(cursor)
|
|
case JsonComparison.DateBetweenExclusive.Name =>
|
|
Decoder[JsonComparison.DateBetweenExclusive].apply(cursor)
|
|
case _ =>
|
|
Left(
|
|
DecodingFailure(Messages.unrecognizedJsonComparison(name), Nil)
|
|
)
|
|
yield comparison
|
|
|
|
/** Generic decoder for any [[JsonComparison]].
|
|
*/
|
|
given jsonComparisonDecoder: Decoder[JsonComparison] =
|
|
Decoder.instance[JsonComparison](decodeJsonComparison)
|
|
|
|
def decodeStringComparison(cursor: HCursor)
|
|
: Either[DecodingFailure, StringComparison] =
|
|
for
|
|
name <- cursor.downField(JsonKeys.name).as[String]
|
|
comparison <- name match
|
|
case StringComparison.And.Name => decodeStringComparisonAnd(cursor)
|
|
case StringComparison.Or.Name => decodeStringComparisonOr(cursor)
|
|
case StringComparison.True.Name =>
|
|
Decoder[StringComparison.True.type].apply(cursor)
|
|
case StringComparison.False.Name =>
|
|
Decoder[StringComparison.False.type].apply(cursor)
|
|
case StringComparison.Eq.Name =>
|
|
Decoder[StringComparison.Eq].apply(cursor)
|
|
case StringComparison.Neq.Name =>
|
|
Decoder[StringComparison.Neq].apply(cursor)
|
|
case StringComparison.StringContains.Name =>
|
|
Decoder[StringComparison.StringContains].apply(cursor)
|
|
case StringComparison.StringPrefix.Name =>
|
|
Decoder[StringComparison.StringPrefix].apply(cursor)
|
|
case StringComparison.StringSuffix.Name =>
|
|
Decoder[StringComparison.StringSuffix].apply(cursor)
|
|
case StringComparison.IntLessThan.Name =>
|
|
Decoder[StringComparison.IntLessThan].apply(cursor)
|
|
case StringComparison.IntLessThanOrEqualTo.Name =>
|
|
Decoder[StringComparison.IntLessThanOrEqualTo].apply(cursor)
|
|
case StringComparison.IntGreaterThan.Name =>
|
|
Decoder[StringComparison.IntGreaterThan].apply(cursor)
|
|
case StringComparison.IntGreaterThanOrEqualTo.Name =>
|
|
Decoder[StringComparison.IntGreaterThanOrEqualTo].apply(cursor)
|
|
case StringComparison.IntBetweenInclusive.Name =>
|
|
Decoder[StringComparison.IntBetweenInclusive].apply(cursor)
|
|
case StringComparison.IntBetweenExclusive.Name =>
|
|
Decoder[StringComparison.IntBetweenExclusive].apply(cursor)
|
|
case StringComparison.DateEq.Name =>
|
|
Decoder[StringComparison.DateEq].apply(cursor)
|
|
case StringComparison.DateBefore.Name =>
|
|
Decoder[StringComparison.DateBefore].apply(cursor)
|
|
case StringComparison.DateAfter.Name =>
|
|
Decoder[StringComparison.DateAfter].apply(cursor)
|
|
case StringComparison.DateBetweenInclusive.Name =>
|
|
Decoder[StringComparison.DateBetweenInclusive].apply(cursor)
|
|
case StringComparison.DateBetweenExclusive.Name =>
|
|
Decoder[StringComparison.DateBetweenExclusive].apply(cursor)
|
|
case _ =>
|
|
Left(
|
|
DecodingFailure(Messages.unrecognizedStringComparison(name), Nil)
|
|
)
|
|
yield comparison
|
|
|
|
/** Generic decoder for any [[StringComparison]].
|
|
*/
|
|
given stringComparisonDecoder: Decoder[StringComparison] =
|
|
Decoder.instance[StringComparison](decodeStringComparison)
|