Since reflection is not possible on the client side, the only solution you have to mimic reflection is using deferred binding.
Use deferred binding to discover all classes you wish to instantiate with the class name during compile time. You may use a marker interface on all such classes to aid TypeOracle to identify these. You dynamically generate a factory class, which takes in the simple name of the class and returns a newly instantiated object of that class. The approach is very straight forward and you will find a good explanation of deferred binding in google's tutorials to boot.
Edit:-
Some skeletal code to get you started. (Stripped down version of my production code, check for compiler errors in the generated file! and debug the flow)
First> Add the following blurb into your *.gwt.xml, to so that the compiler invokes our com.package.ReflectionGenerator, which will generate a simple factory class to mimic reflection on the client side.
<generate-with class="com.package.ReflectionGenerator">
<when-type-assignable class="com.package.client.Reflection" />
</generate-with>
Next> Define an interface for our factory class
public interface Reflection {
public <T> T instantiate( Class<T> clazz );
}
Last> Implement ReflectionGenerator
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.core.ext.BadPropertyValueException;
import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
public class ReflectionGenerator extends Generator
{
@Override
public String generate( TreeLogger logger, GeneratorContext context, String typeName ) throws UnableToCompleteException
{
TypeOracle oracle = context.getTypeOracle( );
JClassType someMarkerInterfaceType = oracle.findType( MarkerInterface.class.getName( ) );
List<JClassType> clazzes = new ArrayList<JClassType>( );
PropertyOracle propertyOracle = context.getPropertyOracle( );
for ( JClassType classType : oracle.getTypes( ) )
{
if ( !classType.equals( someMarkerInterfaceType ) && classType.isAssignableTo( someMarkerInterfaceType ) )
clazzes.add( classType );
}
final String genPackageName = "com.package.client";
final String genClassName = "ReflectionImpl";
ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory( genPackageName, genClassName );
composer.addImplementedInterface( Reflection.class.getCanonicalName( ) );
composer.addImport( "com.package.client.*" );
PrintWriter printWriter = context.tryCreate( logger, genPackageName, genClassName );
if ( printWriter != null )
{
SourceWriter sourceWriter = composer.createSourceWriter( context, printWriter );
sourceWriter.println( "ReflectionImpl( ) {" );
sourceWriter.println( "}" );
printFactoryMethod( clazzes, sourceWriter );
sourceWriter.commit( logger );
}
return composer.getCreatedClassName( );
}
private void printFactoryMethod( List<JClassType> clazzes, SourceWriter sourceWriter )
{
sourceWriter.println( );
sourceWriter.println( "public <T> T instantiate( Class<T> clazz ) {" );
for ( JClassType classType : clazzes )
{
if ( classType.isAbstract( ) )
continue;
sourceWriter.println( );
sourceWriter.indent( );
sourceWriter.println( "if( clazz.getSimpleName().equals(\"" + classType.getName( ) + "\")) {" );
sourceWriter.indent( );
sourceWriter.println( "return new " + classType.getQualifiedSourceName( ) + "( );" );
sourceWriter.outdent( );
sourceWriter.println( "}" );
sourceWriter.outdent( );
sourceWriter.println( );
}
sourceWriter.println( );
sourceWriter.outdent( );
sourceWriter.println( "}" );
sourceWriter.outdent( );
sourceWriter.println( );
}
}
This should generate the factory class ReflectionGenerator in your workspace, check the generated file and tweak the source writer code to generate the code you desire.
Usage GWT.create( Reflection.class ).instantiate( YourClass.class );
I have used a marker interface 'MarkerInterface'
in the generator to restrict the number of classes supported by the factory, hence as a result all the participating classes must implement 'MarkerInterface'