/*
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.dods;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RemoteException;
import java.util.Enumeration;
import visad.DataImpl;
import visad.VisADException;
import visad.data.BadFormException;
import visad.data.in.DataInputSource;
import dods.dap.AttributeTable;
import dods.dap.BaseType;
import dods.dap.DAS;
import dods.dap.DConnect;
import dods.dap.DODSException;
import dods.dap.parser.ParseException;
/**
* Provides support for generating a stream of VisAD data objects from a DODS
* dataset.
*
* <P>Instances are mutable.</P>
*
* @author Steven R. Emmerson
*/
public class DODSSource
implements DataInputSource
{
private DataFactory dataFactory;
private DConnect dConnect;
private DAS das;
private AttributeTable globalTable;
private Enumeration attrEnum;
private Enumeration varEnum;
/**
* Constructs from nothing. The default factory for creating VisAD data
* objects will be used.
*/
public DODSSource()
{
this(DataFactory.dataFactory());
}
/**
* Constructs from a factory for creating VisAD data objects.
*
* @param factory A factory for creating VisAD data objects.
*/
public DODSSource(DataFactory factory)
{
dataFactory = factory;
}
/**
* Opens an existing DODS dataset.
*
* @param spec The URL string specification of the DODS dataset
* The path component should have a ".dods" suffix.
* @throws BadFormException The DODS dataset is corrupt.
* @throws VisADException VisAD failure.
* @throws RemoteException Java RMI failure.
*/
public synchronized void open(String spec)
throws BadFormException, RemoteException, VisADException
{
try
{
URL url = new URL(spec);
String path = url.getFile();
String query = null;
int i = path.lastIndexOf('?');
if (i != -1)
{
query = path.substring(i);
path = path.substring(0, i);
}
/*
* Because the DConnect class won't construct an instance
* from a DODS dataset specification whose path component has a
* ".dods" suffix, such a suffix is removed.
*/
String suffix = ".dods";
if (path.toLowerCase().endsWith(suffix))
{
path = path.substring(0, path.length()-suffix.length());
spec =
new URL(
url.getProtocol(),
url.getHost(),
url.getPort(),
// Change 2004-01-22 query already contains ?
// query == null ? path : path + "?" + query)
query == null ? path : path + query)
.toString();
}
dConnect = new DConnect(spec);
das = dConnect.getDAS();
globalTable = das.getAttributeTable("NC_GLOBAL");
if (globalTable == null)
globalTable = das.getAttributeTable("nc_global");
if (globalTable != null)
{
attrEnum = globalTable.getNames();
}
else
{
attrEnum = null;
varEnum = dConnect.getData(null).getVariables();
}
}
catch (MalformedURLException e)
{
throw new BadFormException(e.getMessage());
}
catch (FileNotFoundException e)
{
throw new BadFormException(e.getMessage());
}
catch (ParseException e)
{
throw new BadFormException(e.getMessage());
}
catch (DODSException e)
{
throw new BadFormException(e.getMessage());
}
catch (IOException e)
{
throw new BadFormException(e.getMessage());
}
}
/**
* Returns the next VisAD data object from the DODS dataset. Returns
* <code>null</code> if there is no more objects.
*
* @return A VisAD data object or <code>null</code> if
* there are no more such objects.
* @throws VisADException VisAD failure.
* @throws RemoteException Java RMI failure.
*/
public synchronized DataImpl readData() throws VisADException, RemoteException
{
DataImpl data;
if (attrEnum != null)
{
if (attrEnum.hasMoreElements())
{
String name = (String)attrEnum.nextElement();
data =
dataFactory.data(
name, globalTable.getAttribute(name), true);
}
else
{
attrEnum = null;
try
{
varEnum = dConnect.getData(null).getVariables();
}
catch (DODSException e)
{
throw new RemoteException(
getClass().getName() + ".readData(): " +
"Couldn't get DDS of DODS dataset: " + e);
}
catch (ParseException e)
{
throw new RemoteException(
getClass().getName() + ".readData(): " +
"Couldn't get DDS of DODS dataset: " + e);
}
catch (IOException e)
{
throw new RemoteException(
getClass().getName() + ".readData(): " +
"Couldn't get DDS of DODS dataset: " + e);
}
data = readData();
}
}
else if (varEnum != null)
{
if (varEnum.hasMoreElements())
{
data =
dataFactory.data(
(BaseType)varEnum.nextElement(), das, true);
}
else
{
data = null;
varEnum = null;
dConnect = null;
das = null;
globalTable = null;
}
}
else
{
data = null;
}
return data;
}
/**
* Returns a VisAD data object corresponding to the next DODS global
* attribute in the currently open dataset. Returns <code>null</code> if
* there isn't another attribute.
*
* @param name The name of the attribute.
* @return A VisAD data object corresponding to the next
* DODS global attribute or <code>null</code> if
* no more attributes.
* @throws BadFormException The DODS datset is corrupt.
* @throws VisADException VisAD failure.
* @throws RemoteException Java RMI failure.
*/
protected synchronized DataImpl readAttribute(String name)
throws BadFormException, VisADException, RemoteException
{
return dataFactory.data(name, globalTable.getAttribute(name), true);
}
/**
* Returns a VisAD data object corresponding to the next DODS variable in
* the currently open dataset. Returns <code>null</code> if there isn't
* another variable.
*
* @return A VisAD data object corresponding to the next
* DODS variable or <code>null</code> if no more
* variables.
* @throws BadFormException The DODS datset is corrupt.
* @throws VisADException VisAD failure.
* @throws RemoteException Java RMI failure.
*/
protected synchronized DataImpl readVariable()
throws BadFormException, VisADException, RemoteException
{
DataImpl data;
if (varEnum == null)
{
data = null;
}
else if (!varEnum.hasMoreElements())
{
varEnum = null;
data = null;
}
else
{
data = dataFactory.data((BaseType)varEnum.nextElement(), das, true);
}
return data;
}
}