/*
 * 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.uibinder.rebind;

import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameter;
import com.google.gwt.core.ext.typeinfo.JParameterizedType;
import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.JTypeParameter;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.core.shared.impl.StringCase;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.TagName;
import com.google.gwt.event.dom.client.DomEvent;
import com.google.gwt.event.dom.client.DomEvent.Type;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.uibinder.attributeparsers.AttributeParsers;
import com.google.gwt.uibinder.client.LazyDomElement;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.uibinder.client.UiRenderer;
import com.google.gwt.uibinder.client.impl.AbstractUiRenderer;
import com.google.gwt.uibinder.elementparsers.AttributeMessageParser;
import com.google.gwt.uibinder.elementparsers.BeanParser;
import com.google.gwt.uibinder.elementparsers.ElementParser;
import com.google.gwt.uibinder.elementparsers.IsEmptyParser;
import com.google.gwt.uibinder.elementparsers.UiChildParser;
import com.google.gwt.uibinder.rebind.messages.MessagesWriter;
import com.google.gwt.uibinder.rebind.model.HtmlTemplateMethodWriter;
import com.google.gwt.uibinder.rebind.model.HtmlTemplatesWriter;
import com.google.gwt.uibinder.rebind.model.ImplicitClientBundle;
import com.google.gwt.uibinder.rebind.model.ImplicitCssResource;
import com.google.gwt.uibinder.rebind.model.OwnerClass;
import com.google.gwt.uibinder.rebind.model.OwnerField;
import com.google.gwt.user.client.ui.IsRenderable;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.RenderableStamper;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import java.beans.Introspector;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * Writer for UiBinder generated classes.
 */
public class UiBinderWriter implements Statements {

  private static final String SAFE_VAR_PREFIX =
    "somethingUnlikelyToCollideWithParamNamesWefio";

  private static final String UI_RENDERER_DISPATCHER_PREFIX = "UiRendererDispatcherFor";

  private static final String PACKAGE_URI_SCHEME = "urn:import:";

  // TODO(rjrjr) Another place that we need a general anonymous field
  // mechanism
  private static final String CLIENT_BUNDLE_FIELD =
      "clientBundleFieldNameUnlikelyToCollideWithUserSpecifiedFieldOkay";

  public static String asCommaSeparatedList(String... args) {
    StringBuilder b = new StringBuilder();
    for (String arg : args) {
      if (b.length() > 0) {
        b.append(", ");
      }
      b.append(arg);
    }

    return b.toString();
  }

  /**
   * Escape text that will be part of a string literal to be interpreted at
   * runtime as an HTML attribute value.
   */
  public static String escapeAttributeText(String text) {
    text = escapeText(text, false);

    /*
     * Escape single-quotes to make them safe to be interpreted at runtime as an
     * HTML attribute value (for which we by convention use single quotes).
     */
    text = text.replaceAll("'", "&#39;");
    return text;
  }

  /**
   * Escape text that will be part of a string literal to be interpreted at
   * runtime as HTML, optionally preserving whitespace.
   */
  public static String escapeText(String text, boolean preserveWhitespace) {
    // Replace reserved XML characters with entities. Note that we *don't*
    // replace single- or double-quotes here, because they're safe in text
    // nodes.
    text = text.replaceAll("&", "&amp;");
    text = text.replaceAll("<", "&lt;");
    text = text.replaceAll(">", "&gt;");

    if (!preserveWhitespace) {
      text = text.replaceAll("\\s+", " ");
    }

    return escapeTextForJavaStringLiteral(text);
  }

  /**
   * Escape characters that would mess up interpretation of this string as a
   * string literal in generated code (that is, protect \, \n and " ).
   */
  public static String escapeTextForJavaStringLiteral(String text) {
    text = text.replace("\\", "\\\\");
    text = text.replace("\"", "\\\"");
    text = text.replace("\n", "\\n");

    return text;
  }

  /**
   * Returns a list of the given type and all its superclasses and implemented
   * interfaces in a breadth-first traversal.
   *
   * @param type the base type
   * @return a breadth-first collection of its type hierarchy
   */
  static Iterable<JClassType> getClassHierarchyBreadthFirst(JClassType type) {
    LinkedList<JClassType> list = new LinkedList<JClassType>();
    LinkedList<JClassType> q = new LinkedList<JClassType>();

    q.add(type);
    while (!q.isEmpty()) {
      // Pop the front of the queue and add it to the result list.
      JClassType curType = q.removeFirst();
      list.add(curType);

      // Add implemented interfaces to the back of the queue (breadth first,
      // remember?)
      for (JClassType intf : curType.getImplementedInterfaces()) {
        q.add(intf);
      }
      // Add then add superclasses
      JClassType superClass = curType.getSuperclass();
      if (superClass != null) {
        q.add(superClass);
      }
    }

    return list;
  }

  private static String capitalizePropName(String propName) {
    return StringCase.toUpper(propName.substring(0, 1)) + propName.substring(1);
  }

  /**
   * Searches for methods named onBrowserEvent in a {@code type}.
   */
  private static JMethod[] findEventMethods(JClassType type) {
    List<JMethod> methods = new ArrayList<JMethod>(Arrays.asList(type.getInheritableMethods()));

    for (Iterator<JMethod> iterator = methods.iterator(); iterator.hasNext();) {
      JMethod jMethod = iterator.next();
      if (!jMethod.getName().equals("onBrowserEvent")) {
        iterator.remove();
      }
    }

    return methods.toArray(new JMethod[methods.size()]);
  }

  /**
   * Scan the base class for the getter methods. Assumes getters begin with
   * "get". See {@link #validateRendererGetters(JClassType)} for a method that
   * guarantees this method will succeed.
   */
  private static List<JMethod> findGetterNames(JClassType owner) {
    List<JMethod> ret = new ArrayList<JMethod>();
    for (JMethod jMethod : owner.getInheritableMethods()) {
      String getterName = jMethod.getName();
      if (getterName.startsWith("get")) {
        ret.add(jMethod);
      }
    }
    return ret;
  }

  /**
   * Scans a class for a method named "render". Returns its parameters except
   * for the first one. See {@link #validateRenderParameters(JClassType)} for a
   * method that guarantees this method will succeed.
   */
  private static JParameter[] findRenderParameters(JClassType owner) {
    JMethod[] methods = owner.getInheritableMethods();
    JMethod renderMethod = null;

    for (JMethod jMethod : methods) {
      if (jMethod.getName().equals("render")) {
        renderMethod = jMethod;
      }
    }

    JParameter[] parameters = renderMethod.getParameters();
    return Arrays.copyOfRange(parameters, 1, parameters.length);
  }

  /**
   * Finds methods annotated with {@code @UiHandler} in a {@code type}.
   */
  private static JMethod[] findUiHandlerMethods(JClassType type) {
    ArrayList<JMethod> result = new ArrayList<JMethod>();
    JMethod[] allMethods = type.getInheritableMethods();

    for (JMethod jMethod : allMethods) {
      if (jMethod.getAnnotation(UiHandler.class) != null) {
        result.add(jMethod);
      }
    }

    return result.toArray(new JMethod[result.size()]);
  }

  private static String formatMethodError(JMethod eventMethod) {
    return "\"" + eventMethod.getReadableDeclaration(true, true, true, true, true) + "\""
        + " of " + eventMethod.getEnclosingType().getQualifiedSourceName();
  }

  /**
   * Determine the field name a getter is trying to retrieve. Assumes getters
   * begin with "get".
   */
  private static String getterToFieldName(String name) {
    String fieldName = name.substring(3);
    return Introspector.decapitalize(fieldName);
  }

  private static String renderMethodParameters(JParameter[] renderParameters) {
    StringBuilder builder = new StringBuilder();

    for (int i = 0; i < renderParameters.length; i++) {
      JParameter parameter = renderParameters[i];
      builder.append("final ");
      builder.append(parameter.getType().getQualifiedSourceName());
      builder.append(" ");
      builder.append(parameter.getName());
      if (i < renderParameters.length - 1) {
        builder.append(", ");
      }
    }

    return builder.toString();
  }

  private final MortalLogger logger;

  /**
   * Class names of parsers for various ui types, keyed by the classname of the
   * UI class they can build.
   */
  private final Map<String, String> elementParsers = new HashMap<String, String>();

  private final List<String> initStatements = new ArrayList<String>();
  private final List<String> statements = new ArrayList<String>();
  private final HandlerEvaluator handlerEvaluator;
  private final MessagesWriter messages;
  private final DesignTimeUtils designTime;
  private final Tokenator tokenator = new Tokenator();

  private final String templatePath;
  private final TypeOracle oracle;
  /**
   * The type we have been asked to generated, e.g. MyUiBinder
   */
  private final JClassType baseClass;

  /**
   * The name of the class we're creating, e.g. MyUiBinderImpl
   */
  private final String implClassName;

  private final JClassType uiOwnerType;

  private final JClassType uiRootType;

  private final JClassType isRenderableClassType;

  private final JClassType lazyDomElementClass;

  private final OwnerClass ownerClass;

  private final FieldManager fieldManager;

  private final HtmlTemplatesWriter htmlTemplates;

  private final ImplicitClientBundle bundleClass;

  private final boolean useLazyWidgetBuilders;

  private final boolean useSafeHtmlTemplates;

  private int domId = 0;

  private int fieldIndex;

  private String gwtPrefix;

  private int renderableStamper = 0;

  private String rendered;
  /**
   * Stack of element variable names that have been attached.
   */
  private final LinkedList<String> attachSectionElements = new LinkedList<String>();
  /**
   * Maps from field element name to the temporary attach record variable name.
   */
  private final Map<String, String> attachedVars = new HashMap<String, String>();

  private int nextAttachVar = 0;
  /**
   * Stack of statements to be executed after we detach the current attach
   * section.
   */
  private final LinkedList<List<String>> detachStatementsStack = new LinkedList<List<String>>();
  private final AttributeParsers attributeParsers;

  private final UiBinderContext uiBinderCtx;

  private final String binderUri;
  private final boolean isRenderer;

  public UiBinderWriter(JClassType baseClass, String implClassName, String templatePath,
      TypeOracle oracle, MortalLogger logger, FieldManager fieldManager,
      MessagesWriter messagesWriter, DesignTimeUtils designTime, UiBinderContext uiBinderCtx,
      boolean useSafeHtmlTemplates, boolean useLazyWidgetBuilders, String binderUri)
      throws UnableToCompleteException {
    this.baseClass = baseClass;
    this.implClassName = implClassName;
    this.oracle = oracle;
    this.logger = logger;
    this.templatePath = templatePath;
    this.fieldManager = fieldManager;
    this.messages = messagesWriter;
    this.designTime = designTime;
    this.uiBinderCtx = uiBinderCtx;
    this.useSafeHtmlTemplates = useSafeHtmlTemplates;
    this.useLazyWidgetBuilders = useLazyWidgetBuilders;
    this.binderUri = binderUri;

    this.htmlTemplates = new HtmlTemplatesWriter(fieldManager, logger);

    // Check for possible misuse 'GWT.create(UiBinder.class)'
    JClassType uibinderItself = oracle.findType(UiBinder.class.getCanonicalName());
    if (uibinderItself.equals(baseClass)) {
      die("You must use a subtype of UiBinder in GWT.create(). E.g.,\n"
          + "  interface Binder extends UiBinder<Widget, MyClass> {}\n"
          + "  GWT.create(Binder.class);");
    }

    JClassType[] uiBinderTypes = baseClass.getImplementedInterfaces();
    if (uiBinderTypes.length == 0) {
      throw new RuntimeException("No implemented interfaces for " + baseClass.getName());
    }
    JClassType uiBinderType = uiBinderTypes[0];

    JClassType[] typeArgs = uiBinderType.isParameterized() == null
        ? new JClassType[0] : uiBinderType.isParameterized().getTypeArgs();

    String binderType = uiBinderType.getName();

    JClassType uiRendererClass = getOracle().findType(UiRenderer.class.getName());
    if (uiBinderType.isAssignableTo(uibinderItself)) {
      if (typeArgs.length < 2) {
        throw new RuntimeException("Root and owner type parameters are required for type %s"
            + binderType);
      }
      uiRootType = typeArgs[0];
      uiOwnerType = typeArgs[1];
      isRenderer = false;
    } else if (uiBinderType.isAssignableTo(uiRendererClass)) {
      if (typeArgs.length >= 1) {
        throw new RuntimeException("UiRenderer is not a parameterizable type in " + binderType);
      }
      if (!useSafeHtmlTemplates) {
        die("Configuration property UiBinder.useSafeHtmlTemplates\n"
            + "  must be set to true to generate a UiRenderer");
      }
      if (!useLazyWidgetBuilders) {
        die("Configuration property UiBinder.useLazyWidgetBuilders\n"
            + "  must be set to true to generate a UiRenderer");
      }

      // UiRenderers do not need owners but UiBinder generation needs some type here
      uiOwnerType = uiBinderType;
      uiRootType = null;
      isRenderer = true;
    } else {
      die(baseClass.getName() + " must implement UiBinder or UiRenderer");
      // This is unreachable in practice, but silences not initialized errors
      throw new UnableToCompleteException();
    }

    isRenderableClassType = oracle.findType(IsRenderable.class.getCanonicalName());
    lazyDomElementClass = oracle.findType(LazyDomElement.class.getCanonicalName());

    ownerClass = new OwnerClass(uiOwnerType, logger, uiBinderCtx);
    bundleClass =
        new ImplicitClientBundle(baseClass.getPackage().getName(), this.implClassName,
            CLIENT_BUNDLE_FIELD, logger);
    handlerEvaluator = new HandlerEvaluator(ownerClass, logger, oracle, useLazyWidgetBuilders);

    attributeParsers = new AttributeParsers(oracle, fieldManager, logger);
  }

  /**
   * Add a statement to be executed right after the current attached element is
   * detached. This is useful for doing things that might be expensive while the
   * element is attached to the DOM.
   *
   * @param format
   * @param args
   * @see #beginAttachedSection(String)
   */
  public void addDetachStatement(String format, Object... args) {
    detachStatementsStack.getFirst().add(String.format(format, args));
  }

  /**
   * Add a statement to be run after everything has been instantiated, in the
   * style of {@link String#format}.
   */
  public void addInitStatement(String format, Object... params) {
    initStatements.add(formatCode(format, params));
  }

  /**
   * Adds a statement to the block run after fields are declared, in the style
   * of {@link String#format}.
   */
  public void addStatement(String format, Object... args) {
    String code = formatCode(format, args);

    if (useLazyWidgetBuilders) {
      /**
       * I'm intentionally over-simplifying this and assuming that the input
       * comes always in the format: field.somestatement(); Thus, field can be
       * extracted easily and the element parsers don't need to be changed all
       * at once.
       */
      int idx = code.indexOf(".");
      String fieldName = code.substring(0, idx);
      fieldManager.require(fieldName).addStatement(format, args);
    } else {
      statements.add(code);
    }
  }

  /**
   * Begin a section where a new attachable element is being parsed--that is,
   * one that will be constructed as a big innerHTML string, and then briefly
   * attached to the dom to allow fields accessing its to be filled (at the
   * moment, HasHTMLParser, HTMLPanelParser, and DomElementParser.).
   * <p>
   * Succeeding calls made to {@link #ensureAttached} and
   * {@link #ensureCurrentFieldAttached} must refer to children of this element,
   * until {@link #endAttachedSection} is called.
   *
   * @param element Java expression for the generated code that will return the
   *          dom element to be attached.
   */
  public void beginAttachedSection(String element) {
    attachSectionElements.addFirst(element);
    detachStatementsStack.addFirst(new ArrayList<String>());
  }

  /**
   * Declare a field that will hold an Element instance. Returns a token that
   * the caller must set as the id attribute of that element in whatever
   * innerHTML expression will reproduce it at runtime.
   * <P>
   * In the generated code, this token will be replaced by an expression to
   * generate a unique dom id at runtime. Further code will be generated to be
   * run after widgets are instantiated, to use that dom id in a getElementById
   * call and assign the Element instance to its field.
   *
   * @param fieldName The name of the field being declared
   * @param ancestorField The name of fieldName parent
   */
  public String declareDomField(XMLElement source, String fieldName, String ancestorField)
      throws UnableToCompleteException {
    ensureAttached();
    String name = declareDomIdHolder(fieldName);

    if (useLazyWidgetBuilders) {
      // Create and initialize the dom field with LazyDomElement.
      FieldWriter field = fieldManager.require(fieldName);

      /**
       * But if the owner field is an instance of LazyDomElement then the code
       * can be optimized, no cast is needed and the getter doesn't need to be
       * called in its ancestral.
       */
      if (isOwnerFieldLazyDomElement(fieldName)) {
        field.setInitializer(formatCode("new %s(%s)", field.getQualifiedSourceName(),
            fieldManager.convertFieldToGetter(name)));
      } else {

        field.setInitializer(formatCode("new %s(%s).get().cast()",
            LazyDomElement.class.getCanonicalName(), fieldManager.convertFieldToGetter(name)));

        // The dom must be created by its ancestor.
        fieldManager.require(ancestorField).addAttachStatement(
            fieldManager.convertFieldToGetter(fieldName) + ";");
      }
    } else {
      setFieldInitializer(fieldName, "null");
      addInitStatement("%s = com.google.gwt.dom.client.Document.get().getElementById(%s).cast();",
          fieldName, name);
      addInitStatement("%s.removeAttribute(\"id\");", fieldName);
    }

    return tokenForStringExpression(source, fieldManager.convertFieldToGetter(name));
  }

  /**
   * Declare a variable that will be filled at runtime with a unique id, safe
   * for use as a dom element's id attribute. For {@code UiRenderer} based code,
   * elements corresponding to a ui:field, need and id initialized to a value
   * that depends on the {@code fieldName}. For all other cases let
   * {@code fieldName} be {@code null}.
   *
   * @param fieldName name of the field corresponding to this variable.
   * @return that variable's name.
   */
  public String declareDomIdHolder(String fieldName) throws UnableToCompleteException {
    String domHolderName = "domId" + domId++;
    FieldWriter domField =
        fieldManager.registerField(FieldWriterType.DOM_ID_HOLDER,
            oracle.findType(String.class.getName()), domHolderName);
    if (isRenderer && fieldName != null) {
      domField.setInitializer("buildInnerId(\"" + fieldName + "\", uiId)");
    } else {
      domField.setInitializer("com.google.gwt.dom.client.Document.get().createUniqueId()");
    }

    return domHolderName;
  }

  /**
   * If this element has a gwt:field attribute, create a field for it of the
   * appropriate type, and return the field name. If no gwt:field attribute is
   * found, do nothing and return null
   *
   * @return The new field name, or null if no field is created
   */
  public String declareFieldIfNeeded(XMLElement elem) throws UnableToCompleteException {
    String fieldName = getFieldName(elem);
    if (fieldName != null) {

      /**
       * We can switch types if useLazyWidgetBuilders is enabled and the
       * respective owner field is a LazyDomElement.
       */
      if (useLazyWidgetBuilders && isOwnerFieldLazyDomElement(fieldName)) {
        fieldManager.registerFieldForLazyDomElement(findFieldType(elem),
            ownerClass.getUiField(fieldName));
      } else {
        fieldManager.registerField(findFieldType(elem), fieldName);
      }
    }
    return fieldName;
  }

  /**
   * Declare a {@link RenderableStamper} instance that will be filled at runtime
   * with a unique token. This instance can then be used to stamp a single
   * {@link IsRenderable}.
   *
   * @return that variable's name.
   */
  public String declareRenderableStamper() throws UnableToCompleteException {
    String renderableStamperName = "renderableStamper" + renderableStamper++;
    FieldWriter domField =
        fieldManager.registerField(FieldWriterType.RENDERABLE_STAMPER,
            oracle.findType(RenderableStamper.class.getName()), renderableStamperName);
    domField.setInitializer(formatCode(
        "new %s(com.google.gwt.dom.client.Document.get().createUniqueId())",
        RenderableStamper.class.getName()));

    return renderableStamperName;
  }

  /**
   * Writes a new SafeHtml template to the generated BinderImpl.
   *
   * @return The invocation of the SafeHtml template function with the arguments
   *         filled in
   */
  public String declareTemplateCall(String html, String fieldName) throws IllegalArgumentException {
    if (!useSafeHtmlTemplates) {
      return '"' + html + '"';
    }
    FieldWriter w = fieldManager.lookup(fieldName);
    HtmlTemplateMethodWriter templateMethod = htmlTemplates.addSafeHtmlTemplate(html, tokenator);
    if (useLazyWidgetBuilders) {
      w.setHtml(templateMethod.getIndirectTemplateCall());
    } else {
      w.setHtml(templateMethod.getDirectTemplateCall());
    }
    return w.getHtml();
  }

  /**
   * Given a string containing tokens returned by
   * {@link #tokenForStringExpression}, {@link #tokenForSafeHtmlExpression} or
   * {@link #declareDomField}, return a string with those tokens replaced by the
   * appropriate expressions. (It is not normally necessary for an
   * {@link XMLElement.Interpreter} or {@link ElementParser} to make this call,
   * as the tokens are typically replaced by the TemplateWriter itself.)
   */
  public String detokenate(String betokened) {
    return tokenator.detokenate(betokened);
  }

  /**
   * Post an error message and halt processing. This method always throws an
   * {@link UnableToCompleteException}
   */
  public void die(String message) throws UnableToCompleteException {
    logger.die(message);
  }

  /**
   * Post an error message and halt processing. This method always throws an
   * {@link UnableToCompleteException}
   */
  public void die(String message, Object... params) throws UnableToCompleteException {
    logger.die(message, params);
  }

  /**
   * Post an error message about a specific XMLElement and halt processing. This
   * method always throws an {@link UnableToCompleteException}
   */
  public void die(XMLElement context, String message, Object... params)
      throws UnableToCompleteException {
    logger.die(context, message, params);
  }

  /**
   * End the current attachable section. This will detach the element if it was
   * ever attached and execute any detach statements.
   *
   * @see #beginAttachedSection(String)
   */
  public void endAttachedSection() {
    String elementVar = attachSectionElements.removeFirst();
    List<String> detachStatements = detachStatementsStack.removeFirst();
    if (attachedVars.containsKey(elementVar)) {
      String attachedVar = attachedVars.remove(elementVar);
      addInitStatement("%s.detach();", attachedVar);
      for (String statement : detachStatements) {
        addInitStatement(statement);
      }
    }
  }

  /**
   * Ensure that the specified element is attached to the DOM.
   *
   * @see #beginAttachedSection(String)
   */
  public void ensureAttached() {
    String attachSectionElement = attachSectionElements.getFirst();
    if (!attachedVars.containsKey(attachSectionElement)) {
      String attachedVar = "attachRecord" + nextAttachVar;
      addInitStatement("UiBinderUtil.TempAttachment %s = UiBinderUtil.attachToDom(%s);",
          attachedVar, attachSectionElement);
      attachedVars.put(attachSectionElement, attachedVar);
      nextAttachVar++;
    }
  }

  /**
   * Ensure that the specified field is attached to the DOM. The field must hold
   * an object that responds to Element getElement(). Convenience wrapper for
   * {@link #ensureAttached}<code>(field + ".getElement()")</code>.
   *
   * @see #beginAttachedSection(String)
   */
  public void ensureCurrentFieldAttached() {
    ensureAttached();
  }

  /**
   * Finds the JClassType that corresponds to this XMLElement, which must be a
   * Widget or an Element.
   *
   * @throws UnableToCompleteException If no such widget class exists
   * @throws RuntimeException if asked to handle a non-widget, non-DOM element
   */
  public JClassType findFieldType(XMLElement elem) throws UnableToCompleteException {
    String tagName = elem.getLocalName();

    if (!isImportedElement(elem)) {
      return findDomElementTypeForTag(tagName);
    }

    String ns = elem.getNamespaceUri();
    String packageName = ns.substring(PACKAGE_URI_SCHEME.length());
    String className = tagName;

    while (true) {
      JClassType rtn = getOracle().findType(packageName + "." + className);
      if (rtn != null) {
        return rtn;
      }

      // Try again: shift one element of the class name onto the package name.
      // If the class name has only one element left, fail.
      int index = className.indexOf(".");
      if (index == -1) {
        die(elem, "No class matching \"%s\" in %s", tagName, ns);
      }
      packageName = packageName + "." + className.substring(0, index);
      className = className.substring(index + 1);
    }
  }

  /**
   * Generates the code to set a property value (assumes that 'value' is a valid
   * Java expression).
   */
  public void genPropertySet(String fieldName, String propName, String value) {
    addStatement("%1$s.set%2$s(%3$s);", fieldName, capitalizePropName(propName), value);
  }

  /**
   * Generates the code to set a string property.
   */
  public void genStringPropertySet(String fieldName, String propName, String value) {
    genPropertySet(fieldName, propName, "\"" + value + "\"");
  }

  /**
   * The type we have been asked to generated, e.g. MyUiBinder
   */
  public JClassType getBaseClass() {
    return baseClass;
  }

  public ImplicitClientBundle getBundleClass() {
    return bundleClass;
  }

  /**
   * Returns the {@link DesignTimeUtils}, not <code>null</code>.
   */
  public DesignTimeUtils getDesignTime() {
    return designTime;
  }

  public FieldManager getFieldManager() {
    return fieldManager;
  }

  /**
   * Returns the logger, at least until we get get it handed off to parsers via
   * constructor args.
   */
  public MortalLogger getLogger() {
    return logger;
  }

  /**
   * Get the {@link MessagesWriter} for this UI, generating it if necessary.
   */
  public MessagesWriter getMessages() {
    return messages;
  }

  /**
   * Gets the type oracle.
   */
  public TypeOracle getOracle() {
    return oracle;
  }

  public OwnerClass getOwnerClass() {
    return ownerClass;
  }

  public String getUiFieldAttributeName() {
    return gwtPrefix + ":field";
  }

  public boolean isBinderElement(XMLElement elem) {
    String uri = elem.getNamespaceUri();
    return uri != null && binderUri.equals(uri);
  }

  public boolean isElementAssignableTo(XMLElement elem, Class<?> possibleSuperclass)
      throws UnableToCompleteException {
    JClassType classType = oracle.findType(possibleSuperclass.getCanonicalName());
    return isElementAssignableTo(elem, classType);
  }

  public boolean isElementAssignableTo(XMLElement elem, JClassType possibleSupertype)
      throws UnableToCompleteException {
    /*
     * Things like <W extends IsWidget & IsPlaid>
     */
    JTypeParameter typeParameter = possibleSupertype.isTypeParameter();
    if (typeParameter != null) {
      JClassType[] bounds = typeParameter.getBounds();
      for (JClassType bound : bounds) {
        if (!isElementAssignableTo(elem, bound)) {
          return false;
        }
      }
      return true;
    }

    /*
     * Binder fields are always declared raw, so we're cheating if the user is
     * playing with parameterized types. We're happy enough if the raw types
     * match, and rely on them to make sure the specific types really do work.
     */
    JParameterizedType parameterized = possibleSupertype.isParameterized();
    if (parameterized != null) {
      return isElementAssignableTo(elem, parameterized.getRawType());
    }

    JClassType fieldtype = findFieldType(elem);
    if (fieldtype == null) {
      return false;
    }
    return fieldtype.isAssignableTo(possibleSupertype);
  }

  public boolean isImportedElement(XMLElement elem) {
    String uri = elem.getNamespaceUri();
    return uri != null && uri.startsWith(PACKAGE_URI_SCHEME);
  }

  /**
   * Checks whether the given owner field name is a LazyDomElement or not.
   */
  public boolean isOwnerFieldLazyDomElement(String fieldName) {
    OwnerField ownerField = ownerClass.getUiField(fieldName);
    if (ownerField == null) {
      return false;
    }

    return lazyDomElementClass.isAssignableFrom(ownerField.getType().getRawType());
  }

  public boolean isRenderableElement(XMLElement elem) throws UnableToCompleteException {
    return findFieldType(elem).isAssignableTo(isRenderableClassType);
  }

  public boolean isRenderer() {
    return isRenderer;
  }

  public boolean isWidgetElement(XMLElement elem) throws UnableToCompleteException {
    return isElementAssignableTo(elem, IsWidget.class);
  }

  /**
   * Parses the object associated with the specified element, and returns the
   * field writer that will hold it. The element is likely to make recursive
   * calls back to this method to have its children parsed.
   *
   * @param elem the xml element to be parsed
   * @return the field holder just created
   */
  public FieldWriter parseElementToField(XMLElement elem) throws UnableToCompleteException {
    if (elementParsers.isEmpty()) {
      registerParsers();
    }

    // Get the class associated with this element.
    JClassType type = findFieldType(elem);

    // Declare its field.
    FieldWriter field = declareField(elem, type.getQualifiedSourceName());

    /*
     * Push the field that will hold this widget on top of the parsedFieldStack
     * to ensure that fields registered by its parsers will be noted as
     * dependencies of the new widget. (See registerField.) Also push the
     * element being parsed, so that the fieldManager can hold that info for
     * later error reporting when field reference left hand sides are validated.
     */
    fieldManager.push(elem, field);

    // Give all the parsers a chance to generate their code.
    for (ElementParser parser : getParsersForClass(type)) {
      parser.parse(elem, field.getName(), type, this);
    }
    fieldManager.pop();

    return field;
  }

  /**
   * Gives the writer the initializer to use for this field instead of the
   * default GWT.create call.
   *
   * @throws IllegalStateException if an initializer has already been set
   */
  public void setFieldInitializer(String fieldName, String factoryMethod) {
    fieldManager.lookup(fieldName).setInitializer(factoryMethod);
  }

  /**
   * Instructs the writer to initialize the field with a specific constructor
   * invocation, instead of the default GWT.create call.
   *
   * @param fieldName the field to initialize
   * @param args arguments to the constructor call
   */
  public void setFieldInitializerAsConstructor(String fieldName, String... args) {
    JClassType assignableType = fieldManager.lookup(fieldName).getAssignableType();
    setFieldInitializer(fieldName, formatCode("new %s(%s)", assignableType.getQualifiedSourceName(),
        asCommaSeparatedList(args)));
  }

  /**
   * Like {@link #tokenForStringExpression}, but used for runtime expressions
   * that we trust to be safe to interpret at runtime as HTML without escaping,
   * like translated messages with simple formatting. Wrapped in a call to
   * {@link com.google.gwt.safehtml.shared.SafeHtmlUtils#fromSafeConstant} to
   * keep the expression from being escaped by the SafeHtml template.
   *
   * @param expression must resolve to trusted HTML string
   */
  public String tokenForSafeConstant(XMLElement source, String expression) {
    if (!useSafeHtmlTemplates) {
      return tokenForStringExpression(source, expression);
    }

    expression = "SafeHtmlUtils.fromSafeConstant(" + expression + ")";
    htmlTemplates.noteSafeConstant(expression);
    return nextToken(source, expression);
  }

  /**
   * Like {@link #tokenForStringExpression}, but used for runtime
   * {@link com.google.gwt.safehtml.shared.SafeHtml SafeHtml} instances.
   *
   * @param expression must resolve to SafeHtml object
   */
  public String tokenForSafeHtmlExpression(XMLElement source, String expression) {
    if (!useSafeHtmlTemplates) {
      return tokenForStringExpression(source, expression + ".asString()");
    }

    htmlTemplates.noteSafeConstant(expression);
    return nextToken(source, expression);
  }

  /**
   * Like {@link #tokenForStringExpression}, but used for runtime
   * {@link com.google.gwt.safehtml.shared.SafeUri SafeUri} instances.
   *
   * @param expression must resolve to SafeUri object
   */
  public String tokenForSafeUriExpression(XMLElement source, String expression) {
    if (!useSafeHtmlTemplates) {
      return tokenForStringExpression(source, expression);
    }

    htmlTemplates.noteUri(expression);
    return nextToken(source, expression);
  }

  /**
   * Returns a string token that can be used in place the given expression
   * inside any string literals. Before the generated code is written, the
   * expression will be stitched back into the generated code in place of the
   * token, surrounded by plus signs. This is useful in strings to be handed to
   * setInnerHTML() and setText() calls, to allow a unique dom id attribute or
   * other runtime expression in the string.
   *
   * @param expression must resolve to String
   */
  public String tokenForStringExpression(XMLElement source, String expression) {
    return nextToken(source, "\" + " + expression + " + \"");
  }

  public boolean useLazyWidgetBuilders() {
    return useLazyWidgetBuilders;
  }

  /**
   * @return true of SafeHtml integration is in effect
   */
  public boolean useSafeHtmlTemplates() {
    return useSafeHtmlTemplates;
  }

  /**
   * Post a warning message.
   */
  public void warn(String message) {
    logger.warn(message);
  }

  /**
   * Post a warning message.
   */
  public void warn(String message, Object... params) {
    logger.warn(message, params);
  }

  /**
   * Post a warning message.
   */
  public void warn(XMLElement context, String message, Object... params) {
    logger.warn(context, message, params);
  }

  /**
   * Entry point for the code generation logic. It generates the
   * implementation's superstructure, and parses the root widget (leading to all
   * of its children being parsed as well).
   *
   * @param doc TODO
   */
  void parseDocument(Document doc, PrintWriter printWriter) throws UnableToCompleteException {
    Element documentElement = doc.getDocumentElement();
    gwtPrefix = documentElement.lookupPrefix(binderUri);

    XMLElement elem =
        new XMLElementProviderImpl(attributeParsers, oracle, logger, designTime).get(documentElement);
    this.rendered = tokenator.detokenate(parseDocumentElement(elem));
    printWriter.print(rendered);
  }

  private void addElementParser(String gwtClass, String parser) {
    elementParsers.put(gwtClass, parser);
  }

  private void addWidgetParser(String className) {
    String gwtClass = "com.google.gwt.user.client.ui." + className;
    String parser = "com.google.gwt.uibinder.elementparsers." + className + "Parser";
    addElementParser(gwtClass, parser);
  }

  /**
   * Declares a field of the given type name, returning the name of the declared
   * field. If the element has a field or id attribute, use its value.
   * Otherwise, create and return a new, private field name for it.
   */
  private FieldWriter declareField(XMLElement source, String typeName)
      throws UnableToCompleteException {
    JClassType type = oracle.findType(typeName);
    if (type == null) {
      die(source, "Unknown type %s", typeName);
    }

    String fieldName = getFieldName(source);
    if (fieldName == null) {
      // TODO(rjrjr) could collide with user declared name, as is
      // also a worry in HandlerEvaluator. Need a general scheme for
      // anonymous fields. See the note in HandlerEvaluator and do
      // something like that, but in FieldManager.
      fieldName = "f_" + source.getLocalName() + ++fieldIndex;
    }
    fieldName = normalizeFieldName(fieldName);
    return fieldManager.registerField(type, fieldName);
  }

  private void dieGettingEventTypeName(JMethod jMethod, Exception e)
      throws UnableToCompleteException {
    die("Could not obtain DomEvent.Type object for first parameter of %s (%s)",
        formatMethodError(jMethod), e.getMessage());
  }

  /**
   * Ensures that all of the internal data structures are cleaned up correctly
   * at the end of parsing the document.
   *
   * @throws IllegalStateException
   */
  private void ensureAttachmentCleanedUp() {
    if (!attachSectionElements.isEmpty()) {
      throw new IllegalStateException("Attachments not cleaned up: " + attachSectionElements);
    }
    if (!detachStatementsStack.isEmpty()) {
      throw new IllegalStateException("Detach not cleaned up: " + detachStatementsStack);
    }
  }

  /**
   * Add call to {@code com.google.gwt.resources.client.CssResource#ensureInjected()}
   * on each CSS resource field.
   */
  private void ensureInjectedCssFields() {
    for (ImplicitCssResource css : bundleClass.getCssMethods()) {
      String fieldName = css.getName();
      FieldWriter cssField = fieldManager.require(fieldName);
      cssField.addStatement("%s.ensureInjected();", fieldName);
    }
  }

  /**
   * Evaluate whether all @UiField attributes are also defined in the template.
   * Dies if not.
   */
  private void evaluateUiFields() throws UnableToCompleteException {
    if (designTime.isDesignTime()) {
      return;
    }
    for (OwnerField ownerField : getOwnerClass().getUiFields()) {
      String fieldName = ownerField.getName();
      FieldWriter fieldWriter = fieldManager.lookup(fieldName);

      if (fieldWriter == null) {
        die("Template %s has no %s attribute for %s.%s#%s", templatePath,
            getUiFieldAttributeName(), uiOwnerType.getPackage().getName(), uiOwnerType.getName(),
            fieldName);
      }
    }
  }

  /**
   * Given a DOM tag name, return the corresponding JSO subclass.
   */
  private JClassType findDomElementTypeForTag(String tag) {
    JClassType elementClass = oracle.findType("com.google.gwt.dom.client.Element");
    JClassType[] types = elementClass.getSubtypes();
    for (JClassType type : types) {
      TagName annotation = type.getAnnotation(TagName.class);
      if (annotation != null) {
        for (String annotationTag : annotation.value()) {
          if (annotationTag.equals(tag)) {
            return type;
          }
        }
      }
    }
    return elementClass;
  }

  /**
   * Calls {@code getType().getName()} on subclasses of {@code DomEvent}.
   */
  private String findEventTypeName(JMethod jMethod)
      throws UnableToCompleteException {
    // Get the event class name (i.e. ClickEvent)
    String eventTypeName = jMethod.getParameterTypes()[0].getQualifiedSourceName();

    Class<?> domType;

    // Get the class instance
    try {
      domType = Class.forName(eventTypeName);
    } catch (ClassNotFoundException e) {
      die("Could not find type %s in %s", eventTypeName, formatMethodError(jMethod));
      return null;
    }

    // Reflectively obtain the type (i.e. ClickEvent.getType())
    try {
      return ((Type<?>) domType.getMethod("getType", (Class[]) null).invoke(null,
          (Object[]) null)).getName();
    } catch (IllegalArgumentException e) {
      dieGettingEventTypeName(jMethod, e);
    } catch (SecurityException e) {
      dieGettingEventTypeName(jMethod, e);
    } catch (IllegalAccessException e) {
      dieGettingEventTypeName(jMethod, e);
    } catch (InvocationTargetException e) {
      dieGettingEventTypeName(jMethod, e);
    } catch (NoSuchMethodException e) {
      dieGettingEventTypeName(jMethod, e);
    }
    // Unreachable, but appeases the compiler
    return null;
  }

