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

com.rojoma.json.v3.-impl.util.ClassAwareMap.scala Maven / Gradle / Ivy

The newest version!
package com.rojoma.json.v3
package `-impl`.util

// A simple immutable map for classes which takes into account variance
// (i.e., a map containing a classOf[Object] will find the associated
// value when interrogated for a classOf[String]).  More-specific classes
// override less-specific ones; for equally-inspecific classes, later-
// added wins.
//
// Note: when calling get, hits are O(1) [expected] and misses are O(n)
class ClassAwareMap[+V] private (map: Map[Class[_], V], order: Vector[Class[_]]) {
  def this() = this(Map.empty, Vector.empty)

  // cache for looking up subclasses of explicitly-added items
  private[this] val keyedMap = new java.util.concurrent.ConcurrentHashMap[Class[_], V]

  private def augmentWith(c: Class[_]): Option[V] = synchronized {
    keyedMap.get(c) match {
      case null =>
        val it = order.iterator
        var best: Class[_] = null
        while(it.hasNext) {
          val existing = it.next()
          if(existing.isAssignableFrom(c)) {
            if(best == null) best = existing
            else if(best.isAssignableFrom(existing)) best = existing
          }
        }
        if(best == null) {
          None
        } else {
          val v = map(best)
          keyedMap.put(best, v)
          Some(v)
        }
      case v =>
        Some(v)
    }
  }

  def get(c: Class[_]): Option[V] =
    keyedMap.get(c) match {
      case null =>
        augmentWith(c)
      case v =>
        Some(v)
    }

  def +[V2 >: V](cv: (Class[_], V2)) = new ClassAwareMap[V2](map + cv, order :+ cv._1)

  def containsExact(c: Class[_]) = map.contains(c)
}

object ClassAwareMap {
  private[this] val Empty = new ClassAwareMap[Nothing]
  def empty[T]: ClassAwareMap[T] = Empty
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy