gs-predicate/src/main/scala/gs/predicate/v0/json/JsonComparisonPredicate.scala

76 lines
2.3 KiB
Scala

package gs.predicate.v0.json
import gs.predicate.v0.api.Messages
import gs.predicate.v0.api.Predicate
import gs.predicate.v0.json.query.JsonQuery
import gs.predicate.v0.serde.json.JsonKeys
import gs.predicate.v0.serde.json.jsonComparisonDecoder
import gs.predicate.v0.serde.json.jsonComparisonEncoder
import io.circe.Decoder
import io.circe.DecodingFailure
import io.circe.Encoder
import io.circe.Json
import io.circe.syntax.*
/** Predicate that matches if the given JSON input matches the comparison
* function when the given query is applied.
*
* @param query
* The [[JsonQuery]] that must be satisfied.
* @param comparison
* The JSON comparison that must match the values identified by the query.
*/
final class JsonComparisonPredicate(
val query: JsonQuery,
val comparison: JsonComparison
) extends JsonPredicate:
/** @inheritDocs
*/
final override val predicateType: String =
JsonComparisonPredicate.PredicateType
/** @inheritDocs
*/
override def evalJson(input: Json): Predicate.Result =
Predicate.Result(query.eval(input, comparison.compare))
object JsonComparisonPredicate:
final val PredicateType: String = "json-query-comparison"
def apply(
query: JsonQuery,
comparison: JsonComparison
): JsonComparisonPredicate = new JsonComparisonPredicate(query, comparison)
given jsonQueryComparisonEncoder: Encoder[JsonComparisonPredicate] =
Encoder.instance[JsonComparisonPredicate] { p =>
Json.obj(
(JsonKeys.predicateType, Json.fromString(PredicateType)),
(JsonKeys.query, Json.fromString(p.query.toString())),
(JsonKeys.comparison, p.comparison.asJson)
)
}
given jsonQueryComparisonDecoder: Decoder[JsonComparisonPredicate] =
Decoder.instance[JsonComparisonPredicate] { cursor =>
cursor.downField(JsonKeys.predicateType).as[String].flatMap {
case PredicateType =>
for
query <- cursor.downField(JsonKeys.query).as[JsonQuery]
comparison <- cursor
.downField(JsonKeys.comparison)
.as[JsonComparison]
yield new JsonComparisonPredicate(query, comparison)
case candidate =>
Left(
DecodingFailure(
Messages.invalidPredicateType(candidate, PredicateType),
Nil
)
)
}
}
end JsonComparisonPredicate