/*
 * Copyright 2007 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.javac;

import com.google.gwt.core.ext.CachedGeneratorResult;
import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.IncrementalGenerator;
import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.RebindResult;
import com.google.gwt.core.ext.RebindRuleResolver;
import com.google.gwt.core.ext.SubsetFilteringPropertyOracle;
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.linker.Artifact;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.core.ext.linker.EmittedArtifact.Visibility;
import com.google.gwt.core.ext.linker.GeneratedResource;
import com.google.gwt.core.ext.linker.impl.StandardGeneratedResource;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.CompilerContext;
import com.google.gwt.dev.cfg.RuleGenerateWith;
import com.google.gwt.dev.resource.Resource;
import com.google.gwt.dev.resource.ResourceOracle;
import com.google.gwt.dev.resource.impl.AbstractResourceOracle;
import com.google.gwt.dev.util.DiskCache;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.collect.HashSet;
import com.google.gwt.dev.util.collect.IdentityHashMap;
import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
import com.google.gwt.thirdparty.guava.common.io.Files;
import com.google.gwt.util.tools.Utility;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedSet;

/**
 * Manages generators and generated units during a single compilation.
 */
public class StandardGeneratorContext implements GeneratorContext {

  /**
   * Wraps a ResourceOracle to collect the paths of Resources read by Generators.
   */
  private class RecordingResourceOracle extends AbstractResourceOracle {

    private final ResourceOracle wrappedResourceOracle;

    public RecordingResourceOracle(ResourceOracle wrappedResourceOracle) {
      this.wrappedResourceOracle = wrappedResourceOracle;
    }

    @Override
    public void clear() {
      wrappedResourceOracle.clear();
    }

    @Override
    public Set<String> getPathNames() {
      return wrappedResourceOracle.getPathNames();
    }

    @Override
    public Resource getResource(String pathName) {
      pathName = Files.simplifyPath(pathName);
      compilerContext.getMinimalRebuildCache().associateReboundTypeWithInputResource(
          currentRebindBinaryTypeName, pathName);
      return wrappedResourceOracle.getResource(pathName);
    }

    @Override
    public Set<Resource> getResources() {
      return wrappedResourceOracle.getResources();
    }
  }

  /**
   * Extras added to {@link GeneratedUnit}.
   */
  private static interface Generated extends GeneratedUnit {
    void abort();

    void commit(TreeLogger logger);
  }

  /**
   * This generated unit acts as a normal generated unit as well as a buffer
   * into which generators can write their source. A controller should ensure
   * that source isn't requested until the generator has finished writing it.
   * This version is backed by {@link StandardGeneratorContext#diskCache}.
   */
  public static class GeneratedUnitImpl implements Generated {

    /**
     * A token to retrieve this object's bytes from the disk cache.
     */
    protected long sourceToken = -1;

    private long creationTime;

    private String strongHash; // cache so that refreshes work correctly

    private StringWriter sw;

    private final String typeName;

    public GeneratedUnitImpl(StringWriter sw, String typeName) {
      this.typeName = typeName;
      this.sw = sw;
    }

    @Override
    public void abort() {
      sw = null;
    }

    /**
     * Finalizes the source and adds this generated unit to the host.
     */
    @Override
    public void commit(TreeLogger logger) {
      String source = sw.toString();
      strongHash = Util.computeStrongName(Util.getBytes(source));
      sourceToken = diskCache.writeString(source);
      sw = null;
      creationTime = System.currentTimeMillis();
    }

    @Override
    public long creationTime() {
      return creationTime;
    }

    @Override
    public String getSource() {
      if (sw != null) {
        throw new IllegalStateException("source not committed");
      }
      return diskCache.readString(sourceToken);
    }

    @Override
    public String getSourceMapPath() {
      return "gen/" + getTypeName().replace('.', '/') + ".java";
    }

    @Override
    public long getSourceToken() {
      if (sw != null) {
        throw new IllegalStateException("source not committed");
      }
      return sourceToken;
    }

    @Override
    public String getStrongHash() {
      return strongHash;
    }

    @Override
    public String getTypeName() {
      return typeName;
    }

    @Override
    public String optionalFileLocation() {
      return null;
    }
  }

