/* * Copyright 1998, University Corporation for Atmospheric Research * All Rights Reserved. * See file LICENSE for copying and redistribution conditions. * * $Id: Plain.java,v 1.28 2002-10-21 20:07:44 donm Exp $ */ package visad.data.netcdf; import java.io.FileNotFoundException; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.rmi.RemoteException; import java.util.Set; import java.util.StringTokenizer; import java.util.TreeSet; import ucar.netcdf.Netcdf; import ucar.netcdf.NetcdfFile; import ucar.netcdf.Schema; import ucar.netcdf.Variable; import ucar.netcdf.VariableIterator; import visad.data.BadFormException; import visad.data.FormNode; import visad.data.netcdf.in.*; import visad.data.netcdf.out.VisADAdapter; import visad.Data; import visad.DataImpl; import visad.UnimplementedException; import visad.VisADException; /** * A moderately stupid implementation of a netCDF data form for the * storage of persistent data objects on local disk. */ public class Plain extends NetCDF { /** * The quantity database to use for mapping netCDF variables to * VisAD Quantity-s. */ private final QuantityDB quantityDB; /** * The flag for transforming netCDF char variables to Text */ private final boolean charToText; /** * Constructs a default, netCDF data form. * * @throws VisADException Couldn't create necessary VisAD object */ public Plain() throws VisADException { this(QuantityDBManager.instance(), false); } /** * Constructs a netCDF data form that converts * * @param charToText The char to Text flag */ public Plain(boolean charToText) { this(QuantityDBManager.instance(), charToText); } /** * Constructs a netCDF data form that uses the given quantity database. * * @param db The quantity database. */ public Plain(QuantityDB db) { this(db, false); } /** * Constructs a netCDF data form that uses the given quantity database, * and the flag for converting char to Text. * * @param db The quantity database. * @param charToText The char to Text flag */ public Plain(QuantityDB db, boolean charToText) { super("Plain"); quantityDB = db; this.charToText = charToText; } /** * Save a VisAD data object in this form. * * @param path The pathname of the netCDF file to * be created. * @param data The data to be saved. * @param replace Whether to replace an existing file. * @exception BadFormException netCDF can't handle data object * @exception VisADException Couldn't create necessary VisAD object * @exception IOException I/O error. File might already exist. * @exception RemoteException Remote execution error * @exception UnimplementedException * Not yet! */ public synchronized void save(String path, Data data, boolean replace) throws BadFormException, IOException, RemoteException, VisADException, UnimplementedException { VisADAdapter adapter = new VisADAdapter(data); Schema schema = new Schema(adapter); NetcdfFile file = new NetcdfFile(path, replace, /*fill=*/false, schema); try { VariableIterator iter = file.iterator(); while (iter.hasNext()) { Variable outVar = iter.next(); Variable inVar = adapter.get(outVar.getName()); int rank = outVar.getRank(); int[] origin = new int[rank]; for (int i = 0; i < rank; ++i) origin[i] = 0; outVar.copyin(origin, inVar); } } finally { file.close(); } } /** * Add data to an existing data object. * * @param id Pathname of the existing netCDF file. * @param data Data to be saved. * @param replace Whether or not to replace duplicate, existing data. * @exception BadFormException * netCDF can't handle data object. */ public synchronized void add(String id, Data data, boolean replace) throws BadFormException { } /** * Returns a VisAD data object corresponding to a netCDF dataset. * * @param spec Specification of the existing netCDF dataset. * @return A VisAD data object corresponding to the netCDF * dataset. * @throws BadFormException if the netCDF dataset cannot be adapted to a * VisAD data object. * @throws VisADException if a problem occurs in core VisAD. Probably a * VisAD object couldn't be created. * @throws IOException if an I/O failure occurs. * @see NetcdfAdapter#getData() */ public synchronized DataImpl open(String spec) throws BadFormException, IOException, VisADException { return new NetcdfAdapter( new NetcdfFile(spec, /*readonly=*/true), quantityDB, charToText ).getData(); } /** * Returns a VisAD data object corresponding to a netCDF dataset * and imported according to a given strategy. Among the * pre-defined import strategies are {@link Strategy#DEFAULT}, * {@link Strategy#MERGED_FILE_FLAT_FIELDS}, {@link * Strategy#UNMERGED_FILE_FLAT_FIELDS}, and {@link Strategy#IN_MEMORY}. * * @param spec Specification of the existing netCDF dataset. * @param strategy The data-import strategy. * @return A VisAD data object corresponding to the netCDF * dataset. * @throws BadFormException if the netCDF dataset cannot be adapted to a * VisAD data object. * @throws VisADException if a problem occurs in core VisAD. Probably a * VisAD object couldn't be created. * @throws IOException if an I/O failure occurs. * @see NetcdfAdapter#getData(Strategy) */ public synchronized DataImpl open(String spec, Strategy strategy) throws BadFormException, IOException, VisADException { return new NetcdfAdapter( new NetcdfFile(spec, /*readonly=*/true), quantityDB, charToText ).getData(strategy); } /** * Open an existing netCDF file and return a proxy for a VisAD data object. * * @param path Pathname of the existing netCDF file. * @return A VisAD object corresponding to the netCDF dataset. * @exception BadFormException * The netCDF variable cannot be adapted to a VisAD API. * @exception VisADException * Problem in core VisAD. Probably some VisAD object * couldn't be created. * @exception IOException * Data access I/O failure. */ public synchronized DataImpl openProxy(String path) throws BadFormException, IOException, VisADException { NetcdfFile file = new NetcdfFile(path, /*readonly=*/true); return new NetcdfAdapter(file, quantityDB, charToText).getProxy(); } /** * Returns a VisAD data object corresponding to a URL. If the query * component of the URL is <code>null</code>, then the returned object will * contain all the variables in the netCDF dataset. If the query component * is non-<code>null</code>, then it must comprise a comma-separated list of * netCDF variable names; the returned VisAD data object will contain only * those variables in the netCDF dataset that are also named in the list * (i.e. the intersection is returned). Consequently, if the list is empty, * then <code>null</code> is returned. For example, this form: * <code> open(new URL("file://myfile.nc?var_one,var_two")); </code> * will return a VisAD data object consisting only of the * netCDF variables <code>var_one</code> and <code>var_two</code> * assuming they are in the file. * * @param url The URL of the netCDF dataset. * @return A VisAD object corresponding to the netCDF datset * or <code>null</code>. * @throws FileNotFoundException * if the URL specifies a file that doesn't exist. * @throws IOException if an I/O failure occurs. * @throws VisADException if a necessary VisAD object couldn't be created. */ public synchronized DataImpl open (URL url) throws FileNotFoundException, IOException, VisADException { /* * URL.getQuery() isn't used to accomodate JDK 1.2. */ String query; { String file = url.getFile(); int i = file.indexOf('?'); if (i == -1) { query = null; } else { query = i == file.length() - 1 ? "" : file.substring(i+1); } } Set names = new TreeSet(); if (query != null) { for (StringTokenizer st = new StringTokenizer(query, ","); st.hasMoreTokens(); ) { names.add(st.nextToken()); } } Netcdf netcdf = new NetcdfFile(url); return new NetcdfAdapter( query == null ? netcdf : new VariableFilter(netcdf, names), quantityDB, charToText).getData(); } /** * Return the data forms that are compatible with a data object. * * @param data The VisAD data object to be examined. * @return <code>this</code> if <code>data</code> is compatible; * otherwise, <code>null</code>. * @exception VisADException Problem with core VisAD. * @exception IOException Problem with local data access. * @exception RemoteException Problem with remote data access. */ public synchronized FormNode getForms(Data data) throws VisADException, RemoteException, IOException { FormNode form; try { VisADAdapter adapter = new VisADAdapter(data); form = this; } catch (BadFormException e) { form = null; } return form; } /** * Test this class. * * @param args Runtime arguments. Ignored. * @exception Exception Something went wrong. */ public static void main(String[] args) throws Exception { String inPath; String outPath = "plain.nc"; if (args.length == 0) inPath = "test.nc"; else inPath = args[0]; Plain plain = new Plain(args.length > 1); System.out.println("Opening netCDF dataset \"" + inPath + "\""); Data data; try { URL url = new URL(inPath); data = plain.open(url); } catch (MalformedURLException e) { data = plain.open(inPath); } if (data == null) { System.out.println("No data"); } else { // System.out.println("Data:\n" + data); System.out.println("data.getType().toString():\n" + data.getType()); System.out.println("Writing netCDF dataset \"" + outPath + "\""); plain.save(outPath, data, /*replace=*/true); } } }