/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.resources.rebind.context;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.ext.BadPropertyValueException;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.GeneratorContextExt;
import com.google.gwt.core.ext.GeneratorExt;
import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.SelectionProperty;
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.JGenericType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameterizedType;
import com.google.gwt.core.ext.typeinfo.JRealClassType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.generator.NameFactory;
import com.google.gwt.dev.javac.rebind.CachedClientDataMap;
import com.google.gwt.dev.javac.rebind.CachedPropertyInformation;
import com.google.gwt.dev.javac.rebind.CachedRebindResult;
import com.google.gwt.dev.javac.rebind.RebindResult;
import com.google.gwt.dev.javac.rebind.RebindStatus;
import com.google.gwt.dev.util.Util;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.ClientBundleWithLookup;
import com.google.gwt.resources.client.ResourcePrototype;
import com.google.gwt.resources.ext.ClientBundleFields;
import com.google.gwt.resources.ext.ClientBundleRequirements;
import com.google.gwt.resources.ext.ResourceContext;
import com.google.gwt.resources.ext.ResourceGenerator;
import com.google.gwt.resources.ext.ResourceGeneratorType;
import com.google.gwt.resources.ext.ResourceGeneratorUtil;
import com.google.gwt.resources.ext.SupportsGeneratorResultCaching;
import com.google.gwt.resources.rg.BundleResourceGenerator;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.JarURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * The base class for creating new ClientBundle implementations.
 * <p>
 * The general structure of the generated class is as follows:
 * 
 * <pre>
 * private void resourceInitializer() {
 *   resource = new Resource();
 * }
 * private static class cellTreeClosedItemInitializer {
 *   // Using a static initializer so the compiler can optimize clinit calls.
 *   // Refers back to an instance method. See comment below.
 *   static {
 *     _instance0.resourceInitializer();
 *   }
 *   static ResourceType get() {
 *     return resource;
 *   }
 * }
 * public ResourceType resource() {
 *   return cellTreeClosedItemInitializer.get();
 * }
 * // Other ResourceGenerator-defined fields
 * private static ResourceType resource;
 * private static HashMap&lt;String, ResourcePrototype&gt; resourceMap;
 * public ResourcePrototype[] getResources() {
 *   return new ResourcePrototype[] { resource() };
 * }
 * public ResourcePrototype getResource(String name) {
 *   if (GWT.isScript()) {
 *     return getResourceNative(name);
 *   } else {
 *     if (resourceMap == null) {
 *       resourceMap = new HashMap<String, ResourcePrototype>();
 *       resourceMap.put("resource", resource());
 *     }
 *     return resourceMap.get(name);
 *   }
 * }
 * private native ResourcePrototype getResourceNative(String name) /-{
 *   switch (name) {
 *     case 'resource': return this.@...::resource()();
 *   }
 *   return null;
 * }-/
 * </pre>
 * The instantiation of the individual ResourcePrototypes is done in the content
 * of an instance of the ClientBundle type so that resources can refer to one
 * another by simply emitting a call to <code>resource()</code>.
 */
public abstract class AbstractClientBundleGenerator extends GeneratorExt {

  private static final String FILE_PROTOCOL = "file";
  private static final String JAR_PROTOCOL = "jar";
  private static final String CACHED_PROPERTY_INFORMATION = "cpi";
  private static final String CACHED_RESOURCE_INFORMATION = "cri";
  private static final String CACHED_TYPE_INFORMATION = "cti";
  private static final String INSTANCE_NAME = "_instance0";

  /**
   * An implementation of ClientBundleFields.
   */
  protected static class FieldsImpl implements ClientBundleFields {
    private final NameFactory factory = new NameFactory();
    /**
     * It is necessary to maintain order in case one field refers to another.
     */
    private final Map<String, String> fieldsToDeclarations = new LinkedHashMap<String, String>();
    private final Map<String, String> fieldsToInitializers = new HashMap<String, String>();

    public String define(JType type, String name) {
      return define(type, name, null, true, false);
    }

    public String define(JType type, String name, String initializer,
        boolean isStatic, boolean isFinal) {

      assert Util.isValidJavaIdent(name) : name
          + " is not a valid Java identifier";

      String ident = factory.createName(name);

      StringBuilder sb = new StringBuilder();
      sb.append("private ");

      if (isStatic) {
        sb.append("static ");
      }

      if (isFinal) {
        sb.append("final ");
      }

      sb.append(type.getParameterizedQualifiedSourceName());
      sb.append(" ");
      sb.append(ident);

      fieldsToDeclarations.put(ident, sb.toString());

      if (initializer != null) {
        fieldsToInitializers.put(ident, initializer);
      }

      return ident;
    }