  /**
   * This generated unit acts as a normal generated unit as well as a buffer
   * into which generators can write their source. A controller should ensure
   * that source isn't requested until the generator has finished writing it.
   * This version is backed by an explicit generated file.
   */
  private static class GeneratedUnitWithFile extends GeneratedUnitImpl {
    private final File file;

    public GeneratedUnitWithFile(File file, StringWriter pw, String typeName) {
      super(pw, typeName);
      this.file = file;
    }

    @Override
    public void commit(TreeLogger logger) {
      super.commit(logger);
      FileOutputStream fos = null;
      try {
        fos = new FileOutputStream(file);
        diskCache.transferToStream(sourceToken, fos);
      } catch (IOException e) {
        logger.log(TreeLogger.WARN, "Error writing out generated unit at '"
            + file.getAbsolutePath() + "': " + e);
      } finally {
        Utility.close(fos);
      }
    }

    @Override
    public String optionalFileLocation() {
      return file.exists() ? Util.stripJarPathPrefix(file.getAbsolutePath()) : null;
    }
  }

  /**
   * Manages a resource that is in the process of being created by a generator.
   */
  private static class PendingResource extends OutputStream {

    private ByteArrayOutputStream baos = new ByteArrayOutputStream();
    private final String partialPath;

    public PendingResource(String partialPath) {
      this.partialPath = partialPath;
    }

    public void abort() {
      baos = null;
    }

    public String getPartialPath() {
      return partialPath;
    }

    public byte[] takeBytes() {
      byte[] result = baos.toByteArray();
      baos = null;
      return result;
    }

    @Override
    public void write(byte[] b) throws IOException {
      if (baos == null) {
        throw new IOException("stream closed");
      }
      baos.write(b);
    }

    @Override
    public void write(byte[] b, int off, int len) throws IOException {
      if (baos == null) {
        throw new IOException("stream closed");
      }
      baos.write(b, off, len);
    }

    @Override
    public void write(int b) throws IOException {
      if (baos == null) {
        throw new IOException("stream closed");
      }
      baos.write(b);
    }
  }

  private static final String GENERATOR_VERSION_ID_KEY = "generator-version-id";

  private static DiskCache diskCache = DiskCache.INSTANCE;

  private static final Map<String, CompilerEventType> eventsByGeneratorType =
      new HashMap<String, CompilerEventType>();
  static {
    eventsByGeneratorType.put(
        "com.google.gwt.resources.rebind.context.InlineClientBundleGenerator",
        CompilerEventType.GENERATOR_CLIENT_BUNDLE);
    eventsByGeneratorType.put("com.google.gwt.i18n.rebind.LocalizableGenerator",
        CompilerEventType.GENERATOR_I18N);
    eventsByGeneratorType.put("com.google.gwt.i18n.rebind.LocaleInfoGenerator",
        CompilerEventType.GENERATOR_I18N);
    eventsByGeneratorType.put("com.google.gwt.i18n.rebind.CurrencyListGenerator",
        CompilerEventType.GENERATOR_I18N);
    eventsByGeneratorType.put("com.google.gwt.i18n.rebind.CustomDateTimeFormatGenerator",
        CompilerEventType.GENERATOR_I18N);
    eventsByGeneratorType.put("com.google.gwt.user.rebind.rpc.ServiceInterfaceProxyGenerator",
        CompilerEventType.GENERATOR_RPC);
    eventsByGeneratorType.put("com.google.gwt.uibinder.rebind.UiBinderGenerator",
        CompilerEventType.GENERATOR_UIBINDER);
    eventsByGeneratorType.put("com.google.gwt.inject.rebind.GinjectorGenerator",
        CompilerEventType.GENERATOR_GIN);
  }

  private final ArtifactSet allGeneratedArtifacts;

  private final Map<String, GeneratedUnit> committedGeneratedCups =
      new HashMap<String, GeneratedUnit>();

  private CompilationState compilationState;

  private Class<? extends Generator> currentGenerator;

  private final File genDir;

  private final Map<Class<? extends Generator>, Generator> generators =
      new IdentityHashMap<Class<? extends Generator>, Generator>();

  private ArtifactSet newlyGeneratedArtifacts = new ArtifactSet();

  private final Set<String> newlyGeneratedTypeNames = new HashSet<String>();

