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

org.orbroker.JoinGroup.scala Maven / Gradle / Ivy

The newest version!
package org.orbroker

import exception.ConfigurationException
import adapt.BrokerAdapter
import callback.ExecutionCallback

import java.util.HashMap
import scala.collection.immutable.{ Map ⇒ iMap }
import java.sql.ResultSet

private[orbroker] class JoinGroup private (
    keyColumns: Set[String],
    rs: ResultSet,
    _columnAliases: Map[String, String],
    cache: HashMap[CacheKey, Any],
    adapter: BrokerAdapter) extends Join {

  def this(keyColumns: Set[String], rs: ResultSet, columnAliases: Map[String, String], adapter: BrokerAdapter) =
    this(keyColumns, rs, columnAliases, new HashMap(128), adapter)

  private val columnAliases = toUpper(_columnAliases)

  private def toUpper(map: Map[String, String]): Map[String, String] = {
    map.map(entry ⇒ entry._1.toUpperCase -> entry._2.toUpperCase)
  }

  def newGroup() {
    row.newGroup(getKeyValues)
  }

  val row = new ResultSetRow(rs, adapter, columnAliases) with StatefulRow

  /** Has result set been advanced internally? */
  var rsAdvanced = false
  /** Is result set readable at current row? */
  var rsReadable = true

  private def getKeyValues(): iMap[String, Any] = {
    var map: iMap[String, Any] = iMap.empty
    for (column ← keyColumns) {
      val value = rs.getObject(columnAliases.getOrElse(column, column))
      if (value == null) return iMap.empty
      map += (column -> value)
    }
    map
  }

  private def getResultOrNull[T](extractor: JoinExtractor[T], proxy: JoinGroup): T = {
    var result: Any = null
    val key = proxy.getKeyValues()
    if (!key.isEmpty) {
      val cacheKey = new CacheKey(extractor, key)
      result = cache.get(cacheKey)
      if (result == null) {
        result = extractor.extract(proxy.row, proxy)
        cache.put(cacheKey, result)
      }
    }
    result.asInstanceOf[T]
  }

  override def extractOne[T](rawExt: JoinExtractor[T], aliases: Map[String, String]) = {
    val extractor = new SafeJoinExtractor[T](rawExt)
    val proxy = new JoinGroup(extractor.key, rs, aliases, cache, adapter)
    val result = getResultOrNull(extractor, proxy)
    row.readable &= proxy.row.readable
    rsAdvanced = proxy.rsAdvanced
    rsReadable = proxy.rsReadable
    Option(result)
  }

  override def extractGroup[T](ext: QueryExtractor[T], aliases: Map[String, String])(receiver: T ⇒ Unit) {
    this.newGroup()
    ext match {
      case re: RowExtractor[_] ⇒ extractRows(re, aliases, receiver)
      case je: JoinExtractor[_] ⇒ extractJoin(je, aliases, receiver)
      case _ ⇒ throw new ConfigurationException("Cannot extract group using " + ext.getClass.getSimpleName)
    }
  }

  private def extractJoin[T](rawExt: JoinExtractor[T], aliases: Map[String, String], receiver: T ⇒ Unit) {
    val extractor = new SafeJoinExtractor[T](rawExt)
    val proxy = new JoinGroup(extractor.key, rs, aliases ++ columnAliases, cache, adapter)
    do {
      proxy.newGroup()
      val result = getResultOrNull(extractor, proxy)
      if (result != null) {
        receiver(result)
      }
      if (proxy.rsAdvanced) {
        rsReadable = proxy.rsReadable
      } else {
        rsReadable = rs.next
      }
    } while (rsReadable && row.matches(getKeyValues))
    row.readable = false
    rsAdvanced = true
  }

  private def extractRows[T](extractor: RowExtractor[T], aliases: Map[String, String], receiver: T ⇒ Unit) {
    val proxy = new JoinGroup(keyColumns, rs, aliases ++ columnAliases, cache, adapter)
    do {
      proxy.newGroup()
      val result = extractor.extract(proxy.row)
      if (result != null) {
        receiver(result)
      }
      if (proxy.rsAdvanced) {
        rsReadable = proxy.rsReadable
      } else {
        rsReadable = rs.next
      }
    } while (rsReadable && row.matches(getKeyValues))
    row.readable = false
    rsAdvanced = true
  }

}

private final class CacheKey(val extractor: JoinExtractor[_], val keyValues: Map[_, _]) {
  override def hashCode = extractor.hashCode ^ keyValues.hashCode
  override def equals(any: Any) = {
    val that = any.asInstanceOf[CacheKey]
    (this.extractor == that.extractor) && (this.keyValues == that.keyValues)
  }
  override def toString = {
    extractor.getClass.getSimpleName + ":" + keyValues
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy