From 16b308b33a0c300e756ff2725affd8259a69ad85 Mon Sep 17 00:00:00 2001 From: vlad Date: Tue, 29 Nov 2016 14:08:56 -0800 Subject: Changed ids underlying type to String and made Ids and Names — value-classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/scala/xyz/driver/core/auth.scala | 10 ++++---- src/main/scala/xyz/driver/core/core.scala | 34 +++++++++++++++---------- src/main/scala/xyz/driver/core/database.scala | 6 ++--- src/main/scala/xyz/driver/core/file.scala | 8 +++--- src/main/scala/xyz/driver/core/generators.scala | 14 +++++++--- src/main/scala/xyz/driver/core/json.scala | 16 +++++------- 6 files changed, 49 insertions(+), 39 deletions(-) (limited to 'src/main/scala') diff --git a/src/main/scala/xyz/driver/core/auth.scala b/src/main/scala/xyz/driver/core/auth.scala index e4d726b..67de21d 100644 --- a/src/main/scala/xyz/driver/core/auth.scala +++ b/src/main/scala/xyz/driver/core/auth.scala @@ -32,32 +32,32 @@ object auth { } case object ObserverRole extends Role { - val id = Id(1L) + val id = Id("1") val name = Name("observer") val permissions = Set[Permission](CanSeeUser, CanSeeAssay, CanSeeReport) } case object PatientRole extends Role { - val id = Id(2L) + val id = Id("2") val name = Name("patient") val permissions = Set.empty[Permission] } case object CuratorRole extends Role { - val id = Id(3L) + val id = Id("3") val name = Name("curator") val permissions = ObserverRole.permissions ++ Set[Permission](CanEditReport, CanReviewReport) } case object PathologistRole extends Role { - val id = Id(4L) + val id = Id("4") val name = Name("pathologist") val permissions = ObserverRole.permissions ++ Set[Permission](CanEditReport, CanSignOutReport, CanAmendReport, CanEditReviewingReport) } case object AdministratorRole extends Role { - val id = Id(5L) + val id = Id("5") val name = Name("administrator") val permissions = CuratorRole.permissions ++ Set[Permission](CanCreateReport, CanShareReportWithPatient, CanAssignRoles) diff --git a/src/main/scala/xyz/driver/core/core.scala b/src/main/scala/xyz/driver/core/core.scala index b7fbeb6..fa0028b 100644 --- a/src/main/scala/xyz/driver/core/core.scala +++ b/src/main/scala/xyz/driver/core/core.scala @@ -3,10 +3,13 @@ package xyz.driver import scalaz.Equal package object core { + import scala.language.reflectiveCalls def make[T](v: => T)(f: T => Unit): T = { - val value = v; f(value); value + val value = v + f(value) + value } def using[R <: { def close() }, P](r: => R)(f: R => P): P = { @@ -17,30 +20,33 @@ package object core { resource.close() } } +} - object tagging { - private[core] trait Tagged[+V, +Tag] +package core { + + final case class Id[+Tag](value: String) extends AnyVal { + def length: Int = value.length + override def toString: String = value } - type @@[+V, +Tag] = V with tagging.Tagged[V, Tag] - type Id[+Tag] = Long @@ Tag object Id { - def apply[Tag](value: Long) = value.asInstanceOf[Id[Tag]] + implicit def idEqual[T]: Equal[Id[T]] = Equal.equal[Id[T]](_ == _) + implicit def idOrdering[T]: Ordering[Id[T]] = Ordering.by[Id[T], String](_.value) } - implicit def idEqual[T]: Equal[Id[T]] = Equal.equal[Id[T]](_ == _) - implicit def idOrdering[T]: Ordering[Id[T]] = Ordering.by(i => i: Long) - type Name[+Tag] = String @@ Tag - object Name { - def apply[Tag](value: String) = value.asInstanceOf[Name[Tag]] + final case class Name[+Tag](value: String) extends AnyVal { + def length: Int = value.length + override def toString: String = value } - implicit def nameEqual[T]: Equal[Name[T]] = Equal.equal[Name[T]](_ == _) - implicit def nameOrdering[T]: Ordering[Name[T]] = Ordering.by(n => n: String) + object Name { + implicit def nameEqual[T]: Equal[Name[T]] = Equal.equal[Name[T]](_ == _) + implicit def nameOrdering[T]: Ordering[Name[T]] = Ordering.by(_.value) + } object revision { final case class Revision[T](id: String) implicit def revisionEqual[T]: Equal[Revision[T]] = Equal.equal[Revision[T]](_.id == _.id) } -} +} \ No newline at end of file diff --git a/src/main/scala/xyz/driver/core/database.scala b/src/main/scala/xyz/driver/core/database.scala index 85a8cc4..a8ad477 100644 --- a/src/main/scala/xyz/driver/core/database.scala +++ b/src/main/scala/xyz/driver/core/database.scala @@ -37,12 +37,12 @@ object database { import database.profile.api._ implicit def idColumnType[T] = - MappedColumnType.base[Id[T], Long](id => id: Long, Id[T](_)) + MappedColumnType.base[Id[T], String](_.value, Id[T](_)) implicit def nameColumnType[T] = - MappedColumnType.base[Name[T], String](name => name: String, Name[T](_)) + MappedColumnType.base[Name[T], String](_.value, Name[T](_)) - implicit val timeColumnType = MappedColumnType.base[Time, Long](time => time.millis, Time(_)) + implicit val timeColumnType = MappedColumnType.base[Time, Long](_.millis, Time.apply) } trait DatabaseObject extends IdColumnTypes { diff --git a/src/main/scala/xyz/driver/core/file.scala b/src/main/scala/xyz/driver/core/file.scala index 38a2766..9cea9e5 100644 --- a/src/main/scala/xyz/driver/core/file.scala +++ b/src/main/scala/xyz/driver/core/file.scala @@ -59,7 +59,7 @@ object file { def upload(localSource: File, destination: Path): Future[Unit] = Future { checkSafeFileName(destination) { - val _ = s3.putObject(bucket, destination.toString, localSource).getETag + val _ = s3.putObject(bucket.value, destination.toString, localSource).getETag } } @@ -72,20 +72,20 @@ object file { if (!tempDestinationFile.getParentFile.mkdirs()) { throw new Exception(s"Failed to create temp directory to download file `$tempDestinationFile`") } else { - Option(s3.getObject(new GetObjectRequest(bucket, filePath.toString), tempDestinationFile)).map { _ => + Option(s3.getObject(new GetObjectRequest(bucket.value, filePath.toString), tempDestinationFile)).map { _ => tempDestinationFile } } }) def delete(filePath: Path): Future[Unit] = Future { - s3.deleteObject(bucket, filePath.toString) + s3.deleteObject(bucket.value, filePath.toString) } def list(path: Path): ListT[Future, FileLink] = ListT.listT(Future { import scala.collection.JavaConverters._ - val req = new ListObjectsV2Request().withBucketName(bucket).withPrefix(path.toString).withMaxKeys(2) + val req = new ListObjectsV2Request().withBucketName(bucket.value).withPrefix(path.toString).withMaxKeys(2) def isInSubFolder(path: Path)(fileLink: FileLink) = fileLink.location.toString.replace(path.toString + "/", "").contains("/") diff --git a/src/main/scala/xyz/driver/core/generators.scala b/src/main/scala/xyz/driver/core/generators.scala index bb026a9..6bf579b 100644 --- a/src/main/scala/xyz/driver/core/generators.scala +++ b/src/main/scala/xyz/driver/core/generators.scala @@ -13,12 +13,18 @@ object generators { private val random = new Random import random._ - private val DefaultMaxLength = 100 + private val DefaultMaxLength = 10 private val StringLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ".toSet - def nextId[T](): Id[T] = Id[T](scala.math.abs(nextLong())) + def nextInt(maxValue: Int): Int = random.nextInt(maxValue) - def nextId[T](maxValue: Int): Id[T] = Id[T](scala.math.abs(nextInt(maxValue).toLong)) + def nextBoolean(): Boolean = random.nextBoolean() + + def nextDouble(): Double = random.nextDouble() + + def nextId[T](): Id[T] = Id[T](nextString(DefaultMaxLength)) + + def nextId[T](maxLength: Int): Id[T] = Id[T](nextString(maxLength)) def nextName[T](maxLength: Int = DefaultMaxLength): Name[T] = Name[T](nextString(maxLength)) @@ -29,7 +35,7 @@ object generators { def nextString(maxLength: Int = DefaultMaxLength): String = (oneOf[Char](StringLetters) +: arrayOf(oneOf[Char](StringLetters), maxLength - 1)).mkString - def nextOption[T](value: => T): Option[T] = if (nextBoolean) Option(value) else None + def nextOption[T](value: => T): Option[T] = if (nextBoolean()) Option(value) else None def nextPair[L, R](left: => L, right: => R): (L, R) = (left, right) diff --git a/src/main/scala/xyz/driver/core/json.scala b/src/main/scala/xyz/driver/core/json.scala index 3917eca..cc27944 100644 --- a/src/main/scala/xyz/driver/core/json.scala +++ b/src/main/scala/xyz/driver/core/json.scala @@ -12,18 +12,16 @@ import scala.reflect.runtime.universe._ object json { - def IdInPath[T]: PathMatcher1[Id[T]] = - PathMatcher("""[+-]?\d*""".r) flatMap { string => - try Some(Id[T](string.toLong)) - catch { case _: IllegalArgumentException => None } - } + def IdInPath[T]: PathMatcher1[Id[T]] = new PathMatcher1[Id[T]] { + def apply(path: Path) = Matched(Path.Empty, Tuple1(Id[T](path.toString))) + } implicit def idFormat[T] = new RootJsonFormat[Id[T]] { - def write(id: Id[T]) = JsNumber(id) + def write(id: Id[T]) = JsString(id.value) def read(value: JsValue) = value match { - case JsNumber(id) => Id[T](id.toLong) - case _ => throw DeserializationException("Id expects number") + case JsString(id) => Id[T](id) + case _ => throw DeserializationException("Id expects string") } } @@ -32,7 +30,7 @@ object json { } implicit def nameFormat[T] = new RootJsonFormat[Name[T]] { - def write(name: Name[T]) = JsString(name) + def write(name: Name[T]) = JsString(name.value) def read(value: JsValue): Name[T] = value match { case JsString(name) => Name[T](name) -- cgit v1.2.3