diff --git a/libats-http/src/main/scala/com/advancedtelematic/libats/http/ValidatedGenericMarshalling.scala b/libats-http/src/main/scala/com/advancedtelematic/libats/http/ValidatedGenericMarshalling.scala deleted file mode 100644 index 845cb6e..0000000 --- a/libats-http/src/main/scala/com/advancedtelematic/libats/http/ValidatedGenericMarshalling.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.advancedtelematic.libats.http - -import akka.http.scaladsl.unmarshalling.{FromStringUnmarshaller, Unmarshaller} -import akka.http.scaladsl.util.FastFuture -import com.advancedtelematic.libats.data.ValidatedGeneric - -object ValidatedGenericMarshalling { - - implicit def validatedStringUnmarshaller[T](implicit gen: ValidatedGeneric[T, String]): FromStringUnmarshaller[T] = - Unmarshaller[String, T](_ => s => gen.from(s) match { - case Left(e) => FastFuture.failed(e) - case Right(t) => FastFuture.successful(t) - }) - -} diff --git a/libats-messaging-datatype/src/main/scala/com/advancedtelematic/libats/messaging_datatype/Messages.scala b/libats-messaging-datatype/src/main/scala/com/advancedtelematic/libats/messaging_datatype/Messages.scala index 00bd2b3..c213ebe 100644 --- a/libats-messaging-datatype/src/main/scala/com/advancedtelematic/libats/messaging_datatype/Messages.scala +++ b/libats-messaging-datatype/src/main/scala/com/advancedtelematic/libats/messaging_datatype/Messages.scala @@ -8,7 +8,6 @@ import java.util.UUID import com.advancedtelematic.libats.codecs.CirceValidatedGeneric import com.advancedtelematic.libats.data.DataType.{Checksum, CorrelationId, Namespace} import com.advancedtelematic.libats.data.EcuIdentifier -import com.advancedtelematic.libats.data.RefinedUtils._ import com.advancedtelematic.libats.messaging_datatype.DataType.DeviceUpdateStatus.DeviceUpdateStatus import com.advancedtelematic.libats.messaging_datatype.DataType.UpdateType.UpdateType import com.advancedtelematic.libats.messaging_datatype.DataType._ diff --git a/libats-slick/src/main/scala/com/advancedtelematic/libats/slick/db/SlickValidatedGeneric.scala b/libats-slick/src/main/scala/com/advancedtelematic/libats/slick/db/SlickValidatedGeneric.scala index 0626b0f..0e05ece 100644 --- a/libats-slick/src/main/scala/com/advancedtelematic/libats/slick/db/SlickValidatedGeneric.scala +++ b/libats-slick/src/main/scala/com/advancedtelematic/libats/slick/db/SlickValidatedGeneric.scala @@ -8,10 +8,7 @@ import scala.reflect.ClassTag object SlickValidatedGeneric { - private def validatedGenericMapper[T, R: BaseColumnType](implicit gen: ValidatedGeneric[T, R], classTag: ClassTag[T]): BaseColumnType[T] = + implicit def validatedGenericMapper[T, R](implicit gen: ValidatedGeneric[T, R], rtype: BaseColumnType[R], classTag: ClassTag[T]): BaseColumnType[T] = MappedColumnType.base[T, R](gen.to, gen.from(_).valueOr(throw _)) - implicit def validatedStringMapper[T](implicit gen: ValidatedGeneric[T, String], classTag: ClassTag[T]): BaseColumnType[T] = - validatedGenericMapper[T, String] - } \ No newline at end of file diff --git a/libats-slick/src/test/scala/com/advancedtelematic/libats/slick/db/SlickExtensionsSpec.scala b/libats-slick/src/test/scala/com/advancedtelematic/libats/slick/db/SlickExtensionsSpec.scala index 05ed4e4..e689148 100644 --- a/libats-slick/src/test/scala/com/advancedtelematic/libats/slick/db/SlickExtensionsSpec.scala +++ b/libats-slick/src/test/scala/com/advancedtelematic/libats/slick/db/SlickExtensionsSpec.scala @@ -1,5 +1,6 @@ package com.advancedtelematic.libats.slick.db +import com.advancedtelematic.libats.data.{ValidatedGeneric, ValidationError} import com.advancedtelematic.libats.test.DatabaseSpec import org.scalatest.concurrent.ScalaFutures import org.scalatest.time.{Seconds, Span} @@ -11,12 +12,24 @@ import scala.concurrent.ExecutionContext import scala.util.control.NoStackTrace object SlickExtensionsSpec { + import SlickValidatedGeneric.validatedGenericMapper - case class Book(id: Long, title: String, code: Option[String] = None) + final case class BookTitle(title: String) extends AnyVal + object BookTitle { + implicit val validatedBookTitle: ValidatedGeneric[BookTitle, String] = new ValidatedGeneric[BookTitle, String] { + override def to(t: BookTitle): String = t.title + + override def from(r: String): Either[ValidationError, BookTitle] = + if (r contains "invalid") Left(ValidationError("The book title is invalid.")) + else Right(new BookTitle(r)) + } + } + + case class Book(id: Long, title: BookTitle, code: Option[String] = None) class BooksTable(tag: Tag) extends Table[Book](tag, "books") { def id = column[Long]("id", O.PrimaryKey) - def title = column[String]("title") + def title = column[BookTitle]("title") def code = column[Option[String]]("code") override def * = (id, title, code) <> ((Book.apply _).tupled, Book.unapply) @@ -43,6 +56,7 @@ object SlickExtensionsSpec { class SlickExtensionsSpec extends FunSuite with Matchers with ScalaFutures with DatabaseSpec { import SlickExtensions._ import SlickExtensionsSpec._ + import SlickExtensionsSpec.BookTitle.validatedBookTitle val Error = new Exception("Expected Error") with NoStackTrace @@ -52,11 +66,11 @@ class SlickExtensionsSpec extends FunSuite with Matchers with ScalaFutures with test("resultHead on a Query returns the first query result") { val f = for { - _ <- db.run(books += Book(10, "Some book")) + _ <- db.run(books += Book(10, validatedBookTitle.from("Some book").right.get)) inserted <- db.run(books.resultHead(Error)) } yield inserted - f.futureValue shouldBe Book(10, "Some book") + f.futureValue shouldBe Book(10, validatedBookTitle.from("Some book").right.get) } test("resultHead on a Query returns the error in arg") { @@ -66,7 +80,7 @@ class SlickExtensionsSpec extends FunSuite with Matchers with ScalaFutures with test("maybeFilter uses filter if condition is defined") { val f = for { - _ <- db.run(books += Book(20, "Some book", Option("20 some code"))) + _ <- db.run(books += Book(20, validatedBookTitle.from("Some book").right.get, Option("20 some code"))) result <- db.run(books.maybeFilter(_.id === Option(20l)).result) } yield result @@ -76,7 +90,7 @@ class SlickExtensionsSpec extends FunSuite with Matchers with ScalaFutures with test("maybeFilter ignores filter if condition is None") { val f = for { - _ <- db.run(books += Book(30, "Some book")) + _ <- db.run(books += Book(30, validatedBookTitle.from("Some book").right.get)) result <- db.run(books.maybeFilter(_.id === Option.empty[Long]).result) } yield result @@ -86,7 +100,7 @@ class SlickExtensionsSpec extends FunSuite with Matchers with ScalaFutures with test("maybeContains uses string if it is defined") { val f = for { - _ <- db.run(books += Book(40, "A very interesting book", Some("30 some code"))) + _ <- db.run(books += Book(40, validatedBookTitle.from("A very interesting book").right.get, Some("30 some code"))) result <- db.run(books.maybeContains(_.title, Some("interesting")).result) } yield result @@ -119,7 +133,7 @@ class SlickExtensionsSpec extends FunSuite with Matchers with ScalaFutures with } test("handleForeignKeyError ignores the error when FK exists") { - val b = Book(15, "The Count of Monte Cristo", Some("9781377261379")) + val b = Book(15, validatedBookTitle.from("The Count of Monte Cristo").right.get, Some("9781377261379")) val bm = BookMeta(15, 15, 0) val f = db.run((books += b).andThen(bookMeta += bm).handleForeignKeyError(Error))