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

java.util.Collections.scala Maven / Gradle / Ivy

package java.util

import java.{lang => jl}
import java.io.Serializable

import scala.language.implicitConversions

import scala.annotation.tailrec

import scala.collection.JavaConverters._

object Collections {

  final lazy val EMPTY_SET: Set[_] = {
    new ImmutableSet(new AbstractSet[Any] with Serializable {
      override def size(): Int = 0

      override def iterator(): Iterator[Any] = emptyIterator[Any]
    })
  }

  final lazy val EMPTY_LIST: List[_] = {
    new ImmutableList(
      new AbstractList[Any] with Serializable with RandomAccess {
        override def get(index: Int): Any =
          throw new IndexOutOfBoundsException(index.toString)

        override def size(): Int = 0
      })
  }

  final lazy val EMPTY_MAP: Map[_, _] = {
    new ImmutableMap(new AbstractMap[Any, Any] with Serializable {
      override def entrySet(): Set[Map.Entry[Any, Any]] =
        EMPTY_SET.asInstanceOf[Set[Map.Entry[Any, Any]]]
    })
  }

  private lazy val EMPTY_ITERATOR: Iterator[_] = new EmptyIterator

  private lazy val EMPTY_LIST_ITERATOR: ListIterator[_] = new EmptyListIterator

  private lazy val EMPTY_ENUMERATION: Enumeration[_] = {
    new Enumeration[Any] {
      def hasMoreElements: Boolean = false

      def nextElement(): Any =
        throw new NoSuchElementException
    }
  }

  // Differs from original type definition, original: [T <: jl.Comparable[_ >: T]]
  def sort[T <: jl.Comparable[T]](list: List[T]): Unit =
    sort(list, naturalComparator[T])

  def sort[T](list: List[T], c: Comparator[_ >: T]): Unit = {
    val sortedList = list.asScala.sorted(c).asJava
    list match {
      case list: RandomAccess => copyImpl(sortedList.iterator, list)
      case _                  => copyImpl(sortedList.iterator, list.listIterator)
    }
  }

  def binarySearch[T](list: List[_ <: jl.Comparable[_ >: T]], key: T): Int =
    binarySearchImpl(list, (elem: Comparable[_ >: T]) => elem.compareTo(key))

  def binarySearch[T](list: List[_ <: T], key: T, c: Comparator[_ >: T]): Int =
    binarySearchImpl(list, (elem: T) => c.compare(elem, key))

  @inline
  private def binarySearchImpl[E](list: List[E],
                                  compareToKey: E => Int): Int = {
    def notFound(insertionPoint: Int): Int = {
      -insertionPoint - 1
    }

    @tailrec
    def binarySearch(lo: Int, hi: Int, get: Int => E): Int = {
      if (lo < hi) {
        val mid = lo + (hi - lo) / 2
        val cmp = compareToKey(get(mid))
        if (cmp == 0) mid
        else if (cmp > 0) binarySearch(lo, mid, get)
        else binarySearch(mid + 1, hi, get)
      } else {
        notFound(lo)
      }
    }

    list match {
      case _: RandomAccess =>
        binarySearch(0, list.size, list.get(_))

      case _ =>
        def getFrom(iter: ListIterator[E])(index: Int): E = {
          val shift = index - iter.nextIndex
          if (shift > 0)
            (0 until shift).foreach(_ => iter.next())
          else
            (0 until -shift).foreach(_ => iter.previous())
          iter.next()
        }
        binarySearch(0, list.size, getFrom(list.listIterator))
    }
  }

  def reverse(list: List[_]): Unit =
    reverseImpl(list)

  @inline
  def reverseImpl[T](list: List[T]): Unit = {
    val size = list.size
    list match {
      case list: RandomAccess =>
        for (i <- 0 until size / 2) {
          val tmp = list.get(i)
          list.set(i, list.get(size - i - 1))
          list.set(size - i - 1, tmp)
        }

      case _ =>
        val it1 = list.listIterator()
        val it2 = list.listIterator(size)
        for (i <- 0 until size / 2) {
          val tmp = it1.next()
          it1.set(it2.previous())
          it2.set(tmp)
        }
    }
  }

  def shuffle(list: List[_]): Unit =
    shuffle(list, new Random)

  def shuffle(list: List[_], rnd: Random): Unit =
    shuffleImpl(list, rnd)

  @inline
  def shuffleImpl[T](list: List[T], rnd: Random): Unit = {
    val scalaRnd     = scala.util.Random.javaRandomToRandom(rnd)
    val shuffledList = scalaRnd.shuffle(list.asScala.toSeq).asJava
    list match {
      case list: RandomAccess => copyImpl(shuffledList.iterator, list)
      case _                  => copyImpl(shuffledList.iterator, list.listIterator)
    }
  }