    /**
     * This can be called to reset the initializer expression on an
     * already-defined field.
     * 
     * @param ident an identifier previously returned by {@link #define}
     * @param initializer a Java expression that will be used to initialize the
     *          field
     */
    public void setInitializer(String ident, String initializer) {
      assert fieldsToDeclarations.containsKey(ident) : ident + " not defined";
      fieldsToInitializers.put(ident, initializer);
    }

    private String getCode() {
      StringBuilder sb = new StringBuilder();
      for (Map.Entry<String, String> entry : fieldsToDeclarations.entrySet()) {
        String ident = entry.getKey();
        sb.append(entry.getValue());

        String initializer = fieldsToInitializers.get(ident);
        if (initializer != null) {
          sb.append(" = ").append(initializer);
        }
        sb.append(";\n");
      }
      return sb.toString();
    }
  }

  private static class RequirementsImpl implements ClientBundleRequirements {
    private final Set<String> axes;
    private boolean axesLocked = false;
    private final boolean canBeCacheable;
    private final Set<String> configProps;
    private final PropertyOracle propertyOracle;
    private final Map<String, URL> resolvedResources;
    private final Set<JClassType> types;

    public RequirementsImpl(PropertyOracle propertyOracle, boolean canBeCacheable) {
      this.propertyOracle = propertyOracle;
      this.canBeCacheable = canBeCacheable;
      
      // always need to track permuationAxes
      axes = new HashSet<String>();
      
      // only need to track these if generator caching is a possibility
      if (canBeCacheable) {
        configProps = new HashSet<String>();
        types = new HashSet<JClassType>();
        resolvedResources = new HashMap<String, URL>();
      } else {
        configProps = null;
        types = null;
        resolvedResources = null;
      }
    }

    public void addConfigurationProperty(String propertyName) 
        throws BadPropertyValueException {
      
      if (!canBeCacheable) {
        return;
      }
      // Ensure the property exists
      propertyOracle.getConfigurationProperty(propertyName).getValues();
      configProps.add(propertyName);
    }

    public void addPermutationAxis(String propertyName)
        throws BadPropertyValueException {

      if (axes.contains(propertyName)) {
        return;
      }

      // Ensure adding of permutationAxes has not been locked
      if (axesLocked) {
        throw new IllegalStateException(
            "addPermutationAxis failed, axes have been locked");
      }

      // Ensure the property exists and add a permutation axis if the
      // property is a deferred binding property.
      try {
        propertyOracle.getSelectionProperty(
            TreeLogger.NULL, propertyName).getCurrentValue();
        axes.add(propertyName);
      } catch (BadPropertyValueException e) {
        addConfigurationProperty(propertyName);
      }
    }

    public void addResolvedResource(String partialPath, URL resolvedResourceUrl) {
      if (!canBeCacheable) {
        return;
      }
      resolvedResources.put(partialPath, resolvedResourceUrl);
    }

    public void addTypeHierarchy(JClassType type) {
      if (!canBeCacheable) {
        return;
      }
      if (!types.add(type)) {
        return;
      }
      Set<? extends JClassType> superTypes = type.getFlattenedSupertypeHierarchy();
      types.addAll(superTypes);
    }

    public Collection<String> getConfigurationPropertyNames() {
      if (!canBeCacheable) {
        return null;
      }
      return configProps;
    }

    public Collection<String> getPermutationAxes() {
      return axes;
    }

    public Map<String, URL> getResolvedResources() {
      if (!canBeCacheable) {
        return null;
      }
      return resolvedResources;
    }

    public Map<String, String> getTypeSignatures() {
      if (!canBeCacheable) {
        return null;
      }
      Map<String, String> typeSignatures = new HashMap<String, String>();
      for (JClassType type : types) {
        String typeName = type.getQualifiedSourceName();
        if (type instanceof JRealClassType) {
          JRealClassType sourceRealType = (JRealClassType) type;
          String typeSignature = sourceRealType.getTypeStrongHash();
          typeSignatures.put(typeName, typeSignature);
        } else {
          typeSignatures.put(typeName, "");
        }
      }
      return typeSignatures;
    }

    /*
     * No further permutation axes can be added after this is called
     */
    public void lockPermutationAxes() {
      axesLocked = true;
    }
  }

