Custom Java Geoprocessing Tool - Delete Features
arcgissamples\geoprocessing\DeleteFeaturesToolRunner.java
/* Copyright 2010 ESRI
* 
* All rights reserved under the copyright laws of the United States
* and applicable international laws, treaties, and conventions.
* 
* You may freely redistribute and use this sample code, with or
* without modification, provided you include the original copyright
* notice and use restrictions.
* 
* See the use restrictions.
* 
*/
package arcgissamples.geoprocessing;

import java.io.File;
import java.io.IOException;

import com.esri.arcgis.geoprocessing.GPParameter;
import com.esri.arcgis.geoprocessing.GPUtilities;
import com.esri.arcgis.geoprocessing.GeoProcessor;
import com.esri.arcgis.geoprocessing.IGPTool;
import com.esri.arcgis.geoprocessing.IGPToolbox;
import com.esri.arcgis.geoprocessing.IToolboxWorkspace;
import com.esri.arcgis.geoprocessing.IToolboxWorkspaceProxy;
import com.esri.arcgis.geoprocessing.ToolboxWorkspaceFactory;
import com.esri.arcgis.geoprocessing.tools.datamanagementtools.Copy;
import com.esri.arcgis.system.AoInitialize;
import com.esri.arcgis.system.EngineInitializer;
import com.esri.arcgis.system.IArray;
import com.esri.arcgis.system.VarArray;
import com.esri.arcgis.system.esriLicenseProductCode;
import com.esri.arcgis.system.esriLicenseStatus;

public class DeleteFeaturesToolRunner
{
  /*
   * GPUtilities class contains several util methods that are useful while working with GP programmatically
   */
  private GPUtilities gpUtil = null;

  /*
   * The Geoprocessor object represents the GP framework and helps setting environment variables and execute tools in
   * toolboxes
   */
  private GeoProcessor gp = null;

  /*
   * The toolBoxName is used to refer to the toolbox during the course of this apps execution.
   */
  private String toolBoxName = null;

  /*
   * Function Factory alias is defined in your Java Function Factory. See the
   * arcgissamples.geoprocessing.customtool.DFFunctionFactory class. After you register your jar file that contains
   * your GP tool and function factory, you can use this alias and create a toolbox that will contain all tools served
   * by this Function Factory.
   */
  private String functionFactoryAlias = null;

  /*
   * The output folder is used to store newly created toolboxes and output datasets that are created during GP tool's
   * execution.
   */
  private String outputFolder = null;

