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

dk.rode.thesis.meta.reflect
Class CallerClass

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

public class CallerClass
extends IdentifiedStackTraceElement
implements Iterable<CallerClass>

A caller class represents the java.lang.Class instance of a given calling context.

The calling context can be either a static initialisation block, an instance initialisation block, a constructor, or a method. The caller class thus represents the class declaring such a member.

Caller classes are immutable. The actual java.lang.Class representing the calling context is available via the callerClass attribute. The context that created a caller class instance is stored in the calleeClass attribute; such a context is called the immediate calling context and is at stack depth 0. It corresponds to the member being called - the callee.

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
       // class at depth 0 (class Bar)...
       CallerClass caller = new CallerClass(); // = 1             
       System.out.println(caller.callerClass); // prints "Foo" 
       System.out.println(caller.calleeClass); // prints "Bar"
       
       caller = new CallerClass(1);             
       System.out.println(caller.callerClass); // prints "Foo" 
       System.out.println(caller.calleeClass); // prints "Bar"
        
       caller = new CallerClass(2);             
       System.out.println(caller.callerClass); // prints "Goo" 
       System.out.println(caller.calleeClass); // prints "Bar" 
     }
   }
   ..
 
Notice that the no-arg constructor does not identify the immediate calling context as the callerClass, but the calling context at stack depth 1. The immediate calling context is always available via the calleeClass 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
protected static class CallerClass.CallerIterator<C extends CallerClass>
          A caller iterator is used to iterator over CallerClass instances, or sub-classes of it.
 
Field Summary
 Class<?> calleeClass
          The callee class represents the class that created this caller class instance, i.e. the class of the immediate calling context.
 Class<?> callerClass
          The caller class represents the class of the calling context, relative to the offset supplied at construction time.
 
Fields inherited from class dk.rode.thesis.meta.reflect.IdentifiedStackTraceElement
element, offset, stack, throwable
 
Constructor Summary
  CallerClass()
          No-arg constructor.
  CallerClass(CallerClass caller)
          Copy constructor.
protected CallerClass(CallerClass 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.
  CallerClass(int offset)
          Constructor.
protected CallerClass(int depth, int offset)
          Constructor.
 
Method Summary
 boolean equals(Object object)
          Returns true if object is an instance of this class representing the same caller and context class in the same call-stack, false if not.
 CallerClass 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.
 CallerClass getCaller()
          Returns the caller representing the calling context of this caller, or null if no such caller exist.
 Iterator<? extends CallerClass> getCallers()
          Returns a new iterator to iterate over all preceding callers in the call-stack.
protected static Class<?> getClass(StackTraceElement element)
          Returns the class associated with the stack trace element supplied as element.
 CallerClass 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.
 CallerClass 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.
 CallerClass 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.
 CallerClass 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.
 CallerClass 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.
 int hashCode()
          Returns the hash code of the caller.
 boolean isAssignableToThisClass()
          Returns true if the class of the calling context is a class that is assignable to the class representing the immediate calling context, false if not.
 boolean isClassInCallStack(Object... objects)
          Returns true if just one of the classes fetched from an object in objects is contained in the call-stack of this caller, false if not.
 boolean isNestedClass()
          Returns true if the class of the calling context is a nested or inner class of the class representing the immediate calling context, false if not.
 boolean isPackageInCallStack(Object... objects)
          Returns true if just one of the packages fetched from an object in objects is contained in the call-stack of this caller, false if not.
 boolean isSubClass()
          Returns true if the class of the calling context is a sub-class of the class representing the immediate calling context, false if not.
 boolean isSuperClass()
          Returns true if the class of the calling context is a super-class of the class representing the immediate calling context, false if not.
 boolean isThisClass()
          Returns true if the class of the calling context is the same class representing the immediate calling context, false if not.
 boolean isThisPackage()
          Returns true if the class of the calling context is defined in the same package as the class representing the immediate calling context, false if not.
 Iterator<CallerClass> 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

calleeClass

public final Class<?> calleeClass
The callee class represents the class that created this caller class instance, i.e. the class of the immediate calling context.

The callee class is "this class" when methods like isAssignableToThisClass() is invoked, where callerClass represents the other class to test.

Never null.


callerClass

public final Class<?> callerClass
The caller class represents the class of the calling context, relative to the offset supplied at construction time.

The caller class is the "other class" to test when methods like isAssignableToThisClass() is invoked, where calleeClass represents "this class".

Never null.

Constructor Detail

CallerClass

public CallerClass()
No-arg constructor.

The caller class is the class of the calling context at stack depth 1 from the class 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 the class of foo, *not* of bar
     CallerClass caller = new CallerClass(); 
   }
   ..
 


CallerClass

public CallerClass(CallerClass caller)
Copy constructor.

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

CallerClass

protected CallerClass(CallerClass 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.

CallerClass

public CallerClass(int offset)
Constructor.

The caller class is the class of the calling context at stack depth offset from the class 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.

CallerClass

protected CallerClass(int depth,
                      int offset)
Constructor.

The caller class is the class of the calling context at stack depth offset from the class 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

equals

public boolean equals(Object object)
Returns true if object is an instance of this class representing the same caller and context class in the same call-stack, false if not.

Overrides:
equals in class IdentifiedStackTraceElement
Parameters:
object - The object to test; can be null.
Returns:
True if equal, false if not.

getAssignableCaller

public CallerClass 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.

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

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

getCaller

public CallerClass getCaller()
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 calleeClass is equal to that of this caller.

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

getCallers

public Iterator<? extends CallerClass> getCallers()
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 calleeClass is equal to that of this caller. The remove() method of the returned iterator will always throw an UnsupportedOperationException.

Returns:
A new iterator; never null.
See Also:
getCaller(), iterator()

getClass

protected static final Class<?> getClass(StackTraceElement element)
Returns the class associated with the stack trace element supplied as element.

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

getClassCaller

public CallerClass 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.

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

getNonAssignableCaller

public CallerClass 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.

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

getNonClassCaller

public CallerClass 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.

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

getNonSubClassCaller

public CallerClass 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.

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

getSubClassCaller

public CallerClass 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.

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

hashCode

public int hashCode()
Returns the hash code of the caller.

Overrides:
hashCode in class IdentifiedStackTraceElement
Returns:
The hash code.

isAssignableToThisClass

public final boolean isAssignableToThisClass()
Returns true if the class of the calling context is a class that is assignable to the class representing the immediate calling context, false if not.

Example:

   ..
   public class Foo implements FooBar {
     public void foo() {
       CallerClass caller = new CallerClass();
       System.out.println(caller.isAssignableToThisClass());
     }
   }
   
   public class Bar implements FooBar {
     public void bar(Foo foo) {
       foo.foo();
     }
   }
   
   public class Goo {
     public void goo(Foo foo) {
       foo.foo();
     }
   }
   ..
   
   Foo foo = new Foo();
   Bar bar = new Bar();
   Goo goo = new Goo();
   
   bar.bar(foo); // prints "true"
   goo.goo(foo); // prints "false"   
   
   ..
 

Returns:
True if the class of the calling context is a class that is assignable to the class representing the immediate calling context, false if not.
See Also:
isThisPackage(), isThisClass(), isSuperClass(), isSubClass()

isClassInCallStack

public boolean isClassInCallStack(Object... objects)
Returns true if just one of the classes 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 classes to test; cannot contain null entries.
Returns:
True if just one of the classes fetched from an object in objects is contained in the call-stack, false if not.
Throws:
NullPointerException - If objects contains null entries.
See Also:
isPackageInCallStack(Object...)

isNestedClass

public final boolean isNestedClass()
Returns true if the class of the calling context is a nested or inner class of the class representing the immediate calling context, false if not.

Example:

   ..
   public class Foo {
     public void foo() {
       CallerClass caller = new CallerClass();
       System.out.println(caller.isNestedClass());
     }
     
     public static class Bar {
       public void bar(Foo foo) {
         foo.foo();
       }
     }
   }
   
   public class Goo {
     public void goo(Foo foo) {
       foo.foo();
     }
   }
   ..
   
   Foo foo     = new Foo();
   Foo.Bar bar = new Foo.Bar();
   Goo goo     = new Goo();
   
   bar.bar(foo); // prints "true"
   goo.goo(foo); // prints "false"   
   
   ..
 

Returns:
True if the class of the calling context is a nested or inner class of the class representing the immediate calling context, false if not.
See Also:
isThisPackage(), isThisClass(), isSuperClass(), isSubClass(), isAssignableToThisClass()

isPackageInCallStack

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

objects may contain Class and Package objects as well.

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

isSubClass

public final boolean isSubClass()
Returns true if the class of the calling context is a sub-class of the class representing the immediate calling context, false if not.

Example:

   ..
   public class Foo {
     public void foo() {
       CallerClass caller = new CallerClass();
       System.out.println(caller.isSubClass());
     }
   }
   
   public class Bar extends Foo {
     public void bar(Foo foo) {
       foo.foo();
     }
   }
   
   public class Goo {
     public void goo(Foo foo) {
       foo.foo();
     }
   }
   ..
   
   Foo foo = new Foo();
   Bar bar = new Bar();
   Goo goo = new Goo();
   
   bar.bar(foo); // prints "true"
   goo.goo(foo); // prints "false"   
   
   ..
 

Returns:
True if the class of the calling context is a sub-class of the class representing the immediate calling context, false if not.
See Also:
isThisPackage(), isThisClass(), isSuperClass(), isNestedClass(), isAssignableToThisClass()

isSuperClass

public final boolean isSuperClass()
Returns true if the class of the calling context is a super-class of the class representing the immediate calling context, false if not.

Example:

   ..
   public abstract class Foo {
     public Foo() {
       this.foo();
     }
     public abstract void foo();
   }
   
   public class Bar extends Foo {
     public Bar() {
       super();
     }
     public void foo() {
       CallerClass caller = new CallerClass();
       System.out.println(caller.isSuperClass());
     }
   }
   
   public class Goo {
     public void goo(Foo foo) {
       foo.foo();
     }
   }
   ..
   
   Bar bar = new Bar(); // prints "true"
   Goo goo = new Goo();
   goo.goo(bar);        // prints "false"   
   
   ..
 

Returns:
True if the class of the calling context is a super-class of the class representing the immediate calling context, false if not.
See Also:
isThisPackage(), isThisClass(), isSubClass(), isNestedClass(), isAssignableToThisClass()

isThisClass

public final boolean isThisClass()
Returns true if the class of the calling context is the same class representing the immediate calling context, false if not.

Example:

   ..
   public class Foo {
     public void foo() {
       this.foofoo();
     }
   
     public void foofoo() {
       CallerClass caller = new CallerClass();
       System.out.println(caller.isThisClass());
     }
   }
   
   public class Bar {
     public void bar(Foo foo) {
       foo.foofoo();
     }
   }
   
   ..
   
   Foo foo = new Foo();
   Bar bar = new Bar();
   
   foo.foo();    // prints "true"
   bar.bar(foo); // prints "false"   
   
   ..
 

Returns:
True if the class of the calling context is the same class representing the immediate calling context, false if not.
See Also:
isThisPackage(), isNestedClass(), isSuperClass(), isSubClass(), isAssignableToThisClass()

isThisPackage

public final boolean isThisPackage()
Returns true if the class of the calling context is defined in the same package as the class representing the immediate calling context, false if not.

Example:

   ..
   
   package foo;
   
   public class Foo {
     public void foo() {
       this.foofoo();
     }
   
     public void foofoo() {
       CallerClass caller = new CallerClass();
       System.out.println(caller.isThisPackage());
     }
   }
   
   package bar;
   
   public class Bar {
     public void bar(foo.Foo foo) {
       foo.foofoo();
     }
   }
   
   ..
   
   Foo foo = new foo.Foo();
   Bar bar = new bar.Bar();
   
   foo.foo();    // prints "true"
   bar.bar(foo); // prints "false"   
   
   ..
 

Returns:
True if the class of the calling context is defined in the same package as the class representing the immediate calling context, false if not.
See Also:
isThisClass(), isNestedClass(), isSuperClass(), isSubClass(), isAssignableToThisClass()

iterator

public Iterator<CallerClass> iterator()
Specified by:
iterator in interface Iterable<CallerClass>

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.