From 985ee69beed836b97f3476306736d3f15ce37e1c Mon Sep 17 00:00:00 2001 From: Jakob Odersky Date: Wed, 2 Aug 2017 13:38:49 -0700 Subject: Add parsers to common --- .../driver/pdsuicommon/parsers/SortingParser.scala | 55 ++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/main/scala/xyz/driver/pdsuicommon/parsers/SortingParser.scala (limited to 'src/main/scala/xyz/driver/pdsuicommon/parsers/SortingParser.scala') diff --git a/src/main/scala/xyz/driver/pdsuicommon/parsers/SortingParser.scala b/src/main/scala/xyz/driver/pdsuicommon/parsers/SortingParser.scala new file mode 100644 index 0000000..c042211 --- /dev/null +++ b/src/main/scala/xyz/driver/pdsuicommon/parsers/SortingParser.scala @@ -0,0 +1,55 @@ +package xyz.driver.server.parsers + +import xyz.driver.server.parsers.errors.ParseQueryArgException +import xyz.driver.pdsuicommon.db.{Sorting, SortingOrder} +import fastparse.all._ +import fastparse.core.Parsed +import play.api.routing.sird._ + +import scala.util.Try + +object SortingParser { + + private val sortingOrderParser: Parser[SortingOrder] = P("-".!.?).map { + case Some(_) => SortingOrder.Descending + case None => SortingOrder.Ascending + } + + private def dimensionSortingParser(validDimensions: Seq[String]): Parser[Sorting.Dimension] = { + P(sortingOrderParser ~ StringIn(validDimensions: _*).!).map { + case (sortingOrder, field) => + val prefixedFields = field.split("\\.", 2) + prefixedFields.size match { + case 1 => Sorting.Dimension(None, field, sortingOrder) + case 2 => Sorting.Dimension(Some(prefixedFields.head), prefixedFields.last, sortingOrder) + } + } + } + + private def sequentialSortingParser(validDimensions: Seq[String]): Parser[Sorting.Sequential] = { + P(dimensionSortingParser(validDimensions).rep(min = 1, sep = ",") ~ End).map { dimensions => + Sorting.Sequential(dimensions) + } + } + + def parse(validDimensions: Set[String], queryString: QueryString): Try[Sorting] = Try { + queryString.getOrElse("sort", Seq.empty) match { + case Nil => Sorting.Sequential(Seq.empty) + + case rawSorting +: Nil => + val parser = sequentialSortingParser(validDimensions.toSeq) + parser.parse(rawSorting) match { + case Parsed.Success(x, _) => x + case e: Parsed.Failure => + throw new ParseQueryArgException("sort" -> formatFailure(e)) + } + + case xs => throw new ParseQueryArgException("sort" -> "multiple sections are not allowed") + } + } + + private def formatFailure(e: Parsed.Failure): String = { + ParseError.msg(e.extra.input, e.extra.traced.expected, e.index) + } + +} -- cgit v1.2.3