/*
 * 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.dev.cfg;

import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.Linker;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.LinkerOrder;
import com.google.gwt.dev.js.JsParser;
import com.google.gwt.dev.js.JsParserException;
import com.google.gwt.dev.js.ast.JsExprStmt;
import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsStatement;
import com.google.gwt.dev.util.Empty;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.xml.AttributeConverter;
import com.google.gwt.dev.util.xml.Schema;

import java.io.IOException;
import java.io.StringReader;
import java.net.URL;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

// CHECKSTYLE_NAMING_OFF
/**
 * Configures a module definition object using XML.
 */
public class ModuleDefSchema extends Schema {

  private final class BodySchema extends Schema {

    protected final String __add_linker_1_name = null;

    protected final String __clear_configuration_property_1_name = null;

    protected final String __collapse_all_properties_1_value = "true";

    protected final String __collapse_property_1_name = null;

    protected final String __collapse_property_2_values = null;

    protected final String __define_configuration_property_1_name = null;

    protected final String __define_configuration_property_2_is_multi_valued = null;

    protected final String __define_linker_1_name = null;

    protected final String __define_linker_2_class = null;

    protected final String __define_property_1_name = null;

    protected final String __define_property_2_values = null;

    protected final String __entry_point_1_class = null;

    protected final String __extend_configuration_property_1_name = null;

    protected final String __extend_configuration_property_2_value = null;

    protected final String __extend_property_1_name = null;

    protected final String __extend_property_2_values = null;

    protected final String __generate_with_1_class = null;

    protected final String __inherits_1_name = null;

    protected final String __property_provider_1_name = null;

    protected final String __public_1_path = null;

    protected final String __public_2_includes = "";

    protected final String __public_3_excludes = "";

    protected final String __public_4_skips = "";

    protected final String __public_5_defaultexcludes = "yes";

    protected final String __public_6_casesensitive = "true";

    protected final String __replace_with_1_class = null;

    protected final String __script_1_src = null;

    protected final String __servlet_1_path = null;

    protected final String __servlet_2_class = null;

    protected final String __set_configuration_property_1_name = null;

    protected final String __set_configuration_property_2_value = null;

    protected final String __set_property_1_name = null;

    protected final String __set_property_2_value = null;

    protected final String __set_property_fallback_1_name = null;

    protected final String __set_property_fallback_2_value = null;

    protected final String __source_1_path = "";

    protected final String __source_2_includes = "";

    protected final String __source_3_excludes = "";

    protected final String __source_4_skips = "";

    protected final String __source_5_defaultexcludes = "yes";

    protected final String __source_6_casesensitive = "true";

    protected final String __stylesheet_1_src = null;

    protected final String __super_source_1_path = "";

    protected final String __super_source_2_includes = "";

    protected final String __super_source_3_excludes = "";

    protected final String __super_source_4_skips = "";

    protected final String __super_source_5_defaultexcludes = "yes";

    protected final String __super_source_6_casesensitive = "true";

    /**
     * Used to accumulate binding property conditions before recording the
     * newly-allowed values.
     */
    private ConditionAll bindingPropertyCondition;

    private Schema fChild;

    protected Schema __add_linker_begin(LinkerName name)
        throws UnableToCompleteException {
      if (moduleDef.getLinker(name.name) == null) {
        Messages.LINKER_NAME_INVALID.log(logger, name.name, null);
        throw new UnableToCompleteException();
      }
      moduleDef.addLinker(name.name);
      return null;
    }

    protected Schema __clear_configuration_property_begin(PropertyName name)
        throws UnableToCompleteException {
      // Don't allow configuration properties with the same name as a
      // deferred-binding property.
      Property prop = moduleDef.getProperties().find(name.token);
      if (prop == null) {
        logger.log(TreeLogger.ERROR, "No property named " + name.token
            + " has been defined");
        throw new UnableToCompleteException();
      } else if (!(prop instanceof ConfigurationProperty)) {
        if (prop instanceof BindingProperty) {
          logger.log(TreeLogger.ERROR, "The property " + name.token
              + " is already defined as a deferred-binding property");
        } else {
          logger.log(TreeLogger.ERROR, "The property " + name.token
              + " is already defined as a property of unknown type");
        }
        throw new UnableToCompleteException();
      }

      ((ConfigurationProperty) prop).clear();

      // No children.
      return null;
    }

    protected Schema __collapse_all_properties_begin(boolean collapse) {
      moduleDef.setCollapseAllProperties(collapse);
      return null;
    }

    protected Schema __collapse_property_begin(PropertyName name,
        PropertyValueGlob[] values) throws UnableToCompleteException {
      Property prop = moduleDef.getProperties().find(name.token);
      if (prop == null) {
        logger.log(TreeLogger.ERROR, "No property named " + name.token
            + " has been defined");
        throw new UnableToCompleteException();
      } else if (!(prop instanceof BindingProperty)) {
        logger.log(TreeLogger.ERROR, "The property " + name.token
            + " is not a deferred-binding property");
        throw new UnableToCompleteException();
      }

      BindingProperty binding = (BindingProperty) prop;
      List<String> allowed = Arrays.asList(binding.getDefinedValues());

      String[] tokens = new String[values.length];
      boolean error = false;
      for (int i = 0, j = values.length; i < j; i++) {
        tokens[i] = values[i].token;
        if (values[i].isGlob()) {
          // Expanded later in BindingProperty
          continue;
        } else if (!allowed.contains(tokens[i])) {
          logger.log(TreeLogger.ERROR, "The value " + tokens[i]
              + " was not previously defined for the property "
              + binding.getName());
          error = true;
        }
      }

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

      binding.addCollapsedValues(tokens);

      // No children
      return null;
    }

