Handler Reflection

From Filtered Push Wiki
Jump to: navigation, search

Overview

Below is some UML (not complete, only parts relevant to the docummentation below are shown) that serves as an architectural overview of the reflection package.

Handler3.png

Using the reflection classes in org.filteredpush.rdf.reflection:

Using an instance of the ClassDesconstructor, one can extract all the methods, fields and related objects from a given class. Related objects include:

  1. Types of the return type of methods in the class and of its related classes.
  2. Types of the public fields of the class and of its related classes.
  3. The generic types of a Collection or a Set and generic types of any Collections or Sets in related classes.

The ClassDeconstructor works by creating a mapping between the name of a class and its members (ClassMembers) and the name of a member (a field or method) and the Java reflection object for accessing that member. Since there is some overhead for the Java reflection, the reflection and these mappings are performed once and stored for later use.

Given an object of the type that the ClassDeconstructor was constructed with (defined in a call to the constructor), a ClassDeconstructor can return a DeconstructedObjectGraph containing DesconstructedObjects and methods that use the mappings described above to invoke methods or obtain fields by supplying the field/method name and arguments.

In this way, we can invoke methods and access fields by specifying its name at runtime. Once the ClassDeconstructor has performed reflection and stored the mappings, there is no additional overhead for any other objects that are of the same type (or of related types).

First create an instance of the ClassDeconstructor with the class to start with (top-level like so:

SomeObject someObject = new SomeObject();
Class c = someObject.getClass();
cd = new ClassDeconstructor(c);

This will deconstsruct all members of the class defined by c and all classes related to c (recursively). The class deconstructor only includes classes that are in the same package as c (for example, the return type String of the toString() method is not considered a related class because it is in a different package).

If you need to add additional classes not referenced by c or any of its related classes, you can add it manually and it will be added to the list of mappings in ClassDeconstructor:

Note: any class not directly referenced in c or by any related classes will not automatically be included. You will need to use this method to include subclasses and implementing classes.

cd.addClass(Class.forName("edu.yourpackage.more.AnotherClass"));

The above steps only need to be performed once. After having done this, if you have instances of SomeObject that you wish to deconstruct, you may do so via the following:

DeconstructedObjectGraph deconstructedObjectGraph = cd.deconstruct(someObject);

From the DeconstructedObjectGraph we can obtain a list of all the related objects as DeconstructedObjects (or we can iterate over the DeconstructedObjectGraph itself with a foreach loop). Both methods are illustrated below:

List<DeconstructedObject> objs = deconstructedObjectGraph.getDeconstructedObjects();

or

for (DeconstructedObject deconstructedObj : deconstructedObjectGraph) {
    ...
}

With the deconstructedObj you can obtain the original object instance that is wrapped in this class, make a call to a method, or access a field. Below are the relevant method signatures:

deconstructedObj.invokeMethod(String name, Object ... param)
deconstructedObj.accessField(String name)
deconstructedObj.public Object getObject()