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
>(val pkgSelection: PackageSelection
, 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
): 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
): Term
? {
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 ? {
if (constraint.isEmpty) return null
return Term(PackageSelection(pkg, constraint), exclusive)
}
fun satisfies(term: Term ): Boolean = term.pkg == pkg &&
(relation(term) == SetRelation.Subset || relation(term) == SetRelation.Equal)
fun difference(rhs: Term ) = intersect(rhs.inverse)
}