    protected Schema __define_configuration_property_begin(PropertyName name,
        String is_multi_valued) throws UnableToCompleteException {
      boolean isMultiValued = toPrimitiveBoolean(is_multi_valued);

      // Don't allow configuration properties with the same name as a
      // deferred-binding property.
      Property existingProperty = moduleDef.getProperties().find(name.token);
      if (existingProperty == null) {
        // Create the property
        moduleDef.getProperties().createConfiguration(name.token, isMultiValued);
        if (!propertyDefinitions.containsKey(name.token)) {
          propertyDefinitions.put(name.token, moduleName);
        }
      } else if (existingProperty instanceof ConfigurationProperty) {
        // Allow redefinition only if the 'is-multi-valued' setting is identical
        // The previous definition may have been explicit, via
        // <define-configuration-property>, or implicit, via
        // <set-configuration-property>. In the latter case, the
        // value of the 'is-multi-valued' attribute was taken as false.
        String originalDefinition = propertyDefinitions.get(name.token);
        if (((ConfigurationProperty) existingProperty).allowsMultipleValues() != isMultiValued) {
          if (originalDefinition != null) {
            logger.log(
                TreeLogger.ERROR,
                "The configuration property named "
                    + name.token
                    + " is already defined with a different 'is-multi-valued' setting");
          } else {
            logger.log(
                TreeLogger.ERROR,
                "The configuration property named "
                    + name.token
                    + " is already defined implicitly by 'set-configuration-property'"
                    + " in " + propertySettings.get(name.token)
                    + " with 'is-multi-valued' set to 'false'");
          }
          throw new UnableToCompleteException();
        } else {
          if (originalDefinition != null) {
            logger.log(TreeLogger.WARN,
                "Ignoring identical definition of the configuration property named "
                    + name.token + " (originally defined in "
                    + originalDefinition + ", redefined in " + moduleName + ")");
          } else {
            logger.log(TreeLogger.WARN,
                "Definition of already set configuration property named "
                    + name.token + " in " + moduleName + " (set in "
                    + propertySettings.get(name.token)
                    + ").  This may be disallowed in the future.");
          }
        }
      } else {
        if (existingProperty instanceof BindingProperty) {
          logger.log(TreeLogger.ERROR, "The property " + name.token
              + " is already defined as a deferred-binding property");
        } else {
          // Future proofing if other subclasses are added.
          logger.log(TreeLogger.ERROR, "May not replace property named "
              + name.token + " of unknown type "
              + existingProperty.getClass().getName());
        }
        throw new UnableToCompleteException();
      }

      // No children.
      return null;
    }

    protected Schema __define_linker_begin(LinkerName name,
        Class<? extends Linker> linker) throws UnableToCompleteException {
      if (!Linker.class.isAssignableFrom(linker)) {
        logger.log(TreeLogger.ERROR, "A linker must extend "
            + Linker.class.getName(), null);
        throw new UnableToCompleteException();
      }
      if (linker.getAnnotation(LinkerOrder.class) == null) {
        logger.log(TreeLogger.ERROR, "Linkers must be annotated with the "
            + LinkerOrder.class.getName() + " annotation", null);
        throw new UnableToCompleteException();
      }
      moduleDef.defineLinker(logger, name.name, linker);
      return null;
    }

    protected Schema __define_property_begin(PropertyName name,
        PropertyValue[] values) throws UnableToCompleteException {

      Property existingProperty = moduleDef.getProperties().find(name.token);
      if (existingProperty != null) {
        // Disallow redefinition of properties, but provide a type-sensitive
        // error message to aid in diagnosis.
        if (existingProperty instanceof BindingProperty) {
          logger.log(TreeLogger.ERROR, "The deferred-binding property named "
              + name.token + " may not be redefined.");
        } else if (existingProperty instanceof ConfigurationProperty) {
          logger.log(TreeLogger.ERROR, "The property " + name.token
              + " is already defined as a configuration property");
        } else {
          // Future proofing if other subclasses are added.
          logger.log(TreeLogger.ERROR, "May not replace property named "
              + name.token + " of unknown type "
              + existingProperty.getClass().getName());
        }
        throw new UnableToCompleteException();
      }

      BindingProperty prop = moduleDef.getProperties().createBinding(name.token);

      for (int i = 0; i < values.length; i++) {
        prop.addDefinedValue(prop.getRootCondition(), values[i].token);
      }

      // No children.
      return null;
    }

    protected Schema __entry_point_begin(String className) {
      moduleDef.addEntryPointTypeName(className);
      return null;
    }