  /**
   * Use this method to format code. It forces the use of the en-US locale, so
   * that things like decimal format don't get mangled.
   */
  private String formatCode(String format, Object... params) {
    String r = String.format(Locale.US, format, params);
    return r;
  }

  /**
   * Inspects this element for a gwt:field attribute. If one is found, the
   * attribute is consumed and its value returned.
   *
   * @return The field name declared by an element, or null if none is declared
   */
  private String getFieldName(XMLElement elem) throws UnableToCompleteException {
    String fieldName = null;
    boolean hasOldSchoolId = false;
    if (elem.hasAttribute("id") && isWidgetElement(elem)) {
      hasOldSchoolId = true;
      // If an id is specified on the element, use that.
      fieldName = elem.consumeRawAttribute("id");
      warn(elem, "Deprecated use of id=\"%1$s\" for field name. "
          + "Please switch to gwt:field=\"%1$s\" instead. " + "This will soon be a compile error!",
          fieldName);
    }
    if (elem.hasAttribute(getUiFieldAttributeName())) {
      if (hasOldSchoolId) {
        die(elem, "Cannot declare both id and field on the same element");
      }
      fieldName = elem.consumeRawAttribute(getUiFieldAttributeName());
    }
    return fieldName;
  }

  private Class<? extends ElementParser> getParserForClass(JClassType uiClass) {
    // Find the associated parser.
    String uiClassName = uiClass.getQualifiedSourceName();
    String parserClassName = elementParsers.get(uiClassName);
    if (parserClassName == null) {
      return null;
    }

    // And instantiate it.
    try {
      return Class.forName(parserClassName).asSubclass(ElementParser.class);
    } catch (ClassNotFoundException e) {
      throw new RuntimeException("Unable to instantiate parser", e);
    } catch (ClassCastException e) {
      throw new RuntimeException(parserClassName + " must extend ElementParser");
    }
  }

  /**
   * Find a set of element parsers for the given ui type.
   *
   * The list of parsers will be returned in order from most- to least-specific.
   */
  private Iterable<ElementParser> getParsersForClass(JClassType type) {
    List<ElementParser> parsers = new ArrayList<ElementParser>();

    /*
     * Let this non-widget parser go first (it finds <m:attribute/> elements).
     * Any other such should land here too.
     *
     * TODO(rjrjr) Need a scheme to associate these with a namespace uri or
     * something?
     */
    parsers.add(new AttributeMessageParser());
    parsers.add(new UiChildParser(uiBinderCtx));

    for (JClassType curType : getClassHierarchyBreadthFirst(type)) {
      try {
        Class<? extends ElementParser> cls = getParserForClass(curType);
        if (cls != null) {
          ElementParser parser = cls.newInstance();
          parsers.add(parser);
        }
      } catch (InstantiationException e) {
        throw new RuntimeException("Unable to instantiate " + curType.getName(), e);
      } catch (IllegalAccessException e) {
        throw new RuntimeException("Unable to instantiate " + curType.getName(), e);
      }
    }

    parsers.add(new BeanParser(uiBinderCtx));
    parsers.add(new IsEmptyParser());

    return parsers;
  }

  /**
   * Writes a field setter if the field is not provided and the field class is
   * compatible with its respective template field.
   */
  private void maybeWriteFieldSetter(IndentedWriter niceWriter, OwnerField ownerField,
      JClassType templateClass, String templateField) throws UnableToCompleteException {
    JClassType fieldType = ownerField.getType().getRawType();

    if (!ownerField.isProvided()) {
      /*
       * Normally check that the type the template created can be slammed into
       * the @UiField annotated field in the owning class
       */
      if (!templateClass.isAssignableTo(fieldType)) {
        die("In @UiField %s, template field and owner field types don't match: %s is not assignable to %s",
            ownerField.getName(), templateClass.getQualifiedSourceName(),
            fieldType.getQualifiedSourceName());
      }
      /*
       * And initialize the field
       */
      niceWriter.write("owner.%1$s = %2$s;", ownerField.getName(), templateField);
    } else {
      /*
       * But with @UiField(provided=true) the user builds it, so reverse the
       * direction of the assignability check and do no init.
       */
      if (!fieldType.isAssignableTo(templateClass)) {
        die("In UiField(provided = true) %s, template field and field types don't match: "
            + "@UiField(provided=true)%s is not assignable to %s", ownerField.getName(),
            fieldType.getQualifiedSourceName(), templateClass.getQualifiedSourceName());
      }
    }
  }

  private String nextToken(XMLElement source, String expression) {
    String nextToken = tokenator.nextToken(source, expression);
    return nextToken;
  }

  private String normalizeFieldName(String fieldName) {
    // If a field name has a '.' in it, replace it with '$' to make it a legal
    // identifier. This can happen with the field names associated with nested
    // classes.
    return fieldName.replace('.', '$');
  }

  /**
   * Parse the document element and return the source of the Java class that
   * will implement its UiBinder.
   */
  private String parseDocumentElement(XMLElement elem) throws UnableToCompleteException {
    fieldManager.registerFieldOfGeneratedType(oracle.findType(ClientBundle.class.getName()),
        bundleClass.getPackageName(), bundleClass.getClassName(), bundleClass.getFieldName());

    // Allow GWT.create() to init the field, the default behavior

    FieldWriter rootField = new UiBinderParser(this, messages, fieldManager, oracle, bundleClass,
            binderUri, uiBinderCtx).parse(elem);

    fieldManager.validate();

    StringWriter stringWriter = new StringWriter();
    IndentedWriter niceWriter = new IndentedWriter(new PrintWriter(stringWriter));

    if (isRenderer) {
      ensureInjectedCssFields();
      writeRenderer(niceWriter, rootField);
    } else if (useLazyWidgetBuilders) {
      ensureInjectedCssFields();
      writeBinderForRenderableStrategy(niceWriter, rootField);
    } else {
      writeBinder(niceWriter, rootField);
    }
    ensureAttachmentCleanedUp();
    return stringWriter.toString();
  }

  private void registerParsers() {
    // TODO(rjrjr): Allow third-party parsers to register themselves
    // automagically

    addElementParser("com.google.gwt.dom.client.Element",
        "com.google.gwt.uibinder.elementparsers.DomElementParser");

    // Register widget parsers.
    addWidgetParser("UIObject");
    addWidgetParser("HasText");
    addWidgetParser("HasHTML");
    addWidgetParser("HasTreeItems");
    addWidgetParser("HasWidgets");
    addWidgetParser("HTMLPanel");
    addWidgetParser("FlowPanel");
    addWidgetParser("AbsolutePanel");
    addWidgetParser("DockPanel");
    addWidgetParser("StackPanel");
    addWidgetParser("DisclosurePanel");
    addWidgetParser("TabPanel");
    addWidgetParser("MenuItem");
    addWidgetParser("MenuBar");
    addWidgetParser("CellPanel");
    addWidgetParser("CustomButton");
    addWidgetParser("DialogBox");
    addWidgetParser("LayoutPanel");
    addWidgetParser("DockLayoutPanel");
    addWidgetParser("StackLayoutPanel");
    addWidgetParser("TabLayoutPanel");
    addWidgetParser("Image");
    addWidgetParser("ListBox");
    addWidgetParser("Grid");
    addWidgetParser("HasAlignment");
    addWidgetParser("DateLabel");
    addWidgetParser("NumberLabel");
    if (useLazyWidgetBuilders) {
      addWidgetParser("LazyPanel");
      addWidgetParser("RenderablePanel");
    }
  }

  /**
   * Validates each {@code eventMethod} (e.g. {@code onBrowserEvent(HandlerType o, NativeEvent e,
   * Element parent, A a, B b, ...)}).
   * <ul>
   * <li> The second parameter type is {@code NativeEvent}
   * <li> The third parameter type is {@code Element}
   * <li> All the handler methods in the type of the first parameter
   *      (any methods annotated with {@code @UiHandler})
   *      have a signature compatible with the {@code eventMethod}
   * </ul>
   */
  private void validateEventMethod(JMethod eventMethod) throws UnableToCompleteException {
    JParameter[] parameters = eventMethod.getParameters();
    if (parameters.length < 3) {
      die("Too few parameters in %s",
          formatMethodError(eventMethod));
    }

    String nativeEventName = NativeEvent.class.getCanonicalName();
    JClassType nativeEventType = oracle.findType(nativeEventName);
    if (!nativeEventType.equals(parameters[1].getType())) {
      die("Second parameter must be of type %s in %s", nativeEventName,
          formatMethodError(eventMethod));
    }

    String elementName = com.google.gwt.dom.client.Element.class.getCanonicalName();
    JClassType elementType = oracle.findType(elementName);
    if (!elementType.equals(parameters[2].getType())) {
      die("Third parameter must be of type %s in %s", elementName,
          formatMethodError(eventMethod));
    }

    if (parameters[0].getType().isClassOrInterface() == null) {
      die("First parameter must be a class or interface in %s",
          formatMethodError(eventMethod));
    }

    JClassType eventReceiver = parameters[0].getType().isClassOrInterface();

    validateEventReceiver(parameters, eventReceiver, eventMethod);
  }