  private final Map<String, PendingResource> pendingResources =
      new HashMap<String, PendingResource>();

  private transient PropertyOracle propertyOracle;

  private RebindRuleResolver rebindRuleResolver;

  private final Map<PrintWriter, Generated> uncommittedGeneratedCupsByPrintWriter =
      new IdentityHashMap<PrintWriter, Generated>();

  private CachedGeneratorResultImpl cachedRebindResult = null;

  private boolean generatorResultCachingEnabled = false;

  private List<String> cachedTypeNamesToReuse = null;

  private boolean isProdMode;

  private CompilerContext compilerContext;

  private String currentRebindBinaryTypeName;

  private final ResourceOracle buildResourceOracle;

  /**
   * Normally, the compiler host would be aware of the same types that are
   * available in the supplied type oracle although it isn't strictly required.
   */
  public StandardGeneratorContext(CompilerContext compilerContext,
      CompilationState compilationState, ArtifactSet allGeneratedArtifacts, boolean isProdMode) {
    this.compilerContext = compilerContext;
    this.compilationState = compilationState;
    this.genDir = compilerContext.getOptions().getGenDir();
    this.allGeneratedArtifacts = allGeneratedArtifacts;
    this.isProdMode = isProdMode;

    this.buildResourceOracle =
        new RecordingResourceOracle(compilerContext.getBuildResourceOracle());

    ResourceLocatorImpl.resetClassLoaderLoadWarningCount();
  }

  /**
   * Adds a generated unit to the context if not already present, but will not
   * overwrite an existing unit.
   */
  public void addGeneratedUnit(GeneratedUnit gu) {
    if (!committedGeneratedCups.containsKey(gu.getTypeName())) {
      committedGeneratedCups.put(gu.getTypeName(), gu);
    }
  }

  /**
   * Adds generated units to the context, but will not overwrite any existing
   * units that might already be present.
   */
  public void addGeneratedUnits(Collection<GeneratedUnit> generatedUnits) {
    for (GeneratedUnit gu : generatedUnits) {
      addGeneratedUnit(gu);
    }
  }

  /**
   * Adds all available cached generated units to the context. Existing units
   * for a given type will not be overwritten.
   */
  public void addGeneratedUnitsFromCache() {
    if (cachedRebindResult != null && cachedRebindResult.getGeneratedUnits() != null) {
      addGeneratedUnits(cachedRebindResult.getGeneratedUnits());
    }
  }

  /**
   * Adds cached generated units to the context that have been marked for reuse.
   * Existing units for a given type will not be overwritten.
   */
  public void addGeneratedUnitsMarkedForReuseFromCache() {
    if (cachedTypeNamesToReuse != null && cachedRebindResult != null) {
      for (String typeName : cachedTypeNamesToReuse) {
        GeneratedUnit gu = cachedRebindResult.getGeneratedUnit(typeName);
        if (gu != null) {
          addGeneratedUnit(gu);
        }
      }
    }
  }

  /**
   * Checks whether a rebind rule is available for a given sourceTypeName.
   */
  @Override
  public boolean checkRebindRuleAvailable(String sourceTypeName) {
    if (rebindRuleResolver != null) {
      return rebindRuleResolver.checkRebindRuleResolvable(sourceTypeName);
    } else {
      return false;
    }
  }

  /**
   * Frees memory used up by compilation state.
   */
  public void clear() {
    compilationState = null;
    generators.clear();
  }

  /**
   * Commits a pending generated type.
   */
  @Override
  public final void commit(TreeLogger logger, PrintWriter pw) {
    Generated gcup = uncommittedGeneratedCupsByPrintWriter.get(pw);
    if (gcup == null) {
      logger.log(TreeLogger.WARN, "Generator attempted to commit an unknown PrintWriter", null);
      return;
    }
    gcup.commit(logger);
    uncommittedGeneratedCupsByPrintWriter.remove(pw);
    committedGeneratedCups.put(gcup.getTypeName(), gcup);

    // Write as a source artifact so that a debugger can use it.
    // TODO: if we're not generating sourcemaps then we should probably skip this entirely
    // since the data will be written to the shard's jar file and never read.
    // (But how do we check that?)

    if (currentGenerator == null) {
      return; // probably a test.
    }

    GeneratedResource debuggerSource =
        new StandardGeneratedResource(gcup.getSourceMapPath(), gcup.getSourceToken());
    debuggerSource.setVisibility(Visibility.Source);
    commitArtifact(logger, debuggerSource);
  }

  /**
   * Adds an Artifact to the context's ArtifactSets. This will replace a
   * pre-existing entry in allGeneratedArtifacts, but will not overwrite an
   * entry in the newlyGeneratedArtifacts (since it is assumed by convention
   * that only new entries will ever be inserted here for a given generator
   * run).
   */
  @Override
  public void commitArtifact(TreeLogger logger, Artifact<?> artifact) {
    allGeneratedArtifacts.replace(artifact);
    newlyGeneratedArtifacts.add(artifact);
  }

  /**
   * Commits all available cached Artifacts to the context.
   */
  public void commitArtifactsFromCache(TreeLogger logger) {
    if (cachedRebindResult != null && cachedRebindResult.getArtifacts() != null) {
      for (Artifact<?> art : cachedRebindResult.getArtifacts()) {
        commitArtifact(logger, art);
      }
    }
  }

  @Override
  public GeneratedResource commitResource(TreeLogger logger, OutputStream os)
      throws UnableToCompleteException {

    PendingResource pendingResource = null;
    String partialPath = null;
    if (os instanceof PendingResource) {
      pendingResource = (PendingResource) os;
      partialPath = pendingResource.getPartialPath();
      // Make sure it's ours by looking it up in the map.
      if (pendingResource != pendingResources.get(partialPath)) {
        pendingResource = null;
      }
    }
    if (pendingResource == null) {
      logger.log(TreeLogger.WARN, "Generator attempted to commit an unknown OutputStream", null);
      throw new UnableToCompleteException();
    }

    // Add the GeneratedResource to the ArtifactSet
    GeneratedResource toReturn =
        new StandardGeneratedResource(partialPath, pendingResource.takeBytes());
    commitArtifact(logger, toReturn);
    pendingResources.remove(pendingResource.getPartialPath());
    return toReturn;
  }

  /**
   * Call this whenever generators are known to not be running to clear out
   * uncommitted compilation units and to force committed compilation units to
   * be parsed and added to the type oracle.
   *
   * @return any newly generated artifacts since the last call
   *
   * @throw UnableToCompleteException if the compiler aborted (not
   * a normal compile error).</p>
   */
  public ArtifactSet finish(TreeLogger logger) throws UnableToCompleteException {
    abortUncommittedResources(logger);

    try {
      TreeLogger branch;
      if (isDirty()) {
        // Assimilate the new types into the type oracle.
        //
        String msg = "Assimilating generated source";
        branch = logger.branch(TreeLogger.DEBUG, msg, null);

        TreeLogger subBranch = null;
        if (branch.isLoggable(TreeLogger.DEBUG)) {
          subBranch = branch.branch(TreeLogger.DEBUG, "Generated source files...", null);
        }

        for (GeneratedUnit gcup : committedGeneratedCups.values()) {
          String qualifiedTypeName = gcup.getTypeName();
          if (subBranch != null) {
            subBranch.log(TreeLogger.DEBUG, qualifiedTypeName, null);
          }
        }

        compilationState.addGeneratedCompilationUnits(logger, committedGeneratedCups.values());
      }
      return newlyGeneratedArtifacts;
    } finally {

      // Remind the user if there uncommitted cups.
      if (!uncommittedGeneratedCupsByPrintWriter.isEmpty()) {
        String msg =
            "For the following type(s), generated source was never committed (did you forget to call commit()?)";
        logger = logger.branch(TreeLogger.WARN, msg, null);

        for (Generated unit : uncommittedGeneratedCupsByPrintWriter.values()) {
          logger.log(TreeLogger.WARN, unit.getTypeName(), null);
        }
      }

      reset();
    }
  }

  public boolean isDirty() {
    return !committedGeneratedCups.isEmpty();
  }

