/*
 * Copyright 2011 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.thirdparty.guava.common.collect.ImmutableMap;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.URL;
import java.util.Arrays;
import java.util.Map;
import java.util.TreeMap;

/**
 * This class represents a file that contains {@link CachedCompilationUnit}s
 * that make up a module.
 * 
 * Intended to work with other CompilationUnitArchives on the class path to
 * allow a project to be compiled incrementally. Therefore, one file may not
 * contain all dependent compilation units. To get all dependent compilation
 * units, the program will need to load all archives, plus any files not
 * contained in any archive.
 *
 * No mater how the archive is created, when serialized, the output file 
 * should be deterministic.
 */
public class CompilationUnitArchive implements Serializable {

  public static CompilationUnitArchive createFromFile(File location) throws IOException,
      ClassNotFoundException {
    return createFromStream(new FileInputStream(location));
  }

  public static CompilationUnitArchive createFromStream(InputStream stream) throws IOException,
      ClassNotFoundException {
    ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(stream));
    CompilationUnitArchive result = (CompilationUnitArchive) ois.readObject();
    ois.close();
    return result;
  }

  public static CompilationUnitArchive createFromURL(URL location) throws IOException,
      ClassNotFoundException {
    return createFromStream(location.openConnection().getInputStream());
  }

  private final String topModuleName;
  private transient Map<String, CompilationUnit> units;

  /**
   * Create an archive object.  Note that data is retained in memory only until
   * the {@link #writeToFile(File)} method is invoked.
   * 
   * @param topModuleName The name of the module used to compile this archive.
   *          That is, the original parameter passed to
   *          {@link com.google.gwt.dev.CompileModule}.
   */
  public CompilationUnitArchive(String topModuleName) {
    units = new TreeMap<String, CompilationUnit>();
    this.topModuleName = topModuleName;
  }

  /**
   * Add a compilation unit to the archive.
   */
  public void addUnit(CompilationUnit unit) {
    units.put(unit.getResourcePath(), unit);
  }

  public CompilationUnit findUnit(String resourcePath) {
    return units.get(resourcePath);
  }

  /**
   * The name of the module used to compile this archive. 
   */
  public String getTopModuleName() {
    return topModuleName;
  }

  /**
   * Retrieve all units stored in this archive.
   */
  public Map<String, CompilationUnit> getUnits() {
    return ImmutableMap.copyOf(units);
  }

  /**
   * Persists the units currently stored in the archive to the specified file.  The file
   * is immediately closed. 
   */
  public void writeToFile(File location) throws IOException {
    ObjectOutputStream oos =
        new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(location)));
    oos.writeObject(this);
    oos.close();
  }

  private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
    stream.defaultReadObject();
    units = new TreeMap<String, CompilationUnit>();
    CompilationUnit unitsIn[] = (CompilationUnit[]) stream.readObject();
    for (CompilationUnit unit : unitsIn) {
      assert unit != null;
      addUnit(unit);
    }
  }

  // CompilationUnits are serialized as a sorted array in order to make sure the
  // output format is deterministic.
  private void writeObject(ObjectOutputStream stream) throws IOException {
    stream.defaultWriteObject();
    CompilationUnit unitsOut[] = units.values().toArray(new CompilationUnit[units.size()]);
    Arrays.sort(unitsOut, CompilationUnit.COMPARATOR);
    stream.writeObject(unitsOut);
  }
}
