Skip to content

Commit aa51933

Browse files
committed
refactor: Minor refactoring to Properties; upgraded SBT version
1 parent 874b316 commit aa51933

File tree

7 files changed

+186
-7
lines changed

7 files changed

+186
-7
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Scala Validators
2+
3+
## Purpose
4+
5+
Provide DSL-like combinators around [Scala Cats `Validated`](https://typelevel.org/cats/datatypes/validated.html) to allow writing data validation components in style similar to testing specs like in [ScalaTest](https://www.scalatest.org/user_guide).
6+
7+
8+
## Usage
9+
10+
See tests and usage in projects [MTB Data Validators](https://github.com/KohlbacherLab/dnpm-dip-mtb-validation-service/blob/main/impl/src/main/scala/de/dnpm/dip/mtb/validation/impl/MTBValidators.scala) and [RD Data Validators](https://github.com/KohlbacherLab/dnpm-dip-rd-validation-service/blob/main/impl/src/main/scala/de/dnpm/dip/rd/validation/impl/RDValidators.scala).
11+
12+
13+
14+

build.sbt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ lazy val compilerOptions = Seq(
4040

4141
lazy val commonSettings = Seq(
4242
scalacOptions ++= compilerOptions,
43-
resolvers ++=
44-
Seq("Local Maven Repository" at "file://" + Path.userHome.absolutePath + "/.m2/repository") ++
45-
Resolver.sonatypeOssRepos("releases") ++
46-
Resolver.sonatypeOssRepos("snapshots")
43+
resolvers ++= Seq(
44+
"Local Maven Repository" at "file://" + Path.userHome.absolutePath + "/.m2/repository",
45+
Resolver.sonatypeCentralSnapshots
46+
)
4747

4848
)
4949

project/build.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sbt.version=1.11.3

src/main/scala/de/ekut/tbi/validation/Properties.scala

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import cats.data.{
66
Validated
77
}
88
import cats.data.Validated.condNel
9+
import scala.language.reflectiveCalls
910

1011

1112
sealed trait Unconstrained[-T]
@@ -16,6 +17,168 @@ object Unconstrained
1617
}
1718

1819

20+
trait CanBeDefined[-T] extends (T => Boolean)
21+
22+
object CanBeDefined
23+
{
24+
25+
type HasDefinedMethod = AnyRef { def isDefined: Boolean }
26+
27+
def apply[T](implicit cbd: CanBeDefined[T]) = cbd
28+
29+
implicit def hasDefinedMethod[T <: HasDefinedMethod]: CanBeDefined[T] =
30+
new CanBeDefined[T]{
31+
override def apply(t: T) = t.asInstanceOf[HasDefinedMethod].isDefined
32+
}
33+
34+
}
35+
36+
37+
trait CanBeSuccess[-T] extends (T => Boolean)
38+
39+
object CanBeSuccess
40+
{
41+
42+
type HasSuccessMethod = AnyRef { def isSuccess: Boolean }
43+
44+
def apply[T](implicit cbd: CanBeSuccess[T]) = cbd
45+
46+
implicit def hasMethodIsSuccess[T <: HasSuccessMethod]: CanBeSuccess[T] =
47+
new CanBeSuccess[T]{
48+
override def apply(t: T) = t.asInstanceOf[HasSuccessMethod].isSuccess
49+
}
50+
51+
implicit def validatedSuccess[E,T]: CanBeSuccess[Validated[E,T]] =
52+
new CanBeSuccess[Validated[E,T]]{
53+
override def apply(v: Validated[E,T]) = v.isValid
54+
}
55+
}
56+
57+
58+
trait CanBeEmpty[-T] extends (T => Boolean)
59+
60+
object CanBeEmpty
61+
{
62+
63+
type HasEmptyMethod = AnyRef { def isEmpty: Boolean }
64+
65+
def apply[T](implicit cbd: CanBeEmpty[T]) = cbd
66+
67+
implicit def hasIsEmpty[T <: HasEmptyMethod]: CanBeEmpty[T] =
68+
new CanBeEmpty[T]{
69+
override def apply(t: T) = t.asInstanceOf[HasEmptyMethod].isEmpty
70+
}
71+
72+
implicit def hasParameterlessIsEmpty[T <: AnyRef { def isEmpty(): Boolean }]: CanBeEmpty[T] =
73+
new CanBeEmpty[T]{
74+
override def apply(t: T) = t.asInstanceOf[{ def isEmpty(): Boolean }].isEmpty()
75+
}
76+
77+
}
78+
79+
80+
trait CanContain[T,-C]{
81+
self =>
82+
83+
def contains(c: C)(t: T): Boolean
84+
85+
def containsOnly(c: C)(t: T): Boolean
86+
87+
def containsAnyOf(c: C)(ts: Set[T]): Boolean =
88+
ts.exists(t => self.contains(c)(t))
89+
90+
def containsAllOf(c: C)(ts: Set[T]): Boolean =
91+
ts.forall(t => self.contains(c)(t))
92+
93+
}
94+
95+
96+
object CanContain
97+
{
98+
def apply[T,C](implicit cc: CanContain[T,C]) = cc
99+
100+
implicit def optionContains[T]: CanContain[T,Option[T]] =
101+
new CanContain[T,Option[T]]{
102+
def contains(opt: Option[T])(t: T) = opt.contains(t)
103+
104+
def containsOnly(opt: Option[T])(t: T): Boolean = opt.contains(t)
105+
}
106+
107+
implicit val stringContainsChar: CanContain[Char,String] =
108+
new CanContain[Char,String]{
109+
def contains(s: String)(ch: Char) = s.contains(ch)
110+
111+
def containsOnly(s: String)(t: Char): Boolean =
112+
s.forall(_ == t)
113+
}
114+
115+
implicit def stringContainsCharSequence[Chars <: CharSequence]: CanContain[Chars,String] =
116+
new CanContain[Chars,String]{
117+
def contains(s: String)(ch: Chars) = s.contains(ch)
118+
119+
def containsOnly(c: String)(t: Chars): Boolean = {
120+
val s = t.toString
121+
122+
if (s.length == 1) c.forall(_ == s.head)
123+
else c contentEquals s
124+
125+
}
126+
}
127+
128+
implicit def iterableContains[T,C[X] <: Iterable[X]]: CanContain[T,C[T]] =
129+
new CanContain[T,C[T]]{
130+
def contains(c: C[T])(t: T) = c.exists(_ == t)
131+
132+
def containsOnly(c: C[T])(t: T): Boolean = c.forall(_ == t)
133+
}
134+
135+
implicit def nelContains[T]: CanContain[T,NonEmptyList[T]] =
136+
new CanContain[T,NonEmptyList[T]]{
137+
def contains(nel: NonEmptyList[T])(t: T) = nel.exists(_ == t)
138+
139+
def containsOnly(nel: NonEmptyList[T])(t: T): Boolean = nel.forall(_ == t)
140+
}
141+
142+
import scala.util.Either
143+
144+
implicit def eitherContains[A,B]: CanContain[B,Either[A,B]] =
145+
new CanContain[B,Either[A,B]]{
146+
def contains(either: Either[A,B])(t: B) = either.contains(t)
147+
148+
def containsOnly(either: Either[A,B])(t: B): Boolean = either.contains(t)
149+
}
150+
151+
}
152+
153+
154+
trait CanHaveSize[-C]{
155+
def sizeOf(c: C): Int
156+
157+
def hasSize(c: C)(size: Int): Boolean = sizeOf(c) == size
158+
}
159+
160+
object CanHaveSize
161+
{
162+
163+
def apply[C](implicit cc: CanHaveSize[C]) = cc
164+
165+
implicit def hasSize[C <: { def size: Int }]: CanHaveSize[C] =
166+
new CanHaveSize[C]{
167+
def sizeOf(c: C): Int =
168+
c.asInstanceOf[{ def size: Int }].size
169+
170+
}
171+
172+
implicit def charSeqSize[Chars <: CharSequence]: CanHaveSize[Chars] =
173+
new CanHaveSize[Chars]{
174+
def sizeOf(chars: Chars): Int =
175+
chars.length
176+
}
177+
178+
}
179+
180+
181+
/*
19182
trait CanBeDefined[-T]{
20183
def isDefined(t: T): Boolean
21184
}
@@ -192,3 +355,4 @@ object CanHaveSize
192355
}
193356
194357
}
358+
*/

src/main/scala/de/ekut/tbi/validation/dsl/DefinedWord.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ sealed trait DefinedWord extends NegatableValidatorBuilder[String,CanBeDefined]
2323

2424
def apply[T](implicit cbd: CanBeDefined[T]): NegatableValidator[String,T] =
2525
Validator[String,T](
26-
cbd.isDefined(_)
26+
cbd(_)
2727
)(
2828
t => s"$t is not defined",
2929
t => s"$t is defined"

src/main/scala/de/ekut/tbi/validation/dsl/EmptyWord.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ sealed trait EmptyWord extends NegatableValidatorBuilder[String,CanBeEmpty]
2323

2424
def apply[T](implicit cbe: CanBeEmpty[T]): NegatableValidator[String,T] =
2525
Validator[String,T](
26-
cbe.isEmpty(_)
26+
cbe(_)
2727
)(
2828
t => s"$t is not empty",
2929
t => s"$t is empty"

src/main/scala/de/ekut/tbi/validation/dsl/SuccessWord.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ sealed trait SuccessWord extends NegatableValidatorBuilder[String,CanBeSuccess]
2323

2424
def apply[T](implicit cbd: CanBeSuccess[T]): NegatableValidator[String,T] =
2525
Validator[String,T](
26-
cbd.isSuccess(_)
26+
cbd(_)
2727
)(
2828
t => s"$t is not success",
2929
t => s"$t is success"

0 commit comments

Comments
 (0)