Class Wrapper<T>

java.lang.Object
io.github.valentinherrmann.levenshtein.Wrapper<T>
Type Parameters:
T - the type of the class the element (e.g. method) belongs to.
Direct Known Subclasses:
AttributeWrapper, ClassWrapper, ConstructorWrapper, MethodWrapper

public abstract class Wrapper<T> extends Object
Abstract base class for wrapping and verifying Java reflection elements (classes, methods, fields, constructors). Provides name and modifier deviation detection using Levenshtein distance or similar fuzzy matching. Tracks whether an element exists exactly, deviates (can be used even though not 100% matches the signature), or is missing.

The (potentially expensive) lookup in the student code runs only once per wrapper, on first use.

  • Field Details

    • name

      protected WrapperProperty<String> name
      The expected and actual name of the wrapped element.
    • modifiers

      protected WrapperProperty<String> modifiers
      The expected and actual modifiers (e.g., "public static final") of the wrapped element.
    • existence

      protected WrapperProperty.Existence existence
      The overall existence (considering all parts state of the wrapped element (EXACT, DEVIATES, MISSING, or UNCHECKED). DEVIATES means that the element was found but has some deviations from the expected signature, but can still be used for further testing. UNCHECKED means that existence has not yet been verified and is a state which should not be shown to users.
  • Constructor Details

    • Wrapper

      public Wrapper(ClassWrapper<T> parentClass, String expectedName, String... expectedModifiers)
      Constructs a new Wrapper for a reflection element with expected name and modifiers.
      Parameters:
      parentClass - the class wrapper containing this element
      expectedName - the expected name of the element
      expectedModifiers - the expected modifiers (e.g., "public", "static", "final"); a single string may also contain several space separated modifiers. A ? suffix marks an optional modifier that may be present or absent (e.g. "final?").
      Throws:
      IllegalArgumentException - if an expected modifier is unknown (a typo in the test specification), if a visibility is marked optional or if a modifier is both required and optional
  • Method Details

    • verifyExistence

      public abstract void verifyExistence(boolean throwAssertion)
      Verifies that the wrapped element exists in the actual class. Subclasses must implement this to perform element-specific existence checks.
      Parameters:
      throwAssertion - if true, throws an AssertJ assertion failure when the element is missing. Usually set to true for behavioral tests, and false for structural tests to allow further deviation analysis.
    • verifyExistence

      protected void verifyExistence(String failMessage, boolean throwAssertion)
      Verifies existence with a custom failure message. Runs the lookup if it has not run yet, then throws an assertion if the element is not usable and throwAssertion is true.
      Parameters:
      failMessage - the custom failure message to display if the element is missing
      throwAssertion - if true, throws an AssertJ assertion failure when the element is missing. Usually set to true for behavioral tests, and false for structural tests to allow further deviation analysis.
    • usability

      protected WrapperProperty.Existence usability()
      Returns the state that decides whether the element can be used in behavioral tests. By default this is the overall existence; subclasses may relax it (a class whose superclass deviates can still be instantiated, for example).
      Returns:
      the existence state relevant for using the element
    • ensureChecked

      protected final void ensureChecked()
      Runs the lookup in the student code exactly once.
    • getOverallExistence

      public WrapperProperty.Existence getOverallExistence()
      Retrieves the overall existence state of this wrapped element. Triggers deviation detection if not yet checked. Worst part-wise existence determines the overall existence.
      Returns:
      the existence state (EXACT, DEVIATES or MISSING)
    • findWithDeviation

      protected abstract void findWithDeviation()
      Searches for the wrapped element using deviation detection (e.g., Levenshtein distance). Subclasses must implement this to perform element-specific searches and update the property states. Called at most once per wrapper, see ensureChecked().
    • relevantModifierMask

      protected int relevantModifierMask()
      The modifier bits that are meaningful for this kind of element. Other bits of the bitmask are ignored: for methods, the bits of volatile and transient mean bridge and varargs. The default fits classes; methods, attributes and constructors override it.
      Returns:
      the mask of relevant modifier bits
    • implicitModifiers

      protected int implicitModifiers()
      The modifier bits that the actual element has implicitly, e.g. abstract for interfaces or static final for constants of interfaces. They are never reported as unexpected. Called after the element was found.
      Returns:
      the mask of implicit modifier bits
    • legacyReportsUnexpectedStatic

      protected boolean legacyReportsUnexpectedStatic()
      Whether an unexpected static is reported with LevenshteinSettings.UnexpectedModifiers.IGNORE (the behaviour before unexpected modifiers were reported in general). Attributes and methods turn it on.
      Returns:
      true if an unexpected static is reported in the legacy mode
    • verifyModifiers

      public void verifyModifiers(int modifierBitmask)
      Verifies that the actual modifiers match the expected modifiers.
      • An expected modifier that is missing is a deviation (WrapperProperty.Existence.DEVIATES): behaviour tests go on with the actual element, e.g. a method that should be static is called on the default object.
      • An actual modifier that is neither expected, optional ("final?") nor implicit (see implicitModifiers()) is a deviation as well. A different visibility is only reported as a missing expected visibility.
      • If no modifier is specified at all (neither required nor optional), package-private access is expected. Otherwise a visibility is only checked if one is specified.
      With LevenshteinSettings.UnexpectedModifiers.IGNORE the previous behaviour applies: a missing static makes the element WrapperProperty.Existence.MISSING and only an unexpected static of attributes and methods is reported.
      Parameters:
      modifierBitmask - the actual modifiers as a bitmask (from Member.getModifiers())
    • hasUnexpectedModifier

      protected boolean hasUnexpectedModifier(String modifier)
      Returns whether the actual element has the given modifier although it is neither expected, optional nor implicit. Only meaningful after the lookup ran.
      Parameters:
      modifier - the modifier keyword, e.g. "static"
      Returns:
      true if the modifier was reported as unexpected
    • getMissingModifiers

      public List<String> getMissingModifiers()
      Returns:
      the expected modifiers the actual element lacks (empty if the element is missing or matches)
    • getUnexpectedModifiers

      public List<String> getUnexpectedModifiers()
      Returns:
      the modifiers of the actual element that are neither expected, optional nor implicit
    • isModifierExpected

      protected boolean isModifierExpected(String modifier)
      Returns whether the given modifier keyword is part of the expected modifiers.
      Parameters:
      modifier - the modifier keyword, e.g. "abstract"
      Returns:
      true if it was expected
    • getParentClassWrapper

      public ClassWrapper<T> getParentClassWrapper()
      Retrieves the parent class wrapper containing this element. If this wrapper is itself a ClassWrapper, returns itself; otherwise returns the parent.
      Returns:
      the parent ClassWrapper
    • toString

      public String toString()

      Returns a string representation of this wrapped element showing its existence state. The returned string is formatted to be shown to users, indicating whether the element matches exactly, deviates, is missing, or is unchecked. Reuses expectedToString() and actualToString() for representing the two states.

      For WrapperProperty.Existence.EXACT matches, shows expected (= actual) values.

      For WrapperProperty.Existence.DEVIATES, shows both expected and actual values.

      For WrapperProperty.Existence.MISSING, shows what was expected.

      Overrides:
      toString in class Object
      Returns:
      a formatted string describing the element's state
    • expectedToString

      public abstract String expectedToString()
      Returns a string representation of the expected element signature. Subclasses must implement this to provide element-specific formatting.
      Returns:
      a string showing the expected element details
    • actualToString

      public abstract String actualToString()
      Returns a string representation of the actual element signature found. Subclasses must implement this to provide element-specific formatting.
      Returns:
      a string showing the actual element details
    • parseExistence

      protected abstract void parseExistence()
      Parses and updates the existence state based on all properties. Subclasses must implement this to define how to aggregate property states.
    • parseExistence

      protected void parseExistence(WrapperProperty<?>... properties)
      Helper method to parse existence state from multiple wrapper properties. Selects the worst existence state among all provided properties; unchecked properties are ignored.
      Parameters:
      properties - the wrapper properties to check
    • getExpectedName

      public String getExpectedName()
      Retrieves the expected name of this wrapped element instead of exposing the name property directly.
      Returns:
      the expected name as a string
    • getActualName

      public String getActualName()
      Retrieves the actual name of the element found in the student code.
      Returns:
      the actual name, or null if the element is missing
    • getActualModifiers

      public String getActualModifiers()
      Retrieves the actual modifiers of the element found in the student code.
      Returns:
      the actual modifiers (e.g. "public static"), or null if the element is missing