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

import com.google.gwt.codegen.server.StringGenerator;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.impl.ResourceLocatorImpl;
import com.google.gwt.core.ext.typeinfo.JArrayType;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JEnumConstant;
import com.google.gwt.core.ext.typeinfo.JEnumType;
import com.google.gwt.core.ext.typeinfo.JField;
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.TypeOracle;
import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
import com.google.gwt.i18n.client.Messages.AlternateMessage;
import com.google.gwt.i18n.client.Messages.Offset;
import com.google.gwt.i18n.client.Messages.Optional;
import com.google.gwt.i18n.client.Messages.PluralCount;
import com.google.gwt.i18n.client.Messages.PluralText;
import com.google.gwt.i18n.client.Messages.Select;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.i18n.client.PluralRule;
import com.google.gwt.i18n.client.PluralRule.PluralForm;
import com.google.gwt.i18n.client.impl.plurals.DefaultRule;
import com.google.gwt.i18n.rebind.AbstractResource.MissingResourceException;
import com.google.gwt.i18n.rebind.AbstractResource.ResourceEntry;
import com.google.gwt.i18n.rebind.AbstractResource.ResourceList;
import com.google.gwt.i18n.rebind.MessageFormatParser.ArgumentChunk;
import com.google.gwt.i18n.rebind.MessageFormatParser.DefaultTemplateChunkVisitor;
import com.google.gwt.i18n.rebind.MessageFormatParser.StaticArgChunk;
import com.google.gwt.i18n.rebind.MessageFormatParser.StringChunk;
import com.google.gwt.i18n.rebind.MessageFormatParser.TemplateChunk;
import com.google.gwt.i18n.shared.AlternateMessageSelector;
import com.google.gwt.i18n.shared.GwtLocale;
import com.google.gwt.safehtml.shared.OnlyToBeUsedInGeneratedCodeStringBlessedAsSafeHtml;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.rebind.AbstractGeneratorClassCreator;
import com.google.gwt.user.rebind.AbstractMethodCreator;
import com.google.gwt.user.rebind.SourceWriter;

import org.apache.tapestry.util.text.LocalizedPropertiesLoader;

import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Creator for methods of the Messages interface.
 */
@SuppressWarnings("deprecation") // for @PluralText
class MessagesMethodCreator extends AbstractMethodCreator {

  private abstract static class AlternateFormSelector {
    protected final int argNumber;
    protected final JType argType;

    public AlternateFormSelector(TreeLogger logger, int argNumber, JParameter[] params) {
      this.argNumber = argNumber;
      this.argType = params[argNumber].getType();
    }

    public abstract void generatePrepCode(SourceWriter out);

    public abstract void generateSelectEnd(SourceWriter out);

    public abstract void generateSelectMatchEnd(SourceWriter out, String value);

    /**
     * @param out
     * @param logger
     * @param value
     * @throws UnableToCompleteException
     */
    public abstract void generateSelectMatchStart(SourceWriter out,
        TreeLogger logger, String value) throws UnableToCompleteException;

    public abstract void generateSelectStart(SourceWriter out,
        boolean exactMatches);

    public abstract void issueWarnings(TreeLogger logger, JMethod m,
        GwtLocale locale);
  }

  /**
   * Implements {x,date...} references in MessageFormat.
   */
  private static class DateFormatter implements ValueFormatter {
    public boolean format(TreeLogger logger, GwtLocale locale,
        StringGenerator out, Map<String, String> formatArgs, String subformat,
        String argName, JType argType, Parameters params) {
      if (!"java.util.Date".equals(argType.getQualifiedSourceName())) {
        logger.log(TreeLogger.ERROR, "Only java.util.Date acceptable for date format");
        return true;
      }
      String tzParam = "";
      String tzArg = formatArgs.get("tz");
      if (tzArg != null) {
        if (tzArg.startsWith("$")) {
          int paramNum = params.getParameterIndex(tzArg.substring(1));
          if (paramNum < 0) {
            logger.log(TreeLogger.ERROR, "Unable to resolve tz argument " + tzArg);
            return true;
          } else if (!"com.google.gwt.i18n.client.TimeZone".equals(
              params.getParameter(paramNum).getType().getQualifiedSourceName())) {
            logger.log(TreeLogger.ERROR, "Currency code parameter must be TimeZone");
            return true;
          } else {
            tzParam = ", arg" + paramNum;
          }
        } else {
          tzParam = ", com.google.gwt.i18n.client.TimeZone.createTimeZone(" + tzArg + ")";
        }
      }
      if (subformat == null || "medium".equals(subformat)) {
        out.appendStringValuedExpression(
            dtFormatClassName + ".getMediumDateFormat()" + ".format(" + argName + tzParam + ")");
      } else if ("full".equals(subformat)) {
        out.appendStringValuedExpression(
            dtFormatClassName + ".getFullDateFormat().format(" + argName + tzParam + ")");
      } else if ("long".equals(subformat)) {
        out.appendStringValuedExpression(
            dtFormatClassName + ".getLongDateFormat().format(" + argName + tzParam + ")");
      } else if ("short".equals(subformat)) {
        out.appendStringValuedExpression(
            dtFormatClassName + ".getShortDateFormat()" + ".format(" + argName + tzParam + ")");
      } else {
        logger.log(TreeLogger.WARN, "Use localdatetime format instead");
        out.appendStringValuedExpression(
            dtFormatClassName + ".getFormat(" + wrap(subformat) + ").format(" + argName + tzParam
                + ")");
      }
      return false;
    }
  }

  /**
   * Comparator that ensures all exact value matches (=N) strings come before
   * all non-exact matches.
   */
  private static class ExactValueComparator implements Comparator<String> {

    private static int compareOne(String a, String b) {
      boolean aExact = a.startsWith("=");
      boolean bExact = a.startsWith("=");
      if (aExact != bExact) {
        return aExact ? -1 : 1;
      }
      if (aExact) {
        return a.substring(1).compareTo(b.substring(1));
      } else {
        return a.compareTo(b);
      }
    }

    public int compare(String a, String b) {
      String[] aSplit = a.split("\\|");
      String[] bSplit = b.split("\\|");
      int c = 0;
      for (int i = 0; c == 0 && i < aSplit.length && i < bSplit.length; ++i) {
        c = compareOne(aSplit[i], bSplit[i]);
      }
      if (c == 0 && aSplit.length != bSplit.length) {
        c = aSplit.length < bSplit.length ? -1 : 1;
      }
      return c;
    }
  }

  /**
   * An {@link AlternateFormSelector} used with {@link Select}.
   */
  private static class GenericSelector extends AlternateFormSelector {

    private final JEnumType enumType;
    private final boolean isBoolean;
    private final boolean isString;
    private final boolean needsIf;
    private boolean startedIfChain;