  @Override
  public RebindResult generateIncrementally(TreeLogger logger,
      GeneratorContextExt generatorContext, String typeName)
      throws UnableToCompleteException {

    /*
     * Do a series of checks to see if we can use a previously cached result,
     * and if so, we can skip further execution and return immediately.
     */
    if (checkPropertyCacheability(logger, generatorContext)
        && checkSourceTypeCacheability(generatorContext)
        && checkDependentResourceCacheability(logger, generatorContext, null)) {
      return new RebindResult(RebindStatus.USE_ALL_CACHED, typeName);
    }
      
    // The TypeOracle knows about all types in the type system
    TypeOracle typeOracle = generatorContext.getTypeOracle();

    // Get a reference to the type that the generator should implement
    JClassType sourceType = typeOracle.findType(typeName);

    // Ensure that the requested type exists
    if (sourceType == null) {
      logger.log(TreeLogger.ERROR, "Could not find requested typeName");
      throw new UnableToCompleteException();
    } else if (sourceType.isInterface() == null) {
      // 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();
    }

    /*
     * This associates the methods to implement with the ResourceGenerator class
     * that will generate the implementations of those methods.
     */
    Map<Class<? extends ResourceGenerator>, List<JMethod>> taskList = createTaskList(
        logger, typeOracle, sourceType);

    /*
     * Check the resource generators associated with our taskList, and see if
     * they all support generator result caching.
     */
    boolean canBeCacheable = checkResourceGeneratorCacheability(
        generatorContext, taskList);

    /*
     * Additional objects that hold state during the generation process.
     */
    AbstractResourceContext resourceContext = createResourceContext(logger,
        generatorContext, sourceType);
    FieldsImpl fields = new FieldsImpl();
    RequirementsImpl requirements = new RequirementsImpl(
        generatorContext.getPropertyOracle(), canBeCacheable);
    resourceContext.setRequirements(requirements);
    doAddFieldsAndRequirements(logger, generatorContext, fields, requirements);

    /*
     * Add our source type (and it's supertypes) as a requirement.  Note further
     * types may be added during the processing of the taskList.
     */
    requirements.addTypeHierarchy(sourceType);

    /*
     * Initialize the ResourceGenerators and prepare them for subsequent code
     * generation.
     */
    Map<ResourceGenerator, List<JMethod>> generators = initAndPrepare(logger,
        taskList, resourceContext, requirements);

    /*
     * Now that the ResourceGenerators have been initialized and prepared, we
     * can compute the actual name of the implementation class in order to
     * ensure that we use a distinct name between permutations.
     */
    String generatedSimpleSourceName = generateSimpleSourceName(logger,
        resourceContext, requirements);
    String packageName = sourceType.getPackage().getName();
    String createdClassName = packageName + "." + generatedSimpleSourceName;

    PrintWriter out = generatorContext.tryCreate(logger, packageName,
        generatedSimpleSourceName);

    // If an implementation already exists, we don't need to do any work
    if (out != null) {
      // There is actual work to do
      doCreateBundleForPermutation(logger, generatorContext, fields,
          generatedSimpleSourceName);
      // Begin writing the generated source.
      ClassSourceFileComposerFactory f = new ClassSourceFileComposerFactory(
          packageName, generatedSimpleSourceName);

      // The generated class needs to be able to determine the module base URL
      f.addImport(GWT.class.getName());

      // Used by the map methods
      f.addImport(ResourcePrototype.class.getName());

      // The whole point of this exercise
      f.addImplementedInterface(sourceType.getQualifiedSourceName());

      // All source gets written through this Writer
      SourceWriter sw = f.createSourceWriter(generatorContext, out);

      // Set the now-calculated simple source name
      resourceContext.setSimpleSourceName(generatedSimpleSourceName);

      JParameterizedType hashMapStringResource = getHashMapStringResource(typeOracle);
      String resourceMapField = fields.define(hashMapStringResource, "resourceMap");

      // Write a static instance for use by the static initializers.
      sw.print("private static " + generatedSimpleSourceName + " ");
      sw.println(INSTANCE_NAME + " = new " + generatedSimpleSourceName + "();");

      // Write the generated code to disk
      createFieldsAndAssignments(logger, sw, generators, resourceContext,
          fields);

      // Print the accumulated field definitions
      sw.println(fields.getCode());

      /*
       * The map-accessor methods use JSNI and need a fully-qualified class
       * name, but should not include any sub-bundles.
       */
      taskList.remove(BundleResourceGenerator.class);
      writeMapMethods(sw, taskList, hashMapStringResource, resourceMapField);

      sw.commit(logger);
    }

    finish(logger, resourceContext, generators.keySet());
    doFinish(logger);

    if (canBeCacheable) {
      // remember the current set of required properties, and their values
      CachedPropertyInformation cpi = new CachedPropertyInformation(logger, 
          generatorContext.getPropertyOracle(), 
          requirements.getPermutationAxes(), 
          requirements.getConfigurationPropertyNames());

      // remember the type signatures for required source types
      Map<String, String> cti = requirements.getTypeSignatures();

      // remember the required resources
      Map<String, URL> cri = requirements.getResolvedResources();

      // create data map to be returned the next time the generator is run
      CachedClientDataMap data = new CachedClientDataMap();
      data.put(CACHED_PROPERTY_INFORMATION, cpi);
      data.put(CACHED_RESOURCE_INFORMATION, cri);
      data.put(CACHED_TYPE_INFORMATION, cti);

      // Return a new cacheable result
      return new RebindResult(RebindStatus.USE_ALL_NEW, createdClassName, data);
    } else {
      // If we can't be cacheable, don't return a cacheable result
      return new RebindResult(RebindStatus.USE_ALL_NEW_WITH_NO_CACHING,
          createdClassName);
    }
  }

  /**
   * Create the ResourceContext object that will be used by
   * {@link ResourceGenerator} subclasses. This is the primary way to implement
   * custom logic in the resource generation pass.
   */
  protected abstract AbstractResourceContext createResourceContext(
      TreeLogger logger, GeneratorContext context, JClassType resourceBundleType)
      throws UnableToCompleteException;

  /**
   * Provides a hook for subtypes to add additional fields or requirements to
   * the bundle.
   * 
   * @param logger a TreeLogger
   * @param context the GeneratorContext
   * @param fields ClentBundle fields
   * @param requirements ClientBundleRequirements
   * 
   * @throws UnableToCompleteException if an error occurs.
   */
  protected void doAddFieldsAndRequirements(TreeLogger logger,
      GeneratorContext context, FieldsImpl fields,
      ClientBundleRequirements requirements) throws UnableToCompleteException {
  }

  /**
   * This method is called after the ClientBundleRequirements have been
   * evaluated and a new ClientBundle implementation is being created.
   * 
   * @param logger a TreeLogger
   * @param generatorContext the GeneratoContext
   * @param fields ClientBundle fields
   * @param generatedSimpleSourceName a String
   * 
   * @throws UnableToCompleteException if an error occurs.
   */
  protected void doCreateBundleForPermutation(TreeLogger logger,
      GeneratorContext generatorContext, FieldsImpl fields,
      String generatedSimpleSourceName) throws UnableToCompleteException {
  }

  /**
   * Provides a hook for finalizing generated resources.
   * 
   * @param logger a TreeLogger
   * 
   * @throws UnableToCompleteException if an error occurs.
   */
  protected void doFinish(TreeLogger logger) throws UnableToCompleteException {
  }

  /**
   * Check that the map of cached type signatures matches those from the current
   * typeOracle.
   */
  private boolean checkCachedTypeSignatures(
      GeneratorContextExt generatorContext, Map<String, String> typeSignatures) {
    
    TypeOracle oracle = generatorContext.getTypeOracle();
    
    for (String sourceTypeName : typeSignatures.keySet()) {
      JClassType sourceType = oracle.findType(sourceTypeName);
      if (sourceType == null || !(sourceType instanceof JRealClassType)) {
        return false;
      }
      JRealClassType sourceRealType = (JRealClassType) sourceType;
      
      String signature = sourceRealType.getTypeStrongHash();
      if (!signature.equals(typeSignatures.get(sourceTypeName))) {
        return false;
      }
    }
    
    return true;
  }

  /**
   * Check dependent resources for cacheability.
   */
  private boolean checkDependentResourceCacheability(TreeLogger logger,
      GeneratorContextExt genContext, ResourceContext resourceContext) {

    CachedRebindResult lastRebindResult = genContext.getCachedGeneratorResult();

    if (lastRebindResult == null 
        || !genContext.isGeneratorResultCachingEnabled()) {
      return false;
    }
    long lastTimeGenerated = lastRebindResult.getTimeGenerated();

    // check that resource URL's haven't moved, and haven't been modified
    @SuppressWarnings("unchecked")
    Map<String, URL> cachedResolvedResources = (Map<String, URL>)
      lastRebindResult.getClientData(CACHED_RESOURCE_INFORMATION);
    
    if (cachedResolvedResources == null) {
      return false;
    }
    
    for (Entry<String, URL> entry : cachedResolvedResources.entrySet()) {
      String resourceName = entry.getKey();
      URL resolvedUrl = entry.getValue();
      URL currentUrl = ResourceGeneratorUtil.tryFindResource(logger, genContext,
          resourceContext, resourceName);
      if (currentUrl == null || resolvedUrl == null
          || !resolvedUrl.toExternalForm().equals(currentUrl.toExternalForm())) {
        return false;
      }
      
      if (!checkDependentResourceUpToDate(lastTimeGenerated, resolvedUrl)) {
        return false;
      }
    }

    return true;
  }