  /**
   * Clears all accumulated artifacts and state so that the context can be used
   * as if from scratch. Is useful for clearing out undesired changes after
   * having used the context to explore some hypothetical situations, for
   * example to run Generators for the purpose of discovering the properties
   * they depend on.
   */
  public void reset() {
    uncommittedGeneratedCupsByPrintWriter.clear();
    committedGeneratedCups.clear();
    newlyGeneratedTypeNames.clear();
    newlyGeneratedArtifacts = new ArtifactSet();
    cachedTypeNamesToReuse = null;
  }

  public Set<String> getActiveLinkerNames() {
    return compilerContext.getModule().getActiveLinkerNames();
  }

  /**
   * Gets newly committed artifacts.
   */
  public ArtifactSet getArtifacts() {
    return new ArtifactSet(newlyGeneratedArtifacts);
  }

  /**
   * Gets the previously cached rebind result for the current generator.
   */
  @Override
  public CachedGeneratorResult getCachedGeneratorResult() {
    return cachedRebindResult;
  }

  public GeneratorContext getCanonicalContext() {
    return this;
  }

  public CompilationState getCompilationState() {
    return compilationState;
  }

  /**
   * Gets all committed Java units.
   */
  public Map<String, GeneratedUnit> getGeneratedUnitMap() {
    return committedGeneratedCups;
  }

  @Override
  public final PropertyOracle getPropertyOracle() {
    return propertyOracle;
  }

  @Override
  public ResourceOracle getResourcesOracle() {
    return buildResourceOracle;
  }

  @Override
  public final TypeOracle getTypeOracle() {
    return compilationState.getTypeOracle();
  }

  @Override
  public boolean isGeneratorResultCachingEnabled() {
    return generatorResultCachingEnabled;
  }

  @Override
  public boolean isProdMode() {
    return isProdMode;
  }

  /**
   * This method is maintained for backwards compatibility.
   * {@link #runGeneratorIncrementally} should be used instead.
   */
  public String runGenerator(TreeLogger logger, Class<? extends Generator> generatorClass,
      String typeName) throws UnableToCompleteException {

    RebindResult result = runGeneratorIncrementally(logger, generatorClass, typeName);

    return result.getResultTypeName();
  }