  /**
   * Validates the signature of all methods annotated with {@code @UiHandler}
   * in the {@code eventReceiver} type. All event handlers must have the same signature
   * where:
   * <ul>
   * <li> The annotation must list valid {@code ui:field}s
   * <li> The first parameter must be assignable to
   *      {@link com.google.gwt.event.dom.client.DomEvent DomEvent}
   * <li> If present, the second parameter must be of type
   *      {@link com.google.gwt.dom.client.Element Element}
   * <li> For all other parameters in position {@code n} must be of the same type as
   *      {@code parameters[n + 1]}
   * </ul>
   */
  private void validateEventReceiver(JParameter[] onBrowserEventParameters,
      JClassType eventReceiver, JMethod sourceMethod)
      throws UnableToCompleteException {

    // Pre-compute the expected parameter types (after the first one, that is)
    JType[] onBrowserEventParamTypes = new JType[onBrowserEventParameters.length - 2];

    // If present, second parameter must be an Element
    onBrowserEventParamTypes[0] = oracle.findType(com.google.gwt.dom.client.Element.class
        .getCanonicalName());
    // And the rest must be the same type
    for (int i = 3; i < onBrowserEventParameters.length; i++) {
      onBrowserEventParamTypes[i - 2] = onBrowserEventParameters[i].getType();
    }

    for (JMethod jMethod : eventReceiver.getInheritableMethods()) {
      Class<UiHandler> annotationClass = UiHandler.class;
      UiHandler annotation = jMethod.getAnnotation(annotationClass);
      // Ignore methods not annotated with @UiHandler
      if (annotation == null) {
        continue;
      }
      // Are the fields in @UiHandler known?
      String[] fields = annotation.value();
      if (fields == null) {
        die("@UiHandler returns null from its value in %s",
            formatMethodError(jMethod));
      }
      for (String fieldName : fields) {
        FieldWriter field = fieldManager.lookup(fieldName);
        if (field == null) {
          die("\"%s\" is not a known field name as listed in the @UiHandler annotation in %s",
              fieldName, formatMethodError(jMethod));
        }
      }

      // First parameter
      JParameter[] eventHandlerParameters = jMethod.getParameters();
      JClassType domEventType = oracle.findType(DomEvent.class.getCanonicalName());
      JClassType firstParamType = eventHandlerParameters[0].getType().isClassOrInterface();
      if (firstParamType == null || !firstParamType.isAssignableTo(domEventType)) {
        die("First parameter must be assignable to com.google.gwt.dom.client.DomEvent in %s",
            formatMethodError(jMethod));
      }

      // All others
      if (onBrowserEventParamTypes.length < eventHandlerParameters.length - 1) {
        die("Too many parameters in %s", formatMethodError(jMethod));
      }
      for (int i = 1; i < eventHandlerParameters.length; i++) {
        if (!eventHandlerParameters[i].getType().equals(onBrowserEventParamTypes[i - 1])) {
          die("Parameter %s in %s is not of the same type as parameter %s in %s",
              eventHandlerParameters[i].getName(), formatMethodError(jMethod),
              onBrowserEventParameters[i + 1].getName(),
              formatMethodError(sourceMethod));
        }
      }
    }
  }

  /**
   * Scan the base class for the getter methods. Assumes getters begin with
   * "get" and validates that each corresponds to a field declared with
   * {@code ui:field}. If the getter return type is assignable to
   * {@code Element}, the getter must have a single parameter and the parameter
   * must be assignable to {@code Element}. If the getter return type is assignable
   * to {@code com.google.gwt.resources.client.CssResource}, the getter must
   * have no parameters.
   */
  private void validateRendererGetters(JClassType owner) throws UnableToCompleteException {
    for (JMethod jMethod : owner.getInheritableMethods()) {
      String getterName = jMethod.getName();
      if (getterName.startsWith("get")) {
        String fieldName = getterToFieldName(getterName);
        FieldWriter field = fieldManager.lookup(fieldName);
        if (field == null || (!FieldWriterType.DEFAULT.equals(field.getFieldType())
            && !FieldWriterType.GENERATED_CSS.equals(field.getFieldType()))) {
          die("%s does not match a \"ui:field='%s'\" declaration in %s, "
              + "or '%s' refers to something other than a ui:style"
              + " or an HTML element in the template", getterName, fieldName,
              owner.getQualifiedSourceName(), fieldName);
        }
        if (FieldWriterType.DEFAULT.equals(field.getFieldType())
             && jMethod.getParameterTypes().length != 1) {
          die("Field getter %s must have exactly one parameter in %s", getterName,
              owner.getQualifiedSourceName());
        } else if (FieldWriterType.GENERATED_CSS.equals(field.getFieldType())
            && jMethod.getParameterTypes().length != 0) {
          die("Style getter %s must have no parameters in %s", getterName,
              owner.getQualifiedSourceName());
        } else if (jMethod.getParameterTypes().length == 1) {
          String elementClassName = com.google.gwt.dom.client.Element.class.getCanonicalName();
          JClassType elementType = oracle.findType(elementClassName);
          JClassType getterParamType =
              jMethod.getParameterTypes()[0].getErasedType().isClassOrInterface();

          if (!elementType.isAssignableFrom(getterParamType)) {
            die("Getter %s must have exactly one parameter of type assignable to %s in %s",
                getterName, elementClassName, owner.getQualifiedSourceName());
          }
        }
      } else if (!getterName.equals("render") && !getterName.equals("onBrowserEvent")
          && !getterName.equals("isParentOrRenderer")) {
        die("Unexpected method \"%s\" found in %s", getterName, owner.getQualifiedSourceName());
      }
    }
  }

  /**
   * Scans a class to validate that it contains a single method called render,
   * which has a {@code void} return type, and its first parameter is of type
   * {@code SafeHtmlBuilder}.
   */
  private void validateRenderParameters(JClassType owner) throws UnableToCompleteException {
    JMethod[] methods = owner.getInheritableMethods();
    JMethod renderMethod = null;

    for (JMethod jMethod : methods) {
      if (jMethod.getName().equals("render")) {
        if (renderMethod == null) {
          renderMethod = jMethod;
        } else {
          die("%s declares more than one method named render", owner.getQualifiedSourceName());
        }
      }
    }

    if (renderMethod == null
        || renderMethod.getParameterTypes().length < 1
        || !renderMethod.getParameterTypes()[0].getErasedType().getQualifiedSourceName().equals(
            SafeHtmlBuilder.class.getCanonicalName())) {
      die("%s does not declare a render(SafeHtmlBuilder ...) method",
          owner.getQualifiedSourceName());
    }
    if (!JPrimitiveType.VOID.equals(renderMethod.getReturnType())) {
      die("%s#render(SafeHtmlBuilder ...) does not return void", owner.getQualifiedSourceName());
    }
  }

  /**
   * Write statements that parsers created via calls to {@link #addStatement}.
   * Such statements will assume that {@link #writeGwtFields} has already been
   * called.
   */
  private void writeAddedStatements(IndentedWriter niceWriter) {
    for (String s : statements) {
      niceWriter.write(s);
    }
  }

  /**
   * Writes the UiBinder's source.
   */
  private void writeBinder(IndentedWriter w, FieldWriter rootField) throws UnableToCompleteException {
    writePackage(w);

    writeImports(w);
    w.newline();

    writeClassOpen(w);
    writeStatics(w);
    w.newline();

    // Create SafeHtml Template
    writeTemplatesInterface(w);
    w.newline();

    // createAndBindUi method
    w.write("public %s createAndBindUi(final %s owner) {",
        uiRootType.getParameterizedQualifiedSourceName(),
        uiOwnerType.getParameterizedQualifiedSourceName());
    w.indent();
    w.newline();

    writeGwtFields(w);
    w.newline();

    designTime.writeAttributes(this);
    writeAddedStatements(w);
    w.newline();

    writeInitStatements(w);
    w.newline();

    writeHandlers(w);
    w.newline();

    writeOwnerFieldSetters(w);

    writeCssInjectors(w);

    w.write("return %s;", rootField.getNextReference());
    w.outdent();
    w.write("}");

    // Close class
    w.outdent();
    w.write("}");
  }

  /**
   * Writes a different optimized UiBinder's source for the renderable strategy.
   */
  private void writeBinderForRenderableStrategy(IndentedWriter w, FieldWriter rootField)
      throws UnableToCompleteException {
    writePackage(w);

    writeImports(w);
    w.newline();

    writeClassOpen(w);
    writeStatics(w);
    w.newline();

    writeTemplatesInterface(w);

    w.newline();

    // createAndBindUi method
    w.write("public %s createAndBindUi(final %s owner) {",
        uiRootType.getParameterizedQualifiedSourceName(),
        uiOwnerType.getParameterizedQualifiedSourceName());
    w.indent();
    w.newline();

    designTime.writeAttributes(this);
    w.newline();

    w.write("return new Widgets(owner).%s;", rootField.getNextReference());
    w.outdent();
    w.write("}");

    // Writes the inner class Widgets.
    w.newline();
    w.write("/**");
    w.write(" * Encapsulates the access to all inner widgets");
    w.write(" */");
    w.write("class Widgets {");
    w.indent();

    String ownerClassType = uiOwnerType.getParameterizedQualifiedSourceName();
    w.write("private final %s owner;", ownerClassType);
    w.newline();

    writeHandlers(w);
    w.newline();

    w.write("public Widgets(final %s owner) {", ownerClassType);
    w.indent();
    w.write("this.owner = owner;");
    fieldManager.initializeWidgetsInnerClass(w, getOwnerClass());
    w.outdent();
    w.write("}");
    w.newline();

    htmlTemplates.writeTemplateCallers(w);

    evaluateUiFields();

    fieldManager.writeFieldDefinitions(w, getOracle(), getOwnerClass(), getDesignTime());

    w.outdent();
    w.write("}");

    // Close class
    w.outdent();
    w.write("}");
  }