  /**
   * Checks whether a dependent resource referenced by the provided URL is
   * up to date, based on the provided referenceTime.
   */
  private boolean checkDependentResourceUpToDate(long referenceTime, URL url) {
    try {
      if (url.getProtocol().equals(JAR_PROTOCOL)) {
        /*
         * If this resource is contained inside a jar file, such as can
         * happen if it's bundled in a 3rd-party library, we use the jar 
         * file itself to test whether it's up to date.  We don't want
         * to call JarURLConnection.getLastModified(), as this is much
         * slower than using the jar File resource directly.
         */
        JarURLConnection jarConn = (JarURLConnection) url.openConnection();
        url = jarConn.getJarFileURL();
      }

      long lastModified;
      if (url.getProtocol().equals(FILE_PROTOCOL)) {
        /*
         * Need to handle possibly wonky syntax in a file URL resource.
         * Modeled after suggestion in this blog entry:
         * http://weblogs.java.net/blog/2007/04/25/how-convert-javaneturl-javaiofile
         */
        File file;
        try {
          file = new File(url.toURI());
        } catch (URISyntaxException uriEx) {
          file = new File(url.getPath());
        }
        lastModified = file.lastModified();
      } else {
        /*
         * Don't attempt to handle any other protocol
         */
        return false;
      }
      if (lastModified == 0L ||
          lastModified > referenceTime) {
        return false;
      }
    } catch (IOException ioEx) {
      return false;
    } catch (RuntimeException ruEx) {
      /*
       * Return false for any RuntimeException (e.g. a SecurityException), and 
       * allow the cacheability check to fail, since we don't want to change the 
       * behavior that would be encountered if no cache is available.  Force 
       * resource generators to utilize their own exception handling.
       */
      return false;
    }
    return true;
  }

  /*
   * Check properties for cacheability
   */
  private boolean checkPropertyCacheability(TreeLogger logger,
      GeneratorContextExt genContext) {

    CachedRebindResult lastRebindResult = genContext.getCachedGeneratorResult();

    if (lastRebindResult == null 
        || !genContext.isGeneratorResultCachingEnabled()) {
      return false;
    }

    /*
     * Do a check of deferred-binding and configuration properties, comparing
     * the cached values saved previously with the current properties.
     */
    CachedPropertyInformation cpi = (CachedPropertyInformation) 
        lastRebindResult.getClientData(CACHED_PROPERTY_INFORMATION);
      
    return cpi != null && cpi.checkPropertiesWithPropertyOracle(logger, 
        genContext.getPropertyOracle());
  }
  
  /**
   * Check cacheability for resource generators in taskList.
   */
  private boolean checkResourceGeneratorCacheability(
      GeneratorContextExt genContext,
      Map<Class<? extends ResourceGenerator>, List<JMethod>> taskList) {
    
    if (!genContext.isGeneratorResultCachingEnabled()) {
      return false;
    }

    /*
     * Loop through each of our ResouceGenerator classes, and check those that
     * implement the SupportsGeneratorResultCaching interface.
     */
    for (Class<? extends ResourceGenerator> rgClass : taskList.keySet()) {
      if (!SupportsGeneratorResultCaching.class.isAssignableFrom(rgClass)) {
        return false;
      }
    } 
    return true;
  }

  /*
   * Check source types for cacheability
   */
  private boolean checkSourceTypeCacheability(GeneratorContextExt genContext) {

    CachedRebindResult lastRebindResult = genContext.getCachedGeneratorResult();

    if (lastRebindResult == null 
        || !genContext.isGeneratorResultCachingEnabled()) {
      return false;
    }

    /*
     * Do a check over the cached list of types that were previously flagged as
     * required.  Check that none of these types has undergone a version change
     * since the previous cached result was generated.
     */
    @SuppressWarnings("unchecked")
    Map<String, String> cachedTypeSignatures = (Map<String, String>)
      lastRebindResult.getClientData(CACHED_TYPE_INFORMATION);

    return cachedTypeSignatures != null 
      && checkCachedTypeSignatures(genContext, cachedTypeSignatures);
  }

