package com.xsn.explorer.parsers import com.alexitc.playsonify.core.{ApplicationErrors, ApplicationResult} import com.xsn.explorer.errors.{InvalidOrderingConditionError, InvalidOrderingError, UnknownOrderingFieldError} import com.xsn.explorer.models.base.{FieldOrdering, OrderingCondition, OrderingQuery} import org.scalactic._ trait FieldOrderingParser[+A] { protected def parseField(unsafeField: String): Option[A] protected def defaultField: A protected def defaultOrderingCondition: OrderingCondition = OrderingCondition.AscendingOrder /** * Accepts values in the format field[:condition], being condition * an optional argument allowing the these values: * - asc: for ascending order. * - desc: for descending order. * * The empty string is also accepted returning a default ordering. */ def from(orderByQuery: OrderingQuery): ApplicationResult[FieldOrdering[A]] = { Option(orderByQuery.string) .filter(_.nonEmpty) .map { string => from(string.split(":")) } .getOrElse { val ordering = FieldOrdering(defaultField, defaultOrderingCondition) Good(ordering) } } private def from(parts: Seq[String]): FieldOrdering[A] Or ApplicationErrors = parts match { case Seq(unsafeField) => for { field <- getFieldResult(unsafeField) } yield FieldOrdering(field, defaultOrderingCondition) case Seq(unsafeField, unsafeOrderingCondition) => Accumulation.withGood( getFieldResult(unsafeField), getOrderingConditionResult(unsafeOrderingCondition)) { FieldOrdering.apply } case _ => Bad(InvalidOrderingError).accumulating } private def getFieldResult(unsafeField: String) = { val maybe = parseField(unsafeField) Or.from(maybe, One(UnknownOrderingFieldError)) } private def getOrderingConditionResult(unsafeOrderingCondition: String) = { val maybe = parseOrderingCondition(unsafeOrderingCondition) Or.from(maybe, One(InvalidOrderingConditionError)) } protected def parseOrderingCondition(unsafeOrderingCondition: String): Option[OrderingCondition] = unsafeOrderingCondition match { case "asc" => Some(OrderingCondition.AscendingOrder) case "desc" => Some(OrderingCondition.DescendingOrder) case _ => None } }