  public DeleteFeaturesToolRunner()
  {
    // initialize the GPUtilities object, Geoprocessor and all names
    try
    {
      gpUtil = new GPUtilities();

      gp = new GeoProcessor();
      gp.setOverwriteOutput(true);
      gp.resetEnvironments();
      gp.clearMessages();

      toolBoxName = "dftoolbox.tbx";
      functionFactoryAlias = "dffunctionfactory";
      outputFolder = this.getOutputPath();

      // create output folder if it does not exist
      this.createFolder(outputFolder);

      System.out.print("\nRemoving toolbox from previous run, if it exists...");
      File f = new File(outputFolder + File.separator + toolBoxName);
      if (f.exists())
      {
        f.delete();
      }
      System.out.println("Done.");

      // if it does, clean it up
      this.emptyFolder(outputFolder);

    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
  }

  public static void main(String[] args)
  {
    try
    {
      EngineInitializer.initializeEngine();
      AoInitialize aoInit = new AoInitialize();
      initializeArcGISLicenses(aoInit);

      DeleteFeaturesToolRunner toolRunner = new DeleteFeaturesToolRunner();
      toolRunner.runTool();

      aoInit.shutdown();
    }
    catch (Exception re)
    {
      re.printStackTrace();
    }
  }

  private void runTool() throws Exception
  {
    System.out.print("\nIn order to run this sample, please ensure that this GP tool's jar file is already in " + 
    "ENGINE HOME OR DESKTOP HOME/java/lib/ext folder.");

    System.out.print("\nCreating new toolbox from the Function Factory - " + functionFactoryAlias + "...");
    gpUtil.createToolboxFromFactory(functionFactoryAlias, outputFolder, toolBoxName);
    System.out.println("Done. \nToolbox " + toolBoxName + " created in " + outputFolder + ".");

    System.out.print("\nAdding Toolbox " + toolBoxName + " to the GeoProcessor...");
    gp.addToolbox(outputFolder + File.separator + toolBoxName);
    System.out.println("Done.");

    System.out.print("\nCreating Toolbox WS Factory and opening toolbox " + toolBoxName + "...");
    ToolboxWorkspaceFactory toolboxWorkspaceFactory = new ToolboxWorkspaceFactory();
    IToolboxWorkspace toolboxWorkspace = new IToolboxWorkspaceProxy(toolboxWorkspaceFactory.openFromFile(
        outputFolder, 0));
    IGPToolbox gpToolbox = toolboxWorkspace.openToolbox(toolBoxName);
    System.out.println("Done.");

    System.out.print("\nRetrieving GP tool's info...");
    String toolName = "DeleteFeatures";
    IGPTool gpTool = gpToolbox.openTool(toolName);
    IArray parameters = gpTool.getParameterInfo();
    int count = parameters.getCount();
    System.out.println("Total number of parameters in " + toolName + " tool: " + count);

    for (int i = 0; i < count; i++)
    {
      GPParameter parameter = (GPParameter) parameters.getElement(i);
      System.out.println("\nParameter " + (i + 1) + ": " + "\nName: " + parameter.getName() + "\nType: "
          + parameter.getParameterType() + "\nDirection: " + parameter.getDirection() + "\nData Type: "
          + parameter.getDataType().getName());
    }

    System.out.print("\nMaking a copy of an existing feature class in the output folder. This copy will be used as input to the gp tool...");
    //Get DEVKITHOME Home
    String devKitHome = System.getenv("AGSDEVKITJAVA");
    copyFeatureClass(devKitHome + File.separator + "java" + File.separator + "samples" + File.separator + "data"
        + File.separator + "usa", outputFolder, "wind.shp");
    System.out.println("Done.");

    System.out.print("\nExecuting the Delete Features tool...");
    /*
     * The Delete Features tool has 2 input parameters: 1. The feature class you want to delete features from, and
     * 2. The sql expression that will indicate which features to delete. We are creating an array that will hold
     * values for above 2 params. The tool also has 1 output param. But we need not specify it here, since it uses
     * the first input parameter, deletes features from it, and considers it as output parameter.
     */
    VarArray inputValues = new VarArray();
    inputValues.add(outputFolder + File.separator + "wind.shp");// input feature
    // class
    inputValues.add("\"VELOCITY\" = 11");// sql expression
    executeTool(toolName, inputValues);
    System.out.println("Done.\nPlease check the output of your tool in " + outputFolder);
  }

  private void executeTool(String toolName, VarArray inputValues) throws Exception
  {

    try
    {
      gp.clearMessages();

      long t0 = System.currentTimeMillis();
      gp.execute(toolName + "_" + functionFactoryAlias, inputValues, null);
      long t1 = System.currentTimeMillis();

      System.out.println("Execution took : " + (t1 - t0) + " ms.");
      for (int i = 0; i < gp.getMessageCount(); i++)
      {
        System.out.println(gp.getMessage(i));
      }
    }
    catch (IOException e)
    {
      e.printStackTrace();
      System.out.println("Geoprocessing.execute() encountered errors:");
      int c = gp.getMessageCount();

      for (int i = 0; i < c; i++)
      {
        System.out.println(gp.getMessage(i));
      }
    }
  }

  /**
   * Copies a feature class from source folder to dest folder, using the Copy GP tools
   * 
   * @param sourceFolder
   * @param destFolder
   * @param fcName
   * @throws Exception
   */
  private void copyFeatureClass(String sourceFolder, String destFolder, String fcName) throws Exception
  {
    Copy copy = new Copy(sourceFolder + File.separator + fcName, destFolder + File.separator + fcName);
    copy.setDataType("ShapeFile");
    gp.execute(copy, null);
  }

  /**
   * Returns output path
   * 
   * @return String
   * @throws Exception
   */
  public String getOutputPath() throws Exception
  {
    String fullyQualifiedClassName = this.getClass().getName();
    String classFile = fullyQualifiedClassName.substring(fullyQualifiedClassName.lastIndexOf(".") + 1) + ".class";
    String pathIncludingClassFile = this.getClass().getResource(classFile).getPath();
    String pathToClassFile = null;
    String osName = System.getProperty("os.name");
    if (osName.toLowerCase().startsWith("win"))
    {
      pathToClassFile = pathIncludingClassFile.substring(1, pathIncludingClassFile.lastIndexOf(classFile));
    }
    else
    {
      pathToClassFile = pathIncludingClassFile.substring(0, pathIncludingClassFile.lastIndexOf(classFile));
    }

    return pathToClassFile + "output";
  }

  /**
   * Creates a new directory
   * 
   * @param pathName
   *            String
   */
  public void createFolder(String pathName)
  {
    File f = new File(pathName);
    if (!f.exists())
    {
      f.mkdir();
    }
  }

  /**
   * Empties specified directory of all files
   * 
   * @param dirName
   *            String
   */
  public void emptyFolder(String dirName)
  {
    File src = new File(dirName);
    if (src.isDirectory() && src.exists())
    {
      File list[] = src.listFiles();
      for (int i = 0; i < list.length; i++)
      {
        if (list[i].isDirectory())
        {
          emptyFolder(list[i].getPath());
        }
        else
        {
          list[i].delete();
        }
      }
      // src.delete();
    }
    else
    {
      src.delete();
    }
  }

  /**
   * Empties specified directory of all files
   * 
   * @param dirName
   *            String
   */
  public void deleteFolder(String dirName)
  {
    File src = new File(dirName);
    if (src.isDirectory() && src.exists())
    {
      File list[] = src.listFiles();
      for (int i = 0; i < list.length; i++)
      {
        if (list[i].isDirectory())
        {
          emptyFolder(list[i].getPath());
          list[i].delete();
        }
        else
        {
          list[i].delete();
        }
      }
      src.delete();
    }
    else
    {
      src.delete();
    }
  }

  /**
   * Initializes the lowest available ArcGIS License
   */
  private static void initializeArcGISLicenses(AoInitialize aoInit)
  {
    try
    {
      if (aoInit.isProductCodeAvailable(esriLicenseProductCode.esriLicenseProductCodeEngine) == esriLicenseStatus.esriLicenseAvailable)
      {
        aoInit.initialize(esriLicenseProductCode.esriLicenseProductCodeEngine);
      }
      else if (aoInit.isProductCodeAvailable(esriLicenseProductCode.esriLicenseProductCodeArcView) == esriLicenseStatus.esriLicenseAvailable)
      {
        aoInit.initialize(esriLicenseProductCode.esriLicenseProductCodeArcView);
      }
      else
      {
        System.err.println("Could not initialize an Engine or ArcView license. Exiting application.");
        System.exit(-1);
      }
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
  }    
  
}