  def swap(list: List[_], i: Int, j: Int): Unit =
    swapImpl(list, i, j)

  @inline
  private def swapImpl[E](list: List[E], i: Int, j: Int): Unit = {
    list match {
      case list: RandomAccess =>
        val tmp = list.get(i)
        list.set(i, list.get(j))
        list.set(j, tmp)

      case _ =>
        val it1 = list.listIterator(i)
        val it2 = list.listIterator(j)
        if (!it1.hasNext || !it2.hasNext)
          throw new IndexOutOfBoundsException
        val tmp = it1.next()
        it1.set(it2.next())
        it2.set(tmp)
    }
  }

  def fill[T](list: List[_ >: T], obj: T): Unit = {
    list match {
      case list: RandomAccess =>
        (0 until list.size).foreach(list.set(_, obj))

      case _ =>
        val iter = list.listIterator
        while (iter.hasNext) {
          iter.next()
          iter.set(obj)
        }
    }
  }

  def copy[T](dest: List[_ >: T], src: List[_ <: T]): Unit = {
    (dest, src) match {
      case (dest: RandomAccess, src: RandomAccess) => copyImpl(src, dest)
      case (dest: RandomAccess, _)                 => copyImpl(src.iterator, dest)
      case (_, src: RandomAccess)                  => copyImpl(src, dest.listIterator)
      case (_, _)                                  => copyImpl(src.iterator, dest.listIterator)
    }
  }

  private def copyImpl[T](source: List[_ <: T] with RandomAccess,
                          dest: List[T] with RandomAccess): Unit = {
    (0 until source.size).foreach(i => dest.set(i, source.get(i)))
  }

  private def copyImpl[T](source: Iterator[_ <: T],
                          dest: List[T] with RandomAccess): Unit = {
    val destEnd = dest.size()
    var i       = 0
    while (source.hasNext) {
      if (i < destEnd)
        dest.set(i, source.next())
      else
        throw new IndexOutOfBoundsException
      i += 1
    }
  }

  private def copyImpl[T](source: List[_ <: T] with RandomAccess,
                          dest: ListIterator[T]): Unit = {
    for (i <- 0 until source.size) {
      if (dest.hasNext) {
        dest.next()
        dest.set(source.get(i))
      } else {
        throw new IndexOutOfBoundsException
      }
    }
  }

  private def copyImpl[T](source: Iterator[_ <: T],
                          dest: ListIterator[T]): Unit = {
    while (source.hasNext) {
      if (dest.hasNext) {
        dest.next()
        dest.set(source.next())
      } else {
        throw new IndexOutOfBoundsException
      }
    }
  }

  // Differs from original type definition, original: [T <: jl.Comparable[_ >: T]]
  def min[T <: AnyRef with jl.Comparable[T]](coll: Collection[_ <: T]): T =
    min(coll, naturalComparator[T])

  def min[T](coll: Collection[_ <: T], comp: Comparator[_ >: T]): T =
    coll.asScala.min(comp)

  // Differs from original type definition, original: [T <: jl.Comparable[_ >: T]]
  def max[T <: AnyRef with jl.Comparable[T]](coll: Collection[_ <: T]): T =
    max(coll, naturalComparator[T])

  def max[T](coll: Collection[_ <: T], comp: Comparator[_ >: T]): T =
    coll.asScala.max(comp)

  def rotate(list: List[_], distance: Int): Unit =
    rotateImpl(list, distance)

  private def rotateImpl[T](list: List[T], distance: Int): Unit = {
    val listSize = list.size
    if (listSize > 1 && distance % listSize != 0) {
      def exchangeRotation(): Unit = {
        def indexModulo(i: Int): Int = modulo(i, listSize)

        @tailrec
        def rotateNext(cycleStartIndex: Int,
                       count: Int,
                       index: Int,
                       value: T): Unit = {
          val nextValue = list.get(index)
          val newCount  = count + 1
          list.set(index, value)
          if (index != cycleStartIndex) {
            rotateNext(cycleStartIndex,
                       newCount,
                       indexModulo(index + distance),
                       nextValue)
          } else if (newCount < listSize) {
            val nextCycleStart = cycleStartIndex + 1
            rotateNext(nextCycleStart,
                       newCount,
                       indexModulo(nextCycleStart + distance),
                       list.get(nextCycleStart))
          }
        }
        rotateNext(0, 0, indexModulo(distance), list.get(0))
      }

      def splitReverseRotation(): Unit = {
        val splitPoint = modulo(-distance, listSize)
        reverse(list.subList(0, splitPoint))
        reverse(list.subList(splitPoint, listSize))
        reverse(list)
      }

      list match {
        case _: RandomAccess => exchangeRotation()
        case _ if listSize < 16 =>
          exchangeRotation() // TODO benchmark and set proper limit
        case _ => splitReverseRotation()
      }
    }
  }