    protected Schema __extend_configuration_property_begin(PropertyName name,
        String value) throws UnableToCompleteException {

      // Property must already exist as a configuration property
      Property prop = moduleDef.getProperties().find(name.token);
      if ((prop == null) || !(prop instanceof ConfigurationProperty)) {
        logger.log(TreeLogger.ERROR, "The property " + name.token
            + " must already exist as a configuration property");
        throw new UnableToCompleteException();
      }

      ConfigurationProperty configProp = (ConfigurationProperty) prop;
      if (!configProp.allowsMultipleValues()) {
        logger.log(TreeLogger.ERROR, "The property " + name.token
            + " does not support multiple values");
        throw new UnableToCompleteException();
      }
      configProp.addValue(value);

      return null;
    }

    protected Schema __extend_property_begin(BindingProperty property,
        PropertyValue[] values) {
      for (int i = 0; i < values.length; i++) {
        property.addDefinedValue(property.getRootCondition(), values[i].token);
      }

      // No children.
      return null;
    }

    protected Schema __fail_begin() {
      RuleFail rule = new RuleFail();
      moduleDef.getRules().prepend(rule);
      return new FullConditionSchema(rule.getRootCondition());
    }

    protected Schema __generate_with_begin(Class<? extends Generator> generator)
        throws UnableToCompleteException {
      if (!Generator.class.isAssignableFrom(generator)) {
        logger.log(TreeLogger.ERROR, "A generator must extend "
            + Generator.class.getName(), null);
        throw new UnableToCompleteException();
      }
      RuleGenerateWith rule = new RuleGenerateWith(generator);
      moduleDef.getRules().prepend(rule);
      return new FullConditionSchema(rule.getRootCondition());
    }

    protected Schema __inherits_begin(String name)
        throws UnableToCompleteException {
      TreeLogger branch = logger.branch(TreeLogger.TRACE,
          "Loading inherited module '" + name + "'", null);
      loader.nestedLoad(branch, name, moduleDef);
      return null;
    }

    @SuppressWarnings("unused")
    protected Schema __property_provider_begin(BindingProperty property) {
      return fChild = new ScriptSchema();
    }

    protected void __property_provider_end(BindingProperty property)
        throws UnableToCompleteException {
      ScriptSchema childSchema = ((ScriptSchema) fChild);
      String script = childSchema.getScript();
      if (script == null) {
        // This is a problem.
        //
        logger.log(TreeLogger.ERROR,
            "Property providers must specify a JavaScript body", null);
        throw new UnableToCompleteException();
      }

      int lineNumber = childSchema.getStartLineNumber();
      JsFunction fn = parseJsBlock(lineNumber, script);

      property.setProvider(new PropertyProvider(fn.getBody().toSource()));
    }

    @SuppressWarnings("unused")
    protected Schema __public_begin(String path, String includes,
        String excludes, String skips, String defaultExcludes,
        String caseSensitive) {
      return fChild = new IncludeExcludeSchema();
    }

    protected void __public_end(String path, String includes, String excludes,
        String skips, String defaultExcludes, String caseSensitive) {
      IncludeExcludeSchema childSchema = ((IncludeExcludeSchema) fChild);
      foundAnyPublic = true;

      Set<String> includeSet = childSchema.getIncludes();
      addDelimitedStringToSet(includes, "[ ,]", includeSet);
      String[] includeList = includeSet.toArray(new String[includeSet.size()]);

      Set<String> excludeSet = childSchema.getExcludes();
      addDelimitedStringToSet(excludes, "[ ,]", excludeSet);
      String[] excludeList = excludeSet.toArray(new String[excludeSet.size()]);

      Set<String> skipSet = childSchema.getSkips();
      addDelimitedStringToSet(skips, "[ ,]", skipSet);
      String[] skipList = skipSet.toArray(new String[skipSet.size()]);

      boolean doDefaultExcludes = toPrimitiveBoolean(defaultExcludes);
      boolean doCaseSensitive = toPrimitiveBoolean(caseSensitive);

      addPublicPackage(modulePackageAsPath, path, includeList, excludeList,
          skipList, doDefaultExcludes, doCaseSensitive);
    }

    protected Schema __replace_with_begin(String className) {
      RuleReplaceWith rule = new RuleReplaceWith(className);
      moduleDef.getRules().prepend(rule);
      return new FullConditionSchema(rule.getRootCondition());
    }

    /**
     * @param src a partial or full url to a script file to inject
     * @return <code>null</code> since there can be no children
     */
    @SuppressWarnings("unused")
    protected Schema __script_begin(String src) {
      return fChild = new ScriptSchema();
    }

    protected void __script_end(String src) {
      ScriptSchema childSchema = (ScriptSchema) fChild;
      String js = childSchema.getScript();
      if (js != null) {
        logger.log(
            TreeLogger.WARN,
            "Injected scripts no longer use an associated JavaScript block; ignoring.",
            null);
      }
      moduleDef.getScripts().append(new Script(src));
    }

    protected Schema __servlet_begin(String path, String servletClass)
        throws UnableToCompleteException {

      // Only absolute paths, although it is okay to have multiple slashes.
      if (!path.startsWith("/")) {
        logger.log(TreeLogger.ERROR, "Servlet path '" + path
            + "' must begin with forward slash (e.g. '/foo')", null);
        throw new UnableToCompleteException();
      }

      // Map the path within this module.
      moduleDef.mapServlet(path, servletClass);

      return null;
    }