  /**
   * Runs a generator incrementally, with support for managing the returned
   * {@link RebindResult} object, which can contain cached results. This is a
   * replacement for the {@link #runGenerator} method.
   * <p>
   * If the passed in generatorClass is an instance of
   * {@link IncrementalGenerator}, it's
   * {@link IncrementalGenerator#generateIncrementally} method will be called.
   * <p>
   * Otherwise, for backwards compatibility, the generatorClass will be wrapped
   * in a {@link IncrementalGenerator} instance, and it's
   * {@link Generator#generate} method will be called.
   *
   * @param logger
   * @param generatorClass
   * @param typeName
   * @return a RebindResult
   * @throws UnableToCompleteException
   */
  public RebindResult runGeneratorIncrementally(TreeLogger logger,
      Class<? extends Generator> generatorClass, String typeName) throws UnableToCompleteException {
    String msg = "Invoking generator " + generatorClass.getName();
    logger = logger.branch(TreeLogger.DEBUG, msg, null);

    Generator generator = generators.get(generatorClass);
    if (generator == null) {
      try {
        generator = generatorClass.newInstance();
        generators.put(generatorClass, generator);
      } catch (Throwable e) {
        logger.log(TreeLogger.ERROR, "Unexpected error trying to instantiate Generator '"
            + generatorClass.getName() + "'", e);
        throw new UnableToCompleteException();
      }
    }

    setCurrentGenerator(generatorClass);

    // Avoid call to System.currentTimeMillis() if not logging DEBUG level
    boolean loggable = logger.isLoggable(TreeLogger.DEBUG);
    long before = loggable ? System.currentTimeMillis() : 0L;

    String generatorClassName = generator.getClass().getName();
    CompilerEventType type = eventsByGeneratorType.get(generatorClassName);

    if (type == null) {
      type = CompilerEventType.GENERATOR_OTHER;
    }

    Event generatorEvent =
        SpeedTracerLogger.start(type, "class", generatorClassName, "type", typeName);

    PropertyOracle originalPropertyOracle = propertyOracle;
    try {
      RebindResult result;
      // TODO(stalcup): refactor the Generator/PropertyOracle system (in a potentially backwards
      // incompatible way) so that all Generators are forced to accurately declare the names of
      // properties they care about.
      propertyOracle = new SubsetFilteringPropertyOracle(
          RuleGenerateWith.getAccessedPropertyNames(generator.getClass()), originalPropertyOracle,
          generatorClassName + "'s RunsLocal annotation may need to be updated.");
      if (generator instanceof IncrementalGenerator) {
        IncrementalGenerator incGenerator = (IncrementalGenerator) generator;

        // check version id for any previously cached rebind result
        if (cachedRebindResult != null) {
          Long cachedVersionId = (Long) cachedRebindResult.getClientData(GENERATOR_VERSION_ID_KEY);
          if (cachedVersionId != null && cachedVersionId != incGenerator.getVersionId()) {
            // remove from context
            if (logger.isLoggable(TreeLogger.TRACE)) {
              logger.log(TreeLogger.TRACE, "Got version mismatch with cached generator result for "
                  + typeName + ", invalidating cached result");
            }
            cachedRebindResult = null;
          }
        }

        // run the generator
        result = incGenerator.generateIncrementally(logger, this, typeName);

        // add version id to the returned result
        result.putClientData(GENERATOR_VERSION_ID_KEY, incGenerator.getVersionId());
      } else {
        // run a non-incremental generator
        result = IncrementalGenerator.generateNonIncrementally(logger, generator, this, typeName);
      }

      if (loggable) {
        long after = System.currentTimeMillis();
        msg =
            "Generator returned type '" + result.getResultTypeName() + "; mode "
                + result.getRebindMode() + "; in " + (after - before) + " ms";
        logger.log(TreeLogger.DEBUG, msg, null);
      }
      return result;
    } catch (AssertionError e) {
      // Catch and log the assertion as a convenience to the developer
      logger.log(TreeLogger.ERROR, "Generator '" + generatorClass.getName()
          + "' failed an assertion while rebinding '" + typeName + "'", e);
      throw new UnableToCompleteException();
    } catch (RuntimeException e) {
      logger.log(TreeLogger.ERROR, "Generator '" + generatorClass.getName()
          + "' threw an exception while rebinding '" + typeName + "'", e);
      throw new UnableToCompleteException();
    } finally {
      propertyOracle = originalPropertyOracle;
      generatorEvent.end();
    }
  }

  /**
   * Set previously cached rebind result for currently active generator.
   */
  public void setCachedGeneratorResult(CachedGeneratorResult cachedRebindResult) {
    this.cachedRebindResult = (CachedGeneratorResultImpl) cachedRebindResult;
  }

  public void setCurrentGenerator(Class<? extends Generator> currentGenerator) {
    this.currentGenerator = currentGenerator;
  }

  public void setCurrentRebindBinaryTypeName(String currentRebindBinaryTypeName) {
    this.currentRebindBinaryTypeName = currentRebindBinaryTypeName;
  }

  public void setGeneratorResultCachingEnabled(boolean enabled) {
    this.generatorResultCachingEnabled = enabled;
  }

  /**
   * Sets the current transient property oracle to answer current property
   * questions.
   */
  public void setPropertyOracle(PropertyOracle propertyOracle) {
    this.propertyOracle = propertyOracle;
  }

  public void setRebindRuleResolver(RebindRuleResolver resolver) {
    this.rebindRuleResolver = resolver;
  }