    /**
     * @param logger
     * @param m
     * @param i
     * @param params
     * @throws UnableToCompleteException
     */
    public GenericSelector(TreeLogger logger, JMethod m, int i,
        JParameter[] params) throws UnableToCompleteException {
      super(logger, i, params);
      JPrimitiveType primType = argType.isPrimitive();
      JClassType classType = argType.isClass();
      JEnumType tempEnumType = null;
      boolean tempIsBoolean = false;
      boolean tempIsString = false;
      boolean tempNeedsIf = false;
      if (primType != null) {
        if (primType == JPrimitiveType.DOUBLE
            || primType == JPrimitiveType.FLOAT) {
          throw error(logger, m.getName() + ": @Select arguments may only be"
              + " integral primitives, boolean, enums, or String");
        }
        tempIsBoolean = (primType == JPrimitiveType.BOOLEAN);
        tempNeedsIf = tempIsBoolean || (primType == JPrimitiveType.LONG);
      } else if (classType != null) {
        tempEnumType = classType.isEnum();
        tempIsString = "java.lang.String".equals(classType.getQualifiedSourceName());
        if (tempEnumType == null && !tempIsString) {
          throw error(logger, m.getName() + ": @Select arguments may only be"
              + " integral primitives, boolean, enums, or String");
        }
      } else {
        throw error(logger, m.getName() + ": @Select arguments may only be"
            + " integral primitives, boolean, enums, or String");
      }
      tempNeedsIf |= tempIsString;
      enumType = tempEnumType;
      isBoolean = tempIsBoolean;
      isString = tempIsString;
      needsIf = tempNeedsIf;
    }

    @Override
    public void generatePrepCode(SourceWriter out) {
      if (enumType != null) {
        out.println("int arg" + argNumber + "_ordinal = -1;");
        out.println("if (arg" + argNumber + " != null) {");
        out.indent();
        out.println("arg" + argNumber + "_ordinal = arg" + argNumber
            + ".ordinal();");
        out.outdent();
        out.println("}");
      }
    }

    @Override
    public void generateSelectEnd(SourceWriter out) {
      if (!startedIfChain) {
        out.outdent();
      }
      out.println("}");
    }

    @Override
    public void generateSelectMatchEnd(SourceWriter out, String value) {
      if (!startedIfChain) {
        out.println("break;");
      }
      out.outdent();
    }

    @Override
    public void generateSelectMatchStart(SourceWriter out, TreeLogger logger,
        String value) throws UnableToCompleteException {
      if (needsIf) {
        if (startedIfChain) {
          out.print("} else ");
        } else {
          startedIfChain = true;
        }
        if (AlternateMessageSelector.OTHER_FORM_NAME.equals(value)) {
          out.println("{  // other");
        } else {
          if (isString) {
            value = value.replace("\"", "\\\"");
            out.println("if (\"" + value + "\".equals(arg" + argNumber + ")) {");
          } else if (isBoolean) {
            boolean isTrue = Boolean.parseBoolean(value);
            out.println("if (" + (isTrue ? "" : "!") + "arg" + argNumber + ") {");
          } else {
            long longVal;
            try {
              longVal = Long.parseLong(value);
            } catch (NumberFormatException e) {
              throw error(logger, "'" + value + "' is not a valid long value",
                  e);
            }
            out.println("if (" + longVal + " == arg" + argNumber + ") {");
          }
        }
      } else {
        if (AlternateMessageSelector.OTHER_FORM_NAME.equals(value)) {
          out.println("default:  // other");
        } else if (enumType != null) {
          JField field = enumType.findField(value);
          JEnumConstant enumConstant = null;
          if (field != null) {
            enumConstant = field.isEnumConstant();
          }
          if (field == null || enumConstant == null) {
            throw error(logger, "'" + value + "' is not a valid value of "
                + enumType.getQualifiedSourceName() + " or 'other'");
          }
          out.println("case " + enumConstant.getOrdinal() + ":  // " + value);
        } else {
          int intVal;
          try {
            intVal = Integer.parseInt(value);
          } catch (NumberFormatException e) {
            throw error(logger, "'" + value + "' is not a valid integral value",
                e);
          }
          out.println("case " + intVal + ":");
        }
      }
      out.indent();
    }

    @Override
    public void generateSelectStart(SourceWriter out, boolean exactMatches) {
      // ignore exactMatches, so "=VALUE" is the same as "VALUE"
      if (needsIf) {
        startedIfChain = false;
        return;
      }
      String suffix = "";
      if (enumType != null) {
        suffix = "_ordinal";
      }
      out.println("switch (arg" + argNumber + suffix + ") {");
      out.indent();
    }

    @Override
    public void issueWarnings(TreeLogger logger, JMethod m, GwtLocale locale) {
      // nothing to warn about
    }
  }

  /**
   * Interface used to abstract away differences between accessing an array and
   * a list.
   */
  private interface ListAccessor {

    String getElement(String element);

    String getSize();
  }

  /**
   * Implementation of ListAccessor for an array.
   */
  private static class ListAccessorArray implements ListAccessor {

    private final int listArgNum;

    public ListAccessorArray(int listArgNum) {
      this.listArgNum = listArgNum;
    }

    public String getElement(String element) {
      return "arg" + listArgNum + "[" + element + "]";
    }

    public String getSize() {
      return "arg" + listArgNum + ".length";
    }
  }

  /**
   * Implementation of ListAccessor for a List.
   */
  private static class ListAccessorList implements ListAccessor {

    private final int listArgNum;

    public ListAccessorList(int listArgNum) {
      this.listArgNum = listArgNum;
    }

    public String getElement(String element) {
      return "arg" + listArgNum + ".get(" + element + ")";
    }

    public String getSize() {
      return "arg" + listArgNum + ".size()";
    }
  }

  /**
   * Implements {x,localdatetime,skeleton} references in MessageFormat.
   */
  private static class LocalDateTimeFormatter implements ValueFormatter {
    private static final String PREDEF = "predef:";