  private void writeClassOpen(IndentedWriter w) {
    if (!isRenderer) {
      w.write("public class %s implements UiBinder<%s, %s>, %s {", implClassName,
          uiRootType.getParameterizedQualifiedSourceName(),
          uiOwnerType.getParameterizedQualifiedSourceName(),
          baseClass.getParameterizedQualifiedSourceName());
    } else {
      w.write("public class %s extends %s implements %s {", implClassName,
          AbstractUiRenderer.class.getName(),
          baseClass.getParameterizedQualifiedSourceName());
    }
    w.indent();
  }

  private void writeCssInjectors(IndentedWriter w) {
    for (ImplicitCssResource css : bundleClass.getCssMethods()) {
      w.write("%s.%s().ensureInjected();", bundleClass.getFieldName(), css.getName());
    }
    w.newline();
  }

  /**
   * Write declarations for variables or fields to hold elements declared with
   * gwt:field in the template. For those that have not had constructor
   * generation suppressed, emit GWT.create() calls instantiating them (or die
   * if they have no default constructor).
   *
   * @throws UnableToCompleteException on constructor problem
   */
  private void writeGwtFields(IndentedWriter niceWriter) throws UnableToCompleteException {
    // For each provided field in the owner class, initialize from the owner
    Collection<OwnerField> ownerFields = getOwnerClass().getUiFields();
    for (OwnerField ownerField : ownerFields) {
      if (ownerField.isProvided()) {
        String fieldName = ownerField.getName();
        FieldWriter fieldWriter = fieldManager.lookup(fieldName);

        // TODO why can this be null?
        if (fieldWriter != null) {
          String initializer;
          if (designTime.isDesignTime()) {
            String typeName = ownerField.getType().getRawType().getQualifiedSourceName();
            initializer = designTime.getProvidedField(typeName, ownerField.getName());
          } else {
            initializer = formatCode("owner.%1$s", fieldName);
          }
          fieldManager.lookup(fieldName).setInitializer(initializer);
        }
      }
    }

    fieldManager.writeGwtFieldsDeclaration(niceWriter);
  }

  private void writeHandlers(IndentedWriter w) throws UnableToCompleteException {
    if (designTime.isDesignTime()) {
      return;
    }
    handlerEvaluator.run(w, fieldManager, "owner");
  }

  private void writeImports(IndentedWriter w) {
    w.write("import com.google.gwt.core.client.GWT;");
    w.write("import com.google.gwt.dom.client.Element;");
    if (!(htmlTemplates.isEmpty())) {
      w.write("import com.google.gwt.safehtml.client.SafeHtmlTemplates;");
      w.write("import com.google.gwt.safehtml.shared.SafeHtml;");
      w.write("import com.google.gwt.safehtml.shared.SafeHtmlUtils;");
      w.write("import com.google.gwt.safehtml.shared.SafeHtmlBuilder;");
      w.write("import com.google.gwt.safehtml.shared.SafeUri;");
      w.write("import com.google.gwt.safehtml.shared.UriUtils;");
      w.write("import com.google.gwt.uibinder.client.UiBinderUtil;");
    }

    if (!isRenderer) {
      w.write("import com.google.gwt.uibinder.client.UiBinder;");
      w.write("import com.google.gwt.uibinder.client.UiBinderUtil;");
      w.write("import %s.%s;", uiRootType.getPackage().getName(), uiRootType.getName());
    } else {
      w.write("import com.google.gwt.text.shared.AbstractSafeHtmlRenderer;");
    }
  }

  /**
   * Write statements created by {@link #addInitStatement}. This code must be
   * placed after all instantiation code.
   */
  private void writeInitStatements(IndentedWriter niceWriter) {
    for (String s : initStatements) {
      niceWriter.write(s);
    }
  }

  /**
   * Write the statements to fill in the fields of the UI owner.
   */
  private void writeOwnerFieldSetters(IndentedWriter niceWriter) throws UnableToCompleteException {
    if (designTime.isDesignTime()) {
      return;
    }
    for (OwnerField ownerField : getOwnerClass().getUiFields()) {
      String fieldName = ownerField.getName();
      FieldWriter fieldWriter = fieldManager.lookup(fieldName);

      if (fieldWriter != null) {
        // ownerField is a widget.
        JClassType type = fieldWriter.getInstantiableType();
        if (type != null) {
          maybeWriteFieldSetter(niceWriter, ownerField, fieldWriter.getInstantiableType(),
              fieldName);
        } else {
          // Must be a generated type
          if (!ownerField.isProvided()) {
            niceWriter.write("owner.%1$s = %1$s;", fieldName);
          }
        }

      } else {
        // ownerField was not found as bundle resource or widget, must die.
        die("Template %s has no %s attribute for %s.%s#%s", templatePath,
            getUiFieldAttributeName(), uiOwnerType.getPackage().getName(), uiOwnerType.getName(),
            fieldName);
      }
    }
  }

  private void writePackage(IndentedWriter w) {
    String packageName = baseClass.getPackage().getName();
    if (packageName.length() > 0) {
      w.write("package %1$s;", packageName);
      w.newline();
    }
  }

  /**
   * Writes the UiRenderer's source for the renderable strategy.
   */
  private void writeRenderer(IndentedWriter w, FieldWriter rootField) throws UnableToCompleteException {
    validateRendererGetters(baseClass);
    validateRenderParameters(baseClass);
    JMethod[] eventMethods = findEventMethods(baseClass);
    for (JMethod jMethod : eventMethods) {
      validateEventMethod(jMethod);
    }

    writePackage(w);

    writeImports(w);
    w.newline();

    writeClassOpen(w);
    writeStatics(w);
    w.newline();

    // Create SafeHtml Template
    writeTemplatesInterface(w);
    w.newline();
    htmlTemplates.writeTemplateCallers(w);

    w.newline();

    JParameter[] renderParameters = findRenderParameters(baseClass);
    for (JParameter param : renderParameters) {
      // Prevent fields from render() parameters from being optimized.
      fieldManager.disableOptimization(param.getName());
    }

    // public UiRendererImplClass() {
    w.write("public %s() {", implClassName);
    w.indent();
    w.write("build_fields();");
    w.outdent();
    // }
    w.write("}");
    w.newline();

    // private build_fields() {
    w.write("private void build_fields() {");
    w.indent();
    fieldManager.initializeWidgetsInnerClass(w, getOwnerClass());
    w.outdent();
    // }
    w.write("}");
    w.newline();

    String renderParameterDeclarations = renderMethodParameters(renderParameters);
    w.write("public void render(final %s sb%s%s) {", SafeHtmlBuilder.class.getName(),
        renderParameterDeclarations.length() != 0 ? ", " : "", renderParameterDeclarations);
    w.indent();
    w.newline();

    writeRenderParameterInitializers(w, renderParameters);

    w.write("uiId = com.google.gwt.dom.client.Document.get().createUniqueId();");
    w.newline();

    w.write("build_fields();");
    w.newline();

    String safeHtml = rootField.getSafeHtml();

    // TODO(rchandia) it should be possible to add the attribute when parsing
    // the UiBinder file
    w.write(
        "sb.append(stampUiRendererAttribute(%s, RENDERED_ATTRIBUTE, uiId));",
        safeHtml);
    w.outdent();

    w.write("}");
    w.newline();

    fieldManager.writeFieldDefinitions(w, getOracle(), getOwnerClass(), getDesignTime());

    writeRendererGetters(w, baseClass, rootField.getName());

    writeRendererEventMethods(w, eventMethods, rootField.getName());

    // Close class
    w.outdent();
    w.write("}");
  }

  private void writeRendererDispatcher(IndentedWriter w, String dispatcherName,
      JClassType targetType, String rootFieldName, JMethod[] uiHandlerMethods, JMethod sourceMethod)
      throws UnableToCompleteException {

    // static class UiRendererDispatcherForFoo extends UiRendererDispatcher<Foo> {
    w.write("static class %s extends UiRendererDispatcher<%s> {", dispatcherName,
        targetType.getQualifiedSourceName());
    w.indent();

    writeRendererDispatcherTableInit(w, rootFieldName, uiHandlerMethods,
        dispatcherName);

    writeRendererDispatcherExtraParameters(w, sourceMethod);

    writeRendererDispatcherFire(w, sourceMethod);

    w.write("@SuppressWarnings(\"rawtypes\")");
    w.write("@Override");
    // public void fireEvent(GwtEvent<?> somethingUnlikelyToCollideWithParamNames) {
    w.write("public void fireEvent(com.google.gwt.event.shared.GwtEvent<?> %sEvent) {",
        SAFE_VAR_PREFIX);
    w.indent();
    //   switch (getMethodIndex()) {
    w.write("switch (getMethodIndex()) {");
    w.indent();
    for (int j = 0; j < uiHandlerMethods.length; j++) {
      JMethod uiMethod = uiHandlerMethods[j];

      // case 0:
      w.write("case %s:", j);
      w.indent();

      //   getEventTarget().onClickRoot((ClickEvent) somethingUnlikelyToCollideWithParamNames,
      //       getRoot(), a, b);
      StringBuffer sb = new StringBuffer();
      JParameter[] sourceParameters = sourceMethod.getParameters();
      // Cat the extra parameters i.e. ", a, b"
      JType[] uiHandlerParameterTypes = uiMethod.getParameterTypes();
      if (uiHandlerParameterTypes.length >= 2) {
        sb.append(", getRoot()");
      }
      for (int k = 2; k < uiHandlerParameterTypes.length; k++) {
        JParameter sourceParam = sourceParameters[k + 1];
        sb.append(", ");
        sb.append(sourceParam.getName());
      }
      w.write("getEventTarget().%s((%s) %sEvent%s);", uiMethod.getName(),
          uiHandlerParameterTypes[0].getQualifiedSourceName(), SAFE_VAR_PREFIX,
          sb.toString());
      //   break;
      w.write("break;");
      w.newline();
      w.outdent();
    }
    //    default:
    w.write("default:");
    w.indent();
    //      break;
    w.write("break;");
    w.outdent();
    w.outdent();
    w.write("}");

    w.outdent();
    w.write("}");

    w.outdent();
    w.write("}");
  }

