0

As an overview, I am trying to dynamically create a constructor for a case class from a Cassandra Java Row using reflection to find the primary constructor for the case class, and then trying to extract the values from the Cassandra Row.

Specifically, I want to support an Option in a case class as being an optional field in the Row, such that case class Person(name: String, age: Option[Int]) will successfully populate if the Row has a name and an age, or just the name (and fill in a None for age).

To this end, I followed this very helpful blog post that achieves a similar objective between Case Classes and Maps.

However, I seem to be stuck trying to consolidate the dynamic nature of reflectively extracting types from the Case Class and the compile-time nature of quasiquotes. As an example:

I have a type fieldType which could be a native type or an Option of a native type. If it is an Option, I want to pass returnType.typeArgs.head to my quasiquote construction, so that it can extract the parameterized type from the Row, and if it is not an Option, I will just pass returnType.

if (fieldType <:< typeOf[Option[_]]) q"r.getAs[${returnType.typeArgs.head}]($fieldName)" else q"r.as[$returnType]($fieldName)"

(assuming r is a Cassandra Row and as and getAs exist for this Row)

When I try to compile this, I get an error saying that it does not know how to deal with doing r.as[Option[String]]. This makes conceptual sense to me because there is no way the compiler would know which way the runtime comparison will resolve and so needs to check both cases.

So how might I go about making this type check? If I could maybe compare the types fieldType and typeOf[Option[_]] within the quasiquote, it might stop complaining, but I can't figure out how to compare types in a quasiquote, and I'm not sure it's even possible. If I could extract the parameterized type of the Option within the quasiquote, it might stop complaining, but I could not figure that out either.

Sorry, I am very new to Scala and this stuff is, at the moment, very confusing and esoteric to me. If you want to look more closely at what I am doing, I have a repo: https://github.com/thurstonsand/scala-cass/blob/master/src/main/scala/com/weather/scalacass/ScalaCass.scala where the interesting part is ScalaCass.CaseClassRealizer, and I am testing it in CaseClassUnitTests.

1 Answers1

0

I found help from @liff on the gitter scala/scala page. Apparently, I was finding my fieldType incorrectly.

I was doing: val fieldType = tpe.decl(encodedName).typeSignature where I should have been doing val fieldType = field.infoIn(tpe). Will update once I know what this difference means.