    protected Schema __set_configuration_property_begin(PropertyName name,
        String value) throws UnableToCompleteException {

      Property existingProperty = moduleDef.getProperties().find(name.token);
      if (existingProperty == null) {
        // If a property is created by "set-configuration-property" without
        // a previous "define-configuration-property", allow it for backwards
        // compatibility but don't allow multiple values.
        existingProperty = moduleDef.getProperties().createConfiguration(
            name.token, false);
        if (!propertySettings.containsKey(name.token)) {
          propertySettings.put(name.token, moduleName);
        }

        logger.log(TreeLogger.WARN, "Setting configuration property named "
            + name.token + " in " + moduleName
            + " that has not been previously defined."
            + "  This may be disallowed in the future.");
      } else if (!(existingProperty instanceof ConfigurationProperty)) {
        if (existingProperty instanceof BindingProperty) {
          logger.log(TreeLogger.ERROR, "The property " + name.token
              + " is already defined as a deferred-binding property");
        } else {
          // Future proofing if other subclasses are added.
          logger.log(TreeLogger.ERROR, "May not replace property named "
              + name.token + " of unknown type "
              + existingProperty.getClass().getName());
        }
        throw new UnableToCompleteException();
      }
      ((ConfigurationProperty) existingProperty).setValue(value);

      // No children.
      return null;
    }

    @SuppressWarnings("unused")
    protected Schema __set_property_begin(BindingProperty prop,
        PropertyValue[] value) throws UnableToCompleteException {
      bindingPropertyCondition = new ConditionAll();
      return new PropertyConditionSchema(bindingPropertyCondition);
    }

    protected void __set_property_end(BindingProperty prop,
        PropertyValue[] value) throws UnableToCompleteException {
      boolean error = false;
      String[] stringValues = new String[value.length];
      for (int i = 0, len = stringValues.length; i < len; i++) {
        if (!prop.isDefinedValue(stringValues[i] = value[i].token)) {
          logger.log(TreeLogger.ERROR, "The value " + stringValues[i]
              + " was not previously defined.");
          error = true;
        }
      }
      if (error) {
        throw new UnableToCompleteException();
      }

      // No conditions were specified, so use the property's root condition
      if (!bindingPropertyCondition.getConditions().iterator().hasNext()) {
        bindingPropertyCondition = prop.getRootCondition();
      }

      prop.setAllowedValues(bindingPropertyCondition, stringValues);
    }

    protected Schema __set_property_fallback_begin(BindingProperty prop,
        PropertyValue value) throws UnableToCompleteException {
      boolean error = true;
      for (String possibleValue : prop.getAllowedValues(prop.getRootCondition())) {
        if (possibleValue.equals(value.token)) {
          error = false;
          break;
        }
      }
      if (error) {
        logger.log(TreeLogger.ERROR, "The fallback value '" + value.token
            + "' was not previously defined for property '" + prop.getName()
            + "'");
        throw new UnableToCompleteException();
      }
      prop.setFallback(value.token);
      return null;
    }

    /**
     * Indicates which subdirectories contain translatable source without
     * necessarily adding a sourcepath entry.
     */
    @SuppressWarnings("unused")
    protected Schema __source_begin(String path, String includes,
        String excludes, String skips, String defaultExcludes,
        String caseSensitive) {
      return fChild = new IncludeExcludeSchema();
    }

    protected void __source_end(String path, String includes, String excludes,
        String skips, String defaultExcludes, String caseSensitive) {
      addSourcePackage(path, includes, excludes, skips, defaultExcludes,
          caseSensitive, false);
    }

    /**
     * @param src a partial or full url to a stylesheet file to inject
     * @return <code>null</code> since there can be no children
     */
    protected Schema __stylesheet_begin(String src) {
      moduleDef.getStyles().append(src);
      return null;
    }

    /**
     * Like adding a translatable source package, but such that it uses the
     * module's package itself as its sourcepath root entry.
     */
    @SuppressWarnings("unused")
    protected Schema __super_source_begin(String path, String includes,
        String excludes, String skips, String defaultExcludes,
        String caseSensitive) {
      return fChild = new IncludeExcludeSchema();
    }

    protected void __super_source_end(String path, String includes,
        String excludes, String skips, String defaultExcludes,
        String caseSensitive) {
      addSourcePackage(path, includes, excludes, skips, defaultExcludes,
          caseSensitive, true);
    }

    private void addDelimitedStringToSet(String delimited, String delimiter,
        Set<String> toSet) {
      if (delimited.length() > 0) {
        String[] split = delimited.split(delimiter);
        for (int i = 0; i < split.length; ++i) {
          if (split[i].length() > 0) {
            toSet.add(split[i]);
          }
        }
      }
    }

