/**
   * Provides an implementation of the <code>readProductNodes</code> interface method. Clients
   * implementing this method can be sure that the input object and eventually the subset
   * information has already been set.
   *
   * <p>
   *
   * <p>This method is called as a last step in the <code>readProductNodes(input, subsetInfo)</code>
   * method.
   *
   * @throws java.io.IOException if an I/O error occurs
   */
  @Override
  protected Product readProductNodesImpl() throws IOException {

    Product product;
    try {
      final File fileFromInput = ReaderUtils.getFileFromInput(getInput());
      dataDir = createDirectory(fileFromInput);
      dataDir.readProductDirectory();
      product = dataDir.createProduct();
      addCalibrationLUT(product, fileFromInput.getParentFile());
      product.getGcpGroup();
      product.setFileLocation(fileFromInput);
      product.setProductReader(this);
      product.setModified(false);

      final MetadataElement absRoot = AbstractMetadata.getAbstractedMetadata(product);
      isAscending = absRoot.getAttributeString(AbstractMetadata.PASS).equals("ASCENDING");
      isAntennaPointingRight =
          absRoot.getAttributeString(AbstractMetadata.antenna_pointing).equals("right");
    } catch (Exception e) {
      Debug.trace(e.toString());
      final IOException ioException = new IOException(e.getMessage());
      ioException.initCause(e);
      throw ioException;
    }

    return product;
  }
 /**
  * Closes the access to all currently opened resources such as file input streams and all
  * resources of this children directly owned by this reader. Its primary use is to allow the
  * garbage collector to perform a vanilla job.
  *
  * <p>
  *
  * <p>This method should be called only if it is for sure that this object instance will never be
  * used again. The results of referencing an instance of this class after a call to <code>close()
  * </code> are undefined.
  *
  * <p>
  *
  * <p>Overrides of this method should always call <code>super.close();</code> after disposing this
  * instance.
  *
  * @throws java.io.IOException if an I/O error occurs
  */
 @Override
 public void close() throws IOException {
   if (dataDir != null) {
     dataDir.close();
     dataDir = null;
   }
   super.close();
 }
  /** {@inheritDoc} */
  @Override
  protected void readBandRasterDataImpl(
      int sourceOffsetX,
      int sourceOffsetY,
      int sourceWidth,
      int sourceHeight,
      int sourceStepX,
      int sourceStepY,
      Band destBand,
      int destOffsetX,
      int destOffsetY,
      int destWidth,
      int destHeight,
      ProductData destBuffer,
      ProgressMonitor pm)
      throws IOException {

    final ImageIOFile.BandInfo bandInfo = dataDir.getBandInfo(destBand);
    if (bandInfo != null && bandInfo.img != null) {
      if (isAscending) {
        readAscendingRasterBand(
            sourceOffsetX,
            sourceOffsetY,
            sourceStepX,
            sourceStepY,
            destBuffer,
            destOffsetX,
            destOffsetY,
            destWidth,
            destHeight,
            0,
            bandInfo.img,
            bandInfo.bandSampleOffset,
            isAntennaPointingRight);
      } else {
        readDescendingRasterBand(
            sourceOffsetX,
            sourceOffsetY,
            sourceStepX,
            sourceStepY,
            destBuffer,
            destOffsetX,
            destOffsetY,
            destWidth,
            destHeight,
            0,
            bandInfo.img,
            bandInfo.bandSampleOffset,
            isAntennaPointingRight);
      }
    }
  }