private Product createProduct() {
    Product sourceProduct = getSourceProduct();
    Debug.assertNotNull(sourceProduct);
    Debug.assertTrue(getSceneRasterWidth() > 0);
    Debug.assertTrue(getSceneRasterHeight() > 0);
    final String newProductName;
    if (this.newProductName == null || this.newProductName.length() == 0) {
      newProductName = sourceProduct.getName();
    } else {
      newProductName = this.newProductName;
    }
    final Product product =
        new Product(
            newProductName,
            sourceProduct.getProductType(),
            getSceneRasterWidth(),
            getSceneRasterHeight(),
            this);
    product.setPointingFactory(sourceProduct.getPointingFactory());
    if (newProductDesc == null || newProductDesc.length() == 0) {
      product.setDescription(sourceProduct.getDescription());
    } else {
      product.setDescription(newProductDesc);
    }
    if (!isMetadataIgnored()) {
      ProductUtils.copyMetadata(sourceProduct, product);
      addTiePointGridsToProduct(product);
      addFlagCodingsToProduct(product);
      addIndexCodingsToProduct(product);
    }
    addBandsToProduct(product);
    if (!isMetadataIgnored()) {
      addGeoCodingToProduct(product);
    }
    ProductUtils.copyVectorData(sourceProduct, product);
    ProductUtils.copyMasks(sourceProduct, product);
    ProductUtils.copyOverlayMasks(sourceProduct, product);
    ProductUtils.copyPreferredTileSize(sourceProduct, product);
    setSceneRasterStartAndStopTime(product);
    addSubsetInfoMetadata(product);

    return product;
  }
 private static void copyLine(
     ProductData sourceBuffer,
     int sourceOffsetPos,
     int sourceWidth,
     int sourceStepX,
     ProductData destBuffer,
     int destOffsetPos) {
   final int sourceMinX = sourceOffsetPos;
   final int sourceMaxX = sourceOffsetPos + sourceWidth - 1;
   if (destBuffer.getElems() instanceof byte[]) {
     byte[] destArray = (byte[]) destBuffer.getElems();
     byte[] sourceArray = (byte[]) sourceBuffer.getElems();
     for (int sourceX = sourceMinX; sourceX <= sourceMaxX; sourceX += sourceStepX) {
       destArray[destOffsetPos] = sourceArray[sourceX];
       destOffsetPos++;
     }
   } else if (destBuffer.getElems() instanceof short[]) {
     short[] destArray = (short[]) destBuffer.getElems();
     short[] sourceArray = (short[]) sourceBuffer.getElems();
     for (int sourceX = sourceMinX; sourceX <= sourceMaxX; sourceX += sourceStepX) {
       destArray[destOffsetPos] = sourceArray[sourceX];
       destOffsetPos++;
     }
   } else if (destBuffer.getElems() instanceof int[]) {
     int[] destArray = (int[]) destBuffer.getElems();
     int[] sourceArray = (int[]) sourceBuffer.getElems();
     for (int sourceX = sourceMinX; sourceX <= sourceMaxX; sourceX += sourceStepX) {
       destArray[destOffsetPos] = sourceArray[sourceX];
       destOffsetPos++;
     }
   } else if (destBuffer.getElems() instanceof float[]) {
     float[] destArray = (float[]) destBuffer.getElems();
     float[] sourceArray = (float[]) sourceBuffer.getElems();
     for (int sourceX = sourceMinX; sourceX <= sourceMaxX; sourceX += sourceStepX) {
       destArray[destOffsetPos] = sourceArray[sourceX];
       destOffsetPos++;
     }
   } else if (destBuffer.getElems() instanceof double[]) {
     double[] destArray = (double[]) destBuffer.getElems();
     double[] sourceArray = (double[]) sourceBuffer.getElems();
     for (int sourceX = sourceMinX; sourceX <= sourceMaxX; sourceX += sourceStepX) {
       destArray[destOffsetPos] = sourceArray[sourceX];
       destOffsetPos++;
     }
   } else {
     Debug.assertTrue(false, "illegal product data type");
     throw new IllegalStateException("illegal product data type");
   }
 }