/*
VisAD system for interactive analysis and visualization of numerical
data.  Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom
Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
Tommy Jasmin.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 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
Library General Public License for more details.

You should have received a copy of the GNU Library 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 visad.data;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import java.net.URL;
import java.net.MalformedURLException;

import java.rmi.RemoteException;

import java.util.Enumeration;

import visad.Data;
import visad.DataImpl;
import visad.VisADException;

public class FunctionFormFamily
	extends FormFamily
{
  public FunctionFormFamily(String name)
  {
    super(name);
  }

  /**
    * Base class which tries to perform an operation on an object
    * using the first valid Form.
    */
  abstract class FormFunction
  {
    /**
      * Return 'true' if this object's name applies to the given node.
      */
    abstract boolean check(FormFileInformer node);

    /**
      * Return an InputStream for the object.
      *
      * Used to read in the first block of the object.
      */
    abstract InputStream getStream() throws IOException;

    /**
      * The operation to be performed on the object.
      */
    abstract boolean function(FormNode node);

    /**
      * Perform an operation on an object
      * using the first valid Form.
      *
      * If a Form successfully performs the operation, return 'true'.
      */
    public boolean run()
	throws IOException
    {
      // see if we can guess the file type based on the name
      for (Enumeration en = forms.elements(); en.hasMoreElements(); ) {
	FormNode node = (FormNode)en.nextElement();

	if (node instanceof FormFileInformer) {
          // WLH 19 Feb 2000 - switch order of try and check
          // needed for HDF5
	  try {
	    if (check((FormFileInformer) node)) {
	      if (function(node)) {
		return true;
	      }
	    }
	  } catch (Exception e) {
	  } catch (Error e) {
            // WLH 19 Feb 2000 - needed for HDF5
	  }
	}
      }

      // get the first block of data from the file
      byte[] block = new byte[2048];
      InputStream is = getStream();
      if (is != null) {
        is.read(block);
        is.close();

        // see if we can guess the file type based on first block of data
        for (Enumeration en = forms.elements(); en.hasMoreElements(); ) {
          FormNode node = (FormNode)en.nextElement();

          if (node instanceof FormFileInformer) {
            // WLH 19 Feb 2000 - switch order of try and check
            // needed for HDF5
            try {
              if (((FormFileInformer )node).isThisType(block)) {
                if (function(node)) {
                  return true;
                }
              }
            } catch (Exception e) {
            } catch (Error e) {
              // WLH 19 Feb 2000 - needed for HDF5
            }
          }
        }
      }

      // use the brute-force method of checking all the forms
      for (Enumeration en = forms.elements(); en.hasMoreElements(); ) {
	FormNode node = (FormNode)en.nextElement();

	try {
	  if (function(node)) {
	    return true;
	  }
	} catch (Exception e) {
	} catch (UnsatisfiedLinkError ule) {
	}
      }

      return false;
    }
  }

  /**
    * Perform an operation on a local file object
    * using the first valid Form.
    */
  abstract class FileFunction
	extends FormFunction
  {
    String name;

    public FileFunction()
    {
      name = null;
    }

    boolean check(FormFileInformer node)
    {
      return node.isThisType(name);
    }

    InputStream getStream()
	throws IOException
    {
      return new FileInputStream(name);
    }
  }

  /**
    * Save a Data object to a local file
    * using the first valid Form.
    */
  class SaveForm
	extends FileFunction
  {
    private Data data;
    private boolean replace;

    public SaveForm(String name, Data data, boolean replace)
    {
      this.name = name;
      this.data = data;
      this.replace = replace;
    }

    boolean function(FormNode node)
    {
      try {
	node.save(name, data, replace);
      } catch (Exception e) {
	return false;
      }

      return true;
    }

    InputStream getStream()
	throws IOException
    {
      FileInputStream stream;
      try {
        stream = new FileInputStream(name);
      } catch (FileNotFoundException fnfe) {
        stream = null;
      }

      return stream;
    }
  }

  /**
    * Add a Data object to an existing local file
    * using the first valid Form.
    */
  class AddForm
	extends FileFunction
  {
    private Data data;
    private boolean replace;

    public AddForm(String name, Data data, boolean replace)
    {
      this.name = name;
      this.data = data;
      this.replace = replace;
    }

    boolean function(FormNode node)
    {
      try {
	node.add(name, data, replace);
      } catch (Exception e) {
	return false;
      }

      return true;
    }
  }

  /**
    * Read a Data object from a local file
    * using the first valid Form.
    */
  class OpenStringForm
	extends FileFunction
  {
    private DataImpl data;

    public OpenStringForm(String name)
    {
      this.name = name;
      data = null;
    }

    boolean function(FormNode node)
    {
      try {
	data = node.open(name);
      } catch (OutOfMemoryError t) { // WLH 5 Feb 99
	throw t;
      } catch (Throwable t) {
	return false;
      }

      return true;
    }

    public DataImpl getData()
    {
      return data;
    }
  }

  /**
    * Perform an operation on a remote file object
    * using the first valid Form.
    */
  abstract class URLFunction
	extends FormFunction
  {
    URL url;

    public URLFunction()
    {
      url = null;
    }

    boolean check(FormFileInformer node)
    {
      // try both file part of URL and full URL
      return (node.isThisType(url.getFile()) ||
              node.isThisType(url.toString()));
    }

    InputStream getStream()
	throws IOException
    {
      return url.openStream();
    }
  }

  /**
    * Read a Data object from a remote file
    * using the first valid Form.
    */
  class OpenURLForm
	extends URLFunction
  {
    /* CTR: 13 Oct 1998
    private URL url;
    */
    private DataImpl data;

    public OpenURLForm(URL url)
    {
      this.url = url;
      data = null;
    }

    boolean function(FormNode node)
    {
      try {
	data = node.open(url);
      } catch (Throwable t) {
	return false;
      }

      return true;
    }

    public DataImpl getData()
    {
      return data;
    }
  }

  /**
    * Save a Data object using the first appropriate Form.
    */
  public synchronized void save(String id, Data data, boolean replace)
	throws BadFormException, RemoteException, IOException, VisADException
  {
    SaveForm s = new SaveForm(id, data, replace);
    if (!s.run()) {
      throw new BadFormException("Data object not compatible with \"" +
				 getName() + "\" data family");
    }
  }

  /**
    * Add data to an existing data object using the first appropriate Form.
    */
  public synchronized void add(String id, Data data, boolean replace)
	throws BadFormException
  {
    AddForm a = new AddForm(id, data, replace);
    try {
      if (a.run()) {
	return;
      }
    } catch (IOException e) {
    }

    throw new BadFormException("Data object not compatible with \"" +
			       getName() + "\" data family");
  }

  /**
    * Open a local data object using the first appropriate Form.
    */
  public synchronized DataImpl open(String id)
	throws BadFormException, VisADException
  {
    // Garbage in, garbage out
    if (id == null) {
      return null;
    }

    // try to build a URL from the string
    URL url;
    try {
      url = new URL(id);
    } catch (MalformedURLException mue) {
      url = null;
    }

    DataImpl data = null;

    // if we got a URL, try to extract a Data object from it
    if (url != null) {
      OpenURLForm u = new OpenURLForm(url);

      try {
        if (!u.run()) {
          data = null;
        } else {
          data = u.getData();
        }
      } catch (Exception e) {
        data = null;
      }
    }

    // if we didn't get a Data object, look for a filename
    String file = null;
    if (data == null) {
      if (url == null) {
        file = id;
      } else if (url.getProtocol() == "file") {
        file = url.getFile();

        // if file looks like it starts with a Windows drive spec...
        if (file.length() > 2 && file.charAt(2) == ':' &&
            file.charAt(0) == '/')
        {
          file = file.substring(1);
        }
      }
    }

    // if we found a filename, try to open it
    if (file != null) {
      OpenStringForm o = new OpenStringForm(file);

      try {
        if (!o.run()) {
          data = null;
        } else {
          data = o.getData();
        }
      } catch (IOException ioe) {
        data = null;
      }
    }

    // puke if we didn't find a data object
    if (data == null) {
      if (file != null && !new java.io.File(file).exists()) {
        throw new BadFormException("No such data object \"" + id + "\"");
      }
      throw new BadFormException("Data object \"" + id +
                                 "\" not compatible with \"" + getName() +
                                 "\" data family");
    }

    return data;
  }

  /**
    * Open a remote data object using the first appropriate Form.
    */
  public synchronized DataImpl open(URL url)
	throws BadFormException, IOException, VisADException
  {
    OpenURLForm o = new OpenURLForm(url);
    if (!o.run()) {
      throw new BadFormException("Data object \"" + url +
				 "\" not compatible with \"" + getName() +
				 "\" data family");
    }

    return o.getData();
  }
}

 

Ads help maintain this website.