  def replaceAll[T](list: List[T], oldVal: T, newVal: T): Boolean = {
    list match {
      case _: RandomAccess =>
        var modified = false
        for (i <- 0 until list.size) {
          if (list.get(i) === oldVal) {
            list.set(i, newVal)
            modified = true
          }
        }
        modified

      case _ =>
        @tailrec
        def replaceAll(iter: ListIterator[T], mod: Boolean): Boolean = {
          if (iter.hasNext) {
            val isEqual = iter.next() === oldVal
            if (isEqual)
              iter.set(newVal)
            replaceAll(iter, mod || isEqual)
          } else {
            mod
          }
        }
        replaceAll(list.listIterator(), false)
    }
  }

  def indexOfSubList(source: List[_], target: List[_]): Int =
    indexOfSubListImpl(source, target, fromStart = true)

  def lastIndexOfSubList(source: List[_], target: List[_]): Int =
    indexOfSubListImpl(source, target, fromStart = false)

  @inline
  private def indexOfSubListImpl(source: List[_],
                                 target: List[_],
                                 fromStart: Boolean): Int = {
    val targetSize = target.size
    if (targetSize == 0) {
      if (fromStart) 0
      else source.size
    } else {
      val indices        = 0 to source.size - targetSize
      val indicesInOrder = if (fromStart) indices else indices.reverse
      indicesInOrder
        .find { i =>
          source.subList(i, i + target.size).equals(target)
        }
        .getOrElse(-1)
    }
  }

  def unmodifiableCollection[T](c: Collection[_ <: T]): Collection[T] =
    new UnmodifiableCollection[T, Collection[T]](c.asInstanceOf[Collection[T]])

  def unmodifiableSet[T](a: Set[_ <: T]): Set[T] =
    new UnmodifiableSet[T, Set[T]](a.asInstanceOf[Set[T]])

  def unmodifiableSortedSet[T](s: SortedSet[T]): SortedSet[T] =
    new UnmodifiableSortedSet[T](s)

  def unmodifiableList[T](list: List[_ <: T]): List[T] = {
    list match {
      case _: RandomAccess =>
        new UnmodifiableList[T](list.asInstanceOf[List[T]]) with RandomAccess
      case _ =>
        new UnmodifiableList[T](list.asInstanceOf[List[T]])
    }
  }

  def unmodifiableMap[K, V](m: Map[_ <: K, _ <: V]): Map[K, V] =
    new UnmodifiableMap[K, V, Map[K, V]](m.asInstanceOf[Map[K, V]])

  def unmodifiableSortedMap[K, V](m: SortedMap[K, _ <: V]): SortedMap[K, V] =
    new UnmodifiableSortedMap[K, V](m.asInstanceOf[SortedMap[K, V]])

  def synchronizedCollection[T](c: Collection[T]): Collection[T] = {
    new WrappedCollection[T, Collection[T]] {
      override protected val inner: Collection[T] = c
    }
  }

  def synchronizedSet[T](s: Set[T]): Set[T] = {
    new WrappedSet[T, Set[T]] {
      override protected val inner: Set[T] = s
    }
  }

  def synchronizedSortedSet[T](s: SortedSet[T]): SortedSet[T] = {
    new WrappedSortedSet[T] {
      override protected val inner: SortedSet[T] = s
    }
  }

  def synchronizedList[T](list: List[T]): List[T] = {
    class BasicSynchronizedList extends WrappedList[T] {
      override protected val inner: List[T] = list
    }
    list match {
      case _: RandomAccess => new BasicSynchronizedList with RandomAccess
      case _               => new BasicSynchronizedList
    }
  }

  def synchronizedMap[K, V](m: Map[K, V]): Map[K, V] = {
    new WrappedMap[K, V, Map[K, V]] {
      override protected val inner: Map[K, V] = m
    }
  }

  def synchronizedSortedMap[K, V](m: SortedMap[K, V]): SortedMap[K, V] = {
    new WrappedSortedMap[K, V] {
      override protected val inner: SortedMap[K, V] = m
    }
  }

  def checkedCollection[E](c: Collection[E], typ: Class[E]): Collection[E] =
    new CheckedCollection[E, Collection[E]](c, typ)