    public boolean format(TreeLogger logger,
        GwtLocale locale,
        StringGenerator out,
        Map<String, String> formatArgs,
        String subformat,
        String argName,
        JType argType,
        Parameters params) {
      if (!"java.util.Date".equals(argType.getQualifiedSourceName())) {
        logger.log(TreeLogger.ERROR, "Only java.util.Date acceptable for localdatetime format");
        return true;
      }
      if (subformat == null || subformat.length() == 0) {
        logger.log(TreeLogger.ERROR, "localdatetime format requires a skeleton pattern");
        return true;
      }
      String tzParam = "";
      String tzArg = formatArgs.get("tz");
      if (tzArg != null) {
        if (tzArg.startsWith("$")) {
          int paramNum = params.getParameterIndex(tzArg.substring(1));
          if (paramNum < 0) {
            logger.log(TreeLogger.ERROR, "Unable to resolve tz argument " + tzArg);
            return true;
          } else if (!"com.google.gwt.i18n.client.TimeZone".equals(
              params.getParameter(paramNum).getType().getQualifiedSourceName())) {
            logger.log(TreeLogger.ERROR, "tz parameter must be of type TimeZone");
            return true;
          } else {
            tzParam = ", arg" + paramNum;
          }
        } else {
          tzParam = ", com.google.gwt.i18n.client.TimeZone.createTimeZone(" + tzArg + ")";
        }
      }
      if (subformat.startsWith(PREDEF)) {
        // TODO(jat): error checking/logging
        PredefinedFormat predef;
        try {
          predef = PredefinedFormat.valueOf(subformat.substring(PREDEF.length()));
        } catch (IllegalArgumentException e) {
          logger.log(TreeLogger.ERROR, "Unrecognized predefined format '" + subformat + "'");
          return true;
        }
        out.appendStringValuedExpression(
            dtFormatClassName + ".getFormat("
                + PredefinedFormat.class.getCanonicalName() + "."
                + predef.toString() + ").format(" + argName + tzParam + ")");
        return false;
      }
      DateTimePatternGenerator dtpg = new DateTimePatternGenerator(locale);
      try {
        String pattern = dtpg.getBestPattern(subformat);
        if (pattern == null) {
          logger.log(
              TreeLogger.ERROR, "Invalid localdatetime skeleton pattern \"" + subformat + "\"");
          return true;
        }
        out.appendStringValuedExpression(
            dtFormatClassName + ".getFormat(" + wrap(pattern) + ").format(" + argName + tzParam
                + ")");
      } catch (IllegalArgumentException e) {
        logger.log(TreeLogger.ERROR, "Unable to parse '" + subformat + ": " + e.getMessage());
        return true;
      }
      return false;
    }
  }

  /**
   * Implements {x,number...} references in MessageFormat.
   */
  private static class NumberFormatter implements ValueFormatter {

    public boolean format(TreeLogger logger,
        GwtLocale locale,
        StringGenerator out,
        Map<String, String> formatArgs,
        String subformat,
        String argName,
        JType argType,
        Parameters params) {
      JPrimitiveType argPrimType = argType.isPrimitive();
      if (argPrimType != null) {
        if (argPrimType == JPrimitiveType.BOOLEAN || argPrimType == JPrimitiveType.VOID) {
          logger.log(TreeLogger.ERROR, "Illegal argument type for number format");
          return true;
        }
      } else {
        JClassType classType = argType.isClass();
        if (classType == null) {
          logger.log(TreeLogger.ERROR, "Unexpected argument type for number format");
          return true;
        }
        TypeOracle oracle = classType.getOracle();
        JClassType numberType = oracle.findType("java.lang.Number");
        if (!classType.isAssignableTo(numberType)) {
          logger.log(TreeLogger.ERROR, "Only Number subclasses may be formatted as a number");
          return true;
        }
      }
      String curCodeParam = "";
      String curCode = formatArgs.get("curcode");
      if (curCode != null) {
        if (curCode.startsWith("$")) {
          int paramNum = params.getParameterIndex(curCode.substring(1));
          if (paramNum < 0) {
            logger.log(TreeLogger.ERROR, "Unable to resolve curcode argument " + curCode);
            return true;
          } else if (!"java.lang.String".equals(
              params.getParameter(paramNum).getType().getQualifiedSourceName())) {
            logger.log(TreeLogger.ERROR, "Currency code parameter must be String");
            return true;
          } else {
            curCodeParam = "arg" + paramNum;
          }
        } else {
          curCodeParam = '"' + curCode + '"';
        }
      }
      if (subformat == null) {
        out.appendStringValuedExpression(
            numFormatClassName + ".getDecimalFormat().format(" + argName + ")");
      } else if ("integer".equals(subformat)) {
        out.appendStringValuedExpression(
            numFormatClassName + ".getDecimalFormat().overrideFractionDigits(0).format(" + argName + ")");
      } else if ("currency".equals(subformat)) {
        out.appendStringValuedExpression(
            numFormatClassName + ".getCurrencyFormat(" + curCodeParam + ").format(" + argName
                + ")");
      } else if ("percent".equals(subformat)) {
        out.appendStringValuedExpression(
            numFormatClassName + ".getPercentFormat().format(" + argName + ")");
      } else {
        if (curCodeParam.length() > 0) {
          curCodeParam = ", " + curCodeParam;
        }
        out.appendStringValuedExpression(
            numFormatClassName + ".getFormat(" + wrap(subformat) + curCodeParam + ").format("
                + argName + ")");
      }
      return false;
    }
  }

  /**
   * An interface for accessing parameters, giving the ability to record
   * accesses.
   */
  private interface Parameters {

    /**
     * Allow generated code to take advantage of plural offsets (see
     * {@link Offset}).
     */
    void enablePluralOffsets();

    /**
     * Return the count of parameters.
     * @return the count of parameters
     */
    int getCount();

    /**
     * Returns the given parameter.
     *
     * @param i index of the parameter to return, 0 .. getCount() - 1
     * @return parameter or null if i is out of range
     */
    JParameter getParameter(int i);

    /**
     * Returns the given parameter.
     *
     * @param name the name of the parameter to return
     * @return parameter or null if the named parameter doesn't exist
     */
    JParameter getParameter(String name);

    /**
     * Return an expression to get the value of the requested parameter.  Note
     * that for arrays or lists this will return an expression giving the count
     * of items in the array or list.
     *
     * @param i index of the parameter, 0 .. getCount() - 1
     * @return the source of code to access the parameter value
     */
    String getParameterExpression(int i);

    /**
     * Find the index of a parameter by name.
     *
     * @param name
     * @return index of requested parameter or -1 if not found
     */
    int getParameterIndex(String name);
  }

  private static class ParametersImpl implements Parameters {

    private JParameter[] params;
    private boolean[] seenFlag;
    private int[] offset;
    private boolean[] isList;
    private boolean[] isArray;
    private boolean enablePluralOffsets;

    public ParametersImpl(JParameter[] params, boolean[] seenFlag) {
      this.params = params;
      this.seenFlag = seenFlag;
      int n = params.length;
      offset = new int[n];
      isList = new boolean[n];
      isArray = new boolean[n];
      for (int i = 0; i < n; ++i) {
        Offset offsetAnnot = params[i].getAnnotation(Offset.class);
        if (offsetAnnot != null) {
          offset[i] = offsetAnnot.value();
        }
        JType type = params[i].getType();
        if (type.isArray() != null) {
          isArray[i] = true;
        } else if (type.isInterface() != null) {
          JClassType rawType = type.isInterface().getErasedType();
          if ("java.util.List".equals(rawType.getQualifiedSourceName())) {
            isList[i] = true;
          }
        }
      }
    }

