如何提供正确的类型信息以使我的通用过滤器功能适用于光滑

时间:2014-07-07 18:54:27

标签: scala generics playframework playframework-2.2 slick

我正在尝试在基础类中为我的光滑表实现一些通用过滤器。

我想要实现的是将url查询字符串转换为数据库过滤器的能力。我想出了一个可行的解决方案,但代码不是很干。

这是我修改过的代码。

package db.utils.repos

import common.utils.request.filters.{StringMatchesFilter, RequestFilter}
import scala.slick.lifted.{Column => LiftedColumn}
import db.environments.slick.interfaces.SlickEnv
import org.joda.time.DateTime

import scala.slick.profile.RelationalProfile

trait SlickPageable {

  val slickEnv: SlickEnv

  import slickEnv.profile.simple._

  trait FieldMapped {
    def longField(f: String): Option[LiftedColumn[Long]]

    def optLongField(f: String): Option[LiftedColumn[Option[Long]]]

    def stringField(f: String): Option[LiftedColumn[String]]

    def optStringField(f: String): Option[LiftedColumn[Option[String]]]
  }

  trait FieldSet{
    def stringField(table: FieldMapped, f: String): Option[LiftedColumn[Any]]
  }

  object FSet extends FieldSet {
    override def stringField(table: FieldMapped, f: String): Option[LiftedColumn[String]] = {
      table.stringField(f)
    }

  }

  object OptFSet extends FieldSet {
    override def stringField(table: FieldMapped, f: String): Option[LiftedColumn[Option[String]]] = {
      table.optStringField(f)
    }
  }

  def filter(table: FieldMapped, f: RequestFilter) = {
    queryFilter(table, f, QSet)
  }

  def optFilter(table: FieldMapped, f: RequestFilter) ={
    queryFilter(table, f, OptQSet)
  }


  def queryFilter[T, R](table: FieldMapped, f: RequestFilter, querySet: QuerySet[T, R]) = {
    def checkField[A](field: Option[A], op: (A, String) => R) = {
      field match {
        case Some(fi) =>
          op(fi, f.value)
        case None =>
          throw new IllegalArgumentException(s"could not retrieve field ${f.field}")
      }
    }
    f match {
      case sf: StringMatchesFilter => {
            checkField(querySet.fSet.stringField(table, f.field), querySet.sEq)
      }
      case _ => throw new IllegalArgumentException("No such filter")
    }
  }

  trait QuerySet[T, R] {
    val fSet: FieldSet
    def sEq(col: T, value: String): R
  }

  object QSet extends QuerySet[LiftedColumn[String], LiftedColumn[Boolean]] {
    override val fSet = FSet
    override def sEq(col: LiftedColumn[String], value: String): LiftedColumn[Boolean] = {
      col === value
    }
  }

  object OptQSet extends QuerySet[LiftedColumn[Option[String]], LiftedColumn[Option[Boolean]]] {
    override val fSet = OptFSet
    override def sEq(col: LiftedColumn[Option[String]], value: String): LiftedColumn[Option[Boolean]] = {
      col === value
    }
  }

}

错误消息

type mismatch;
[error]  found   : (T, String) => R
[error]  required: (scala.slick.lifted.Column[_], String) => R
[error]             checkField(fieldSet.stringField(table, f.field), querySet.sEq)

如果我从FieldSet参数列表中删除queryFilter,我可以使其正常运行。但后来我需要分离函数:一个调用字段映射方法,另一个调用可选字段映射方法。它可以工作,类型推理和一切正常工作。

那么我怎样才能使用FieldSet?据我所知,在编译时似乎没有足够的类型信息。但我不知道如何提供它。

0 个答案:

没有答案