    private void addPublicPackage(String parentDir, String relDir,
        String[] includeList, String[] excludeList, String[] skipList,
        boolean defaultExcludes, boolean caseSensitive) {
      String normChildDir = normalizePathEntry(relDir);
      if (normChildDir.startsWith("/")) {
        logger.log(TreeLogger.WARN, "Non-relative public package: "
            + normChildDir, null);
        return;
      }
      if (normChildDir.startsWith("./") || normChildDir.indexOf("/./") >= 0) {
        logger.log(TreeLogger.WARN, "Non-canonical public package: "
            + normChildDir, null);
        return;
      }
      if (normChildDir.startsWith("../") || normChildDir.indexOf("/../") >= 0) {
        logger.log(TreeLogger.WARN, "Non-canonical public package: "
            + normChildDir, null);
        return;
      }
      String fullDir = parentDir + normChildDir;
      moduleDef.addPublicPackage(fullDir, includeList, excludeList, skipList,
          defaultExcludes, caseSensitive);
    }

    private void addSourcePackage(String relDir, String includes,
        String excludes, String skips, String defaultExcludes,
        String caseSensitive, boolean isSuperSource) {
      IncludeExcludeSchema childSchema = ((IncludeExcludeSchema) fChild);
      foundExplicitSourceOrSuperSource = true;

      Set<String> includeSet = childSchema.getIncludes();
      addDelimitedStringToSet(includes, "[ ,]", includeSet);
      String[] includeList = includeSet.toArray(new String[includeSet.size()]);

      Set<String> excludeSet = childSchema.getExcludes();
      addDelimitedStringToSet(excludes, "[ ,]", excludeSet);
      String[] excludeList = excludeSet.toArray(new String[excludeSet.size()]);

      Set<String> skipSet = childSchema.getSkips();
      addDelimitedStringToSet(skips, "[ ,]", skipSet);
      String[] skipList = skipSet.toArray(new String[skipSet.size()]);

      boolean doDefaultExcludes = toPrimitiveBoolean(defaultExcludes);
      boolean doCaseSensitive = toPrimitiveBoolean(caseSensitive);

      addSourcePackage(modulePackageAsPath, relDir, includeList, excludeList,
          skipList, doDefaultExcludes, doCaseSensitive, isSuperSource);
    }

    private void addSourcePackage(String modulePackagePath, String relDir,
        String[] includeList, String[] excludeList, String[] skipList,
        boolean defaultExcludes, boolean caseSensitive, boolean isSuperSource) {
      String normChildDir = normalizePathEntry(relDir);
      if (normChildDir.startsWith("/")) {
        logger.log(TreeLogger.WARN, "Non-relative source package: "
            + normChildDir, null);
        return;
      }
      if (normChildDir.startsWith("./") || normChildDir.indexOf("/./") >= 0) {
        logger.log(TreeLogger.WARN, "Non-canonical source package: "
            + normChildDir, null);
        return;
      }
      if (normChildDir.startsWith("../") || normChildDir.indexOf("/../") >= 0) {
        logger.log(TreeLogger.WARN, "Non-canonical source package: "
            + normChildDir, null);
        return;
      }

      String fullPackagePath = modulePackagePath + normChildDir;

      if (isSuperSource) {
        /*
         * Super source does not include the module package path as part of the
         * logical class names.
         */
        moduleDef.addSuperSourcePackage(fullPackagePath, includeList,
            excludeList, skipList, defaultExcludes, caseSensitive);
      } else {
        /*
         * Add the full package path to the include/exclude/skip lists since the
         * logical name of classes on the source path includes the package path
         * but the include, exclude, and skip lists do not.
         */
        addPrefix(includeList, fullPackagePath);
        addPrefix(excludeList, fullPackagePath);
        addPrefix(skipList, fullPackagePath);

        moduleDef.addSourcePackage(fullPackagePath, includeList, excludeList,
            skipList, defaultExcludes, caseSensitive);
      }
    }

    /**
     * Normalizes a path entry such that it does not start with but does end
     * with '/'.
     */
    private String normalizePathEntry(String path) {
      path = path.trim();

      if (path.length() == 0) {
        return "";
      }

      path = path.replace('\\', '/');

      if (!path.endsWith("/")) {
        path += "/";
      }

      return path;
    }
  }

  /**
   * Processes attributes of java.lang.Class type.
   */
  private final class ClassAttrCvt extends AttributeConverter {
    @Override
    public Object convertToArg(Schema schema, int line, String elem,
        String attr, String value) throws UnableToCompleteException {
      try {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        return cl.loadClass(value);
      } catch (ClassNotFoundException e) {
        Messages.UNABLE_TO_LOAD_CLASS.log(logger, value, e);
        throw new UnableToCompleteException();
      }
    }
  }

  /**
   * All conditional expressions, including those based on types.
   */
  private final class FullConditionSchema extends PropertyConditionSchema {

    protected final String __when_type_assignable_1_class = null;

    protected final String __when_type_is_1_class = null;

    public FullConditionSchema(CompoundCondition parentCondition) {
      super(parentCondition);
    }

    protected Schema __when_type_assignable_begin(String className) {
      Condition cond = new ConditionWhenTypeAssignableTo(className);
      parentCondition.getConditions().add(cond);

      // No children allowed.
      return null;
    }

    protected Schema __when_type_is_begin(String className) {
      Condition cond = new ConditionWhenTypeIs(className);
      parentCondition.getConditions().add(cond);

      // No children allowed.
      return null;
    }

