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

com.adform.bitmaps.BitmapExecutor.scala Maven / Gradle / Ivy

The newest version!
package com.adform.bitmaps

import scala.annotation.tailrec

class BitmapExecutor[T](val db: BitmapDB[T])(implicit bi: BitmapsImpl[T]) {
  def execute(expression: BitmapOperation): T = (expression: @unchecked) match {
    case or: Alternative => accumulateOR(or.bitmaps, Nil)
    case and: Conjunction => accumulateAND(and.bitmaps, Nil)
    case Get(id) => db.getBitmap(id)
    case Empty => bi.empty
    case Full => db.full
    case db.BitmapReference(bitmap) => bitmap
    case Negation(not) => processNegation(db.full, not)
  }

  @tailrec
  private[this] def accumulateAND(list: List[BitmapOperation], acc: List[T]): T = list match {
    case h :: tail => (h: @unchecked) match {
      case Get(id) => accumulateAND(tail, db.getBitmap(id) :: acc)
      case db.BitmapReference(bitmap) => accumulateAND(tail, bitmap :: acc)
      case negation: Negation =>
        val base = if (acc.isEmpty) db.full else bi.batchAnd(acc)
        val negated = processNegation(base, negation.not)
        accumulateAND(tail, negated :: Nil)
      case Alternative(expressions) => accumulateAND(tail, accumulateOR(expressions, Nil) :: acc)
      case Conjunction(expressions) => accumulateAND(expressions ::: tail, if (acc.isEmpty) Nil else List(bi.batchAnd(acc)))
      case Empty => bi.empty
      case Full => accumulateAND(tail, acc)
    }
    case Nil => bi.batchAnd(acc)
  }

  @tailrec
  private[this] def accumulateOR(list: List[BitmapOperation], acc: List[T]): T = list match {
    case h :: tail => (h: @unchecked) match {
      case Get(id) => accumulateOR(tail, db.getBitmap(id) :: acc)
      case db.BitmapReference(bitmap) => accumulateOR(tail, bitmap :: acc)
      case negation: Negation =>
        val negated = processNegation(db.full, negation.not)
        accumulateOR(tail, negated :: acc)
      case Alternative(expressions) => accumulateOR(expressions ::: tail, if (acc.isEmpty) Nil else List(bi.batchOr(acc)))
      case Conjunction(expressions) => accumulateOR(tail, accumulateAND(expressions, Nil) :: acc)
      case Empty => accumulateOR(tail, acc)
      case Full => db.full
    }
    case Nil => bi.batchOr(acc)
  }

  private[this] def processNegation(base: T, operation: BitmapOperation): T = (operation: @unchecked) match {
    case Empty => db.full
    case Full => bi.empty
    case Negation(not) => execute(not)
    case _ => bi.andNot(base, execute(operation))
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy