Evaluating Software Design Patterns
— the "Gang of Four" patterns implemented in Java 6

dk.rode.thesis.meta.reflect
Class Caller

java.lang.Object
  extended by dk.rode.thesis.meta.reflect.IdentifiedStackTraceElement
      extended by dk.rode.thesis.meta.reflect.CallerClass
          extended by dk.rode.thesis.meta.reflect.Caller
All Implemented Interfaces:
Iterable<CallerClass>

public class Caller
extends CallerClass

A caller represents one or more java.lang.reflect.Member instances representing a specific calling context.

The calling context can be either a static initialisation block, an instance initialisation block, a constructor, or a method. The caller thus represents a corresponding Member instance, if possible.

However, the member may not be able to identified uniquely based on the stack trace. It will not be possible to uniquely resolve a member in case the calling context represents an overloaded method; a constructor and/or instance initialisation block declared in a class that declares multiple constructors and/or initialisation blocks; or a static initialisation block declared in a class that declares several static initialisation blocks.

The calling context is stored in the callerMember attribute, while the member representing the immediate calling context is stored in the calleeMember attribute. The attributes are never null, but may not be able to identify the unique member, as stated. They can, however, still be used to test on the different types of members, and list the possible candidates as well.

Callers are immutable.

Example:

   ..
   public class Goo {
     public void goo {
       // Calling context at depth 2...
       new Foo().foo();
     }
   }
   ..
   public class Foo {
      public void foo {
         // Calling context at depth 1...
         new Bar().bar();
      }
   }
   ..
   public class Bar {
     public void bar {
       // Immediate calling context is the callee, i.e. the
       // member at depth 0 (method bar)...
       Caller caller = new Caller();  // = 1             
       System.out.println(caller.callerMember); // prints "foo" 
       System.out.println(caller.calleeMember); // prints "bar"
       
       caller = new Caller(1);             
       System.out.println(caller.callerMember); // prints "foo" 
       System.out.println(caller.calleeMember); // prints "bar"
        
       caller = new Caller(2);             
       System.out.println(caller.callerMember); // prints "goo" 
       System.out.println(caller.calleeMember); // prints "bar" 
     }
   }
   ..
 
Notice that the no-arg constructor does not identify the immediate calling context as the callerMember, but the calling context at stack depth 1. The immediate calling context is always available via the calleeMember method.

An offset can be supplied at construction time to specify a stack depth to identify the calling context. The offset is relative to the immediate calling context.

Stack traces are local to the thread in question.

Author:
Gunni Rode / rode.dk

Nested Class Summary
static class Caller.CallerType
          A caller type identifies possible caller contexts a given caller represents.
static class Caller.MemberContext
          A member context represents a member in a given calling context, which may or may not be uniquely Caller.MemberContext.resolved.
 
Nested classes/interfaces inherited from class dk.rode.thesis.meta.reflect.CallerClass
CallerClass.CallerIterator<C extends CallerClass>
 
Field Summary
 Caller.MemberContext calleeMember
          The callee member context represents the member that created this caller instance, i.e. the member representing the the immediate calling context.
 Caller.MemberContext callerMember
          The caller member context represents the member of the calling context, relative to the offset supplied at construction time.
 
Fields inherited from class dk.rode.thesis.meta.reflect.CallerClass
calleeClass, callerClass
 
Fields inherited from class dk.rode.thesis.meta.reflect.IdentifiedStackTraceElement
element, offset, stack, throwable
 
Constructor Summary
  Caller()
          No-arg constructor.
  Caller(Caller caller)
          Copy constructor.
protected Caller(Caller caller, int offset)
          Constructor, which creates this caller using an existing stack trace supplied from caller, but using a perhaps different offset supplied as offset.
  Caller(int offset)
          Constructor.
protected Caller(int depth, int offset)
          Constructor.
 
Method Summary
 Caller getAssignableCaller()
          Returns the first caller in the call-stack where the class of the calling context is assignable to the class representing the immediate calling context.
 Caller getCaller()
          Returns the caller representing the calling context of this caller, or null if no such caller exist.
 Caller getCaller(Caller.CallerType type)
          Returns the first caller of this caller found in the call-stack matching the caller type supplied as type, if any.
 Iterator<Caller> getCallers()
          Returns a new iterator to iterate over all preceding callers in the call-stack.
 Caller getClassCaller()
          Returns the first caller in the call-stack where the class of the calling context is identical to the class representing the immediate calling context.
protected static Member[] getMember(StackTraceElement element)
          Returns the members associated with the stack trace element supplied as element.
 Caller getNonAssignableCaller()
          Returns the first caller in the call-stack where the class of the calling context is not assignable to the class representing the immediate calling context.
 Caller getNonClassCaller()
          Returns the first caller in the call-stack where the class of the calling context is not identical to the class representing the immediate calling context.
 Caller getNonSubClassCaller()
          Returns the first caller in the call-stack where the class of the calling context is a not a sub-class of the class representing the immediate calling context.
 Caller getSubClassCaller()
          Returns the first caller in the call-stack where the class of the calling context is a sub-class of the class representing the immediate calling context.
 boolean isConstructor()
          Returns true if the member of the calling context is a constructor or instance initialisation block, false if not.
 boolean isMemberInCallStack(Member... members)
          Returns true if just one of the members supplied in members is contained in the call-stack of this caller, false if not.
 boolean isMemberInCallStack(Object... objects)
          Returns true if just one of the declared methods and constructors fetched from an object in objects is contained in the call-stack of this caller, false if not.
 boolean isMethod()
          Returns true if the member of the calling context is a method, false if not.
 boolean isStatic()
          Returns true if the member of the calling context is a static initialiser block, false if not.
 
Methods inherited from class dk.rode.thesis.meta.reflect.CallerClass
equals, getClass, hashCode, isAssignableToThisClass, isClassInCallStack, isNestedClass, isPackageInCallStack, isSubClass, isSuperClass, isThisClass, isThisPackage, iterator
 
Methods inherited from class dk.rode.thesis.meta.reflect.IdentifiedStackTraceElement
getStackTrace, printStackTrace, toString
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
 

Field Detail

calleeMember

public final Caller.MemberContext calleeMember
The callee member context represents the member that created this caller instance, i.e. the member representing the the immediate calling context.

Never null.

See Also:
CallerClass.calleeClass

callerMember

public final Caller.MemberContext callerMember
The caller member context represents the member of the calling context, relative to the offset supplied at construction time.

The member is the "other member" to test when methods like isConstructor() is invoked, where calleeMember represents "this class".

Never null.

See Also:
CallerClass.callerClass
Constructor Detail

Caller

public Caller()
No-arg constructor.

The caller member is the member of the calling context at stack depth 1 from the member of the immediate calling context, i.e. the calling context of the immediate calling context.

Example:

   ..
   public void foo {
     this.bar();
   }
 
   public void bar {
     // Represents foo, *not* bar
     Caller caller = new Caller(); 
   }
   ..
 


Caller

public Caller(Caller caller)
Copy constructor.

Parameters:
caller - The caller to copy; cannot be null.
Throws:
NullPointerException - If caller is null.

Caller

protected Caller(Caller caller,
                 int offset)
Constructor, which creates this caller using an existing stack trace supplied from caller, but using a perhaps different offset supplied as offset.

Parameters:
caller - The caller to supply the stack trace; cannot be null.
offset - The stack offset; must be within bounds.
Throws:
NullPointerException - If caller is null.
IndexOutOfBoundsException - If offset is illegal, i.e., does not represent a valid stack trace element.

Caller

public Caller(int offset)
Constructor.

The caller member is the member of the calling context at stack depth offset from the member of the immediate calling context.

Invoking this constructor with a value of zero corresponds to invoking the no-arg constructor.

Parameters:
offset - The stack offset; must be within bounds.
Throws:
IndexOutOfBoundsException - If offset is illegal, i.e., does not represent a valid stack trace element.

Caller

protected Caller(int depth,
                 int offset)
Constructor.

The caller member is the member of the calling context at stack depth offset from the member of the immediate calling context.

Invoking this constructor with zero values corresponds to invoking the no-arg constructor.

Parameters:
depth - The increase in stack depth added by this class or by sub-classes. The depth of this class is zero, the depth of an immediate sub-class is one, and so forth.
offset - The stack offset; must be within bounds.
Throws:
IndexOutOfBoundsException - If offset is illegal, i.e., does not represent a valid stack trace element.
Method Detail

getAssignableCaller

public Caller getAssignableCaller()
Description copied from class: CallerClass
Returns the first caller in the call-stack where the class of the calling context is assignable to the class representing the immediate calling context.

This may be the same class as the class of the immediate calling context represented by this caller.

Overrides:
getAssignableCaller in class CallerClass
Returns:
The first caller representing a class that is assignable, or null.
See Also:
CallerClass.getNonAssignableCaller()

getCaller

public Caller getCaller()
Description copied from class: CallerClass
Returns the caller representing the calling context of this caller, or null if no such caller exist.

The returned caller will represents the same immediate calling context as this caller, i.e. the CallerClass.calleeClass is equal to that of this caller.

Overrides:
getCaller in class CallerClass
Returns:
The caller representing the calling context of this caller, or null if no such caller exist (end of call-stack).
See Also:
CallerClass.getCallers()

getCaller

public Caller getCaller(Caller.CallerType type)
Returns the first caller of this caller found in the call-stack matching the caller type supplied as type, if any.

Parameters:
type - The caller type; cannot be null.
Returns:
The first matching caller, or null.
Throws:
NullPointerException - If type is null.

getCallers

public Iterator<Caller> getCallers()
Description copied from class: CallerClass
Returns a new iterator to iterate over all preceding callers in the call-stack.

Each returned caller will represents the same immediate calling context as this caller, i.e. the CallerClass.calleeClass is equal to that of this caller. The remove() method of the returned iterator will always throw an UnsupportedOperationException.