  private void writeRendererDispatcherExtraParameters(IndentedWriter w, JMethod sourceMethod) {
    for (int i = 3; i < sourceMethod.getParameters().length; i++) {
      JParameter param = sourceMethod.getParameters()[i];

      // private int a;
      // private String b;
      w.write("private %s %s;", param.getType().getParameterizedQualifiedSourceName(),
          param.getName());
    }
  }

  private void writeRendererDispatcherFire(IndentedWriter w, JMethod sourceMethod) {
    // public void fire(Foo o, NativeEvent e, Element parent, int a, String b) {
    w.write("public void fire(");
    w.indent();
    JParameter[] sourceParameters = sourceMethod.getParameters();
    for (int i = 0; i < sourceParameters.length; i++) {
      JParameter param = sourceParameters[i];
      w.write(i == 0 ? "%s %s" : ", %s %s", param.getType().getQualifiedSourceName(), param.getName());
    }
    w.write(") {");
    w.indent();

    // this.a = a;
    for (int i = 3; i < sourceParameters.length; i++) {
      JParameter sourceParam = sourceParameters[i];
      w.write("this.%s = %s;", sourceParam.getName(), sourceParam.getName());
    }

    // fireEvent(o, e, parent);
    w.write("fireEvent(%s, %s, %s);", sourceParameters[0].getName(), sourceParameters[1].getName(),
        sourceParameters[2].getName());

    w.outdent();
    w.write("}");
    w.newline();
  }

  private void writeRendererDispatcherTableInit(IndentedWriter w,
      String rootFieldName, JMethod[] uiHandlerMethods, String dispatcherName)
      throws UnableToCompleteException {
    ArrayList<String> keys = new ArrayList<String>();
    ArrayList<Integer> values = new ArrayList<Integer>();

    // Collect the event types and field names to form the dispatch table
    for (int i = 0; i < uiHandlerMethods.length; i++) {
      JMethod jMethod = uiHandlerMethods[i];
      String eventType = findEventTypeName(jMethod);
      String[] fieldNames = jMethod.getAnnotation(UiHandler.class).value();
      for (String fieldName : fieldNames) {
        if (rootFieldName.equals(fieldName)) {
          fieldName = AbstractUiRenderer.ROOT_FAKE_NAME;
        }
        keys.add(eventType + AbstractUiRenderer.UI_ID_SEPARATOR + fieldName);
        values.add(i);
      }
    }

    // private static String[] somethingUnlikelyToCollideWithParamNames_keys;
    w.write("private static String[] %s_keys;", SAFE_VAR_PREFIX);
    // private static Integer[] somethingUnlikelyToCollideWithParamNames_values;
    w.write("private static Integer[] %s_values;", SAFE_VAR_PREFIX);

    w.write("static {");
    w.indent();
    // private static String[] somethingUnlikelyToCollideWithParamNames_keys = new String[] {
    w.write("%s_keys = new String[] {", SAFE_VAR_PREFIX);
    w.indent();
    for (String key : keys) {
      // "click:aField",
      w.write("\"%s\",", key);
    }
    w.outdent();
    w.write("};");
    w.newline();

    // somethingUnlikelyToCollideWithParamNames_values = {0,1};
    w.write("%s_values = new Integer[] {", SAFE_VAR_PREFIX);
    w.indent();
    StringBuffer commaSeparatedValues = new StringBuffer();
    for (Integer value : values) {
      commaSeparatedValues.append(value);
      commaSeparatedValues.append(",");
    }
    // "0,0,0,1,1,",
    w.write("%s", commaSeparatedValues.toString());
    w.outdent();
    w.write("};");
    w.newline();

    w.outdent();
    w.write("}");
    w.newline();

    // public Foo() {
    w.write("public %s() {", dispatcherName);
    w.indent();
    // initDispatchTable(keys, values);
    w.write("initDispatchTable(%s_keys, %s_values);", SAFE_VAR_PREFIX, SAFE_VAR_PREFIX);

    // This ensures the DomEvent#TYPE fields are properly initialized and registered
    // ClickEvent.getType();
    HashSet<String> eventTypes = new HashSet<String>();
    for (JMethod uiMethod : uiHandlerMethods) {
      eventTypes.add(uiMethod.getParameterTypes()[0].getQualifiedSourceName());
    }
    for (String eventType : eventTypes) {
      w.write("%s.getType();", eventType);
    }


    w.outdent();
    w.write("}");
    w.newline();
  }

  private void writeRendererEventMethods(IndentedWriter w, JMethod[] eventMethods,
      String rootField) throws UnableToCompleteException {
    for (JMethod jMethod : eventMethods) {
      JClassType eventTargetType = jMethod.getParameterTypes()[0].isClassOrInterface();
      String eventTargetSimpleName = eventTargetType.getSimpleSourceName();
      String dispatcherClassName = UI_RENDERER_DISPATCHER_PREFIX + eventTargetSimpleName;
      JMethod[] uiHandlerMethods = findUiHandlerMethods(eventTargetType);

      // public void onBrowserEvent(Foo f, NativeEvent event, Element parent, A a, B b ...) {
      w.write("@Override");
      w.write("public %s {", jMethod.getReadableDeclaration(true, true, true, true, true));

      if (uiHandlerMethods.length != 0) {
        w.indent();
        //  if (singletonUiRendererDispatcherForFoo == null) {
        w.write("if (singleton%s == null) {", dispatcherClassName);
        w.indent();
        // singletonUiRendererDispatcherForFoo = new UiRendererDispatcherForFoo();
        w.write("singleton%s = new %s();", dispatcherClassName, dispatcherClassName);

        w.outdent();
        w.write("}");

        // singletonUiRendererDispatcherForFoo.fire(o, event, parent, a, b);
        StringBuffer sb = new StringBuffer();
        JParameter[] parameters = jMethod.getParameters();
        for (int i = 0; i < parameters.length; i++) {
          JParameter callParam = parameters[i];
          if (i != 0) {
            sb.append(", ");
          }
          sb.append(callParam.getName());
        }
        w.write("singleton%s.fire(%s);", dispatcherClassName, sb.toString());
        w.outdent();
      }

      w.write("}");
      w.newline();

      if (uiHandlerMethods.length != 0) {
        // private static UiRendererDispatcherForFoo singletonUiRendererDispatcherForFoo;
        w.write("private static %s singleton%s;", dispatcherClassName, dispatcherClassName);

        writeRendererDispatcher(w, dispatcherClassName, eventTargetType, rootField, uiHandlerMethods,
            jMethod);
      }
    }
  }

  private void writeRendererGetters(IndentedWriter w, JClassType owner, String rootFieldName) {
    List<JMethod> getters = findGetterNames(owner);

    // For every requested getter
    for (JMethod getter : getters) {
      // public ElementSubclass getFoo(Element parent) {
      w.write("%s {", getter.getReadableDeclaration(false, false, false, false, true));
      w.indent();
      String getterFieldName = getterToFieldName(getter.getName());
      // Is this a CSS resource field?
      FieldWriter fieldWriter = fieldManager.lookup(getterFieldName);
      if (FieldWriterType.GENERATED_CSS.equals(fieldWriter.getFieldType())) {
        // return (CssResourceSubclass) get_styleField;
        w.write("return (%s) %s;", getter.getReturnType().getErasedType().getQualifiedSourceName(),
                FieldManager.getFieldGetter(getterFieldName));
      } else {
        // Else the non-root elements are found by id
        String elementParameter = getter.getParameters()[0].getName();
        if (!getterFieldName.equals(rootFieldName)) {
          // return (ElementSubclass) findInnerField(parent, "foo", RENDERED_ATTRIBUTE);
          w.write("return (%s) findInnerField(%s, \"%s\", RENDERED_ATTRIBUTE);",
              getter.getReturnType().getErasedType().getQualifiedSourceName(), elementParameter,
              getterFieldName);
        } else {
          // return (ElementSubclass) findRootElement(parent);
          w.write("return (%s) findRootElement(%s, RENDERED_ATTRIBUTE);",
              getter.getReturnType().getErasedType().getQualifiedSourceName(), elementParameter);
        }
      }
      w.outdent();
      w.write("}");
    }
  }

  private void writeRenderParameterInitializers(IndentedWriter w, JParameter[] renderParameters) {
    for (int i = 0; i < renderParameters.length; i++) {
      JParameter parameter = renderParameters[i];
      if (fieldManager.lookup(parameter.getName()) != null) {
        w.write("this.%s = %s;", parameter.getName(), parameter.getName());
        w.newline();
      }
    }
  }

  private void writeStaticMessagesInstance(IndentedWriter niceWriter) {
    if (messages.hasMessages()) {
      niceWriter.write(messages.getDeclaration());
    }
  }

  private void writeStatics(IndentedWriter w) {
    writeStaticMessagesInstance(w);
    designTime.addDeclarations(w);
  }

  /**
   * Write statements created by {@link HtmlTemplatesWriter#addSafeHtmlTemplate}
   * . This code must be placed after all instantiation code.
   */
  private void writeTemplatesInterface(IndentedWriter w) {
    if (!(htmlTemplates.isEmpty())) {
      assert useSafeHtmlTemplates : "SafeHtml is off, but templates were made.";
      htmlTemplates.writeInterface(w);
      w.newline();
    }
  }
}
