// $Id: FileWriter.java,v 1.5 2004/12/08 23:24:30 rkambic Exp $
/*
 * Copyright 1997-2000 Unidata Program Center/University Corporation for
 * Atmospheric Research, P.O. Box 3000, Boulder, CO 80307,
 * support@unidata.ucar.edu.
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or (at
 * your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
 * General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
package ucar.nc2;

import ucar.ma2.*;

import java.io.*;
import java.util.*;

/**
 * Helper class to copy a Netcdf File to another. This allows you to create a "view" of another
 *  NetcdfFile using NcML, and/or to write a remote or OpenDAP file into a local netcdf file.
 *  All metadata and data is copied out of the NetcdfFile and into the NetcdfFileWritable.
 *
 * <p>
 * If the NetcdfDataset doesnt have a uriString (which refers to the backing store), then only metadata is written,
 *  so ncml can be used like ncgen.
 *
 * @see ucar.nc2.NetcdfFile
 * @author caron
 * @version $Revision: 1.5 $ $Date: 2004/12/08 23:24:30 $
 */

public class FileWriter {
  private static boolean debug = false;

  /**
   * Copy a NetcdfFile to a physical file, using Netcdf-3 file format.
   * Cannot do groups, etc, until we get a Netcdf-4 file format.
   *
   * @param fileIn write from this NetcdfFile
   * @param fileName write to this local file
   * @return NetcdfFile that was written. It is closed, so all you can do is read its metadata.
   * To read data, you must open a new NetcdfFile.
   * @throws IOException
   */
  public static NetcdfFile writeToFile(NetcdfFile fileIn, String fileName) throws IOException {

    NetcdfFileWriteable ncfile = new NetcdfFileWriteable( fileName, false);
    if (debug) {
      System.out.println("FileWriter write "+fileIn.getLocation()+" to "+fileName);
      System.out.println("File In = "+fileIn);
    }

    // global attributes
    List glist = fileIn.getGlobalAttributes();
    for (int i=0; i<glist.size(); i++) {
      Attribute att = (Attribute) glist.get(i);

      if (att.isString())
        ncfile.addGlobalAttribute(att.getName(), att.getStringValue());
      else if (att.isArray())
        ncfile.addGlobalAttribute(att.getName(), att.getValues());
      else
        ncfile.addGlobalAttribute(att.getName(), att.getNumericValue());
      if (debug) System.out.println("add gatt= "+att);
    }

    // copy dimensions LOOK anon dimensions
    HashMap dimHash = new HashMap();
    Iterator iter = fileIn.getDimensions().iterator();
    while (iter.hasNext()) {
      Dimension oldD = (Dimension) iter.next();
      Dimension newD = ncfile.addDimension(oldD.getName(), oldD.isUnlimited() ? -1 : oldD.getLength(),
          oldD.isShared(), oldD.isUnlimited(), oldD.isUnknown());
      dimHash.put( newD.getName(), newD);
      if (debug) System.out.println("add dim= "+newD);
   }

    // Variables
    List varlist = fileIn.getVariables();
    for (int i=0; i<varlist.size(); i++) {
      Variable oldVar = (Variable) varlist.get(i);

      // copy dimensions LOOK anon dimensions
      Dimension[] dims = new Dimension[ oldVar.getRank()];
      List dimvList = oldVar.getDimensions();
      for (int j=0; j< dimvList.size(); j++) {
        Dimension oldD = (Dimension) dimvList.get(j);
        dims[j] = (Dimension) dimHash.get( oldD.getName());
      }

      ncfile.addVariable( oldVar.getName(), oldVar.getDataType(), dims);
      if (debug) System.out.println("add var= "+oldVar.getName());

          // attributes
      List attList = oldVar.getAttributes();
      for (int j=0; j<attList.size(); j++) {
        Attribute att = (Attribute) attList.get(j);
        if (att.isString())
          ncfile.addVariableAttribute(oldVar.getName(), att.getName(), att.getStringValue());
        if (att.isString())
          ncfile.addVariableAttribute(oldVar.getName(), att.getName(), att.getStringValue());
        else if (att.isArray())
         ncfile.addVariableAttribute(oldVar.getName(), att.getName(), att.getValues());
        else
          ncfile.addVariableAttribute(oldVar.getName(), att.getName(), att.getNumericValue());
      }

    }

    // create the file
    ncfile.create();
    if (debug)
      System.out.println("File Out= "+ncfile.toString());

    // if there is no uriString, then we are creating an empty file, ala ncgen, so copy only metadata
    // boolean metadataOnly = (ds.getUriString() == null);

    // write data
    for (int i=0; i<varlist.size(); i++) {
      Variable oldVar = (Variable) varlist.get(i);
      //if (metadataOnly && !oldVar.isMetadata()) continue;

      if (debug) System.out.println("write var= "+oldVar.getName()+ " size = "+oldVar.getSize());
      if (debug) System.out.println("time dim= "+ncfile.findDimension("time"));

      Array data = (Array) oldVar.read(); // LOOK: read all in one gulp!!
      try {
        ncfile.write(oldVar.getName(), data);
      } catch (InvalidRangeException e) {
        e.printStackTrace();
      }
      //if (debug) System.out.println("write var= "+oldVar.getName()+ " size = "+data.getSize());
      //if (debug) System.out.println("time dim= "+ncfile.findDimension("time"));
    }

    ncfile.close();
    if (debug) System.out.println("FileWriter done");

    return ncfile;
  }

  public static void main( String arg[]) {
    String uriString = (arg.length > 0) ? arg[0] : "test/data/dataset/xml/renameVar.xml"; // "dods://dods.coas.oregonstate.edu:8080/dods/dts/ingrid";
    String filenameOut = (arg.length > 1) ? arg[1] : "fileWriterTest.nc";

    try {
      NetcdfFile ncfileIn = ucar.nc2.dataset.NetcdfDataset.openDataset(uriString);

      // now can write as netcdf file
      NetcdfFile ncfile = FileWriter.writeToFile( ncfileIn, filenameOut);
      System.out.println("NetcdfFile = "+ncfile);

    } catch (java.net.MalformedURLException e) {
      System.out.println("bad URL error = "+e);
    } catch (IOException e) {
      System.out.println("IO error = "+e);
      e.printStackTrace();
    }
  }

}

/* Change History:
   $Log: FileWriter.java,v $
   Revision 1.5  2004/12/08 23:24:30  rkambic
   chks were too rigid, relaxed. debug is now off

   Revision 1.4  2004/12/08 21:51:36  caron
   no message

   Revision 1.3  2004/12/08 21:14:26  caron
   no message

   Revision 1.2  2004/12/03 04:46:27  caron
   no message

   Revision 1.1  2004/12/01 05:57:45  caron
   no message

   Revision 1.4  2003/10/28 23:57:20  caron
   minor

   Revision 1.3  2003/05/15 23:12:52  caron
   debug off

   Revision 1.2  2003/05/14 21:18:44  caron
   use NCML like ncgen

   Revision 1.1  2003/04/08 15:06:24  caron
   nc2 version 2.1

 */



