@Override
  /**
   * inputData a HashMap of the input data:
   *
   * @param inputObservations: the observations
   * @param inputAuthoritativeData: the polygons
   * @param bufferSize: the size of the buffer around the polygons results a HashpMap of the
   *     results:
   * @result result: the input data with the polygon attributes attached, null values for no match
   * @result qual_result: the matched input only data with polygon attributes attached
   */
  public Map<String, IData> run(Map<String, List<IData>> inputData) throws ExceptionReport {

    HashMap<String, Object> metadataMap = new HashMap<String, Object>();
    ArrayList<SimpleFeature> list = new ArrayList<SimpleFeature>();
    List<IData> inputObs = inputData.get("inputObservations");
    List<IData> inputAuth = inputData.get("inputAuthoritativeData");
    List<IData> inputLit = inputData.get("bufferSize");
    IData observations = inputObs.get(0);
    IData authoritative = inputAuth.get(0);

    IData buffersize = inputLit.get(0);

    double doubleB = (Double) buffersize.getPayload();

    FeatureCollection obsFC = ((GTVectorDataBinding) observations).getPayload();
    FeatureCollection authFC = ((GTVectorDataBinding) authoritative).getPayload();

    SimpleFeatureIterator obsIt = (SimpleFeatureIterator) obsFC.features();

    SimpleFeatureIterator authIt = (SimpleFeatureIterator) authFC.features();

    // setup result feature

    SimpleFeature obsItFeat = obsIt.next();

    SimpleFeature obsItAuth = authIt.next();

    Collection<Property> property = obsItFeat.getProperties();
    Collection<Property> authProperty = obsItAuth.getProperties();

    // setup result type builder
    SimpleFeatureTypeBuilder resultTypeBuilder = new SimpleFeatureTypeBuilder();
    resultTypeBuilder.setName("typeBuilder");

    Iterator<Property> pItObs = property.iterator();
    Iterator<Property> pItAuth = authProperty.iterator();

    metadataMap.put("element", "elementBufferedMetadata");
    File metadataFile = createXMLMetadata(metadataMap);

    while (pItObs.hasNext() == true) {

      try {
        Property tempProp = pItObs.next();

        PropertyType type = tempProp.getDescriptor().getType();
        String name = type.getName().getLocalPart();
        Class<String> valueClass = (Class<String>) tempProp.getType().getBinding();

        resultTypeBuilder.add(name, valueClass);

      } catch (Exception e) {
        LOGGER.error("property error " + e);
      }
    }
    int i = 0;
    while (pItAuth.hasNext() == true) {
      try {
        Property tempProp = pItAuth.next();

        PropertyType type = tempProp.getDescriptor().getType();
        String name = type.getName().getLocalPart();
        Class<String> valueClass = (Class<String>) tempProp.getType().getBinding();

        if (i > 3) {

          resultTypeBuilder.add(name, valueClass);
        }

        i++;

      } catch (Exception e) {
        LOGGER.error("property error " + e);
      }
    }

    obsIt.close();
    authIt.close();
    resultTypeBuilder.add("withinBuffer", Integer.class);

    // set up result feature builder

    SimpleFeatureType type = resultTypeBuilder.buildFeatureType();
    SimpleFeatureBuilder resultFeatureBuilder = new SimpleFeatureBuilder(type);

    // process data here:

    SimpleFeatureIterator obsIt2 = (SimpleFeatureIterator) obsFC.features();

    int within = 0;

    FeatureCollection resultFeatureCollection = DefaultFeatureCollections.newCollection();

    while (obsIt2.hasNext() == true) {
      within = 0;
      SimpleFeature tempObs = obsIt2.next();
      Geometry obsGeom = (Geometry) tempObs.getDefaultGeometry();

      for (Property obsProperty : tempObs.getProperties()) {

        String name = obsProperty.getName().getLocalPart();
        Object value = obsProperty.getValue();

        resultFeatureBuilder.set(name, value);
        // LOGGER.warn("obs Property set " + name);
      }

      double bufferSizeDouble = doubleB;

      Geometry bufferGeom = obsGeom.buffer(bufferSizeDouble);

      int j = 0;
      SimpleFeatureIterator authIt2 = (SimpleFeatureIterator) authFC.features();
      while (authIt2.hasNext() == true) {

        SimpleFeature tempAuth = authIt2.next();
        Geometry authGeom = (Geometry) tempAuth.getDefaultGeometry();

        if (bufferGeom.intersects(authGeom) == true) {
          within = 1;
          j = 0;

          LOGGER.warn("Intersection = true");
          for (Property authProperty1 : tempAuth.getProperties()) {

            String name = authProperty1.getName().getLocalPart();
            Object value = authProperty1.getValue();
            // Class valueClass = (Class<String>)authProperty1.getType().getBinding();

            //		LOGGER.warn("Auth property " + name);
            if (j > 3) {
              resultFeatureBuilder.set(name, value);
              //	LOGGER.warn("Auth property set " + name);

            }

            j++;
          }
        }
      }
      resultFeatureBuilder.set("withinBuffer", within);

      SimpleFeature resultFeature = resultFeatureBuilder.buildFeature(tempObs.getName().toString());
      Geometry geom = (Geometry) tempObs.getDefaultGeometry();
      resultFeature.setDefaultGeometry(geom);

      list.add(resultFeature);

      // resultFeatureCollection.add(resultFeature);
      // LOGGER.warn("RESULT FEATURE " + resultFeatureCollection.getSchema().toString());
      // resultFeatureCollection = obsFC;
    }

    ListFeatureCollection listFeatureCollection = new ListFeatureCollection(type, list);
    LOGGER.warn("Result Feature Size " + listFeatureCollection.size());

    // sort HashMap
    GenericFileData gf = null;
    try {
      gf = new GenericFileData(metadataFile, "text/xml");
    } catch (IOException e) {
      LOGGER.error("GenericFileData " + e);
    }

    HashMap<String, IData> results = new HashMap<String, IData>();
    results.put("result", new GTVectorDataBinding((FeatureCollection) obsFC));
    results.put("qual_result", new GTVectorDataBinding((FeatureCollection) listFeatureCollection));
    results.put("metadata", new GenericFileDataBinding(gf));

    return results;
  }
  @Override
  /**
   * @param inputData a HashMap of the input data: inputObservations: the observations
   *     inputAuthoritativeData: the authoritative points inputDistance: the distance threshold
   *     minNumber: the minimum number of named features to pass fieldName: the name of the field
   *     within the observations to match
   * @result results a HashpMap of the results: result: the input data with the polygon attributes
   *     attached, null values for no match qual_result: the matched input only data with polygon
   *     attributes attached
   */
  public Map<String, IData> run(Map<String, List<IData>> inputData) throws ExceptionReport {

    List obsList = inputData.get("inputObservations");
    List authList = inputData.get("inputAuthoritativeData");
    List distList = inputData.get("inputDistance");
    List minList = inputData.get("minNumber");
    List fieldList = inputData.get("fieldName");

    FeatureCollection obsFc = ((GTVectorDataBinding) obsList.get(0)).getPayload();
    FeatureCollection authFc = ((GTVectorDataBinding) authList.get(0)).getPayload();
    double dist = ((LiteralDoubleBinding) distList.get(0)).getPayload();
    int minNum = ((LiteralIntBinding) minList.get(0)).getPayload();
    String fieldName = ((LiteralStringBinding) fieldList.get(0)).getPayload();

    ArrayList<SimpleFeature> resultFeatures = new ArrayList<SimpleFeature>();
    ArrayList<SimpleFeature> returnFeatures = new ArrayList<SimpleFeature>();

    SimpleFeatureIterator obsIt = (SimpleFeatureIterator) obsFc.features();
    SimpleFeatureIterator authIt = (SimpleFeatureIterator) authFc.features();

    SimpleFeatureIterator sfi = (SimpleFeatureIterator) obsFc.features();
    SimpleFeatureType fType = null;
    SimpleFeature tempPropFeature = sfi.next();
    CoordinateReferenceSystem inputObsCrs = obsFc.getSchema().getCoordinateReferenceSystem();

    Collection<Property> obsProp = tempPropFeature.getProperties();

    SimpleFeatureTypeBuilder resultTypeBuilder = new SimpleFeatureTypeBuilder();
    resultTypeBuilder.setName("typeBuilder");
    resultTypeBuilder.setCRS(inputObsCrs);

    Iterator<Property> pItObs = obsProp.iterator();

    sfi.close();
    while (pItObs.hasNext() == true) {

      try {

        Property tempProp = pItObs.next();
        PropertyType type = tempProp.getDescriptor().getType();
        String name = type.getName().getLocalPart();
        Class<String> valueClass = (Class<String>) tempProp.getType().getBinding();

        resultTypeBuilder.add(name, valueClass);

        // LOG.warn ("Obs property " + name + " " + valueClass + " " +type.toString());
      } catch (Exception e) {
        LOG.error("property error " + e);
      }
    }

    // add DQ_Field

    resultTypeBuilder.add("DQ_SA_SimilarF", Double.class);
    SimpleFeatureType typeF = resultTypeBuilder.buildFeatureType();
    // LOG.warn("Get Spatial Accuracy Feature Type " + typeF.toString());

    SimpleFeatureBuilder resultFeatureBuilder = new SimpleFeatureBuilder(typeF);

    obsIt.close();

    SimpleFeatureIterator obsIt2 = (SimpleFeatureIterator) obsFc.features();

    while (obsIt2.hasNext()) {
      SimpleFeature tempFeature = obsIt2.next();

      fType = tempFeature.getType();

      // LOG.warn("fieldName " + fieldName + " featureName " + featureN + " tempFeature Type " +
      // fType);
      // LOG.warn("TableFeatureName " + tempFeature.getProperty(fieldName).getValue());

      String tempFeatureName = (String) tempFeature.getProperty(fieldName).getValue();

      Geometry geom = (Geometry) tempFeature.getDefaultGeometry();
      for (Property obsProperty : tempFeature.getProperties()) {

        String name = obsProperty.getName().toString();
        Object value = obsProperty.getValue();

        resultFeatureBuilder.set(name, value);
      }

      Geometry bufferGeom = geom.buffer(dist);

      SimpleFeatureIterator authIt2 = (SimpleFeatureIterator) authFc.features();

      int count = 0;
      int within = 0;

      while (authIt2.hasNext() && count <= minNum) {
        SimpleFeature tempAuth = authIt2.next();
        String featureN = (String) tempAuth.getProperty(fieldName).getValue();

        Geometry tempGeom = (Geometry) tempAuth.getDefaultGeometry();

        String authProperty = (String) tempAuth.getProperty(fieldName).getValue();

        if (tempGeom.within(bufferGeom) && authProperty.equalsIgnoreCase(featureN)) {

          count++;

          if (count >= minNum) {
            within = 1;
          }
        }
      }
      LOG.warn("HERE " + within);
      resultFeatureBuilder.set("DQ_SA_SimilarF", within);

      SimpleFeature result = resultFeatureBuilder.buildFeature(tempFeature.getID());
      result.setDefaultGeometry(geom);
      LOG.warn("HERE " + result);
      returnFeatures.add(result);

      if (within == 1) {
        resultFeatures.add(result);
      }

      authIt2.close();
    }
    obsIt2.close();

    ListFeatureCollection qualResult = new ListFeatureCollection(fType, resultFeatures);
    ListFeatureCollection returns = new ListFeatureCollection(fType, returnFeatures);

    LOG.warn("HERE 2 " + qualResult.size() + " " + returns.size());

    Map<String, IData> results = new HashMap<String, IData>();
    results.put("qual_result", new GTVectorDataBinding(qualResult));
    results.put("result", new GTVectorDataBinding(returns));

    return results;
  }
  @Execute
  /**
   * inputData a HashMap of the input data:
   *
   * @param inputObservations: the observations
   * @param inputAuthoritativeData: the polygons
   * @param bufferSize: the size of the buffer in the same units as the input data (degrees for
   *     lat/long) results a HashpMap of the results:
   * @result result: the input data with the polygon attributes attached, null values for no match
   * @result qual_result: the matched input only data with polygon attributes attached
   * @result metadata: an unused output that was supposed to return an XML document for GeoNetwork
   */
  public void runBuffer() {

    Logger LOGGER = Logger.getLogger(BufferAuthoritativeDataComparison.class);

    SimpleFeatureIterator obsIt = (SimpleFeatureIterator) obsFC.features();

    SimpleFeatureIterator authIt = (SimpleFeatureIterator) authFC.features();

    // setup result feature

    SimpleFeature obsItFeat = obsIt.next();

    SimpleFeature obsItAuth = authIt.next();

    Collection<Property> property = obsItFeat.getProperties();
    Collection<Property> authProperty = obsItAuth.getProperties();

    // setup result type builder
    SimpleFeatureTypeBuilder resultTypeBuilder = new SimpleFeatureTypeBuilder();
    resultTypeBuilder.setName("typeBuilder");

    Iterator<Property> pItObs = property.iterator();
    Iterator<Property> pItAuth = authProperty.iterator();

    metadataMap.put("element", "elementBufferedMetadata");
    metadataFile = createXMLMetadata(metadataMap);

    while (pItObs.hasNext() == true) {

      try {
        Property tempProp = pItObs.next();

        PropertyType type = tempProp.getDescriptor().getType();
        String name = type.getName().getLocalPart();
        Class<String> valueClass = (Class<String>) tempProp.getType().getBinding();

        resultTypeBuilder.add(name, valueClass);

      } catch (Exception e) {
        LOGGER.error("property error " + e);
      }
    }
    int i = 0;
    while (pItAuth.hasNext() == true) {
      try {
        Property tempProp = pItAuth.next();

        PropertyType type = tempProp.getDescriptor().getType();
        String name = type.getName().getLocalPart();
        Class<String> valueClass = (Class<String>) tempProp.getType().getBinding();

        if (i > 3) {

          resultTypeBuilder.add(name, valueClass);
        }

        i++;

      } catch (Exception e) {
        LOGGER.error("property error " + e);
      }
    }

    obsIt.close();
    authIt.close();
    resultTypeBuilder.add("withinBuffer", Integer.class);

    // set up result feature builder

    SimpleFeatureType type = resultTypeBuilder.buildFeatureType();
    SimpleFeatureBuilder resultFeatureBuilder = new SimpleFeatureBuilder(type);

    // process data here:

    SimpleFeatureIterator obsIt2 = (SimpleFeatureIterator) obsFC.features();

    int within = 0;

    resultFeatureCollection = DefaultFeatureCollections.newCollection();

    while (obsIt2.hasNext() == true) {
      within = 0;
      SimpleFeature tempObs = obsIt2.next();
      Geometry obsGeom = (Geometry) tempObs.getDefaultGeometry();

      for (Property obsProperty : tempObs.getProperties()) {

        String name = obsProperty.getName().getLocalPart();
        Object value = obsProperty.getValue();

        resultFeatureBuilder.set(name, value);
        // LOGGER.warn("obs Property set " + name);
      }

      double bufferSizeDouble = Double.parseDouble(bufferSize);

      Geometry bufferGeom = obsGeom.buffer(bufferSizeDouble);

      int j = 0;
      SimpleFeatureIterator authIt2 = (SimpleFeatureIterator) authFC.features();
      while (authIt2.hasNext() == true) {

        SimpleFeature tempAuth = authIt2.next();
        Geometry authGeom = (Geometry) tempAuth.getDefaultGeometry();

        if (bufferGeom.intersects(authGeom) == true) {
          within = 1;
          j = 0;

          LOGGER.warn("Intersection = true");
          for (Property authProperty1 : tempAuth.getProperties()) {

            String name = authProperty1.getName().getLocalPart();
            Object value = authProperty1.getValue();
            // Class valueClass = (Class<String>)authProperty1.getType().getBinding();

            //		LOGGER.warn("Auth property " + name);
            if (j > 3) {
              resultFeatureBuilder.set(name, value);
              //	LOGGER.warn("Auth property set " + name);

            }

            j++;
          }
        }
      }
      resultFeatureBuilder.set("withinBuffer", within);

      SimpleFeature resultFeature = resultFeatureBuilder.buildFeature(tempObs.getName().toString());
      Geometry geom = (Geometry) tempObs.getDefaultGeometry();
      resultFeature.setDefaultGeometry(geom);

      list.add(resultFeature);

      // resultFeatureCollection.add(resultFeature);
      // LOGGER.warn("RESULT FEATURE " + resultFeatureCollection.getSchema().toString());
      // resultFeatureCollection = obsFC;
    }

    listFeatureCollection = new ListFeatureCollection(type, list);
    LOGGER.warn("Result Feature Size " + listFeatureCollection.size());
  }