  /**
   * Create fields and assignments for a single ResourceGenerator.
   */
  private boolean createFieldsAndAssignments(TreeLogger logger,
      AbstractResourceContext resourceContext, ResourceGenerator rg,
      List<JMethod> generatorMethods, SourceWriter sw,
      ClientBundleFields fields) {

    // Defer failure until this phase has ended
    boolean fail = false;

    resourceContext.setCurrentResourceGenerator(rg);

    // Write all field values
    try {
      rg.createFields(logger.branch(TreeLogger.DEBUG, "Creating fields"),
          resourceContext, fields);
    } catch (UnableToCompleteException e) {
      return false;
    }

    // Create the instance variables in the IRB subclass by calling
    // writeAssignment() on the ResourceGenerator
    for (JMethod m : generatorMethods) {
      String rhs;

      try {
        rhs = rg.createAssignment(logger.branch(TreeLogger.DEBUG,
            "Creating assignment for " + m.getName() + "()"), resourceContext,
            m);
      } catch (UnableToCompleteException e) {
        fail = true;
        continue;
      }

      // Define a field that will hold the ResourcePrototype
      String ident = fields.define(m.getReturnType().isClassOrInterface(),
          m.getName(), null, true, false);

      /*
       * Create an initializer method in the context of an instance so that
       * resources can refer to one another by simply emitting a call to
       * <code>resource()</code>.
       */
      String initializerName = m.getName() + "Initializer";
      sw.println("private void " + initializerName + "() {");
      sw.indentln(ident + " = " + rhs + ";");
      sw.println("}");
      
      /*
       * Create a static Initializer class to lazily initialize the field on
       * first access. The compiler can efficiently optimize this static class
       * using clinits.
       */
      sw.println("private static class " + initializerName + " {");

      sw.indent();
      sw.println("static {");
      sw.indentln(INSTANCE_NAME + "." + initializerName + "();");
      sw.println("}");

      sw.print("static ");
      sw.print(m.getReturnType().getParameterizedQualifiedSourceName());
      sw.println(" get() {");
      sw.indentln("return " + ident + ";");
      sw.println("}");

      sw.outdent();
      sw.println("}");
      
      // Strip off all but the access modifiers
      sw.print(m.getReadableDeclaration(false, true, true, true, true));
      sw.println(" {");
      sw.indentln("return " + initializerName + ".get();");
      sw.println("}");
    }

    if (fail) {
      return false;
    }

    return true;
  }

  /**
   * Create fields and assignments for multiple ResourceGenerators.
   */
  private void createFieldsAndAssignments(TreeLogger logger, SourceWriter sw,
      Map<ResourceGenerator, List<JMethod>> generators,
      AbstractResourceContext resourceContext, ClientBundleFields fields)
      throws UnableToCompleteException {
    // Try to provide as many errors as possible before failing.
    boolean success = true;

    // Run the ResourceGenerators to generate implementations of the methods
    for (Map.Entry<ResourceGenerator, List<JMethod>> entry : generators.entrySet()) {
      success &= createFieldsAndAssignments(logger, resourceContext,
          entry.getKey(), entry.getValue(), sw, fields);
    }

    if (!success) {
      throw new UnableToCompleteException();
    }
  }

  /**
   * Given a ClientBundle subtype, compute which ResourceGenerators should
   * implement which methods. The data returned from this method should be
   * stable across identical modules.
   */
  private Map<Class<? extends ResourceGenerator>, List<JMethod>> createTaskList(
      TreeLogger logger, TypeOracle typeOracle, JClassType sourceType)
      throws UnableToCompleteException {

    Map<Class<? extends ResourceGenerator>, List<JMethod>> toReturn = new LinkedHashMap<Class<? extends ResourceGenerator>, List<JMethod>>();

    JClassType bundleType = typeOracle.findType(ClientBundle.class.getName());
    assert bundleType != null;

    JClassType bundleWithLookupType = typeOracle.findType(ClientBundleWithLookup.class.getName());
    assert bundleWithLookupType != null;

    JClassType resourcePrototypeType = typeOracle.findType(ResourcePrototype.class.getName());
    assert resourcePrototypeType != null;

    // Accumulate as many errors as possible before failing
    boolean throwException = false;

    // Using overridable methods allows composition of interface types
    for (JMethod m : sourceType.getOverridableMethods()) {
      JClassType returnType = m.getReturnType().isClassOrInterface();

      if (m.getEnclosingType().equals(bundleType)
          || m.getEnclosingType().equals(bundleWithLookupType)) {
        // Methods that we must generate, but that are not resources
        continue;

      } else if (!m.isAbstract()) {
        // Covers the case of an abstract class base type
        continue;

      } else if (returnType == null
          || !(returnType.isAssignableTo(resourcePrototypeType) || returnType.isAssignableTo(bundleType))) {
        // Primitives and random other abstract methods
        logger.log(TreeLogger.ERROR, "Unable to implement " + m.getName()
            + " because it does not derive from "
            + resourcePrototypeType.getQualifiedSourceName() + " or "
            + bundleType.getQualifiedSourceName());
        throwException = true;
        continue;
      }

      try {
        Class<? extends ResourceGenerator> clazz = findResourceGenerator(
            logger, m);
        List<JMethod> generatorMethods;
        if (toReturn.containsKey(clazz)) {
          generatorMethods = toReturn.get(clazz);
        } else {
          generatorMethods = new ArrayList<JMethod>();
          toReturn.put(clazz, generatorMethods);
        }

        generatorMethods.add(m);
      } catch (UnableToCompleteException e) {
        throwException = true;
      }
    }

    if (throwException) {
      throw new UnableToCompleteException();
    }

    return toReturn;
  }