    @Override
    protected Schema subSchema(CompoundCondition cond) {
      return new FullConditionSchema(cond);
    }
  }

  private static final class IncludeExcludeSchema extends Schema {

    protected final String __exclude_1_name = null;

    protected final String __include_1_name = null;

    protected final String __skip_1_name = null;

    /**
     * Files neither in this module, nor available from other modules.
     */
    private final Set<String> excludes = new HashSet<String>();

    /**
     * Files in this module.
     */
    private final Set<String> includes = new HashSet<String>();

    /**
     * Files not in this module, but available from other modules.
     */
    private final Set<String> skips = new HashSet<String>();

    public Set<String> getExcludes() {
      return excludes;
    }

    public Set<String> getIncludes() {
      return includes;
    }

    public Set<String> getSkips() {
      return skips;
    }

    protected Schema __exclude_begin(String name) {
      excludes.add(name);
      return null;
    }

    protected Schema __include_begin(String name) {
      includes.add(name);
      return null;
    }

    protected Schema __skip_begin(String name) {
      skips.add(name);
      return null;
    }
}

  private static class LinkerName {
    public final String name;

    public LinkerName(String name) {
      this.name = name;
    }
  }

  /**
   * Converts a string into a linker name, validating it in the process.
   */
  private final class LinkerNameAttrCvt extends AttributeConverter {

    public Object convertToArg(Schema schema, int line, String elem,
        String attr, String value) throws UnableToCompleteException {
      // Ensure the value is a valid Java identifier
      if (!Util.isValidJavaIdent(value)) {
        Messages.LINKER_NAME_INVALID.log(logger, value, null);
        throw new UnableToCompleteException();
      }

      // It is a valid name.
      return new LinkerName(value);
    }
  }

  /**
   * A dotted Java identifier or null. Zero-length names are represented as
   * null.
   */
  private static class NullableName {
    public final String token;

    public NullableName(String token) {
      this.token = token;
    }
  }

  /**
   * Converts a string into a nullable name, validating it in the process.
   */
  private final class NullableNameAttrCvt extends AttributeConverter {

    public Object convertToArg(Schema schema, int line, String elem,
        String attr, String value) throws UnableToCompleteException {
      if (value == null || value.length() == 0) {
        return new NullableName(null);
      }

      // Ensure each part of the name is valid.
      //
      String[] tokens = (value + ". ").split("\\.");
      for (int i = 0; i < tokens.length - 1; i++) {
        String token = tokens[i];
        if (!Util.isValidJavaIdent(token)) {
          Messages.NAME_INVALID.log(logger, value, null);
          throw new UnableToCompleteException();
        }
      }

      // It is a valid name.
      //
      return new NullableName(value);
    }
  }

  /**
   * Converts property names into their corresponding property objects.
   */
  private final class PropertyAttrCvt extends AttributeConverter {
    private Class<? extends Property> concreteType;

    public PropertyAttrCvt(Class<? extends Property> concreteType) {
      this.concreteType = concreteType;
    }

    public Object convertToArg(Schema schema, int line, String elem,
        String attr, String value) throws UnableToCompleteException {
      // Find the named property.
      //
      Property prop = moduleDef.getProperties().find(value);

      if (prop != null) {
        // Found it.
        //
        if (concreteType.isInstance(prop)) {
          return prop;
        }
        logger.log(TreeLogger.ERROR, "The specified property '"
            + prop.getName() + "' is not of the correct type; found '"
            + prop.getClass().getSimpleName() + "' expecting '"
            + concreteType.getSimpleName() + "'");
      } else {
        // Property not defined. This is a problem.
        //
        Messages.PROPERTY_NOT_FOUND.log(logger, value, null);
      }
      throw new UnableToCompleteException();
    }
  }

  /**
   * A limited number of conditional predicates based only on properties.
   */
  private class PropertyConditionSchema extends Schema {
    protected final String __when_linker_added_1_name = null;

    protected final String __when_property_is_1_name = null;

    protected final String __when_property_is_2_value = null;

    protected final CompoundCondition parentCondition;

    public PropertyConditionSchema(CompoundCondition parentCondition) {
      this.parentCondition = parentCondition;
    }

    protected Schema __all_begin() {
      CompoundCondition cond = new ConditionAll();
      parentCondition.getConditions().add(cond);
      return subSchema(cond);
    }

    protected Schema __any_begin() {
      CompoundCondition cond = new ConditionAny();
      parentCondition.getConditions().add(cond);
      return subSchema(cond);
    }

    protected Schema __none_begin() {
      CompoundCondition cond = new ConditionNone();
      parentCondition.getConditions().add(cond);
      return subSchema(cond);
    }

    protected Schema __when_linker_added_begin(LinkerName linkerName) {
      Condition cond = new ConditionWhenLinkerAdded(linkerName.name);
      parentCondition.getConditions().add(cond);

      // No children allowed.
      return null;
    }

    /*
     * We intentionally use the BindingProperty type here for tough-love on
     * module writers. It prevents them from trying to create property providers
     * for unknown properties.
     */
    protected Schema __when_property_is_begin(BindingProperty prop,
        PropertyValue value) {
      Condition cond = new ConditionWhenPropertyIs(prop.getName(), value.token);
      parentCondition.getConditions().add(cond);

      // No children allowed.
      return null;
    }