    public void enablePluralOffsets() {
      enablePluralOffsets = true;
    }

    public int getCount() {
      return params.length;
    }

    public JParameter getParameter(int i) {
      if (i < 0 || i >= params.length) {
        return null;
      }
      seenFlag[i] = true;
      return params[i];
    }

    public JParameter getParameter(String name) {
      return getParameter(getParameterIndex(name));
    }

    public String getParameterExpression(int i) {
      if (i < 0 || i >= params.length) {
        return null;
      }
      String argName = "arg" + i;
      seenFlag[i] = true;
      if (enablePluralOffsets && offset[i] != 0) {
        return argName + "_count";
      }
      if (isArray[i]) {
        return argName + ".length";
      }
      if (isList[i]) {
        return argName + ".size()";
      }
      return argName;
    }

    public int getParameterIndex(String name) {
      for (int i = 0; i < params.length; ++i) {
        if (params[i].getName().equals(name)) {
          return i;
        }
      }
      return -1;
    }
  }

  /**
   * An {@link AlternateFormSelector} used with {@link PluralCount}.
   */
  private static class PluralFormSelector extends AlternateFormSelector {
    protected final String countSuffix;
    protected final String listSuffix;
    protected final Set<String> missingPluralForms;
    protected final int pluralOffset;
    protected final PluralRule pluralRule;
    private boolean hasExactMatches;
    private boolean inExactMatches;

    // used to generate unique case values for bogus plural forms
    private int bogusCaseValue = 1000;

    public PluralFormSelector(TreeLogger logger, JMethod method, int argNumber,
        JParameter[] params, GwtLocale locale)
        throws UnableToCompleteException {
      super(logger, argNumber, params);
      PluralCount pluralCount = params[argNumber].getAnnotation(
          PluralCount.class);
      Class<? extends PluralRule> ruleClass = pluralCount.value();
      if (ruleClass == PluralRule.class) {
        ruleClass = DefaultRule.class;
      }
      pluralRule = createLocalizedPluralRule(logger,
          method.getEnclosingType().getOracle(), ruleClass, locale);
      missingPluralForms = new HashSet<String>();
      for (PluralForm form : pluralRule.pluralForms()) {
        if (form.getWarnIfMissing() && !AlternateMessageSelector.OTHER_FORM_NAME.equals(form.getName())) {
          missingPluralForms.add(form.getName());
        }
      }

      Offset offsetAnnot = params[argNumber].getAnnotation(Offset.class);
      int offset = 0;
      if (offsetAnnot != null) {
        offset = offsetAnnot.value();
      }
      this.pluralOffset = offset;
      boolean isArray = false;
      boolean isList = false;
      JPrimitiveType primType = argType.isPrimitive();
      JClassType classType = argType.isInterface();
      if (classType != null) {
        classType = classType.getErasedType();
        if ("java.util.List".equals(classType.getQualifiedSourceName())) {
          isList = true;
        } else {
          classType = null;
        }
      }

      JArrayType arrayType = argType.isArray();
      if (arrayType != null) {
        isArray = true;
      }
      if (!isList && !isArray && (primType == null
          || (primType != JPrimitiveType.INT
              && primType != JPrimitiveType.SHORT))) {
        throw error(logger, method.getName()
            + ": PluralCount parameter must be int, short, array, or List");
      }
      String tempListSuffix = "";
      if (isList) {
        tempListSuffix = ".size()";
      } else if (isArray) {
        tempListSuffix = ".length";
      }
      String tempCountSuffix = tempListSuffix;
      if (isList || isArray || offset != 0) {
        tempCountSuffix = "_count";
      }
      listSuffix = tempListSuffix;
      countSuffix = tempCountSuffix;
    }

    @Override
    public void generatePrepCode(SourceWriter out) {
      // save a value with the count value, applying an offset if present
      if (countSuffix.length() > 0) {
        out.print("int arg" + argNumber + countSuffix + " = arg" + argNumber
            + listSuffix);
        if (pluralOffset != 0) {
          out.print(" - " + pluralOffset);
        }
        out.println(";");
      }
      // save the selected plural form
      // TODO(jat): cache instances of the same plural rule?
      out.println("int arg" + argNumber + "_form = new "
          + pluralRule.getClass().getCanonicalName()
          + "().select(arg" + argNumber + countSuffix + ");");
    }

    @Override
    public void generateSelectEnd(SourceWriter out) {
      if (hasExactMatches && !inExactMatches) {
        // undo extra nesting level
        out.outdent();
        out.println("}");
        out.println("break;");
        out.outdent();
      }
      out.outdent();
      out.println("}");
    }

    @Override
    public void generateSelectMatchEnd(SourceWriter out, String value) {
      out.println("break;");
      out.outdent();
    }

    @Override
    public void generateSelectMatchStart(SourceWriter out, TreeLogger logger,
        String value) throws UnableToCompleteException {
      missingPluralForms.remove(value);
      if (value.startsWith("=")) {
        try {
          long val = Long.parseLong(value.substring(1));
          out.println("case " + val + ":  // " + value);
        } catch (NumberFormatException e) {
          throw error(logger, "Exact match value '" + value
              + "' must be integral", e);
        }
        out.indent();
        return;
      }
      if (inExactMatches) {
        /*
         * If this is the first non-exact value, create a nested select that
         * chooses the message based on the plural form only if no exact values
         * matched.
         */
        inExactMatches = false;
        out.println("default: // non-exact matches");
        out.indent();
        out.println("switch (arg" + argNumber + "_form) {");
        out.indent();
      }
      if (AlternateMessageSelector.OTHER_FORM_NAME.equals(value)) {
        out.println("default: // other");
        out.indent();
        return;
      }
      PluralForm[] pluralForms = pluralRule.pluralForms();
      for (int i = 0; i < pluralForms.length; ++i) {
        if (pluralForms[i].getName().equals(value)) {
          out.println("case " + i + ":  // " + value);
          out.indent();
          return;
        }
      }
      logger.log(TreeLogger.WARN, "Plural form '" + value + "' unknown in "
          + pluralRule.getClass().getCanonicalName() + ": ignoring");
      // TODO(jat): perhaps return a failure instead, and let the called skip
      // the nested selector code?  It gets complicated really quick though.
      out.println("case " + (bogusCaseValue++) + ": // unknown plural form '"
          + value + "'");
      out.indent();
    }

    @Override
    public void generateSelectStart(SourceWriter out, boolean hasExactMatches) {
      this.hasExactMatches = hasExactMatches;
      inExactMatches = hasExactMatches;
      String suffix = hasExactMatches ? listSuffix : "_form";
      out.println("switch (arg" + argNumber + suffix + ") {");
      out.indent();
    }