  def checkedSet[E](s: Set[E], typ: Class[E]): Set[E] =
    new CheckedSet[E, Set[E]](s, typ)

  def checkedSortedSet[E](s: SortedSet[E], typ: Class[E]): SortedSet[E] =
    new CheckedSortedSet[E](s, typ)

  def checkedList[E](list: List[E], typ: Class[E]): List[E] = {
    list match {
      case _: RandomAccess => new CheckedList[E](list, typ) with RandomAccess
      case _               => new CheckedList[E](list, typ)
    }
  }

  def checkedMap[K, V](m: Map[K, V],
                       keyType: Class[K],
                       valueType: Class[V]): Map[K, V] =
    new CheckedMap[K, V, Map[K, V]](m, keyType, valueType)

  def checkedSortedMap[K, V](m: SortedMap[K, V],
                             keyType: Class[K],
                             valueType: Class[V]): SortedMap[K, V] =
    new CheckedSortedMap[K, V](m, keyType, valueType)

  def emptyIterator[T](): Iterator[T] =
    EMPTY_ITERATOR.asInstanceOf[Iterator[T]]

  def emptyListIterator[T](): ListIterator[T] =
    EMPTY_LIST_ITERATOR.asInstanceOf[ListIterator[T]]

  def emptyEnumeration[T](): Enumeration[T] =
    EMPTY_ENUMERATION.asInstanceOf[Enumeration[T]]

  def emptySet[T](): Set[T] =
    EMPTY_SET.asInstanceOf[Set[T]]

  def emptyList[T](): List[T] =
    EMPTY_LIST.asInstanceOf[List[T]]

  def emptyMap[K, V](): Map[K, V] =
    EMPTY_MAP.asInstanceOf[Map[K, V]]

  def singleton[T](o: T): Set[T] = {
    new ImmutableSet(new AbstractSet[T] with Serializable {
      def size(): Int = 1

      def iterator(): Iterator[T] = {
        new Iterator[T] {
          private var _hasNext: Boolean = true

          def hasNext(): Boolean = _hasNext

          def next(): T = {
            if (!_hasNext)
              throw new NoSuchElementException
            _hasNext = false
            o
          }

          def remove(): Unit =
            throw new UnsupportedOperationException
        }
      }
    })
  }

  def singletonList[T](o: T): List[T] = {
    new ImmutableList(new AbstractList[T] with Serializable {
      def size(): Int = 1

      def get(index: Int): T =
        if (index == 0) o
        else throw new IndexOutOfBoundsException(index.toString)
    })
  }

  def singletonMap[K, V](key: K, value: V): Map[K, V] = {
    new ImmutableMap(new AbstractMap[K, V] with Serializable {
      def entrySet(): Set[Map.Entry[K, V]] =
        singleton(new AbstractMap.SimpleImmutableEntry(key, value))
    })
  }

  def nCopies[T](n: Int, o: T): List[T] = {
    if (n < 0)
      throw new IllegalArgumentException

    val inner = new AbstractList[T] with Serializable with RandomAccess {
      def size(): Int = n

      def get(index: Int): T = {
        if (index < 0 || index >= n)
          throw new IndexOutOfBoundsException
        o
      }
    }
    new ImmutableList(inner) with RandomAccess
  }

  def reverseOrder[T](): Comparator[T] = {
    new Comparator[T] with Serializable {
      def compare(o1: T, o2: T): Int =
        o2.asInstanceOf[Comparable[T]].compareTo(o1)
    }
  }

  def reverseOrder[T](cmp: Comparator[T]): Comparator[T] = {
    new Comparator[T] with Serializable {
      override def compare(o1: T, o2: T): Int = cmp.compare(o2, o1)
    }
  }

  def enumeration[T](c: Collection[T]): Enumeration[T] = {
    val it = c.iterator
    new Enumeration[T] {
      override def hasMoreElements: Boolean =
        it.hasNext

      override def nextElement(): T =
        it.next()
    }
  }

  def list[T](e: Enumeration[T]): ArrayList[T] = {
    val arrayList = new ArrayList[T]
    e.asScala.foreach(arrayList.add(_))
    arrayList
  }

  def frequency(c: Collection[_], o: AnyRef): Int =
    c.asScala.count(_ === o)

  def disjoint(c1: Collection[_], c2: Collection[_]): Boolean = {
    if (c1.size < c2.size)
      !c1.asScala.exists(elem => c2.contains(elem))
    else
      !c2.asScala.exists(elem => c1.contains(elem))
  }

