You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

63 lines
2.0 KiB
Kotlin

package net.cijber.pubgrub
import net.cijber.pubgrub.packages.PackageSelection
import net.cijber.pubgrub.stubs.PackageId
import net.cijber.pubgrub.stubs.Version
import net.cijber.pubgrub.version.VersionConstraint
open class Term<P : PackageId, V : Version<V>>(val pkgSelection: PackageSelection<P, V>, val exclusive: Boolean) {
val constraint
get() = pkgSelection.constraint
val pkg
get() = pkgSelection.pkg
val inverse by lazy {
Term(pkgSelection, !exclusive)
}
infix fun relation(rhs: Term<P, V>): SetRelation {
if (rhs.pkg !== pkg) {
throw RuntimeException("Relations between terms can only be compared if they have the same package id")
}
val rhsConstraint = rhs.constraint
if (!rhs.exclusive) {
if (exclusive) {
if (rhsConstraint.allowsAll(constraint))
return SetRelation.Subset
}
}
return SetRelation.Disjoint
}
fun intersect(rhs: Term<P, V>): Term<P, V>? {
if (rhs.pkg !== pkg) {
throw RuntimeException("Relations between terms can only be compared if they have the same package id")
}
return if (exclusive != rhs.exclusive) {
val positive = if (!exclusive) this else rhs
val negative = if (!exclusive) rhs else this
nonEmptyTerm(positive.constraint.difference(negative.constraint), false)
} else if (!exclusive) {
nonEmptyTerm(constraint.intersect(rhs.constraint), false)
} else {
nonEmptyTerm(constraint.union(rhs.constraint), true)
}
}
private fun nonEmptyTerm(constraint: VersionConstraint<V>, exclusive: Boolean): Term<P, V>? {
if (constraint.isEmpty) return null
return Term(PackageSelection(pkg, constraint), exclusive)
}
fun satisfies(term: Term<P, V>): Boolean = term.pkg == pkg &&
(relation(term) == SetRelation.Subset || relation(term) == SetRelation.Equal)
fun difference(rhs: Term<P, V>) = intersect(rhs.inverse)
}