  /**
   * Given a JMethod, find the a ResourceGenerator class that will be able to
   * provide an implementation of the method.
   */
  private Class<? extends ResourceGenerator> findResourceGenerator(
      TreeLogger logger, JMethod method) throws UnableToCompleteException {
    JClassType resourceType = method.getReturnType().isClassOrInterface();
    assert resourceType != null;

    ResourceGeneratorType annotation = resourceType.findAnnotationInTypeHierarchy(ResourceGeneratorType.class);
    if (annotation == null) {
      logger.log(TreeLogger.ERROR, "No @"
          + ResourceGeneratorType.class.getName() + " was specifed for type "
          + resourceType.getQualifiedSourceName() + " or its supertypes");
      throw new UnableToCompleteException();
    }

    return annotation.value();
  }

  /**
   * Call finish() on several ResourceGenerators.
   */
  private void finish(TreeLogger logger, AbstractResourceContext context,
      Collection<ResourceGenerator> generators)
      throws UnableToCompleteException {
    boolean fail = false;
    // Finalize the ResourceGenerator
    for (ResourceGenerator rg : generators) {
      context.setCurrentResourceGenerator(rg);
      try {
        rg.finish(
            logger.branch(TreeLogger.DEBUG, "Finishing ResourceGenerator"),
            context);
      } catch (UnableToCompleteException e) {
        fail = true;
      }
    }
    if (fail) {
      throw new UnableToCompleteException();
    }
  }

  /**
   * Given a user-defined type name, determine the type name for the generated
   * class based on accumulated requirements.
   */
  private String generateSimpleSourceName(TreeLogger logger,
      ResourceContext context, RequirementsImpl requirements) {
    StringBuilder toReturn = new StringBuilder(
        context.getClientBundleType().getName().replaceAll("[.$]", "_"));

    try {
      // always add the locale property
      requirements.addPermutationAxis("locale");
    } catch (BadPropertyValueException e) {
    }

    try {
      // no further additions to the permutation axes allowed after this point
      requirements.lockPermutationAxes();
      
      PropertyOracle oracle = context.getGeneratorContext().getPropertyOracle();
      for (String property : requirements.getPermutationAxes()) {
        SelectionProperty prop = oracle.getSelectionProperty(logger, property);
        String value = prop.getCurrentValue();
        toReturn.append("_" + value);
      }
    } catch (BadPropertyValueException e) {
    }

    toReturn.append("_" + getClass().getSimpleName());

    return toReturn.toString();
  }

  /**
   * Returns HashMap&lt;String, ResourcePrototype&gt;.
   */
  private JParameterizedType getHashMapStringResource(TypeOracle typeOracle) {
    JGenericType hashMap = (JGenericType) typeOracle.findType(HashMap.class.getName());
    assert hashMap != null;
    JClassType string = typeOracle.findType(String.class.getName());
    assert string != null;
    JClassType resourcePrototype = typeOracle.findType(ResourcePrototype.class.getName());
    assert resourcePrototype != null;
    JParameterizedType mapStringRes = typeOracle.getParameterizedType(hashMap,
        new JClassType[]{string, resourcePrototype});
    return mapStringRes;
  }

