All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ucar.nc2.ft.point.remote.PointCollectionStreamAbstract Maven / Gradle / Ivy

The newest version!
package ucar.nc2.ft.point.remote;

import java.io.IOException;
import java.io.InputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ucar.nc2.ft.PointFeatureIterator;
import ucar.nc2.ft.point.PointCollectionImpl;
import ucar.nc2.ft.point.PointIteratorEmpty;
import ucar.nc2.stream.NcStream;
import ucar.nc2.stream.NcStreamProto;
import ucar.nc2.time.CalendarDateUnit;

/**
 * Abstract superclass for creating a {@link ucar.nc2.ft.PointFeatureCollection} from a point stream.
 * Subclasses must implement {@link #getInputStream()}.
 *
 * @author cwardgar
 * @since 2014/10/02
 */
public abstract class PointCollectionStreamAbstract extends PointCollectionImpl {
  private static final Logger logger = LoggerFactory.getLogger(PointCollectionStreamAbstract.class);

  // True if we must retrieve values for timeUnit and altUnits from the stream.
  private boolean needUnits;

  /**
   * Creates a feature collection with the specified name. {@link #getTimeUnit} and {@link #getAltUnits} will return
   * default values until {@link #getPointFeatureIterator} is called for the first time.
   *
   * @param name the name of this feature collection. May be null.
   */
  public PointCollectionStreamAbstract(String name) {
    super(name, CalendarDateUnit.unixDateUnit, null); // Default values. altUnits can be null; timeUnit must not be.
    this.needUnits = true; // Client did not provide explicit values for timeUnit and altUnits.
  }

  /**
   * Creates a feature collection with the specified name, time unit, and altitude unit.
   *
   * @param name the name of this feature collection. May be null.
   * @param timeUnit the time unit. May not be null.
   * @param altUnits the UDUNITS altitude unit string. May be null.
   */
  public PointCollectionStreamAbstract(String name, CalendarDateUnit timeUnit, String altUnits) {
    super(name, timeUnit, altUnits);
    this.needUnits = false; // Client provided explicit values for timeUnit and altUnits.
  }

  /**
   * Returns the input stream from which to read point data.
   *
   * @return the input stream from which to read point data.
   * @throws IOException if an I/O error occurs.
   */
  public abstract InputStream getInputStream() throws IOException;

  @Override
  public PointFeatureIterator getPointFeatureIterator() throws IOException {
    InputStream in = getInputStream();
    boolean leaveStreamOpen = false;

    try {
      PointStream.MessageType mtype = PointStream.readMagic(in);

      if (mtype == PointStream.MessageType.PointFeatureCollection) {
        int len = NcStream.readVInt(in);
        byte[] data = new byte[len];
        NcStream.readFully(in, data);

        PointStreamProto.PointFeatureCollection pfc = PointStreamProto.PointFeatureCollection.parseFrom(data);

        if (needUnits) {
          try {
            this.altUnits = !pfc.getAltUnit().isEmpty() ? pfc.getAltUnit() : null;
            this.timeUnit = CalendarDateUnit.of(null, pfc.getTimeUnit());
          } catch (IllegalArgumentException e) {
            String message = String.format("Invalid time unit found in stream (%s). Using default (%s).",
                pfc.getTimeUnit(), this.timeUnit.getUdUnit());
            logger.error(message, e);
            // Default value for timeUnit will remain.
          }

          needUnits = false;
        }

        PointFeatureIterator iter = new PointIteratorStream(this, in, new PointStream.ProtobufPointFeatureMaker(pfc));

        leaveStreamOpen = true; // It is now iter's responsiblity to close the stream.
        return iter;
      } else if (mtype == PointStream.MessageType.End) {
        return new PointIteratorEmpty(); // nothing in the iteration
      } else if (mtype == PointStream.MessageType.Error) {
        int len = NcStream.readVInt(in);
        byte[] data = new byte[len];
        NcStream.readFully(in, data);

        NcStreamProto.Error proto = NcStreamProto.Error.parseFrom(data);
        throw new IOException(NcStream.decodeErrorMessage(proto));
      } else {
        throw new IOException("Illegal pointstream message type= " + mtype); // maybe kill the socket ?
      }
    } finally {
      if (!leaveStreamOpen) {
        in.close();
      }
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy