final JClassType sourceType = typeOracle.findType(typeName);
// Ensure that the requested type exists
if (sourceType == null) {
logger.log(TreeLogger.ERROR, "Could not find requested typeName", null);
throw new UnableToCompleteException();
}
String locale;
try {
locale = context.getPropertyOracle().getPropertyValue(logger, "locale");
} catch (BadPropertyValueException e) {
// Don't care, likely the user isn't using localization.
locale = "";
}
// Pick a name for the generated class to not conflict. Enclosing class
// names must be preserved.
final String generatedSimpleSourceName = generateSimpleSourceName(sourceType.getName())
+ locale;
// Begin writing the generated source.
final ClassSourceFileComposerFactory f = new ClassSourceFileComposerFactory(
sourceType.getPackage().getName(), generatedSimpleSourceName);
// The generated class needs to be able to determine the module base URL
f.addImport(GWT.class.getName());
f.addImport(ResourcePrototype.class.getName());
// Determine the interface to implement
if (sourceType.isInterface() != null) {
f.addImplementedInterface(sourceType.getQualifiedSourceName());
} else {
// The incoming type wasn't a plain interface, we don't support
// abstract base classes
logger.log(TreeLogger.ERROR, sourceType.getQualifiedSourceName()
+ " is not an interface.", null);
throw new UnableToCompleteException();
}
// All source gets written through this Writer
final PrintWriter out = context.tryCreate(logger,
sourceType.getPackage().getName(), generatedSimpleSourceName);
// Aggregates the field names of the resources for use with
// ResourceBundle.getResources()
List<String> fieldNames = new ArrayList<String>();
// If an implementation already exists, we don't need to do any work
if (out != null) {
// We really use a SourceWriter since it's convenient
final SourceWriter sw = f.createSourceWriter(context, out);
JMethod[] methods = sourceType.getMethods();
Map<Class<? extends ResourceGenerator>, List<JMethod>> resourceGenerators = new HashMap<Class<? extends ResourceGenerator>, List<JMethod>>();
ResourceContext resourceContext = createResourceContext(logger, context,
sourceType, sw);
// First assemble all of the ResourceGenerators that we may need for the
// type
for (JMethod m : methods) {
JClassType returnType = m.getReturnType().isClassOrInterface();
if (returnType == null) {
logger.log(TreeLogger.ERROR, "Cannot implement " + m.getName()
+ ": not a class or interface.", null);
throw new UnableToCompleteException();
}
Class<? extends ResourceGenerator> clazz = findResourceGenerator(
logger, typeOracle, m);
List<JMethod> generatorMethods;
if (resourceGenerators.containsKey(clazz)) {
generatorMethods = resourceGenerators.get(clazz);
} else {
generatorMethods = new ArrayList<JMethod>();
resourceGenerators.put(clazz, generatorMethods);
}
generatorMethods.add(m);
}
// Run the ResourceGenerator code
for (Map.Entry<Class<? extends ResourceGenerator>, List<JMethod>> entry : resourceGenerators.entrySet()) {
Class<? extends ResourceGenerator> generatorClass = entry.getKey();
List<JMethod> generatorMethods = entry.getValue();
// Create the ResourceGenerator
ResourceGenerator rg;
try {
rg = generatorClass.newInstance();
rg.init(logger.branch(TreeLogger.DEBUG,
"Initializing ResourceGenerator", null), resourceContext);
} catch (InstantiationException e) {
logger.log(TreeLogger.ERROR,
"Unable to initialize ResourceGenerator", e);
throw new UnableToCompleteException();
} catch (IllegalAccessException e) {
logger.log(TreeLogger.ERROR,
"Unable to instantiate ResourceGenerator. "
+ "Does it have a public default constructor?", e);
throw new UnableToCompleteException();
}
// Prepare the ResourceGenerator by telling it all methods that it is
// expected to produce.
for (JMethod m : generatorMethods) {