/* BSD 2-Clause License - see OPAL/LICENSE for details. */ package org.opalj package av package checking import org.opalj.bi.AccessFlagsMatcher import org.opalj.br.Attributes as SourceElementAttributes import org.opalj.br.ConcreteSourceElement /** * A predicate related to a specific source element. * * @author Michael Eichberg */ trait SourceElementPredicate[-S <: ConcreteSourceElement] extends (S => Boolean) { left => infix def and[T <: ConcreteSourceElement, X <: S & T]( right: SourceElementPredicate[T] ): SourceElementPredicate[X] = { new SourceElementPredicate[X] { def apply(s: X): Boolean = left(s) && right(s) def toDescription = left.toDescription + " and " + right.toDescription } } final def having[T <: ConcreteSourceElement, X <: S & T]( right: SourceElementPredicate[T] ): SourceElementPredicate[X] = and(right) /** * Returns a human-readable representation of this predicate that is well suited * for presenting it in messages related to architectural deviations. * * It should not end with a white space and should not use multiple lines. * It should not be a complete sentence as this description may be composed with * other descriptions. */ def toDescription: String } case class AccessFlags( accessFlags: AccessFlagsMatcher ) extends SourceElementPredicate[ConcreteSourceElement] { def apply(sourceElement: ConcreteSourceElement): Boolean = { this.accessFlags.unapply(sourceElement.accessFlags) } def toDescription: String = accessFlags.toString } /** * @author Marco Torsello * @author Michael Eichberg */ case class Attributes( attributes: SourceElementAttributes ) extends SourceElementPredicate[ConcreteSourceElement] { def apply(sourceElement: ConcreteSourceElement): Boolean = { // sourceElement.attributes.size == this.attributes.size && this.attributes.forall(a => sourceElement.attributes.contains(a)) } def toDescription: String = { attributes.view.map(_.getClass.getSimpleName).mkString(" « ", ", ", " »") } }