    public PluralForm[] getPluralForms() {
      return pluralRule.pluralForms();
    }

    @Override
    public void issueWarnings(TreeLogger logger, JMethod m, GwtLocale locale) {
      if (!missingPluralForms.isEmpty()) {
        // TODO(jat): avoid giving warnings for values that are not necessary
        // due to exact value matches.  For example, in English there is no need
        // for ONE if the =1 value was given, and it may be important to have
        // the =1 value across all locales.
        logger.log(TreeLogger.WARN, "In locale '" + locale
            + "', required plural forms are missing: " + missingPluralForms);
      }
    }
  }

  /**
   * Implements {x,time...} references in MessageFormat.
   */
  private static class TimeFormatter implements ValueFormatter {

    public boolean format(TreeLogger logger,
        GwtLocale locale,
        StringGenerator out,
        Map<String, String> formatArgs,
        String subformat,
        String argName,
        JType argType,
        Parameters params) {
      if (!"java.util.Date".equals(argType.getQualifiedSourceName())) {
        logger.log(TreeLogger.ERROR, "Only java.util.Date acceptable for date format");
        return true;
      }
      String tzParam = "";
      String tzArg = formatArgs.get("tz");
      if (tzArg != null) {
        if (tzArg.startsWith("$")) {
          int paramNum = params.getParameterIndex(tzArg.substring(1));
          if (paramNum < 0) {
            logger.log(TreeLogger.ERROR, "Unable to resolve tz argument " + tzArg);
            return true;
          } else if (!"com.google.gwt.i18n.client.TimeZone".equals(
              params.getParameter(paramNum).getType().getQualifiedSourceName())) {
            logger.log(TreeLogger.ERROR, "Currency code parameter must be TimeZone");
            return true;
          } else {
            tzParam = ", arg" + paramNum;
          }
        } else {
          tzParam = ", com.google.gwt.i18n.client.TimeZone.createTimeZone(" + tzArg + ")";
        }
      }
      if (subformat == null || "medium".equals(subformat)) {
        out.appendStringValuedExpression(
            dtFormatClassName + ".getMediumTimeFormat().format(" + argName + tzParam + ")");
      } else if ("full".equals(subformat)) {
        out.appendStringValuedExpression(
            dtFormatClassName + ".getFullTimeFormat().format(" + argName + tzParam + ")");
      } else if ("long".equals(subformat)) {
        out.appendStringValuedExpression(
            dtFormatClassName + ".getLongTimeFormat().format(" + argName + tzParam + ")");
      } else if ("short".equals(subformat)) {
        out.appendStringValuedExpression(
            dtFormatClassName + ".getShortTimeFormat().format(" + argName + tzParam + ")");
      } else {
        logger.log(TreeLogger.WARN, "Use localdatetime format instead");
        out.appendStringValuedExpression(
            dtFormatClassName + ".getFormat(" + wrap(subformat) + ").format(" + argName + tzParam
                + ")");
      }
      return false;
    }
  }

  private interface ValueFormatter {

    /**
     * Creates code to format a value according to a format string.
     *
     * @param logger
     * @param locale current locale
     * @param out StringBuilder to append to
     * @param formatArgs format-specific arguments
     * @param subformat the remainder of the format string
     * @param argName the name of the argument to use in the generated code
     * @param argType the type of the argument
     * @param params argument list or null
     * @return true if a fatal error occurred (which will already be logged)
     */
    boolean format(TreeLogger logger,
        GwtLocale locale,
        StringGenerator out,
        Map<String, String> formatArgs,
        String subformat,
        String argName,
        JType argType,
        Parameters params);
  }

  /**
   * Class names, in a refactor-friendly manner.
   */
  private static final String dtFormatClassName = DateTimeFormat.class.getCanonicalName();

  /**
   * Fully-qualified class name of the SafeHtml interface.
   */
  public static final String SAFE_HTML_FQCN = SafeHtml.class.getCanonicalName();

  /**
   * Fully-qualified class name of the SafeHtmlBuilder class.
   */
  public static final String SAFE_HTML_BUILDER_FQCN = SafeHtmlBuilder.class.getCanonicalName();

  /**
   * Map of supported formats.
   */
  private static Map<String, ValueFormatter> formatters = new HashMap<String, ValueFormatter>();

  private static final String numFormatClassName = NumberFormat.class.getCanonicalName();

  /*
   * Register supported formats.
   */
  static {
    formatters.put("date", new DateFormatter());
    formatters.put("number", new NumberFormatter());
    formatters.put("time", new TimeFormatter());
    formatters.put("localdatetime", new LocalDateTimeFormatter());
  }

  /**
   * Creates an instance of a locale-specific plural rule implementation.
   *
   *  Note that this uses TypeOracle's ability to find all subclasses of the
   * supplied parent class, then uses reflection to actually load the class.
   * This works because PluralRule instances are required to be translatable,
   * since part of them is executed at runtime and part at compile time.
   *
   * @param logger TreeLogger instance
   * @param oracle TypeOracle instance to use
   * @param ruleClass PluralRule implementation to localize
   * @param locale current locale we are compiling for
   * @return an instance of a PluralRule implementation. If an appropriate
   *         implementation of the requested class cannot be found, an instance
   *         of DefaultRule is used instead as a default of last resort.
   * @throws UnableToCompleteException if findDerivedClasses fails
   *
   *         TODO: consider impact of possibly having multiple TypeOracles
   */
  private static PluralRule createLocalizedPluralRule(
      TreeLogger logger, TypeOracle oracle, Class<? extends PluralRule> ruleClass, GwtLocale locale)
      throws UnableToCompleteException {
    String baseName = ruleClass.getCanonicalName();
    JClassType ruleJClassType = oracle.findType(baseName);
    Map<String, JClassType> matchingClasses =
        LocalizableLinkageCreator.findDerivedClasses(logger, ruleJClassType);
    for (GwtLocale search : locale.getCompleteSearchList()) {
      JClassType localizedType = matchingClasses.get(search.toString());
      if (localizedType != null) {
        try {
          Class<?> testClass = Class.forName(
              localizedType.getQualifiedBinaryName(), false, PluralRule.class.getClassLoader());
          if (PluralRule.class.isAssignableFrom(testClass)) {
            return (PluralRule) testClass.newInstance();
          }
        } catch (ClassCastException e) {
          // ignore classes of the wrong type
        } catch (ClassNotFoundException e) {
          // ignore missing classes
        } catch (InstantiationException e) {
          // skip classes we can't instantiate
        } catch (IllegalAccessException e) {
          // ignore inaccessible classes
        }
      }
    }
    // default of last resort
    return new DefaultRule();
  }

  private final Map<GwtLocale, Map<String, String>> listPatternCache;

