@Test
  public void testThatVerificationFailsIfTheGeoCodingCanNotGetPixelPositionFromGeoPos() {
    PowerMockito.when(M_geoCoding.canGetPixelPos()).thenReturn(false);

    boolean result = _productValidator.isValid(M_product);

    assertEquals(false, result);
    verify(S_logger, times(1))
        .info(
            "Product skipped. The geo-coding of the product 'ProductMock' can not determine the pixel position from a geodetic position.");
  }
 @Override
 public void filter(CoordinateSequence seq, int i) {
   Coordinate coord = seq.getCoordinate(i);
   PixelPos pixelPos = geoCoding.getPixelPos(new GeoPos(coord.y, coord.x), null);
   // rounding needed because closed geometries yield errors if their first and last coordinate
   // do not exactly match
   double x = Math.round(pixelPos.x * 10000) / 10000;
   double y = Math.round(pixelPos.y * 10000) / 10000;
   coord.setCoordinate(new Coordinate(x, y));
   count++;
 }
  @Before
  public void setUp() throws Exception {
    sourceBandName = "sbn";

    _timeRangeStart =
        ProductData.UTC.parse("2012-05-21 00:00:00", TemporalPercentileOp.DATETIME_PATTERN);
    _timeRangeEnd =
        ProductData.UTC.parse("2012-07-08 00:00:00", TemporalPercentileOp.DATETIME_PATTERN);

    Area targetArea = new Area(new Rectangle(9, 51, 20, 15));
    Area intersectingArea = new Area(new Rectangle(3, 45, 20, 15));
    _nonIntersectingArea = new Area(new Rectangle(3, 45, 2, 1));
    PowerMockito.mockStatic(Utils.class);
    PowerMockito.when(Utils.createProductArea(any(Product.class))).thenReturn(intersectingArea);

    final Logger logger = Logger.getAnonymousLogger();
    S_logger = PowerMockito.spy(logger);

    _productValidator =
        new ProductValidator(
            sourceBandName, null, null, _timeRangeStart, _timeRangeEnd, targetArea, S_logger);

    M_geoCoding = PowerMockito.mock(GeoCoding.class);
    PowerMockito.when(M_geoCoding.canGetPixelPos()).thenReturn(true);

    final ProductData.UTC productStartTime =
        ProductData.UTC.parse("2012-05-22 00:00:00", TemporalPercentileOp.DATETIME_PATTERN);
    final ProductData.UTC productEndTime =
        ProductData.UTC.parse("2012-07-07 00:00:00", TemporalPercentileOp.DATETIME_PATTERN);

    M_product = PowerMockito.mock(Product.class);
    PowerMockito.when(M_product.getName()).thenReturn("ProductMock");
    PowerMockito.when(M_product.getGeoCoding()).thenReturn(M_geoCoding);
    PowerMockito.when(M_product.getStartTime()).thenReturn(productStartTime);
    PowerMockito.when(M_product.getEndTime()).thenReturn(productEndTime);
    PowerMockito.when(M_product.containsBand(sourceBandName)).thenReturn(true);
  }
  @Override
  protected void addGeoCoding(final Product product) {

    TiePointGrid latGrid = product.getTiePointGrid(OperatorUtils.TPG_LATITUDE);
    TiePointGrid lonGrid = product.getTiePointGrid(OperatorUtils.TPG_LONGITUDE);
    if (latGrid != null && lonGrid != null) {
      setLatLongMetadata(product, latGrid, lonGrid);

      final TiePointGeoCoding tpGeoCoding = new TiePointGeoCoding(latGrid, lonGrid, Datum.WGS_84);
      product.setGeoCoding(tpGeoCoding);
      return;
    }

    final MetadataElement absRoot = AbstractMetadata.getAbstractedMetadata(product);
    final String acquisitionMode = absRoot.getAttributeString(AbstractMetadata.ACQUISITION_MODE);
    int numOfSubSwath;
    switch (acquisitionMode) {
      case "IW":
        numOfSubSwath = 3;
        break;
      case "EW":
        numOfSubSwath = 5;
        break;
      default:
        return;
    }

    String[] bandNames = product.getBandNames();
    Band firstSWBand = null, lastSWBand = null;
    boolean firstSWBandFound = false, lastSWBandFound = false;
    for (String bandName : bandNames) {
      if (!firstSWBandFound && bandName.contains(acquisitionMode + 1)) {
        firstSWBand = product.getBand(bandName);
        firstSWBandFound = true;
      }

      if (!lastSWBandFound && bandName.contains(acquisitionMode + numOfSubSwath)) {
        lastSWBand = product.getBand(bandName);
        lastSWBandFound = true;
      }
    }
    if (firstSWBand == null && lastSWBand == null) return;

    final GeoCoding firstSWBandGeoCoding = bandGeocodingMap.get(firstSWBand);
    final int firstSWBandHeight = firstSWBand.getRasterHeight();

    final GeoCoding lastSWBandGeoCoding = bandGeocodingMap.get(lastSWBand);
    final int lastSWBandWidth = lastSWBand.getRasterWidth();
    final int lastSWBandHeight = lastSWBand.getRasterHeight();

    final PixelPos ulPix = new PixelPos(0, 0);
    final PixelPos llPix = new PixelPos(0, firstSWBandHeight - 1);
    final GeoPos ulGeo = new GeoPos();
    final GeoPos llGeo = new GeoPos();
    firstSWBandGeoCoding.getGeoPos(ulPix, ulGeo);
    firstSWBandGeoCoding.getGeoPos(llPix, llGeo);

    final PixelPos urPix = new PixelPos(lastSWBandWidth - 1, 0);
    final PixelPos lrPix = new PixelPos(lastSWBandWidth - 1, lastSWBandHeight - 1);
    final GeoPos urGeo = new GeoPos();
    final GeoPos lrGeo = new GeoPos();
    lastSWBandGeoCoding.getGeoPos(urPix, urGeo);
    lastSWBandGeoCoding.getGeoPos(lrPix, lrGeo);

    final float[] latCorners = {
      (float) ulGeo.getLat(), (float) urGeo.getLat(), (float) llGeo.getLat(), (float) lrGeo.getLat()
    };
    final float[] lonCorners = {
      (float) ulGeo.getLon(), (float) urGeo.getLon(), (float) llGeo.getLon(), (float) lrGeo.getLon()
    };

    ReaderUtils.addGeoCoding(product, latCorners, lonCorners);

    AbstractMetadata.setAttribute(absRoot, AbstractMetadata.first_near_lat, ulGeo.getLat());
    AbstractMetadata.setAttribute(absRoot, AbstractMetadata.first_near_long, ulGeo.getLon());
    AbstractMetadata.setAttribute(absRoot, AbstractMetadata.first_far_lat, urGeo.getLat());
    AbstractMetadata.setAttribute(absRoot, AbstractMetadata.first_far_long, urGeo.getLon());

    AbstractMetadata.setAttribute(absRoot, AbstractMetadata.last_near_lat, llGeo.getLat());
    AbstractMetadata.setAttribute(absRoot, AbstractMetadata.last_near_long, llGeo.getLon());
    AbstractMetadata.setAttribute(absRoot, AbstractMetadata.last_far_lat, lrGeo.getLat());
    AbstractMetadata.setAttribute(absRoot, AbstractMetadata.last_far_long, lrGeo.getLon());

    // add band geocoding
    final Band[] bands = product.getBands();
    for (Band band : bands) {
      band.setGeoCoding(bandGeocodingMap.get(band));
    }
  }