  def addAll[T](c: Collection[_ >: T], elements: Array[AnyRef]): Boolean =
    c.addAll((elements.asInstanceOf[Array[T]]: Seq[T]).asJava)

  def newSetFromMap[E](map: Map[E, java.lang.Boolean]): Set[E] = {
    if (!map.isEmpty)
      throw new IllegalArgumentException

    new WrappedSet[E, Set[E]] {
      override protected val inner: Set[E] = map.keySet

      override def add(e: E): Boolean =
        map.put(e, true) == null

      override def addAll(c: Collection[_ <: E]): Boolean =
        c.asScala.foldLeft(false)((prev, elem) =>
          map.put(elem, true) == null || prev)
    }
  }

  @inline
  private def modulo(a: Int, b: Int): Int = ((a % b) + b) % b

  @inline
  private def naturalComparator[T <: jl.Comparable[T]]: Comparator[T] = {
    new Comparator[T] with Serializable {
      final def compare(o1: T, o2: T): Int = o1.compareTo(o2)
    }
  }

  @inline
  private implicit def comparatorToOrdering[E](
      cmp: Comparator[E]): Ordering[E] = {
    new Ordering[E] {
      final def compare(x: E, y: E): Int = cmp.compare(x, y)
    }
  }

  private trait WrappedEquals {
    protected def inner: AnyRef

    override def equals(obj: Any): Boolean =
      inner.equals(obj)

    override def hashCode(): Int =
      inner.hashCode
  }

  private trait WrappedCollection[E, Coll <: Collection[E]]
      extends Collection[E]
      with Serializable {

    protected def inner: Coll

    def size(): Int =
      inner.size

    def isEmpty: Boolean =
      inner.isEmpty

    def contains(o: Any): Boolean =
      inner.contains(o)

    def iterator(): Iterator[E] =
      inner.iterator

    def toArray: Array[AnyRef] =
      inner.toArray()

    def toArray[T <: AnyRef](a: Array[T]): Array[T] =
      inner.toArray[T](a)

    def add(e: E): Boolean =
      inner.add(e)

    def remove(o: Any): Boolean =
      inner.remove(o)

    def containsAll(c: Collection[_]): Boolean =
      inner.containsAll(c)

    def addAll(c: Collection[_ <: E]): Boolean =
      inner.addAll(c)

    def removeAll(c: Collection[_]): Boolean =
      inner.removeAll(c)

    def retainAll(c: Collection[_]): Boolean =
      inner.retainAll(c)

    def clear(): Unit =
      inner.clear()

    override def toString: String =
      inner.toString
  }

  private trait WrappedSet[E, Coll <: Set[E]]
      extends WrappedEquals
      with WrappedCollection[E, Coll]
      with Set[E]

  private trait WrappedSortedSet[E]
      extends WrappedSet[E, SortedSet[E]]
      with SortedSet[E] {

    def comparator(): Comparator[_ >: E] =
      inner.comparator()

    def subSet(fromElement: E, toElement: E): SortedSet[E] =
      inner.subSet(fromElement, toElement)

    def tailSet(fromElement: E): SortedSet[E] =
      inner.tailSet(fromElement)

    def headSet(toElement: E): SortedSet[E] =
      inner.headSet(toElement)

    def first(): E =
      inner.first

    def last(): E =
      inner.last
  }

  private trait WrappedList[E]
      extends WrappedEquals
      with WrappedCollection[E, List[E]]
      with List[E] {

    def addAll(index: Int, c: Collection[_ <: E]): Boolean =
      inner.addAll(index, c)

    def get(index: Int): E =
      inner.get(index)

    def set(index: Int, element: E): E =
      inner.set(index, element)

    def add(index: Int, element: E): Unit =
      inner.add(index, element)

    def remove(index: Int): E =
      inner.remove(index)

    def indexOf(o: scala.Any): Int =
      inner.indexOf(o)

    def lastIndexOf(o: scala.Any): Int =
      inner.lastIndexOf(o)

    def listIterator(): ListIterator[E] =
      inner.listIterator()

    def listIterator(index: Int): ListIterator[E] =
      inner.listIterator(index)

    def subList(fromIndex: Int, toIndex: Int): List[E] =
      inner.subList(fromIndex, toIndex)
  }

