package fr.imag.adele.apam.declarations.instrumentation; import fr.imag.adele.apam.declarations.AtomicImplementationDeclaration; import fr.imag.adele.apam.declarations.references.components.ComponentReference; /** * The base class of all declarations that require instrumenting (injecting, intercepting, invoking, ...) * the code of the implementation * * @author vega * */ public abstract class Instrumentation { /** * A small utility to handle lazy evaluation of values that are calculated from the reflection information, * and that remain constant afterwards. */ protected abstract class Lazy<T> { private boolean isEvaluated; private T value; public Lazy() { value = null; isEvaluated = false; } protected abstract T evaluate(InstrumentedClass instrumentedClass); public T get() { if (isEvaluated) { return value; } value = evaluate(instrumentedClass); isEvaluated = true; return value; } } /** * The implementation associated with this component */ protected final ComponentReference<AtomicImplementationDeclaration> implementation; /** * The instrumented class associated with the implementation */ protected final InstrumentedClass instrumentedClass; protected Instrumentation(ComponentReference<AtomicImplementationDeclaration> implementation, InstrumentedClass instrumentedClass) { this.implementation = implementation; this.instrumentedClass = instrumentedClass; } /** * The component declaring this instrumentation */ public ComponentReference<AtomicImplementationDeclaration> getImplementation() { return implementation; } /** * An unique identifier for this injection, within the scope of the declaring implementation */ public abstract String getName(); /** * Whether the instrumentation declaration is valid in the instrumented code */ public abstract boolean isValidInstrumentation(); }