    protected Schema subSchema(CompoundCondition cond) {
      return new PropertyConditionSchema(cond);
    }
  }

  private static class PropertyName {
    public final String token;

    public PropertyName(String token) {
      this.token = token;
    }
  }

  /**
   * Converts a string into a property name, validating it in the process.
   */
  private final class PropertyNameAttrCvt extends AttributeConverter {

    public Object convertToArg(Schema schema, int line, String elem,
        String attr, String value) throws UnableToCompleteException {
      // Ensure each part of the name is valid.
      //
      String[] tokens = (value + ". ").split("\\.");
      for (int i = 0; i < tokens.length - 1; i++) {
        String token = tokens[i];
        if (!Util.isValidJavaIdent(token)) {
          Messages.PROPERTY_NAME_INVALID.log(logger, value, null);
          throw new UnableToCompleteException();
        }
      }

      // It is a valid name.
      //
      return new PropertyName(value);
    }
  }

  private static class PropertyValue {
    public final String token;

    public PropertyValue(String token) {
      this.token = token;
    }
  }

  /**
   * Converts a comma-separated string into an array of property value tokens.
   */
  private final class PropertyValueArrayAttrCvt extends AttributeConverter {
    public Object convertToArg(Schema schema, int line, String elem,
        String attr, String value) throws UnableToCompleteException {
      String[] tokens = value.split(",");
      PropertyValue[] values = new PropertyValue[tokens.length];

      // Validate each token as we copy it over.
      //
      for (int i = 0; i < tokens.length; i++) {
        values[i] = (PropertyValue) propValueAttrCvt.convertToArg(schema, line,
            elem, attr, tokens[i]);
      }

      return values;
    }
  }

  /**
   * Converts a string into a property value, validating it in the process.
   */
  private final class PropertyValueAttrCvt extends AttributeConverter {
    public Object convertToArg(Schema schema, int line, String elem,
        String attr, String value) throws UnableToCompleteException {

      String token = value.trim();
      if (Util.isValidJavaIdent(token)) {
        return new PropertyValue(token);
      } else {
        Messages.PROPERTY_VALUE_INVALID.log(logger, token, null);
        throw new UnableToCompleteException();
      }
    }
  }

  private static class PropertyValueGlob {
    public final String token;

    public PropertyValueGlob(String token) {
      this.token = token;
    }

    public boolean isGlob() {
      return token.contains(BindingProperty.GLOB_STAR);
    }
  }

  /**
   * Converts a comma-separated string into an array of property value tokens.
   */
  private final class PropertyValueGlobArrayAttrCvt extends AttributeConverter {
    public Object convertToArg(Schema schema, int line, String elem,
        String attr, String value) throws UnableToCompleteException {
      String[] tokens = value.split(",");
      PropertyValueGlob[] values = new PropertyValueGlob[tokens.length];

      // Validate each token as we copy it over.
      //
      for (int i = 0; i < tokens.length; i++) {
        values[i] = (PropertyValueGlob) propValueGlobAttrCvt.convertToArg(
            schema, line, elem, attr, tokens[i]);
      }

      return values;
    }
  }

  /**
   * Converts a string into a property value glob, validating it in the process.
   */
  private final class PropertyValueGlobAttrCvt extends AttributeConverter {
    public Object convertToArg(Schema schema, int line, String elem,
        String attr, String value) throws UnableToCompleteException {

      String token = value.trim();
      String tokenNoStar = token.replaceAll(
          Pattern.quote(BindingProperty.GLOB_STAR), "");
      if (BindingProperty.GLOB_STAR.equals(token)
          || Util.isValidJavaIdent(tokenNoStar)) {
        return new PropertyValueGlob(token);
      } else {
        Messages.PROPERTY_VALUE_INVALID.log(logger, token, null);
        throw new UnableToCompleteException();
      }
    }
  }

  private static class ScriptSchema extends Schema {

    private StringBuffer script;

    private int startLineNumber = -1;

    public ScriptSchema() {
    }

    public void __text(String text) {
      if (script == null) {
        script = new StringBuffer();
        startLineNumber = getLineNumber();
      }
      script.append(text);
    }

    public String getScript() {
      return script != null ? script.toString() : null;
    }

    public int getStartLineNumber() {
      return startLineNumber;
    }
  }

  /**
   * Map of property names to the modules that defined them explicitly using
   * <define-configuration-property>, used to generate warning messages.
   */
  private static final HashMap<String, String> propertyDefinitions = new HashMap<String, String>();

  /**
   * Map of property names to the modules that defined them implicitly using
   * <set-configuration-property>, used to generate warning messages.
   */
  private static final HashMap<String, String> propertySettings = new HashMap<String, String>();

  private static void addPrefix(String[] strings, String prefix) {
    for (int i = 0; i < strings.length; ++i) {
      strings[i] = prefix + strings[i];
    }
  }

  /**
   * Returns <code>true</code> if the string equals "true" or "yes" using a case
   * insensitive comparison.
   */
  private static boolean toPrimitiveBoolean(String s) {
    return "yes".equalsIgnoreCase(s) || "true".equalsIgnoreCase(s);
  }