  private trait WrappedMap[K, V, M <: Map[K, V]]
      extends WrappedEquals
      with Map[K, V] {

    protected def inner: M

    def size(): Int =
      inner.size()

    def isEmpty: Boolean =
      inner.isEmpty

    def containsKey(key: scala.Any): Boolean =
      inner.containsKey(key)

    def containsValue(value: scala.Any): Boolean =
      inner.containsValue(value)

    def get(key: scala.Any): V =
      inner.get(key)

    def put(key: K, value: V): V =
      inner.put(key, value)

    def remove(key: scala.Any): V =
      inner.remove(key)

    def putAll(m: Map[_ <: K, _ <: V]): Unit =
      inner.putAll(m)

    def clear(): Unit =
      inner.clear()

    def keySet(): Set[K] =
      inner.keySet

    def values(): Collection[V] =
      inner.values

    def entrySet(): Set[Map.Entry[K, V]] =
      inner.entrySet.asInstanceOf[Set[Map.Entry[K, V]]]

    override def toString(): String =
      inner.toString
  }

  private trait WrappedSortedMap[K, V]
      extends WrappedMap[K, V, SortedMap[K, V]]
      with SortedMap[K, V] {
    def comparator(): Comparator[_ >: K] =
      inner.comparator

    def subMap(fromKey: K, toKey: K): SortedMap[K, V] =
      inner.subMap(fromKey, toKey)

    def headMap(toKey: K): SortedMap[K, V] =
      inner.headMap(toKey)

    def tailMap(fromKey: K): SortedMap[K, V] =
      inner.tailMap(fromKey)

    def firstKey(): K =
      inner.firstKey

    def lastKey(): K =
      inner.lastKey
  }

  private trait WrappedIterator[E, Iter <: Iterator[E]] extends Iterator[E] {
    protected def inner: Iter

    def hasNext(): Boolean =
      inner.hasNext

    def next(): E =
      inner.next()

    def remove(): Unit =
      inner.remove()
  }

  private trait WrappedListIterator[E]
      extends WrappedIterator[E, ListIterator[E]]
      with ListIterator[E] {
    def hasPrevious(): Boolean =
      inner.hasPrevious

    def previous(): E =
      inner.previous()

    def nextIndex(): Int =
      inner.nextIndex

    def previousIndex(): Int =
      inner.previousIndex

    def set(e: E): Unit =
      inner.set(e)

    def add(e: E): Unit =
      inner.add(e)
  }

  private class UnmodifiableCollection[E, Coll <: Collection[E]](
      protected val inner: Coll)
      extends WrappedCollection[E, Coll] {

    protected val eagerThrow: Boolean = true

    override def clear(): Unit = {
      if (eagerThrow || !isEmpty)
        throw new UnsupportedOperationException
    }

    override def iterator(): Iterator[E] =
      new UnmodifiableIterator(inner.iterator)

    override def add(e: E): Boolean =
      throw new UnsupportedOperationException

    override def remove(o: Any): Boolean =
      if (eagerThrow || contains(o)) throw new UnsupportedOperationException
      else false

    override def addAll(c: Collection[_ <: E]): Boolean =
      if (eagerThrow || !c.isEmpty) throw new UnsupportedOperationException
      else false

    override def removeAll(c: Collection[_]): Boolean = {
      if (eagerThrow) {
        throw new UnsupportedOperationException
      } else {
        val cSet = c.asInstanceOf[Collection[AnyRef]].asScala.toSet
        if (this.asScala.exists(e => cSet(e.asInstanceOf[AnyRef]))) {
          throw new UnsupportedOperationException
        } else {
          false
        }
      }
    }

    override def retainAll(c: Collection[_]): Boolean = {
      if (eagerThrow) {
        throw new UnsupportedOperationException
      } else {
        val cSet = c.asInstanceOf[Collection[AnyRef]].asScala.toSet
        if (this.asScala.exists(e => !cSet(e.asInstanceOf[AnyRef]))) {
          throw new UnsupportedOperationException
        } else {
          false
        }
      }
    }
  }

  private class UnmodifiableSet[E, Coll <: Set[E]](inner: Coll)
      extends UnmodifiableCollection[E, Coll](inner)
      with WrappedSet[E, Coll]

  private class ImmutableSet[E](inner: Set[E])
      extends UnmodifiableSet[E, Set[E]](inner) {
    override protected val eagerThrow: Boolean = false
  }

  private class UnmodifiableSortedSet[E](inner: SortedSet[E])
      extends UnmodifiableSet[E, SortedSet[E]](inner)
      with WrappedSortedSet[E]

