|
Reflection for Creating Decorators
in Java |
|
Prof. David Bernstein |
| Computer Science Department |
| bernstdh@jmu.edu |
import java.awt.*;
import java.io.*;
import java.lang.reflect.*;
/**
* A partial implementation of an application that can be used to
* create a decorator (in the sense of the Decorator Pattern) for
* a given class.
*
* This application uses reflection to create a class that has all of
* the methods of the given class with calls to the same method in the
* decorated object.
*
* Notes:
*
* 1. The current implementation does not consider exceptions.
*
* 2. The current implementation does not consider parameterized types.
*
* @author Prof. David Bernstein, James Madison University
* @version 0.1
*/
public class DecoratorMaker
{
/**
* The entry points
*
* @param args args[0] is the name of the class to decorate
*/
public static void main(String[] args) throws Exception
{
createDecoratorFor(args[0]);
}
/**
* Create a decorator for the given class
*
* @param name The name of the class
*/
private static void createDecoratorFor(String name) throws Exception
{
Class parent, returnType, toDecorate;
Class[] parameters;
int modifiers;
Method[] methods;
PrintStream out;
String decoratorString, nameString, paramString;
String returnTypeString, typedParamString;
toDecorate = Class.forName(name);
// Create an abstract decorator for the parent
parent = toDecorate.getSuperclass();
if (parent != null) createDecoratorFor(parent.getCanonicalName());
decoratorString = "Abstract"+toDecorate.getSimpleName()+"Decorator";
out = new PrintStream(new FileOutputStream(decoratorString+".java"));
out.print("public abstract class " + decoratorString);
if (parent != null)
out.print(" extends Abstract"+parent.getSimpleName()+"Decorator");
out.println();
out.println("{");
// Attributes
out.println("protected "+toDecorate.getCanonicalName()+
" decorated;");
out.println();
// Constructor
out.println("public "+decoratorString+"("+
toDecorate.getCanonicalName()+" decorated)");
out.println("{");
if (parent != null)
out.println("\tsuper(decorated);");
out.println("\tthis.decorated = decorated;");
out.println("}");
out.println();
methods = toDecorate.getDeclaredMethods();
for (int i=0; i<methods.length; i++)
{
modifiers = methods[i].getModifiers();
// Don't include final, native, private, or protected methods
if (!Modifier.isFinal(modifiers) && !Modifier.isNative(modifiers) &&
!Modifier.isPrivate(modifiers) && !Modifier.isProtected(modifiers))
{
// Modifiers
out.print(Modifier.toString(modifiers));
// Return type
returnType = methods[i].getReturnType();
returnTypeString = returnType.getCanonicalName();
out.print(" " + returnTypeString);
// Name
nameString = methods[i].getName();
out.print(" " + nameString);
// Parameters
paramString = "(";
typedParamString = "(";
parameters = methods[i].getParameterTypes();
if (parameters.length > 0)
{
paramString += "param0";
typedParamString += parameters[0].getCanonicalName() + " " +
"param0";
}
for (int p=1; p<parameters.length; p++)
{
paramString += ", " + "param"+p;
typedParamString += ", " + parameters[p].getCanonicalName() +" "+
"param"+p;
}
paramString += ")";
typedParamString += ")";
out.print(typedParamString);
// Body
if (Modifier.isAbstract(modifiers))
out.println(";");
else
{
out.println();
out.println("{");
if (returnTypeString.equals("void"))
out.println("\tdecorated."+nameString+paramString+";");
else
out.println("\treturn decorated."+nameString+paramString+";");
out.println("}");
}
out.println();
}
}
// End of the class
out.println("}");
out.close();
}
}