  private SourceWriter writer;

  private final ResourceOracle resourceOracle;

  /**
   * Constructor for <code>MessagesMethodCreator</code>.
   */
  public MessagesMethodCreator(AbstractGeneratorClassCreator classCreator,
      SourceWriter writer, ResourceOracle resourceOracle) {
    super(classCreator);
    listPatternCache = new HashMap<GwtLocale, Map<String, String>>();
    this.writer = writer;
    this.resourceOracle = resourceOracle;
  }

  /**
   * Append an argument to the output without doing any formatting.
   *
   * @param buf
   * @param argExpr Java source for expression to produce argument value
   * @param argType type of the argument being appended
   */
  private void appendUnformattedArg(StringGenerator buf, String argExpr, JType argType) {
    boolean isSafeHtmlTyped = SAFE_HTML_FQCN.equals(argType.getQualifiedSourceName());
    boolean isPrimitiveType = (argType.isPrimitive() != null);
    boolean needsConversionToString =
        !("java.lang.String".equals(argType.getQualifiedSourceName()));
    buf.appendExpression(argExpr, isSafeHtmlTyped, isPrimitiveType, needsConversionToString);
  }

  @Override
  public void createMethodFor(TreeLogger logger, JMethod m, String key,
      ResourceList resourceList, GwtLocale locale)
      throws UnableToCompleteException {
    ResourceEntry resourceEntry = resourceList.getEntry(key);
    if (resourceEntry == null) {
      throw new MissingResourceException(key, resourceList);
    }
    JParameter[] params = m.getParameters();
    boolean seenPluralCount = false;
    boolean seenSelect = false;

    int numParams = params.length;
    int lastPluralArgNumber = -1;
    List<AlternateFormSelector> selectors = new ArrayList<AlternateFormSelector>();
    // See if any parameter is tagged as a PluralCount or Select parameter.
    for (int i = 0; i < numParams; ++i) {
      PluralCount pluralCount = params[i].getAnnotation(PluralCount.class);
      Select select = params[i].getAnnotation(Select.class);
      if (pluralCount != null && select != null) {
        throw error(logger, params[i].getName() + " cannot be both @PluralCount"
            + " and @Select");
      }
      AlternateFormSelector selector = null;
      if (select != null) {
        selector = new GenericSelector(logger, m, i, params);
        seenSelect = true;
      } else if (pluralCount != null) {
        PluralFormSelector pluralSelector = new PluralFormSelector(logger, m, i,
            params, locale);
        selector = pluralSelector;
        if (!seenPluralCount) {
          // TODO(jat): what if we have different plural rules on the different
          // forms?
          resourceList.setPluralForms(key, pluralSelector.getPluralForms());
        }
        seenPluralCount = true;
        lastPluralArgNumber = i;
      }
      if (selector != null) {
        selectors.add(selector);
      }
    }

    boolean[] seenFlags = new boolean[numParams];
    final Parameters paramsAccessor = new ParametersImpl(params, seenFlags);
    boolean isSafeHtml = m.getReturnType().getQualifiedSourceName().equals(
        SAFE_HTML_FQCN);

    if (!isSafeHtml) {
      // Check that no argument is SafeHtml
      for (JParameter param : params) {
        if (param.getType().getQualifiedSourceName().equals(SAFE_HTML_FQCN)) {
          throw error(logger,
              "Message methods with SafeHtml arguments can only have SafeHtml return type");
        }
      }
    }

    String template = resourceEntry.getForm(null);
    if (template == null) {
      logger.log(TreeLogger.ERROR,"No default form for method " + m.getName()
          + "' in " + m.getEnclosingType() + " for locale " + locale, null);
      throw new UnableToCompleteException();
    }

    // Generate code to format any lists
    // TODO(jat): handle messages with different list formats in alternate forms
    try {
      for (TemplateChunk chunk : MessageFormatParser.parse(template)) {
        if (chunk instanceof ArgumentChunk) {
          ArgumentChunk argChunk = (ArgumentChunk) chunk;
          if (argChunk.isList()) {
            ListAccessor listAccessor = null;
            int listArgNum = argChunk.getArgumentNumber();
            JType listType = params[listArgNum].getType();
            JClassType classType = listType.isInterface();
            JType elemType = null;
            if (classType != null) {
              if ("java.util.List".equals(
                  classType.getErasedType().getQualifiedSourceName())) {
                listAccessor = new ListAccessorList(listArgNum);
              } else {
                logger.log(TreeLogger.ERROR, "Parameters formatted as lists "
                    + "must be declared as java.util.List or arrays in "
                    + m.getEnclosingType().getSimpleSourceName() + "."
                    + m.getName());
                throw new UnableToCompleteException();
              }
              JParameterizedType paramType = classType.isParameterized();
              if (paramType != null) {
                elemType = paramType.getTypeArgs()[0];
              } else {
                elemType = classType.getOracle().getJavaLangObject();
              }
            } else {
              JArrayType arrayType = listType.isArray();
              if (arrayType != null) {
                elemType = arrayType.getComponentType();
                listAccessor = new ListAccessorArray(listArgNum);
              }
            }
            generateListFormattingCode(logger, locale, argChunk,
                elemType, isSafeHtml, listAccessor, paramsAccessor);
          }
        }
      }
    } catch (ParseException pe) {
      throw error(logger, "Error parsing '" + template + "'", pe);
    }

    if (!seenPluralCount && !seenSelect
        && (m.getAnnotation(AlternateMessage.class) != null
        || m.getAnnotation(PluralText.class) != null)) {
      logger.log(TreeLogger.WARN, "Unused @AlternateMessage or @PluralText on "
          + m.getEnclosingType().getSimpleSourceName() + "." + m.getName()
          + "; did you intend to mark a @Select or @PluralCount parameter?",
          null);
    }
    Collection<String> resourceForms = resourceEntry.getForms();
    if (seenPluralCount || seenSelect) {
      paramsAccessor.enablePluralOffsets();
      writer.println(m.getReturnType().getParameterizedQualifiedSourceName()
          + " returnVal = null;");
      for (AlternateFormSelector selector : selectors) {
        selector.generatePrepCode(writer);
      }

      // sort forms so that all exact-value forms come first
      String[] forms = resourceForms.toArray(new String[resourceForms.size()]);
      Arrays.sort(forms, new ExactValueComparator());

      generateMessageSelectors(logger, m, locale, resourceEntry, selectors, paramsAccessor,
          isSafeHtml, forms, lastPluralArgNumber);
      for (AlternateFormSelector selector : selectors) {
        selector.issueWarnings(logger, m, locale);
      }
      writer.println("if (returnVal != null) {");
      writer.indent();
      writer.println("return returnVal;");
      writer.outdent();
      writer.println("}");
    }
    writer.print("return ");
    generateString(logger, locale, template, paramsAccessor, writer,
        isSafeHtml, lastPluralArgNumber);
    writer.println(";");

    // Generate an error if any required parameter was not used somewhere.
    for (int i = 0; i < numParams; ++i) {
      if (!seenFlags[i]) {
        Optional optional = params[i].getAnnotation(Optional.class);
        Select select = params[i].getAnnotation(Select.class);
        if (optional == null && select == null) {
          throw error(logger, "Required argument " + i + " not present: "
              + template);
        }
      }
    }
  }

