gt:                 if (getSubsetDef() != null) {
context: /*
   * Copyright (C) 2012 Brockmann Consult GmbH (info@brockmann-consult.de)
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License as published by the Free
   * Software Foundation; either version 3 of the License, or (at your option)
   * any later version.
   * This program 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 General Public License for
   * more details.
   *
   * You should have received a copy of the GNU General Public License along
   * with this program; if not, see http://www.gnu.org/licenses/
   */
  package org.esa.beam.dataio.envisat;
  
  import com.bc.ceres.core.ProgressMonitor;
  import org.esa.beam.framework.dataio.AbstractProductReader;
  import org.esa.beam.framework.dataio.IllegalFileFormatException;
  import org.esa.beam.framework.datamodel.*;
  import org.esa.beam.framework.dataop.maptransf.Datum;
  import org.esa.beam.util.ArrayUtils;
  import org.esa.beam.util.Debug;
  import org.esa.beam.util.io.FileUtils;
  import org.opengis.referencing.crs.CoordinateReferenceSystem;
  import org.opengis.referencing.crs.CRSFactory;
  import org.opengis.referencing.crs.GeographicCRS;
  import org.opengis.referencing.operation.OperationMethod;
  import org.opengis.referencing.operation.CoordinateOperationFactory;
  import org.opengis.referencing.operation.Conversion;
  import org.opengis.referencing.datum.GeodeticDatum;
  import org.opengis.referencing.FactoryException;
  import org.opengis.parameter.ParameterValueGroup;
  import org.opengis.parameter.ParameterDescriptorGroup;
  import org.opengis.parameter.ParameterDescriptor;
  import org.geotools.referencing.ReferencingFactoryFinder;
  import org.geotools.referencing.datum.DefaultGeodeticDatum;
  import org.geotools.referencing.operation.projection.TransverseMercator;
  import org.geotools.referencing.operation.projection.MapProjection;
  import org.geotools.referencing.cs.DefaultEllipsoidalCS;
  import org.geotools.referencing.cs.DefaultCartesianCS;
  
  import javax.imageio.stream.FileCacheImageInputStream;
  import javax.imageio.stream.ImageInputStream;
  import java.awt.Dimension;
  import java.io.File;
  import java.io.IOException;
  import java.io.InputStream;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  import java.util.Vector;
  
  /**
   * The <code>EnvisatProductReader</code> class is an implementation of the <code>ProductReader</code> interface
   * exclusively for data products having the standard ESA/ENVISAT raw format.
   *
   * @author Norman Fomferra
   * @author Sabine Embacher
   * @version $Revision$ $Date$
   * @see org.esa.beam.dataio.envisat.EnvisatProductReaderPlugIn
   */
  public final class EnvisatProductReader extends AbstractProductReader {
  
      /**
       * @since BEAM 4.9
       */
      private static final String SYSPROP_ENVISAT_USE_PIXEL_GEO_CODING = "beam.envisat.usePixelGeoCoding";
  
      /**
       * Represents the product's file.
       */
      private ProductFile productFile;
  
      /**
       * The width of the raster covering the full scene.
       */
      private int sceneRasterWidth;
      /**
       * The height of the raster covering the full scene.
       */
      private int sceneRasterHeight;
  
      private Map<Band, BandLineReader> bandlineReaderMap;
  
      /**
       * Constructs a new ENVISAT product reader.
       *
       * @param readerPlugIn the plug-in which created this reader instance
       */
      public EnvisatProductReader(EnvisatProductReaderPlugIn readerPlugIn) {
          super(readerPlugIn);
      }
  
      public ProductFile getProductFile() {
          return productFile;
      }
  
      public int getSceneRasterWidth() {
          return sceneRasterWidth;
      }
  
      public int getSceneRasterHeight() {
          return sceneRasterHeight;
      }
  
  
      /**
       * Reads a data product and returns a in-memory representation of it. This method was called by
       * <code>readProductNodes(input, subsetInfo)</code> of the abstract superclass.
       *
       * @throws java.lang.IllegalArgumentException
       *                             if <code>input</code> type is not one of the supported input sources.
       * @throws java.io.IOException if an I/O error occurs
       */
      @Override
      protected Product readProductNodesImpl() throws IOException {
          final Object input = getInput();
          if (input instanceof String || input instanceof File) {
              File file = new File(input.toString());
              try {
                  productFile = ProductFile.open(file);
              } catch (IOException e) {
                  final InputStream inputStream;
                  try {
                      inputStream = EnvisatProductReaderPlugIn.getInflaterInputStream(file);
                  } catch (IOException ignored) {
                      throw e;
                  }
                  productFile = ProductFile.open(file, new FileCacheImageInputStream(inputStream, null));
              }
          } else if (input instanceof ImageInputStream) {
              productFile = ProductFile.open((ImageInputStream) input);
          } else if (input instanceof ProductFile) {
              productFile = (ProductFile) input;
          }
  
          Debug.assertNotNull(productFile);
          sceneRasterWidth = productFile.getSceneRasterWidth();
          sceneRasterHeight = productFile.getSceneRasterHeight();
  
          if (getSubsetDef() != null) {
              Dimension s = getSubsetDef().getSceneRasterSize(sceneRasterWidth, sceneRasterHeight);
              sceneRasterWidth = s.width;
              sceneRasterHeight = s.height;
          }
  
          return createProduct();
      }
  
      /**
       * 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 IOException if an I/O error occurs
       */
      @Override
      public void close() throws IOException {
          if (productFile != null) {
              productFile.close();
              productFile = 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 BandLineReader bandLineReader = bandlineReaderMap.get(destBand);
          final int sourceMinX = sourceOffsetX;
          final int sourceMinY = sourceOffsetY;
          final int sourceMaxX = Math.min(destBand.getRasterWidth() - 1, sourceMinX + sourceWidth - 1);
          final int sourceMaxY = sourceMinY + sourceHeight - 1;
  
  
          pm.beginTask("Reading band '" + destBand.getName() + "'...", (sourceMaxY - sourceMinY) + 1);
          // For each scan in the data source
          try {
  
              int destArrayPos = 0;
              for (int sourceY = sourceMinY; sourceY <= sourceMaxY; sourceY += sourceStepY) {
                  if (pm.isCanceled()) {
                      break;
                  }
  
                  bandLineReader.readRasterLine(sourceMinX, sourceMaxX, sourceStepX,
                                                sourceY,
                                                destBuffer, destArrayPos);
  
                  destArrayPos += destWidth;
                  pm.worked(sourceStepY);
              }
              pm.worked(1);
          } finally {
              pm.done();
          }
  
      }
  
      private Product createProduct() throws IOException {
          Debug.assertNotNull(getProductFile());
          Debug.assertTrue(getSceneRasterWidth() > 0);
          Debug.assertTrue(getSceneRasterHeight() > 0);
  
          File file = getProductFile().getFile();
          String productName;
          if (file != null) {
              final String mission = AsarAbstractMetadata.getMission(getProductFile().getProductType(), file);
              productName = mission + '-' + file.getName();
  //            		productName = file.getName();
          } else {
              productName = getProductFile().getProductId();
          }
          productName = FileUtils.createValidFilename(productName);
  
          Product product = new Product(productName,
                                        getProductFile().getProductType(),
                                        getSceneRasterWidth(),
                                        getSceneRasterHeight(),
                                        this);
  
          product.setFileLocation(getProductFile().getFile());
          product.setDescription(getProductFile().getProductDescription());
          product.setStartTime(getProductFile().getSceneRasterStartTime());
          product.setEndTime(getProductFile().getSceneRasterStopTime());
          product.setAutoGrouping(getProductFile().getAutoGroupingPattern());
  
          addBandsToProduct(product);
          if (!isMetadataIgnored()) {
              addHeaderAnnotationsToProduct(product);
              addDatasetAnnotationsToProduct(product);
              addTiePointGridsToProduct(product);
              addGeoCodingToProduct(product);
              initPointingFactory(product);
          }
          addDefaultMasksToProduct(product);
          addDefaultMasksDefsToBands(product);
          productFile.addCustomMetadata(product);
  
          return product;
      }
  
      private void addBandsToProduct(Product product) {
          Debug.assertNotNull(productFile);
          Debug.assertNotNull(product);
  
          BandLineReader[] bandLineReaders = productFile.getBandLineReaders();
          bandlineReaderMap = new HashMap<Band, BandLineReader>(bandLineReaders.length);
          for (BandLineReader bandLineReader : bandLineReaders) {
              if (bandLineReader.isTiePointBased()) {
                  continue;
              }
              if (!(bandLineReader instanceof BandLineReader.Virtual)) {
                  if (bandLineReader.getPixelDataReader().getDSD().getDatasetSize() == 0 ||
                      bandLineReader.getPixelDataReader().getDSD().getNumRecords() == 0) {
                      continue;
                  }
              }
              String bandName = bandLineReader.getBandName();
              if (isNodeAccepted(bandName)) {
                  BandInfo bandInfo = bandLineReader.getBandInfo();
                  Band band;
  
                  int width = bandInfo.getWidth();
                  int height = bandInfo.getHeight();
  