  private class UnmodifiableList[E](inner: List[E])
      extends UnmodifiableCollection[E, List[E]](inner)
      with WrappedList[E] {

    override def addAll(index: Int, c: Collection[_ <: E]): Boolean =
      if (eagerThrow || !c.isEmpty) throw new UnsupportedOperationException
      else false

    override def set(index: Int, element: E): E =
      throw new UnsupportedOperationException

    override def add(index: Int, element: E): Unit =
      throw new UnsupportedOperationException

    override def remove(index: Int): E =
      throw new UnsupportedOperationException

    override def listIterator(): ListIterator[E] =
      new UnmodifiableListIterator(this.inner.listIterator())

    override def listIterator(index: Int): ListIterator[E] =
      new UnmodifiableListIterator(this.inner.listIterator(index))

    override def subList(fromIndex: Int, toIndex: Int): List[E] =
      unmodifiableList(super.subList(fromIndex, toIndex))
  }

  private class ImmutableList[E](inner: List[E])
      extends UnmodifiableList(inner) {
    override protected val eagerThrow: Boolean = false
  }

  private class UnmodifiableMap[K, V, M <: Map[K, V]](protected val inner: M)
      extends WrappedMap[K, V, M] {

    protected val eagerThrow: Boolean = true

    override def put(key: K, value: V): V =
      throw new UnsupportedOperationException

    override def remove(key: scala.Any): V = {
      if (eagerThrow || containsKey(key))
        throw new UnsupportedOperationException
      else null.asInstanceOf[V]
    }

    override def putAll(m: Map[_ <: K, _ <: V]): Unit = {
      if (eagerThrow || !m.isEmpty)
        throw new UnsupportedOperationException
    }

    override def clear(): Unit = {
      if (eagerThrow || !isEmpty)
        throw new UnsupportedOperationException
    }

    override def keySet(): Set[K] =
      unmodifiableSet(super.keySet)

    override def values(): Collection[V] =
      unmodifiableCollection(super.values)

    override def entrySet(): Set[Map.Entry[K, V]] =
      unmodifiableSet(super.entrySet)
  }

  private class ImmutableMap[K, V](inner: Map[K, V])
      extends UnmodifiableMap[K, V, Map[K, V]](inner) {
    override protected val eagerThrow: Boolean = false
  }

  private class UnmodifiableSortedMap[K, V](inner: SortedMap[K, V])
      extends UnmodifiableMap[K, V, SortedMap[K, V]](inner)
      with WrappedSortedMap[K, V] {

    override def subMap(fromKey: K, toKey: K): SortedMap[K, V] =
      unmodifiableSortedMap(super.subMap(fromKey, toKey))

    override def headMap(toKey: K): SortedMap[K, V] =
      unmodifiableSortedMap(super.headMap(toKey))

    override def tailMap(fromKey: K): SortedMap[K, V] =
      unmodifiableSortedMap(super.tailMap(fromKey))
  }

  private class UnmodifiableIterator[E, Iter <: Iterator[E]](
      protected val inner: Iter)
      extends WrappedIterator[E, Iter] {
    override def remove(): Unit = throw new UnsupportedOperationException
  }

  private class UnmodifiableListIterator[E](innerIterator: ListIterator[E])
      extends UnmodifiableIterator[E, ListIterator[E]](innerIterator)
      with WrappedListIterator[E] {
    override def set(e: E): Unit = throw new UnsupportedOperationException

    override def add(e: E): Unit = throw new UnsupportedOperationException
  }

  private final def checkClass[T](elem: T, clazz: Class[T]): Unit =
    clazz.cast(elem)

  private class CheckedCollection[E, Coll <: Collection[E]](
      protected val inner: Coll,
      protected val elemClazz: Class[E])
      extends WrappedCollection[E, Coll] {

    override def add(e: E): Boolean = {
      checkElem(e)
      super.add(e)
    }

    override def addAll(c: Collection[_ <: E]): Boolean = {
      c.asScala.foreach(checkElem)
      super.addAll(c)
    }

    protected final def checkElem(elem: E) =
      checkClass(elem, elemClazz)
  }

  private class CheckedSet[E, Coll <: Set[E]](inner: Coll, elemClazz: Class[E])
      extends CheckedCollection[E, Coll](inner, elemClazz)
      with WrappedSet[E, Coll]

  private class CheckedSortedSet[E](inner: SortedSet[E], elemClazz: Class[E])
      extends CheckedSet[E, SortedSet[E]](inner, elemClazz)
      with WrappedSortedSet[E] {

    override def subSet(fromElement: E, toElement: E): SortedSet[E] =
      checkedSortedSet(super.subSet(fromElement, toElement), this.elemClazz)

    override def headSet(toElement: E): SortedSet[E] =
      checkedSortedSet(super.headSet(toElement), this.elemClazz)

    override def tailSet(fromElement: E): SortedSet[E] =
      checkedSortedSet(super.tailSet(fromElement), this.elemClazz)
  }

