package nl.astraeus.persistence.reference import nl.astraeus.persistence.Persistable import nl.astraeus.persistence.currentTransaction import java.io.Serializable inline fun referenceCollection( ids: MutableCollection = mutableListOf() ) = ReferenceCollection(T::class.java, ids) open class ReferenceCollection( val cls: Class, val ids: MutableCollection = mutableListOf() ) : MutableCollection, Serializable { protected fun checkElementIsPersisted(element: T) { if (currentTransaction()?.find(cls.kotlin, element.id) == null) { currentTransaction()?.store(element) } } override val size: Int get() { return ids.size } override fun clear() { ids.clear() } override fun isEmpty(): Boolean = ids.isEmpty() override fun iterator(): MutableIterator { return object : MutableIterator { private var idsIterator = ids.iterator() override fun hasNext(): Boolean = idsIterator.hasNext() override fun next(): T = idsIterator.next().let { currentTransaction()?.find(cls.kotlin, it) } ?: throw IllegalStateException("Reference not found") override fun remove() = idsIterator.remove() } } override fun retainAll(elements: Collection): Boolean { return ids.retainAll(elements.map { it.id }.toSet()) } override fun removeAll(elements: Collection): Boolean { return ids.removeAll(elements.map { it.id }.toSet()) } override fun remove(element: T): Boolean { return ids.remove(element.id) } override fun containsAll(elements: Collection): Boolean { return ids.containsAll(elements.map { it.id }) } override fun contains(element: T): Boolean { return ids.contains(element.id) } override fun addAll(elements: Collection): Boolean { for (element in elements) { checkElementIsPersisted(element) } return ids.addAll(elements.map { it.id }) } override fun add(element: T): Boolean { checkElementIsPersisted(element) return ids.add(element.id) } companion object { private const val serialVersionUID: Long = 1L } }