  private void formatArg(TreeLogger logger, GwtLocale locale,
      StringGenerator buf, ArgumentChunk argChunk, String argExpr,
      JType paramType, Parameters params) throws UnableToCompleteException {
    String format = argChunk.getFormat();
    if (format != null) {
      String subformat = argChunk.getSubFormat();
      ValueFormatter formatter = formatters.get(format);
      if (formatter != null) {
        if (formatter.format(logger, locale, buf, argChunk.getFormatArgs(),
            subformat, argExpr, paramType, params)) {
          throw new UnableToCompleteException();
        }
        return;
      }
    }
    // no format specified or unknown format
    // have to ensure that the result is stringified if necessary
    appendUnformattedArg(buf, argExpr, paramType);
  }

  /**
   * Generate code for one list pattern.
   *
   * @param logger logger to use for error/warning messages
   * @param locale locale we are generating code for
   * @param listArg the {n,list,...} argument in the original format pattern
   * @param val0 the expression defining the {0} argument in the list pattern
   * @param val1 the expression defining the {1} argument in the list pattern
   * @param elemType the element type of the list/array being rendered as a list
   *        * @param isSafeHtml true if the resulting string is SafeHtml
   * @param listPattern the list pattern to generate code for, ie "{0}, {1}"
   * @param formatSecond true if the {1} parameter needs to be formatted
   * @param params parameters passed to the Messages method call
   * @return a constructed string containing the code to implement the given
   *         list pattern
   * @throws UnableToCompleteException
   */
  private CharSequence formatListPattern(final TreeLogger logger,
      final GwtLocale locale, final ArgumentChunk listArg, final String val0,
      final String val1, final JType elemType, final boolean isSafeHtml,
      String listPattern, final boolean formatSecond, final Parameters params)
      throws UnableToCompleteException {
    final StringBuilder buf = new StringBuilder();
    final StringGenerator gen = StringGenerator.create(buf, isSafeHtml);
    try {
      List<TemplateChunk> chunks = MessageFormatParser.parse(listPattern);
      for (TemplateChunk chunk : chunks) {
        chunk.accept(new DefaultTemplateChunkVisitor() {
          @Override
          public void visit(ArgumentChunk argChunk) throws UnableToCompleteException {
            // The {0} argument in the list pattern always needs formatting,
            // but the {1} argument is the part of the list already rendered
            // (in either String of SafeHtml form) unless formatSecond is true.
            if (argChunk.getArgumentNumber() == 0 || formatSecond) {
              formatArg(logger, locale, gen, listArg,
                  argChunk.getArgumentNumber() == 0 ? val0 : val1, elemType,
                  params);
            } else {
              gen.appendExpression(val1, isSafeHtml, false, false);
            }
          }

          @Override
          public void visit(StringChunk stringChunk) {
            gen.appendStringLiteral(stringChunk.getString());
          }
        });
      }
    } catch (ParseException e) {
      logger.log(TreeLogger.ERROR,
          "Internal error: can't parse list pattern '" + listPattern
          + "' for locale " + locale, e);
      throw new UnableToCompleteException();
    }
    gen.completeString();
    return buf;
  }

  /**
   * Generates code to format a list in a format pattern.
   *
   * @param logger logger to use for error/warning messages
   * @param locale locale we are generating code for
   * @param listArg the {n,list,...} argument in the original format pattern
   * @param elemType the element type of the list/array being rendered as a list
   * @param isSafeHtml true if the resulting string is SafeHtml
   * @param listAccessor a way to access elements of the list type supplied by
   *        the user
   * @param params parameters passed to the Messages method call
   * @throws UnableToCompleteException
   */
  private void generateListFormattingCode(TreeLogger logger, GwtLocale locale,
      ArgumentChunk listArg, JType elemType,
      boolean isSafeHtml, ListAccessor listAccessor, Parameters params)
      throws UnableToCompleteException {
    Map<String, String> listPatternParts = getListPatternParts(logger, locale);
    int listArgNum = listArg.getArgumentNumber();
    writer.println("int arg" + listArgNum + "_size = " + listAccessor.getSize()
        + ";");
    if (isSafeHtml) {
      writer.println(SafeHtml.class.getCanonicalName() + " arg" + listArgNum
          + "_list = new "
          + OnlyToBeUsedInGeneratedCodeStringBlessedAsSafeHtml.class.getCanonicalName()
          + "(\"\");");
    } else {
      writer.println("String arg" + listArgNum + "_list = \"\";");
    }
    writer.println("switch (arg" + listArgNum + "_size) {");
    writer.indent();
    // TODO(jat): add support for special-cases besides 2 if CLDR ever adds them
    String pairPattern = listPatternParts.get("2");
    if (pairPattern != null) {
      writer.println("case 2:");
      writer.indent();
      writer.println("  arg" + listArgNum + "_list = "
          + formatListPattern(logger, locale, listArg,
          listAccessor.getElement("0"), listAccessor.getElement("1"), elemType,
          isSafeHtml, pairPattern, true, params) + ";");
      writer.println("break;");
      writer.outdent();
    }
    writer.println("default:");
    writer.indent();
    writer.println("int i = arg" + listArgNum + "_size;");
    writer.println("if (i > 0) {");
    writer.indent();
    StringBuilder outbuf = new StringBuilder();
    StringGenerator buf = StringGenerator.create(outbuf, isSafeHtml);
    formatArg(logger, locale, buf, listArg, listAccessor.getElement("--i"),
        elemType, params);
    buf.completeString();
    writer.println("arg" + listArgNum + "_list = " + outbuf + ";");
    writer.outdent();
    writer.println("}");
    writer.println("if (i > 0) {");
    writer.indent();
    writer.println("arg" + listArgNum + "_list = "
        + formatListPattern(logger, locale, listArg,
        listAccessor.getElement("--i"), "arg" + listArgNum + "_list", elemType,
        isSafeHtml, listPatternParts.get("end"), false, params) + ";");
    writer.outdent();
    writer.println("}");
    writer.println("while (i > 1) {");
    writer.indent();
    writer.println("arg" + listArgNum + "_list = "
        + formatListPattern(logger, locale, listArg,
        listAccessor.getElement("--i"), "arg" + listArgNum + "_list", elemType,
        isSafeHtml, listPatternParts.get("middle"), false, params) + ";");
    writer.outdent();
    writer.println("}");
    writer.println("if (i > 0) {");
    writer.indent();
    writer.println("arg" + listArgNum + "_list = "
        + formatListPattern(logger, locale, listArg,
        listAccessor.getElement("--i"), "arg" + listArgNum + "_list", elemType,
        isSafeHtml, listPatternParts.get("start"), false, params) + ";");
    writer.outdent();
    writer.println("}");
    writer.println("break;");
    writer.outdent();
    writer.outdent();
    writer.println("}");
  }