  @Override
  public PrintWriter tryCreate(TreeLogger logger, String packageName, String simpleTypeName) {
    String typeName;
    if (packageName.length() == 0) {
      typeName = simpleTypeName;
    } else {
      typeName = packageName + '.' + simpleTypeName;
    }

    compilerContext.getMinimalRebuildCache().associateReboundTypeWithGeneratedCompilationUnitName(
        currentRebindBinaryTypeName, typeName);

    // Is type already known to the host?
    JClassType existingType = getTypeOracle().findType(packageName, simpleTypeName);
    if (existingType != null) {
      if (logger.isLoggable(TreeLogger.DEBUG)) {
        logger.log(TreeLogger.DEBUG, "Type '" + typeName
            + "' already exists and will not be re-created ", null);
      }
      return null;
    }

    // Type recently generated?
    if (newlyGeneratedTypeNames.contains(typeName)) {
      return null;
    }

    // The type isn't there, so we can let the caller create it. Remember that
    // it is pending so another attempt to create the same type will fail.
    Generated gcup;
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw, true) {
      /**
       * Overridden to force unix-style line endings for consistent behavior
       * across platforms.
       */
      @Override
      public void println() {
        super.print('\n');
        super.flush();
      }
    };
    if (this.genDir == null) {
      gcup = new GeneratedUnitImpl(sw, typeName);
    } else {
      File dir = new File(genDir, packageName.replace('.', File.separatorChar));
      // No need to check mkdirs result because an IOException will occur anyway
      dir.mkdirs();
      File srcFile = new File(dir, simpleTypeName + ".java");
      if (srcFile.exists()) {
        srcFile.delete();
      }
      gcup = new GeneratedUnitWithFile(srcFile, sw, typeName);
    }
    uncommittedGeneratedCupsByPrintWriter.put(pw, gcup);
    newlyGeneratedTypeNames.add(typeName);
    return pw;
  }

  @Override
  public OutputStream tryCreateResource(TreeLogger logger, String partialPath)
      throws UnableToCompleteException {

    logger =
        logger.branch(TreeLogger.DEBUG, "Preparing pending output resource '" + partialPath + "'",
            null);

    // Disallow null or empty names.
    if (partialPath == null || partialPath.trim().equals("")) {
      logger.log(TreeLogger.ERROR, "The resource name must be a non-empty string", null);
      throw new UnableToCompleteException();
    }

    // Disallow absolute paths.
    if (new File(partialPath).isAbsolute()) {
      logger
          .log(
              TreeLogger.ERROR,
              "Resource paths are intended to be relative to the compiled output directory and cannot be absolute",
              null);
      throw new UnableToCompleteException();
    }

    // Disallow backslashes (to promote consistency in calling code).
    if (partialPath.indexOf('\\') >= 0) {
      logger.log(TreeLogger.ERROR,
          "Resource paths must contain forward slashes (not backslashes) to denote subdirectories",
          null);
      throw new UnableToCompleteException();
    }

    // Check for public path collision.
    if (compilerContext.getPublicResourceOracle().getResource(partialPath) != null) {
      logger.log(TreeLogger.WARN, "Cannot create resource '" + partialPath
          + "' because it already exists on the public path", null);
      return null;
    }

    // See if the file is already committed.
    SortedSet<GeneratedResource> resources = allGeneratedArtifacts.find(GeneratedResource.class);
    for (GeneratedResource resource : resources) {
      if (partialPath.equals(resource.getPartialPath())) {
        return null;
      }
    }

    // See if the file is pending.
    if (pendingResources.containsKey(partialPath)) {
      // It is already pending.
      logger.log(TreeLogger.WARN, "The file '" + partialPath + "' is already a pending resource",
          null);
      return null;
    }
    PendingResource pendingResource = new PendingResource(partialPath);
    pendingResources.put(partialPath, pendingResource);
    return pendingResource;
  }

  /**
   * Adds a type name to the list of types to be reused from cache, if
   * available.
   *
   * @param typeName The fully qualified name of a type.
   *
   * @return true, if the type is available in the cache and was successfully
   *         added to the list for reuse, false otherwise.
   */
  @Override
  public boolean tryReuseTypeFromCache(String typeName) {
    if (!isGeneratorResultCachingEnabled() || cachedRebindResult == null
        || !cachedRebindResult.isTypeCached(typeName)) {
      return false;
    }

    if (cachedTypeNamesToReuse == null) {
      cachedTypeNamesToReuse = new ArrayList<String>();
    }
    cachedTypeNamesToReuse.add(typeName);
    return true;
  }

  private void abortUncommittedResources(TreeLogger logger) {
    if (pendingResources.isEmpty()) {
      // Nothing to do.
      return;
    }

    // Warn the user about uncommitted resources.
    logger = logger.branch(TreeLogger.WARN,
        "The following resources will not be created because they were never "
        + "committed (did you forget to call commit()?)", null);

    for (Entry<String, PendingResource> entry : pendingResources.entrySet()) {
      logger.log(TreeLogger.WARN, entry.getKey());
      entry.getValue().abort();
    }
    pendingResources.clear();
  }
}