  private boolean initAndPrepare(TreeLogger logger,
      AbstractResourceContext resourceContext, ResourceGenerator rg,
      List<JMethod> generatorMethods, ClientBundleRequirements requirements) {
    try {
      resourceContext.setCurrentResourceGenerator(rg);
      rg.init(
          logger.branch(TreeLogger.DEBUG, "Initializing ResourceGenerator"),
          resourceContext);
    } catch (UnableToCompleteException e) {
      return false;
    }

    boolean fail = false;

    // Prepare the ResourceGenerator by telling it all methods that it is
    // expected to produce.
    for (JMethod m : generatorMethods) {
      try {
        rg.prepare(logger.branch(TreeLogger.DEBUG, "Preparing method "
            + m.getName()), resourceContext, requirements, m);
      } catch (UnableToCompleteException e) {
        fail = true;
      }
    }

    return !fail;
  }

  private Map<ResourceGenerator, List<JMethod>> initAndPrepare(
      TreeLogger logger,
      Map<Class<? extends ResourceGenerator>, List<JMethod>> taskList,
      AbstractResourceContext resourceContext,
      ClientBundleRequirements requirements) throws UnableToCompleteException {
    // Try to provide as many errors as possible before failing.
    boolean success = true;
    Map<ResourceGenerator, List<JMethod>> toReturn = new LinkedHashMap<ResourceGenerator, List<JMethod>>();

    // Run the ResourceGenerators to generate implementations of the methods
    for (Map.Entry<Class<? extends ResourceGenerator>, List<JMethod>> entry : taskList.entrySet()) {

      ResourceGenerator rg = instantiateResourceGenerator(logger,
          entry.getKey());
      toReturn.put(rg, entry.getValue());

      success &= initAndPrepare(logger, resourceContext, rg, entry.getValue(),
          requirements);
    }

    if (!success) {
      throw new UnableToCompleteException();
    }

    return toReturn;
  }

  /**
   * Utility method to construct a ResourceGenerator that logs errors.
   */
  private <T extends ResourceGenerator> T instantiateResourceGenerator(
      TreeLogger logger, Class<T> generatorClass)
      throws UnableToCompleteException {
    try {
      return generatorClass.newInstance();
    } catch (InstantiationException e) {
      logger.log(TreeLogger.ERROR, "Unable to initialize ResourceGenerator", e);
    } catch (IllegalAccessException e) {
      logger.log(TreeLogger.ERROR, "Unable to instantiate ResourceGenerator. "
          + "Does it have a public default constructor?", e);
    }
    throw new UnableToCompleteException();
  }

  /**
   * Emits getResources() and getResourceMap() implementations.
   * 
   * @param sw the output writer
   * @param taskList the list of methods to map by name
   * @param resourceMapField field containing the Java String to Resource map
   */
  private void writeMapMethods(SourceWriter sw,
      Map<Class<? extends ResourceGenerator>, List<JMethod>> taskList,
      JParameterizedType resourceMapType, String resourceMapField) {

    // Complete the IRB contract
    sw.println("public ResourcePrototype[] getResources() {");
    sw.indent();
    sw.println("return new ResourcePrototype[] {");
    sw.indent();
    for (List<JMethod> methods : taskList.values()) {
      for (JMethod m : methods) {
        sw.println(m.getName() + "(), ");
      }
    }
    sw.outdent();
    sw.println("};");
    sw.outdent();
    sw.println("}");

    // Map implementation for dev mode.
    sw.println("public ResourcePrototype getResource(String name) {");
    sw.indent();
    sw.println("if (GWT.isScript()) {");
    sw.indent();
    sw.println("return getResourceNative(name);");
    sw.outdent();
    sw.println("} else {");
    sw.indent();
    sw.println("if (" + resourceMapField + " == null) {");
    sw.indent();
    sw.println(resourceMapField + " = new "
        + resourceMapType.getParameterizedQualifiedSourceName() + "();");
    for (List<JMethod> list : taskList.values()) {
      for (JMethod m : list) {
        sw.println(resourceMapField + ".put(\"" + m.getName() + "\", "
            + m.getName() + "());");
      }
    }
    sw.outdent();
    sw.println("}");
    sw.println("return resourceMap.get(name);");
    sw.outdent();
    sw.println("}");
    sw.outdent();
    sw.println("}");

    // Use a switch statement as a fast map for script mode.
    sw.println("private native ResourcePrototype "
        + "getResourceNative(String name) /*-{");
    sw.indent();
    sw.println("switch (name) {");
    sw.indent();
    for (List<JMethod> list : taskList.values()) {
      for (JMethod m : list) {
        sw.println("case '" + m.getName() + "': return this."
            + m.getJsniSignature() + "();");
      }
    }
    sw.outdent();
    sw.println("}");
    sw.println("return null;");
    sw.outdent();
    sw.println("}-*/;");
  }
}