  private class CheckedList[E](inner: List[E], elemClazz: Class[E])
      extends CheckedCollection[E, List[E]](inner, elemClazz)
      with WrappedList[E] {

    override def addAll(index: Int, c: Collection[_ <: E]): Boolean = {
      c.asScala.foreach(checkElem)
      super.addAll(index, c)
    }

    override def set(index: Int, element: E): E = {
      checkElem(element)
      super.set(index, element)
    }

    override def add(index: Int, element: E): Unit = {
      checkElem(element)
      super.add(index, element)
    }

    override def listIterator(): ListIterator[E] = listIterator(0)

    override def listIterator(index: Int): ListIterator[E] =
      new CheckedListIterator[E](this.inner.listIterator(index), this.elemClazz)

    override def subList(fromIndex: Int, toIndex: Int): List[E] =
      checkedList(super.subList(fromIndex, toIndex), this.elemClazz)
  }

  private class CheckedMap[K, V, M <: Map[K, V]](
      protected val inner: M,
      protected val keyClazz: Class[K],
      protected val valueClazz: Class[V])
      extends WrappedMap[K, V, M] {

    override def put(key: K, value: V): V = {
      checkKeyAndValue(key, value)
      super.put(key, value)
    }

    override def putAll(m: Map[_ <: K, _ <: V]): Unit = {
      m.entrySet()
        .asScala
        .foreach(entry => checkKeyAndValue(entry.getKey, entry.getValue))
      super.putAll(m)
    }

    override def entrySet(): Set[Map.Entry[K, V]] = {
      val innerSet = super.entrySet()
      new WrappedSet[Map.Entry[K, V], Set[Map.Entry[K, V]]] {
        protected def inner: Set[Map.Entry[K, V]] = innerSet

        override def iterator(): Iterator[Map.Entry[K, V]] = {
          val innerIterator = super.iterator()
          new WrappedIterator[Map.Entry[K, V], Iterator[Map.Entry[K, V]]] {
            protected def inner: Iterator[Map.Entry[K, V]] = innerIterator

            override def next(): Map.Entry[K, V] = {
              val nextEntry = super.next()
              new Map.Entry[K, V] {
                def getKey(): K =
                  nextEntry.getKey()

                def getValue(): V =
                  nextEntry.getValue()

                def setValue(value: V): V = {
                  checkClass(value, valueClazz)
                  nextEntry.setValue(value)
                }

                override def equals(o: Any): Boolean =
                  nextEntry.equals(o)

                override def hashCode(): Int =
                  nextEntry.hashCode()
              }
            }
          }
        }
      }
    }

    protected final def checkKeyAndValue(key: K, value: V): Unit = {
      checkClass(key, keyClazz)
      checkClass(value, valueClazz)
    }
  }

  private class CheckedSortedMap[K, V](inner: SortedMap[K, V],
                                       keyClazz: Class[K],
                                       valueClazz: Class[V])
      extends CheckedMap[K, V, SortedMap[K, V]](inner, keyClazz, valueClazz)
      with WrappedSortedMap[K, V] {

    override def subMap(fromKey: K, toKey: K): SortedMap[K, V] =
      checkedSortedMap(super.subMap(fromKey, toKey), keyClazz, valueClazz)

    override def headMap(toKey: K): SortedMap[K, V] =
      checkedSortedMap(super.headMap(toKey), keyClazz, valueClazz)

    override def tailMap(fromKey: K): SortedMap[K, V] =
      checkedSortedMap(super.tailMap(fromKey), keyClazz, valueClazz)
  }

  private class CheckedListIterator[E](protected val inner: ListIterator[E],
                                       protected val elemClazz: Class[E])
      extends WrappedListIterator[E] {
    override def set(e: E): Unit = {
      checkElem(e)
      super.set(e)
    }

    override def add(e: E): Unit = {
      checkElem(e)
      super.add(e)
    }

    private def checkElem(elem: E): Unit = {
      checkClass(elem, elemClazz)
    }
  }

  private class EmptyIterator extends Iterator[Any] {
    def hasNext(): Boolean = false

    def next(): Any =
      throw new NoSuchElementException

    def remove(): Unit =
      throw new IllegalStateException
  }

  private class EmptyListIterator extends EmptyIterator with ListIterator[Any] {
    def hasPrevious(): Boolean = false

    def previous(): Any =
      throw new NoSuchElementException

    def nextIndex(): Int = 0

    def previousIndex(): Int = -1

    def set(e: Any): Unit =
      throw new IllegalStateException

    def add(e: Any): Unit =
      throw new UnsupportedOperationException
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy