@Override
  public Map<String, Object> execute(Map<String, Object> input, ProgressListener monitor)
      throws ProcessException {
    if (started) throw new IllegalStateException("Process can only be run once");
    started = true;

    if (monitor == null) monitor = new NullProgressListener();
    try {
      monitor.started();
      monitor.setTask(Text.text("Grabbing arguments"));
      monitor.progress(10.0f);

      SimpleFeatureCollection inputFeatures =
          (SimpleFeatureCollection)
              Params.getValue(input, PearsonCorrelationProcessFactory.inputFeatures, null);
      String inputFields =
          (String) Params.getValue(input, PearsonCorrelationProcessFactory.inputFields, null);
      if (inputFeatures == null || inputFields == null) {
        throw new NullPointerException("All parameters required");
      }

      monitor.setTask(Text.text("Processing ..."));
      monitor.progress(25.0f);

      if (monitor.isCanceled()) {
        return null; // user has canceled this operation
      }

      // start process
      PearsonOperation operation = new PearsonOperation();
      PearsonResult ret = operation.execute(inputFeatures, inputFields);
      // end process

      monitor.setTask(Text.text("Encoding result"));
      monitor.progress(90.0f);

      Map<String, Object> resultMap = new HashMap<String, Object>();
      resultMap.put(PearsonCorrelationProcessFactory.RESULT.key, ret);
      monitor.complete(); // same as 100.0f

      return resultMap;
    } catch (Exception eek) {
      monitor.exceptionOccurred(eek);
      return null;
    } finally {
      monitor.dispose();
    }
  }
  /**
   * This process returns a boolean value which indicates if the requested download does not exceed
   * the imposed limits, if present
   *
   * @param layerName the layer name
   * @param filter the filter
   * @param email the email
   * @param outputFormat the output format
   * @param targetCRS the target crs
   * @param roiCRS the roi crs
   * @param roi the roi
   * @param clip the crop to geometry
   * @param targetSizeX the size of the target image along the X axis
   * @param targetSizeY the size of the target image along the Y axis
   * @param bandIndices the band indices selected for output, in case of raster input
   * @param progressListener the progress listener
   * @return the boolean
   */
  @DescribeResult(name = "result", description = "Download Limits are respected or not!")
  public Boolean execute(
      @DescribeParameter(name = "layerName", min = 1, description = "Original layer to download")
          String layerName,
      @DescribeParameter(name = "filter", min = 0, description = "Optional Vectorial Filter")
          Filter filter,
      @DescribeParameter(name = "targetCRS", min = 0, description = "Target CRS")
          CoordinateReferenceSystem targetCRS,
      @DescribeParameter(name = "RoiCRS", min = 0, description = "Region Of Interest CRS")
          CoordinateReferenceSystem roiCRS,
      @DescribeParameter(name = "ROI", min = 0, description = "Region Of Interest") Geometry roi,
      @DescribeParameter(name = "cropToROI", min = 0, description = "Crop to ROI") Boolean clip,
      @DescribeParameter(
              name = "targetSizeX",
              min = 0,
              minValue = 1,
              description = "X Size of the Target Image (applies to raster data only)")
          Integer targetSizeX,
      @DescribeParameter(
              name = "targetSizeY",
              min = 0,
              minValue = 1,
              description = "Y Size of the Target Image (applies to raster data only)")
          Integer targetSizeY,
      @DescribeParameter(name = "selectedBands", description = "Band Selection Indices", min = 0)
          int[] bandIndices,
      ProgressListener progressListener)
      throws Exception {

    //
    // initial checks on mandatory params
    //
    // layer name
    if (layerName == null || layerName.length() <= 0) {
      throw new IllegalArgumentException("Empty or null layerName provided!");
    }
    if (LOGGER.isLoggable(Level.FINE)) {
      LOGGER.log(Level.FINE, "Estimator process called on resource: " + layerName);
    }
    if (clip == null) {
      clip = false;
      if (LOGGER.isLoggable(Level.FINE)) {
        LOGGER.log(Level.FINE, "Clipping disabled");
      }
    }
    if (roi != null) {
      if (LOGGER.isLoggable(Level.FINE)) {
        LOGGER.log(Level.FINE, "ROI present");
      }
      DownloadUtilities.checkPolygonROI(roi);
      if (roiCRS == null) {
        throw new IllegalArgumentException("ROI without a CRS is not usable!");
      }
      roi.setUserData(roiCRS);
    }

    //
    // Move on with the real code
    //
    // checking for the resources on the GeoServer catalog
    LayerInfo layerInfo = catalog.getLayerByName(layerName);
    if (layerInfo == null) {
      // could not find any layer ... abruptly interrupt the process
      throw new IllegalArgumentException("Unable to locate layer: " + layerName);
    }
    ResourceInfo resourceInfo = layerInfo.getResource();
    if (resourceInfo == null) {
      // could not find any data store associated to the specified layer ... abruptly interrupt the
      // process
      throw new IllegalArgumentException("Unable to locate ResourceInfo for layer:" + layerName);
    }

    //
    // Get curent limits
    //
    DownloadServiceConfiguration limits = downloadServiceConfigurationGenerator.getConfiguration();
    if (LOGGER.isLoggable(Level.FINE)) {
      LOGGER.log(Level.FINE, "Getting configuration limits");
    }

    // ////
    // 1. DataStore -> look for vectorial data download
    // 2. CoverageStore -> look for raster data download
    // ////
    if (resourceInfo instanceof FeatureTypeInfo) {
      if (LOGGER.isLoggable(Level.FINE)) {
        LOGGER.log(Level.FINE, "Working with Vectorial dataset");
      }
      final FeatureTypeInfo featureTypeInfo = (FeatureTypeInfo) resourceInfo;

      return new VectorEstimator(limits)
          .execute(featureTypeInfo, roi, clip, filter, targetCRS, progressListener);

    } else if (resourceInfo instanceof CoverageInfo) {
      if (LOGGER.isLoggable(Level.FINE)) {
        LOGGER.log(Level.FINE, "Working with Raster dataset");
      }
      final CoverageInfo coverage = (CoverageInfo) resourceInfo;
      return new RasterEstimator(limits)
          .execute(
              progressListener,
              coverage,
              roi,
              targetCRS,
              clip,
              filter,
              targetSizeX,
              targetSizeY,
              bandIndices);
    }

    if (LOGGER.isLoggable(Level.FINE)) {
      LOGGER.log(Level.FINE, "Working with a wrong Resource");
    }

    // the requested layer is neither a featuretype nor a coverage --> error
    final ProcessException ex =
        new ProcessException(
            "Could not complete the Download Process: target resource is of Illegal type --> "
                        + resourceInfo
                    != null
                ? resourceInfo.getClass().getCanonicalName()
                : "null");

    // Notify the listener if present
    if (progressListener != null) {
      progressListener.exceptionOccurred(ex);
    }
    throw ex;
  }