All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.foursquare.rogue.QueryHelpers.scala Maven / Gradle / Ivy

The newest version!
// Copyright 2011 Foursquare Labs Inc. All Rights Reserved.

package com.foursquare.rogue

import com.foursquare.rogue.Rogue.GenericQuery
import com.mongodb.{WriteConcern, DBObject}
import net.liftweb.json.{Extraction, Formats, Serializer, TypeInfo}
import net.liftweb.json.JsonAST.{JObject, JValue}
import net.liftweb.mongodb.{JObjectParser, ObjectIdSerializer}
import net.liftweb.mongodb.record.{MongoId, MongoRecord}

case class Degrees(value: Double)
case class LatLong(lat: Double, long: Double)

trait HasMongoForeignObjectId[RefType <: MongoRecord[RefType] with MongoId[RefType]]

object QueryHelpers {
  class DBObjectSerializer extends Serializer[DBObject] {
    val DBObjectClass = classOf[DBObject]

    def deserialize(implicit formats: Formats): PartialFunction[(TypeInfo, JValue), DBObject] = {
      case (TypeInfo(klass, _), json : JObject) if DBObjectClass.isAssignableFrom(klass) =>
        JObjectParser.parse(json)
    }

    def serialize(implicit formats: Formats): PartialFunction[Any, JValue] = {
      case x: DBObject =>
        JObjectParser.serialize(x)
    }
  }

  private implicit val formats =
    (net.liftweb.json.DefaultFormats + new ObjectIdSerializer + new DBObjectSerializer)

  trait QueryLogger {
    def log(query: GenericQuery[_, _], msg: => String, timeMillis: Long): Unit
    def logIndexMismatch(query: GenericQuery[_, _], msg: => String)
    def logIndexHit(query: GenericQuery[_, _], index: MongoIndex[_])
    def warn(query: GenericQuery[_, _], msg: => String): Unit
  }

  class DefaultQueryLogger extends QueryLogger {
    override def log(query: GenericQuery[_, _], msg: => String, timeMillis: Long) {}
    override def logIndexMismatch(query: GenericQuery[_, _], msg: => String) {}
    override def logIndexHit(query: GenericQuery[_, _], index: MongoIndex[_]) {}
    override def warn(query: GenericQuery[_, _], msg: => String) {}
  }

  object NoopQueryLogger extends DefaultQueryLogger

  var logger: QueryLogger = NoopQueryLogger

  trait QueryValidator {
    def validateList[T](xs: Traversable[T]): Unit
    def validateRadius(d: Degrees): Degrees
    def validateQuery[M <: MongoRecord[M]](query: BaseQuery[M, _, _, _, _, _, _]): Unit
    def validateModify[M <: MongoRecord[M]](modify: BaseModifyQuery[M]): Unit
    def validateFindAndModify[M <: MongoRecord[M], R](modify: BaseFindAndModifyQuery[M, R]): Unit
  }

  class DefaultQueryValidator extends QueryValidator {
    override def validateList[T](xs: Traversable[T]) {}
    override def validateRadius(d: Degrees) = d
    override def validateQuery[M <: MongoRecord[M]](query: BaseQuery[M, _, _, _, _, _, _]) {}
    override def validateModify[M <: MongoRecord[M]](modify: BaseModifyQuery[M]) {}
    override def validateFindAndModify[M <: MongoRecord[M], R](modify: BaseFindAndModifyQuery[M, R]) {}
  }

  object NoopQueryValidator extends DefaultQueryValidator

  var validator: QueryValidator = NoopQueryValidator

  trait QueryTransformer {
    def transformQuery[M <: MongoRecord[M]](query: BaseQuery[M, _, _, _, _, _, _]): BaseQuery[M, _, _, _, _, _, _]
    def transformModify[M <: MongoRecord[M]](modify: BaseModifyQuery[M]): BaseModifyQuery[M]
    def transformFindAndModify[M <: MongoRecord[M], R](modify: BaseFindAndModifyQuery[M, R]): BaseFindAndModifyQuery[M, R]
  }

  class DefaultQueryTransformer extends QueryTransformer {
    override def transformQuery[M <: MongoRecord[M]](query: BaseQuery[M, _, _, _, _, _, _]): BaseQuery[M, _, _, _, _, _, _] = { query }
    override def transformModify[M <: MongoRecord[M]](modify: BaseModifyQuery[M]): BaseModifyQuery[M] = { modify }
    override def transformFindAndModify[M <: MongoRecord[M], R](modify: BaseFindAndModifyQuery[M, R]): BaseFindAndModifyQuery[M, R] = { modify }
  }

  object NoopQueryTransformer extends DefaultQueryTransformer

  var transformer: QueryTransformer = NoopQueryTransformer

  trait QueryConfig {
    def defaultWriteConcern: WriteConcern
    def defaultUpdateOneWriteConcern: WriteConcern
    def defaultUpdateMultiWriteConcern: WriteConcern
    def defaultUpsertOneWriteConcern: WriteConcern
    def defaultBulkDeleteWriteConcern: WriteConcern
  }

  class DefaultQueryConfig extends QueryConfig {
    override def defaultWriteConcern = WriteConcern.NONE
    override def defaultUpdateOneWriteConcern = defaultWriteConcern
    override def defaultUpdateMultiWriteConcern = defaultWriteConcern
    override def defaultUpsertOneWriteConcern = defaultWriteConcern
    override def defaultBulkDeleteWriteConcern = defaultWriteConcern
  }

  object DefaultQueryConfig extends DefaultQueryConfig

  var config: QueryConfig = DefaultQueryConfig


  def makeJavaList[T](sl: Traversable[T]): java.util.List[T] = {
    val list = new java.util.ArrayList[T]()
    for (id <- sl) list.add(id)
    list
  }

  def validatedList[T](vs: Traversable[T]): java.util.List[T] = {
    validator.validateList(vs)
    makeJavaList(vs)
  }

  def list[T](vs: Traversable[T]): java.util.List[T] = {
    makeJavaList(vs)
  }

  def list(vs: Double*): java.util.List[Double] = list(vs)

  def radius(d: Degrees) = {
    validator.validateRadius(d).value
  }

  def makeJavaMap[K, V](m: Map[K, V]): java.util.Map[K, V] = {
    val map = new java.util.HashMap[K, V]
    for ((k, v) <- m) map.put(k, v)
    map
  }

  def inListClause[V](fieldName: String, vs: Traversable[V]) = {
    new InQueryClause(fieldName, QueryHelpers.validatedList(vs.toSet))
  }

  def allListClause[V](fieldName: String, vs: Traversable[V]) = {
    new AllQueryClause(fieldName, QueryHelpers.validatedList(vs.toSet))
  }

  def asDBObject[T](x: T): DBObject = {
    JObjectParser.parse(Extraction.decompose(x).asInstanceOf[JObject])
  }

  def orConditionFromQueries(subqueries: List[BaseQuery[_, _, _, _, _, _, _]]) = {
    MongoHelpers.OrCondition(subqueries.flatMap(subquery => {
      subquery match {
        case q: BaseQuery[_, _, _, _, _, _, _] => Some(q.condition)
        case _ => None
      }
    }))
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy