For example purposes imagine you have the following:
import play.api.data._
import play.api.data.Forms._
case class TestDomainClass(text: String, number: Int, date: DateTime, long: Long, boolean: Boolean)
val testForm = Form(
mapping(
"textField" -> text,
"numberField" -> number,
"dateField" -> jodaDate,
"longField" -> longNumber,
"booleanField" -> boolean
)(TestDomainClass.apply)(TestDomainClass.unapply)
)
My objective is to pattern match on the parameter type of each of the fields. For example: for the textField
the parameter type would be String
, and for the dateField
would be org.joda.time.DateTime
.
1st Solution attempt
def typeOfMappingUsingTypeTag[T: TypeTag](m: Mapping[T]) = typeOf[T] match {
case t if t =:= typeOf[String] => println("type is String")
case t if t =:= typeOf[Int] => println("type is Int")
case t if t =:= typeOf[org.joda.time.DateTime] => println("type is DateTime")
case t if t =:= typeOf[Long] => println("type is Long")
case t if t =:= typeOf[Boolean] => println("type is boolean")
case _ => println("type is something else")
}
for(m <- testForm.mapping.mappings if m.key.nonEmpty) {
print(m.key)
typeOfMappingUsingTypeTag(m)
}
With the following output:
textFieldtype is something else
numberFieldtype is something else
dateFieldtype is something else
longFieldtype is something else
booleanFieldtype is something else
So no luck, which is somewhat expected since in the source the Mapping does not have a context bound to TypeTag.
2nd Solution attempt
def typeOfMappingUsingPatternMatch[T](m: Mapping[T]) = m match {
case text => println("type is String")
case number => println("type is Int")
case jodaTime => println("type is DateTime")
case longNumber => println("type is Long")
case boolean => println("type is Boolean")
case _ => println("type is something else")
}
for(m <- testForm.mapping.mappings if m.key.nonEmpty) {
print(m.key)
typeOfMappingUsingPatternMatch(m)
}
With the following output:
textFieldtype is String
numberFieldtype is String
dateFieldtype is String
longFieldtype is String
booleanFieldtype is String
And the following compiling warning:
[warn] /aFolder/aProject/app/controllers/IPBlocks.scala:58: patterns after a variable pattern cannot match (SLS 8.1.1)
[warn] case text => println("type is String")
[warn] ^
[warn] /aFolder/aProject/app/controllers/IPBlocks.scala:59: unreachable code due to variable pattern 'text' on line 58
[warn] case number => println("type is Int")
[warn] ^
And the same warning as for the remaining cases.
If I change the order of the cases, whatever case ends up being the first, is the one that gets printed (eg. if case boolean is the first case then the output would be is Boolean
for each of the fields)
3rd Solution attempt
Considering the output of:
val t = text
println("t == number " + (t == number))
println("t == text " + (t == text))
println("t eq number " + (t eq number))
println("t eq text " + (t eq text))
is
t == number true
t == text true
t eq number false
t eq text true
Using ifs and eq seems to solve the problem, so I've tried:
def typeOfMappingUsingIfAndEq[T](m: Mapping[T]) = {
if (m eq text) {
println("type is String")
} else if (m eq number) {
println("type is Int")
} else if (m eq jodaDate) {
println("type is DateTime")
} else if (m eq longNumber) {
println("type is Long")
} else if (m eq boolean) {
println("type is Boolean")
} else {
println("type is something else")
}
}
for(m <- testeForm.mapping.mappings if m.key.nonEmpty) {
print(m.key)
typeOfMappingUsingIfAndEq(m)
}
With the following output
textFieldtype is something else
numberFieldtype is something else
dateFieldtype is something else
longFieldtype is something else
booleanFieldtype is something else
So, is there a solution to the problem? If yes, what it is? Also, why in the hell doesn't the 3rd solution work?