  protected final String __module_1_rename_to = "";
  private final PropertyAttrCvt bindingPropAttrCvt = new PropertyAttrCvt(
      BindingProperty.class);
  private final BodySchema bodySchema;
  private final ClassAttrCvt classAttrCvt = new ClassAttrCvt();
  private final PropertyAttrCvt configurationPropAttrCvt = new PropertyAttrCvt(
      ConfigurationProperty.class);
  private boolean foundAnyPublic;
  private boolean foundExplicitSourceOrSuperSource;
  private final JsProgram jsPgm = new JsProgram();
  private final LinkerNameAttrCvt linkerNameAttrCvt = new LinkerNameAttrCvt();
  private final ModuleDefLoader loader;
  private final TreeLogger logger;
  private final ModuleDef moduleDef;
  private final String moduleName;
  private final String modulePackageAsPath;
  private final URL moduleURL;
  private final NullableNameAttrCvt nullableNameAttrCvt = new NullableNameAttrCvt();
  private final PropertyNameAttrCvt propNameAttrCvt = new PropertyNameAttrCvt();
  private final PropertyValueArrayAttrCvt propValueArrayAttrCvt = new PropertyValueArrayAttrCvt();
  private final PropertyValueAttrCvt propValueAttrCvt = new PropertyValueAttrCvt();
  private final PropertyValueGlobArrayAttrCvt propValueGlobArrayAttrCvt = new PropertyValueGlobArrayAttrCvt();
  private final PropertyValueGlobAttrCvt propValueGlobAttrCvt = new PropertyValueGlobAttrCvt();

  public ModuleDefSchema(TreeLogger logger, ModuleDefLoader loader,
      String moduleName, URL moduleURL, String modulePackageAsPath,
      ModuleDef toConfigure) {
    this.logger = logger;
    this.loader = loader;
    this.moduleName = moduleName;
    this.moduleURL = moduleURL;
    this.modulePackageAsPath = modulePackageAsPath;
    assert (modulePackageAsPath.endsWith("/") || modulePackageAsPath.equals(""));
    this.moduleDef = toConfigure;
    this.bodySchema = new BodySchema();

    registerAttributeConverter(PropertyName.class, propNameAttrCvt);
    registerAttributeConverter(BindingProperty.class, bindingPropAttrCvt);
    registerAttributeConverter(ConfigurationProperty.class,
        configurationPropAttrCvt);
    registerAttributeConverter(PropertyValue.class, propValueAttrCvt);
    registerAttributeConverter(PropertyValue[].class, propValueArrayAttrCvt);
    registerAttributeConverter(PropertyValueGlob.class, propValueGlobAttrCvt);
    registerAttributeConverter(PropertyValueGlob[].class,
        propValueGlobArrayAttrCvt);
    registerAttributeConverter(LinkerName.class, linkerNameAttrCvt);
    registerAttributeConverter(NullableName.class, nullableNameAttrCvt);
    registerAttributeConverter(Class.class, classAttrCvt);
  }

  @SuppressWarnings("unused")
  protected Schema __module_begin(NullableName renameTo) {
    return bodySchema;
  }

  protected void __module_end(NullableName renameTo) {
    // Maybe infer source and public.
    //
    if (!foundExplicitSourceOrSuperSource) {
      bodySchema.addSourcePackage(modulePackageAsPath, "client", Empty.STRINGS,
          Empty.STRINGS, Empty.STRINGS, true, true, false);
    }

    if (!foundAnyPublic) {
      bodySchema.addPublicPackage(modulePackageAsPath, "public", Empty.STRINGS,
          Empty.STRINGS, Empty.STRINGS, true, true);
    }

    // We do this in __module_end so this value is never inherited
    moduleDef.setNameOverride(renameTo.token);
  }

  /**
   * Parses handwritten JavaScript found in the module xml, logging an error
   * message and throwing an exception if there's a problem.
   *
   * @param startLineNumber the start line number where the script was found;
   *          used to report errors
   * @param script the JavaScript to wrap in "function() { script }" to parse
   * @return the parsed function
   * @throws UnableToCompleteException
   */
  private JsFunction parseJsBlock(int startLineNumber, String script)
      throws UnableToCompleteException {
    script = "function() { " + script + "}";
    StringReader r = new StringReader(script);
    List<JsStatement> stmts;
    try {
      // TODO Provide more context here
      stmts = JsParser.parse(jsPgm.createSourceInfo(startLineNumber,
          moduleURL.toExternalForm()), jsPgm.getScope(), r);
    } catch (IOException e) {
      logger.log(TreeLogger.ERROR, "Error reading script source", e);
      throw new UnableToCompleteException();
    } catch (JsParserException e) {
      logger.log(TreeLogger.ERROR, "Error parsing JavaScript source", e);
      throw new UnableToCompleteException();
    }

    // Rip the body out of the parsed function and attach the JavaScript
    // AST to the method.
    //
    JsFunction fn = (JsFunction) ((JsExprStmt) stmts.get(0)).getExpression();
    return fn;
  }

}
// CHECKSTYLE_NAMING_ON
