How To : Write a GWT Generator

3,786 views
Skip to first unread message

riyaz....@gmail.com

unread,
Dec 10, 2007, 10:10:11 PM12/10/07
to Google Web Toolkit

It took me a week to write my first generator (with help - thanks mP).
Am hoping that this How-To will save time for others.

This How-To is targetted for newbies and upwards.

A generator that returns a properties file as a Map.

Usage :: Map myPropertiesMap = (Map) GWT.create(MyPropertiesMap.class)
Valid :: HashMap myPropertiesMap = (HashMap)
GWT.create(MyPropertiesMap.class)


*** Step 1 *** Write a marker interface/class.
**************

In the following example, "extends Map" is not necessary. I have
included it as it is more *descriptive*. This interface/class *must*
reside in a "client side" folder as it needs to be accessed by the
GWTCompiler to generate client side code (example location:
module.client[.generator])

file :: PropertyMap.java
========================

package rm.gwt.core.client.generator;


import java.util.Map;


public interface PropertyMap extends Map {

}





*** Step 2 *** Write your generator.
**************

Writes out the source code for the new class. The source code is self
explanatory. This class *must* *not* reside in a "client side" folder.
This class can use *any* class available to it - it is *not* limited
to the GWT runtimes. By convention, it is placed in the module.rebind
folder.


file :: PropertyMapGenerator.java
=================================


package rm.gwt.core.rebind;


import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
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;

import java.io.PrintWriter;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.ResourceBundle;


/**
* GWT generator that returns a <code>Map</code> (<code>HashMap</
code>)
* from a properties file.
* Usage :: Map myPropertyMap = (Map) GWT.create(MyPropertyMap.class);
* Where :: MyProperMap extends PropertyMap (marker interface)
* :: MyPropertyMap.properties is in same package as
MyPropertyMap.java
*
* @author riyaz....@gmail.com
* @version 2007.12-1
*/
public class PropertyMapGenerator extends Generator {


/** Simple name of class to be generated */
private String className = null;

/** Package name of class to be generated */
private String packageName = null;

/** Fully qualified class name passed into GWT.create() */
private String typeName = null;


// inherited generator method
public String generate(TreeLogger logger, GeneratorContext
context,
String typeName) throws UnableToCompleteException {

this.typeName = typeName;
TypeOracle typeOracle = context.getTypeOracle();

try {

// get classType and save instance variables
JClassType classType = typeOracle.getType(typeName);
packageName = classType.getPackage().getName();
className = classType.getSimpleSourceName() + "Wrapper";
// Generate class source code
generateClass(logger, context);

} catch (Exception e) {

// record to logger that Map generation threw an exception
logger.log(TreeLogger.ERROR, "PropertyMap ERROR!!!", e);

}

// return the fully qualifed name of the class generated
return packageName + "." + className;

}

/**
* Generate source code for new class. Class extends
<code>HashMap</code>.
*
* @param logger Logger object
* @param context Generator context
*/
private void generateClass(TreeLogger logger, GeneratorContext
context) {

// get print writer that receives the source code
PrintWriter printWriter = null;
printWriter = context.tryCreate(logger, packageName, className);
// print writer if null, source code has ALREADY been generated,
return
if (printWriter == null) return;

// init composer, set class properties, create source writer
ClassSourceFileComposerFactory composer = null;
composer = new ClassSourceFileComposerFactory(packageName,
className);
composer.setSuperclass("java.util.HashMap");
SourceWriter sourceWriter = null;
sourceWriter = composer.createSourceWriter(context, printWriter);

// generator constructor source code
generateConstructor(sourceWriter);
// close generated class
sourceWriter.outdent();
sourceWriter.println("}");

// commit generated class
context.commit(logger, printWriter);

}

/**
* Generate source code for the default constructor. Create
default
* constructor, call super(), and insert all key/value pairs from
* the resoruce bundle.
*
* @param sourceWriter Source writer to output source code
*/
private void generateConstructor(SourceWriter sourceWriter) {

// init resource bundle
ResourceBundle bundle = ResourceBundle.getBundle(typeName);

// start constructor source generation
sourceWriter.println("public " + className + "() { ");
sourceWriter.indent();
sourceWriter.println("super();");

// add statements to pub key/value pairs from the resrouce bundle
for (Enumeration<String> keys = bundle.getKeys();
keys.hasMoreElements();) {
String key = keys.nextElement();
sourceWriter.println("put(\"" + Generator.escape(key) +
"\", \""
+ bundle.getString(key) + "\");");
}

// end constructor source generation
sourceWriter.outdent();
sourceWriter.println("}");

}

}




*** Step 3 *** Update the module.gwt.xml file
**************

Include generator info as the last element within your xml file.

Module.xml (sample) ::
======================

<?xml version="1.0" encoding="UTF-8"?>
<module>
<inherits name="com.google.gwt.user.User"/>
<generate-with class="rm.gwt.core.rebind.PropertyMapGenerator" >
<when-type-assignable
class="rm.gwt.core.client.generator.PropertyMap"/>
</generate-with>
</module>




*** Step 4 *** Write sample files. *Must* be in the same folder.
**************

file :: MyPropertiesMap.java
============================
package <package>;
import <imports>;
public interface MyPropertiesMap extends PropertiesMap {}

file :: MyPropertiesMap.properties
==================================
key1=value1
key2=value2


END

hablutzel1

unread,
Feb 5, 2014, 2:49:26 AM2/5/14
to google-we...@googlegroups.com, Google Web Toolkit
Thanks to you, it just took me 15 minutes :)
Reply all
Reply to author
Forward
0 new messages