A client uses the NetcdfFile, NetcdfDataset, or one of the Scientific Feature Type APIs to read data from a CDM file. These provide a rich and sometimes complicated API to the client. Behind the scenes, when any of these APIs actually read from a dataset, however, they use a very much simpler interface, the I/O Service Provider or IOSP for short. The Netcdf Java library has many implementations of this interface, one for each different file format that it knows how to read. This design pattern is called a Service Provider.
IOSPs are managed by the NetcdfFile class. When a client requests a dataset (by calling NetcdfFile.open), the file is opened as a ucar.unidata.io.RandomAccessFile (an improved version of java.io.RandomAccessFile). Each registered IOSP is then asked "is this your file?" by calling isValidFile(). The first one that returns true claims it. When you implement isValidFile() in your IOSP, it must be very fast and accurate.
public interface ucar.nc2.iosp.IOServiceProvider { // Check if this is a valid file for this IOServiceProvider // Required if you are registering your IOSP with NetcdfFile.registerIOProvider() public boolean isValidFile( ucar.unidata.io.RandomAccessFile raf) throws IOException; // Open existing file, and populate ncfile with it. public void open(ucar.unidata.io.RandomAccessFile raf, NetcdfFile ncfile, CancelTask cancelTask) throws IOException; // Read data from a top level Variable and return a memory resident Array. public ucar.ma2.Array readData(ucar.nc2.Variable v2, Section section) throws java.io.IOException, ucar.ma2.InvalidRangeException; // Allows reading sections of nested variables // Only implement if you have Structures public ucar.ma2.Array readSection(ParsedSectionSpec cer) throws IOException, InvalidRangeException; // Get a structure iterator. iosps with top level sequences must override // Only implement if you have Sequences public StructureDataIterator getStructureIterator(Structure s, int bufferSize) throws java.io.IOException; // Close the file. public void close() throws IOException; // Extend the file if needed in a way that is compatible with the current metadata. public boolean syncExtend() throws IOException; // A way to communicate arbitrary information to an iosp. public Object sendIospMessage( Object message); // print Debug info for this object. public String toStringDebug(Object o); // Show debug / underlying implementation details public String getDetailInfo(); // Get a unique id for this file type public String getFileTypeId(); // Get the version of this file type. public String getFileTypeVersion(); // Get a human-readable description for this file type. public String getFileTypeDescription(); }
Your implementataion class should extend ucar.nc2.iosp.AbstractIOServiceProvider. This provides default implementation of some of the methods, so minimally, you only have to implement a few methods:
public class MyIosp extends ucar.nc2.iosp.AbstractIOServiceProvider { 1) public boolean isValidFile(RandomAccessFile raf) throws IOException {} 2) public void open(RandomAccessFile raf, NetcdfFile ncfile, CancelTask cancelTask) throws IOException {} 3) public Array readData(Variable v2, Section wantSection) throws IOException, InvalidRangeException {} 4) public void close() throws IOException {} 5) public String getFileTypeId() {} 5) public String getFileTypeVersion() {} 5) public String getFileTypeDescription(); // optional 6) public ucar.ma2.Array readSection(ParsedSectionSpec cer) throws IOException, InvalidRangeException {} 7) public StructureDataIterator getStructureIterator(Structure s, int bufferSize) throws java.io.IOException {} 8) public boolean syncExtend() throws IOException {} 9) public Object sendIospMessage( Object message) {} 10) public String getDetailInfo() {} }