private void setSceneRasterStartAndStopTime(Product product) {
   final Product sourceProduct = getSourceProduct();
   final ProductData.UTC startTime = sourceProduct.getStartTime();
   final ProductData.UTC stopTime = sourceProduct.getEndTime();
   final ProductSubsetDef subsetDef = getSubsetDef();
   if (startTime != null
       && stopTime != null
       && subsetDef != null
       && subsetDef.getRegion() != null) {
     final double height = sourceProduct.getSceneRasterHeight();
     final Rectangle region = subsetDef.getRegion();
     final double regionY = region.getY();
     final double regionHeight = region.getHeight();
     final double dStart = startTime.getMJD();
     final double dStop = stopTime.getMJD();
     final double vPerLine = (dStop - dStart) / (height - 1);
     final double newStart = vPerLine * regionY + dStart;
     final double newStop = vPerLine * (regionHeight - 1) + newStart;
     product.setStartTime(new ProductData.UTC(newStart));
     product.setEndTime(new ProductData.UTC(newStop));
   } else {
     product.setStartTime(startTime);
     product.setEndTime(stopTime);
   }
 }
  private static void setSubsetSRGRCoefficients(
      final Product sourceProduct,
      final Product targetProduct,
      final ProductSubsetDef subsetDef,
      final MetadataElement absRoot,
      final boolean nearRangeOnLeft) {

    final MetadataElement SRGRCoefficientsElem = absRoot.getElement("SRGR_Coefficients");
    if (SRGRCoefficientsElem != null) {
      final double rangeSpacing = absRoot.getAttributeDouble("RANGE_SPACING", 0);
      final double colIndex = subsetDef.getRegion() == null ? 0 : subsetDef.getRegion().getX();

      for (MetadataElement srgrList : SRGRCoefficientsElem.getElements()) {
        final double grO = srgrList.getAttributeDouble("ground_range_origin", 0);
        double ground_range_origin_subset;
        if (nearRangeOnLeft) {
          ground_range_origin_subset = grO + colIndex * rangeSpacing;
        } else {
          final double colIndexFromRight =
              sourceProduct.getSceneRasterWidth() - colIndex - targetProduct.getSceneRasterWidth();
          ground_range_origin_subset = grO + colIndexFromRight * rangeSpacing;
        }
        srgrList.setAttributeDouble("ground_range_origin", ground_range_origin_subset);
      }
    }
  }
 private boolean isFullScene(ProductSubsetDef subsetDef) {
   if (subsetDef == null) {
     return true;
   }
   final Rectangle sourceRegion =
       new Rectangle(0, 0, sourceProduct.getSceneRasterWidth(), getSceneRasterHeight());
   return subsetDef.getRegion() == null
       || subsetDef.getRegion().equals(sourceRegion)
           && subsetDef.getSubSamplingX() == 1
           && subsetDef.getSubSamplingY() == 1;
 }
 private void addSubsetInfoMetadata(Product product) {
   if (getSubsetDef() != null) {
     ProductSubsetDef subsetDef = getSubsetDef();
     Product sourceProduct = getSourceProduct();
     String nameSubsetinfo = "SubsetInfo";
     MetadataElement subsetElem = new MetadataElement(nameSubsetinfo);
     addAttribString("SourceProduct.name", sourceProduct.getName(), subsetElem);
     subsetElem.setAttributeInt("SubSampling.x", subsetDef.getSubSamplingX());
     subsetElem.setAttributeInt("SubSampling.y", subsetDef.getSubSamplingY());
     if (subsetDef.getRegion() != null) {
       Rectangle region = subsetDef.getRegion();
       subsetElem.setAttributeInt("SubRegion.x", region.x);
       subsetElem.setAttributeInt("SubRegion.y", region.y);
       subsetElem.setAttributeInt("SubRegion.width", region.width);
       subsetElem.setAttributeInt("SubRegion.height", region.height);
     }
     String[] nodeNames = subsetDef.getNodeNames();
     if (nodeNames != null) {
       for (int i = 0; i < nodeNames.length; i++) {
         addAttribString("ProductNodeName." + (i + 1), nodeNames[i], subsetElem);
       }
     }
     ProductUtils.addElementToHistory(product, subsetElem);
   }
 }
  private static void updateMetadata(
      final Product sourceProduct, final Product targetProduct, ProductSubsetDef subsetDef)
      throws IOException {

    try {
      final MetadataElement root = targetProduct.getMetadataRoot();
      if (root == null) return;

      final MetadataElement absRoot = root.getElement("Abstracted_Metadata");
      if (absRoot == null) return;

      boolean nearRangeOnLeft = isNearRangeOnLeft(targetProduct);

      final MetadataAttribute firstLineTime = absRoot.getAttribute("first_line_time");
      if (firstLineTime != null) {
        final ProductData.UTC startTime = targetProduct.getStartTime();
        if (startTime != null) firstLineTime.getData().setElems(startTime.getArray());
      }
      final MetadataAttribute lastLineTime = absRoot.getAttribute("last_line_time");
      if (lastLineTime != null) {
        final ProductData.UTC endTime = targetProduct.getEndTime();
        if (endTime != null) lastLineTime.getData().setElems(endTime.getArray());
      }
      final MetadataAttribute totalSize = absRoot.getAttribute("total_size");
      if (totalSize != null) totalSize.getData().setElemUInt(targetProduct.getRawStorageSize());

      if (nearRangeOnLeft) {
        setLatLongMetadata(targetProduct, absRoot, "first_near_lat", "first_near_long", 0.5f, 0.5f);
        setLatLongMetadata(
            targetProduct,
            absRoot,
            "first_far_lat",
            "first_far_long",
            targetProduct.getSceneRasterWidth() - 1 + 0.5f,
            0.5f);

        setLatLongMetadata(
            targetProduct,
            absRoot,
            "last_near_lat",
            "last_near_long",
            0.5f,
            targetProduct.getSceneRasterHeight() - 1 + 0.5f);
        setLatLongMetadata(
            targetProduct,
            absRoot,
            "last_far_lat",
            "last_far_long",
            targetProduct.getSceneRasterWidth() - 1 + 0.5f,
            targetProduct.getSceneRasterHeight() - 1 + 0.5f);
      } else {
        setLatLongMetadata(
            targetProduct,
            absRoot,
            "first_near_lat",
            "first_near_long",
            targetProduct.getSceneRasterWidth() - 1 + 0.5f,
            0.5f);
        setLatLongMetadata(targetProduct, absRoot, "first_far_lat", "first_far_long", 0.5f, 0.5f);

        setLatLongMetadata(
            targetProduct,
            absRoot,
            "last_near_lat",
            "last_near_long",
            targetProduct.getSceneRasterWidth() - 1 + 0.5f,
            targetProduct.getSceneRasterHeight() - 1 + 0.5f);
        setLatLongMetadata(
            targetProduct,
            absRoot,
            "last_far_lat",
            "last_far_long",
            0.5f,
            targetProduct.getSceneRasterHeight() - 1 + 0.5f);
      }

      final MetadataAttribute height = absRoot.getAttribute("num_output_lines");
      if (height != null) height.getData().setElemUInt(targetProduct.getSceneRasterHeight());

      final MetadataAttribute width = absRoot.getAttribute("num_samples_per_line");
      if (width != null) width.getData().setElemUInt(targetProduct.getSceneRasterWidth());

      final MetadataAttribute offsetX = absRoot.getAttribute("subset_offset_x");
      if (offsetX != null && subsetDef.getRegion() != null)
        offsetX.getData().setElemUInt(subsetDef.getRegion().x);

      final MetadataAttribute offsetY = absRoot.getAttribute("subset_offset_y");
      if (offsetY != null && subsetDef.getRegion() != null)
        offsetY.getData().setElemUInt(subsetDef.getRegion().y);

      final MetadataAttribute slantRange = absRoot.getAttribute("slant_range_to_first_pixel");
      if (slantRange != null) {
        final TiePointGrid srTPG = targetProduct.getTiePointGrid("slant_range_time");
        if (srTPG != null) {
          final double slantRangeTime;
          if (nearRangeOnLeft) {
            slantRangeTime = srTPG.getPixelDouble(0, 0) / 1000000000.0; // ns to s
          } else {
            slantRangeTime =
                srTPG.getPixelDouble(targetProduct.getSceneRasterWidth() - 1, 0)
                    / 1000000000.0; // ns to s
          }
          final double halfLightSpeed = 299792458.0 / 2.0;
          final double slantRangeDist = slantRangeTime * halfLightSpeed;
          slantRange.getData().setElemDouble(slantRangeDist);
        }
      }

      setSubsetSRGRCoefficients(sourceProduct, targetProduct, subsetDef, absRoot, nearRangeOnLeft);
    } catch (Exception e) {
      throw new IOException(e);
    }
  }