Overrides:
getCallers in class CallerClass
Returns:
A new iterator; never null.
See Also:
CallerClass.getCaller(), CallerClass.iterator()

getClassCaller

public Caller getClassCaller()
Description copied from class: CallerClass
Returns the first caller in the call-stack where the class of the calling context is identical to the class representing the immediate calling context.

Overrides:
getClassCaller in class CallerClass
Returns:
The first caller representing the same class, or null.
See Also:
CallerClass.getNonClassCaller()

getMember

protected static final Member[] getMember(StackTraceElement element)
Returns the members associated with the stack trace element supplied as element. The members will always be constructors or methods.

The order of the members is their declaration order in the class represented by element, and only members from that class are considered, i.e. no inherited members.

Parameters:
element - The stack trace element; cannot be null.
Returns:
The matching members; never null.
Throws:
NullPointerException - If element is null.

getNonAssignableCaller

public Caller getNonAssignableCaller()
Description copied from class: CallerClass
Returns the first caller in the call-stack where the class of the calling context is not assignable to the class representing the immediate calling context.

Overrides:
getNonAssignableCaller in class CallerClass
Returns:
The first caller representing a class that is not assignable, or null.
See Also:
CallerClass.getAssignableCaller()

getNonClassCaller

public Caller getNonClassCaller()
Description copied from class: CallerClass
Returns the first caller in the call-stack where the class of the calling context is not identical to the class representing the immediate calling context.

Overrides:
getNonClassCaller in class CallerClass
Returns:
The first caller representing a different class, or null.
See Also:
CallerClass.getClassCaller()

getNonSubClassCaller

public Caller getNonSubClassCaller()
Description copied from class: CallerClass
Returns the first caller in the call-stack where the class of the calling context is a not a sub-class of the class representing the immediate calling context.

Overrides:
getNonSubClassCaller in class CallerClass
Returns:
The first caller representing a class that is not a sub-class, or null.
See Also:
CallerClass.getSubClassCaller()

getSubClassCaller

public Caller getSubClassCaller()
Description copied from class: CallerClass
Returns the first caller in the call-stack where the class of the calling context is a sub-class of the class representing the immediate calling context.

Overrides:
getSubClassCaller in class CallerClass
Returns:
The first caller representing a class that is a sub-class, or null.
See Also:
CallerClass.getNonSubClassCaller()

isConstructor

public final boolean isConstructor()
Returns true if the member of the calling context is a constructor or instance initialisation block, false if not.

Example:

   class Foo {
 
     {
       bar();
     }
     
     public Foo {
       bar();
     }
 
     public static void bar {
       Caller caller = new Caller();
       boolean isConstructor = caller.isConstructor(); // True, True...
       ..
     }
 
     ..
   }
 

Returns:
True if the member of the calling context is a constructor or instance initialisation block, false if not.

See Also:
isStatic(), isMethod()

isMemberInCallStack

public boolean isMemberInCallStack(Member... members)
Returns true if just one of the members supplied in members is contained in the call-stack of this caller, false if not.

Only Method or Constructor members can ever result in a match, while all other member types will cause false to be returned.

Parameters:
members - The members to test; cannot contain null entries.
Returns:
True if just one of the members in members is contained in the call-stack, false if not.
Throws:
NullPointerException - If members contains null entries.
See Also:
isMemberInCallStack(Object...)

isMemberInCallStack

public boolean isMemberInCallStack(Object... objects)
Returns true if just one of the declared methods and constructors fetched from an object in objects is contained in the call-stack of this caller, false if not.

objects may contain Class objects as well.

Parameters:
objects - The objects delivering the methods and constructors to test; cannot contain null entries.
Returns:
True if just one of the methods or constructors fetched from an object in objects is contained in the call-stack, false if not.
Throws:
NullPointerException - If objects contains null entries.
See Also:
isMemberInCallStack(Member...)

isMethod

public final boolean isMethod()
Returns true if the member of the calling context is a method, false if not.

Example:

   ..
   public void foo {
     this.bar();
   }
 
   public void bar {
     Caller caller = new Caller();
     boolean isMethod = caller.isMethod(); // True: foo is a method...
     ..
   }
   ..
 

Returns:
True if the member of the calling context is a method, false if not.
See Also:
isStatic(), isConstructor()

isStatic

public final boolean isStatic()
Returns true if the member of the calling context is a static initialiser block, false if not.

Example:

   class Foo {

     static {
       bar();
     } 
 
     public void bar {
       Caller caller = new Caller();
       boolean isStatic = caller.isStatic(); // True...
       ..
     }
 
     ..
   }
 
To test if a given static method is the caller, use the isMethod() instead, and then test on method modifiers.

Returns:
True if the member of the calling context is a static initialiser block, false if not.

See Also:
isConstructor(), isMethod()

Gunni Rode / rode.dk

Feel free to use and/or modify the Java 6 source code developed for this thesis AT YOUR OWN RISK, but note that the source code comes WITHOUT ANY — and I do mean WITHOUT ANY — form of warranty WHAT SO EVER!

The original thesis and source code are available at rode.dk/thesis.