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.index.UntypedMongoIndex
import com.mongodb.{DBObject, WriteConcern}

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

object QueryHelpers {

  trait QueryLogger {
    def log(query: Query[_, _, _], instanceName: String, msg: => String, timeMillis: Long): Unit
    def onExecuteQuery[T](query: Query[_, _, _], instanceName: String, msg: => String, func: => T): T
    def logIndexMismatch(query: Query[_, _, _], msg: => String)
    def logIndexHit(query: Query[_, _, _], index: UntypedMongoIndex)
    def warn(query: Query[_, _, _], msg: => String): Unit
  }

  class DefaultQueryLogger extends QueryLogger {
    override def log(query: Query[_, _, _], instanceName: String, msg: => String, timeMillis: Long) {}
    override def onExecuteQuery[T](query: Query[_, _, _], instanceName: String, msg: => String, func: => T): T = func
    override def logIndexMismatch(query: Query[_, _, _], msg: => String) {}
    override def logIndexHit(query: Query[_, _, _], index: UntypedMongoIndex) {}
    override def warn(query: Query[_, _, _], 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](query: Query[M, _, _], indexes: Option[List[UntypedMongoIndex]]): Unit
    def validateModify[M](modify: ModifyQuery[M, _], indexes: Option[List[UntypedMongoIndex]]): Unit
    def validateFindAndModify[M, R](modify: FindAndModifyQuery[M, R], indexes: Option[List[UntypedMongoIndex]]): Unit
  }

  class DefaultQueryValidator extends QueryValidator {
    override def validateList[T](xs: Traversable[T]) {}
    override def validateRadius(d: Degrees) = d
    override def validateQuery[M](query: Query[M, _, _], indexes: Option[List[UntypedMongoIndex]]) {}
    override def validateModify[M](modify: ModifyQuery[M, _], indexes: Option[List[UntypedMongoIndex]]) {} // todo possibly validate for update without upsert, yet setOnInsert present -- ktoso
    override def validateFindAndModify[M, R](modify: FindAndModifyQuery[M, R], indexes: Option[List[UntypedMongoIndex]]) {}
  }

  object NoopQueryValidator extends DefaultQueryValidator

  var validator: QueryValidator = NoopQueryValidator

  trait QueryTransformer {
    def transformQuery[M](query: Query[M, _, _]): Query[M, _, _]
    def transformModify[M](modify: ModifyQuery[M, _]): ModifyQuery[M, _]
    def transformFindAndModify[M, R](modify: FindAndModifyQuery[M, R]): FindAndModifyQuery[M, R]
  }

  class DefaultQueryTransformer extends QueryTransformer {
    override def transformQuery[M](query: Query[M, _, _]): Query[M, _, _] = { query }
    override def transformModify[M](modify: ModifyQuery[M, _]): ModifyQuery[M, _] = { modify }
    override def transformFindAndModify[M, R](modify: FindAndModifyQuery[M, R]): FindAndModifyQuery[M, R] = { modify }
  }

  object NoopQueryTransformer extends DefaultQueryTransformer

  var transformer: QueryTransformer = NoopQueryTransformer

  trait QueryConfig {
    def defaultWriteConcern: WriteConcern
    def cursorBatchSize: Option[Option[Int]]
  }

  class DefaultQueryConfig extends QueryConfig {
    override def defaultWriteConcern: WriteConcern = WriteConcern.SAFE
    /**
     * Batch size to set on the underlying DBCursor.
     * None = take value from the query if specified
     * Some(None) = never set batch size on the cursor
     * Some(Some(n)) = always set batch size to n
     */
    override def cursorBatchSize: Option[Option[Int]] = None
  }

  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]) = {
    if (vs.isEmpty)
      new EmptyQueryClause[java.util.List[V]](fieldName)
    else
      new InQueryClause(fieldName, QueryHelpers.validatedList(vs.toSet))
  }

  def allListClause[V](fieldName: String, vs: Traversable[V]) = {
    if (vs.isEmpty)
      new EmptyQueryClause[java.util.List[V]](fieldName)
    else
      new AllQueryClause(fieldName, QueryHelpers.validatedList(vs.toSet))
  }

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




© 2015 - 2025 Weber Informatics LLC | Privacy Policy