  /**
   * @param logger
   * @param m
   * @param locale
   * @param resourceEntry
   * @param selectors
   * @param paramsAccessor
   * @param isSafeHtml
   * @param forms
   * @param lastPluralArgNumber index of most recent plural argument, used for
   *     processing inner-plural arguments ({#})
   * @throws UnableToCompleteException
   */
  private void generateMessageSelectors(TreeLogger logger, JMethod m,
      GwtLocale locale, ResourceEntry resourceEntry,
      List<AlternateFormSelector> selectors, Parameters paramsAccessor,
      boolean isSafeHtml, String[] forms, int lastPluralArgNumber)
      throws UnableToCompleteException {
    int numSelectors = selectors.size();
    String[] lastForm = new String[numSelectors];
    for (String form : forms) {
      String[] splitForms = form.split("\\|");
      if (splitForms.length != numSelectors) {
        throw error(logger, "Incorrect number of selector forms for "
            + m.getName() + " - '" + form + "'");
      }
      boolean allOther = true;
      for (String splitForm : splitForms) {
        if (splitForm.startsWith("=")) {
          allOther = false;
        } else if (!AlternateMessageSelector.OTHER_FORM_NAME.equals(splitForm)) {
          allOther = false;
        }
      }
      if (allOther) {
        // don't process the all-other case, that is the default return value
        logger.log(TreeLogger.WARN, "Ignoring supplied alternate form with all"
            + " 'other' values, @DefaultMessage will be used");
        continue;
      }

      // find where the changes are
      int firstDifferent = 0;
      while (firstDifferent < numSelectors
          && splitForms[firstDifferent].equals(lastForm[firstDifferent])) {
        firstDifferent++;
      }

      // close nested selects deeper than where the change was
      for (int i = numSelectors; i-- > firstDifferent; ) {
        if (lastForm[i] != null) {
          selectors.get(i).generateSelectMatchEnd(writer, lastForm[i]);
          if (i > firstDifferent) {
            selectors.get(i).generateSelectEnd(writer);
          }
        }
      }

      // open all the nested selects from here
      for (int i = firstDifferent; i < numSelectors; ++i) {
        if (i > firstDifferent || lastForm[i] == null) {
          selectors.get(i).generateSelectStart(writer,
              splitForms[i].startsWith("="));
        }
        selectors.get(i).generateSelectMatchStart(writer, logger,
            splitForms[i]);
        lastForm[i] = splitForms[i];
      }
      writer.print("returnVal = ");
      generateString(logger, locale, resourceEntry.getForm(form),
          paramsAccessor, writer, isSafeHtml, lastPluralArgNumber);
      writer.println(";");
    }
    for (int i = numSelectors; i-- > 0; ) {
      if (lastForm[i] != null) {
        selectors.get(i).generateSelectMatchEnd(writer, lastForm[i]);
        selectors.get(i).generateSelectEnd(writer);
      }
    }
  }

  /**
   * Generate a Java string for a given MessageFormat string.
   *
   * @param logger
   * @param template
   * @param paramsAccessor
   * @param writer
   * @param lastPluralArgNumber index of most recent plural argument, used for
   *     processing inner-plural arguments ({#})
   * @throws UnableToCompleteException
   */
  private void generateString(final TreeLogger logger, final GwtLocale locale,
      final String template, final Parameters paramsAccessor, SourceWriter writer,
      final boolean isSafeHtml, final int lastPluralArgNumber) throws UnableToCompleteException {
    StringBuilder outputBuf = new StringBuilder();
    final StringGenerator buf = StringGenerator.create(outputBuf, isSafeHtml);
    final int n = paramsAccessor.getCount();
    try {
      for (TemplateChunk chunk : MessageFormatParser.parse(template)) {
        chunk.accept(new DefaultTemplateChunkVisitor() {
          @Override
          public void visit(ArgumentChunk argChunk) throws UnableToCompleteException {
            int argNumber = argChunk.getArgumentNumber();
            if (argNumber >= n) {
              throw error(logger, "Argument " + argNumber + " beyond range of arguments: " + template);
            }
            if (argNumber < 0) {
              if (lastPluralArgNumber < 0) {
                throw error(logger, "Inner-plural notation {#} used outside in non-plural message");
              }
              argNumber = lastPluralArgNumber;
            }
            JParameter param = paramsAccessor.getParameter(argNumber);
            String arg = "arg" + argNumber;
            if (argChunk.isList()) {
              buf.appendExpression(arg + "_list", isSafeHtml, false, false);
            } else {
              JType paramType = param.getType();
              formatArg(logger, locale, buf, argChunk,
                  paramsAccessor.getParameterExpression(argNumber), paramType,
                  paramsAccessor);
            }
          }

          @Override
          public void visit(StaticArgChunk staticArgChunk) {
            buf.appendStringLiteral(staticArgChunk.getReplacement());
          }

          @Override
          public void visit(StringChunk stringChunk) {
            buf.appendStringLiteral(stringChunk.getString());
          }
        });
      }
    } catch (ParseException e) {
      throw error(logger, e);
    }
    buf.completeString();
    writer.print(outputBuf.toString());
  }

  private Map<String, String> getListPatternParts(TreeLogger logger, GwtLocale locale) {
    Map<String, String> map = listPatternCache.get(locale);
    if (map == null) {
      String baseName = MessagesMethodCreator.class.getPackage().getName().replace('.', '/')
          + "/cldr/ListPatterns_";
      for (GwtLocale search : locale.getCompleteSearchList()) {
        String propFile = baseName + search.getAsString() + ".properties";
        InputStream stream =
            ResourceLocatorImpl.tryFindResourceAsStream(logger, resourceOracle, propFile);
        if (stream != null) {
          try {
            LocalizedPropertiesLoader loader = new LocalizedPropertiesLoader(stream, "UTF-8");
            map = new HashMap<String, String>();
            loader.load(map);
            break;
          } catch (IOException e) {
            logger.log(TreeLogger.WARN, "Ignoring error reading file " + propFile, e);
          } finally {
            try {
              stream.close();
            } catch (IOException e) {
            }
          }
        }
      }
      listPatternCache.put(locale, map);
    }
    return map;
  }
}
