Feature service table

Download Sample Viewer

Description

This sample shows how to perform an attribute query against a GeodatabaseFeatureServiceTable.

On application load, a GeodatabaseFeatureServiceTable is created from a feature service URL and layer ID, then a FeatureLayer is created from the GeodatabaseFeatureServiceTable to display the table's features in the map. The GeodatabaseFeatureServiceTable queries the service for features within the current map extent and caches those features locally in a feature table. As you pan and zoom the map, more features get added to this local feature cache.

In this application, pressing the 'Query Features' button calls GeodatabaseFeatureServiceTable's queryFeatures method. This method queries the table's locally cached features. The query results are highlighted in the feature layer in the query callback.

To instead query the service directly, you can create a QueryTask from the feature service layer URL and call its execute method.

Code snippet


  // create the query parameters
  QueryParameters queryParameters = new QueryParameters();
  queryParameters.setWhere("typdamage LIKE '" + damageType
      + "' AND primcause LIKE '" + causeType + "'");
  
  // execute the query against the feature service table
  featureServiceTable.queryFeatures(queryParameters, callback) {
    ...
  }
  

Sample Code

/* Copyright 2014 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 com.esri.client.samples.search;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;

import com.esri.core.geodatabase.GeodatabaseFeatureServiceTable;
import com.esri.core.geodatabase.GeodatabaseFeatureServiceTable.Status;
import com.esri.core.geometry.Envelope;
import com.esri.core.map.CallbackListener;
import com.esri.core.map.Feature;
import com.esri.core.map.FeatureResult;
import com.esri.core.tasks.query.QueryParameters;
import com.esri.map.ArcGISTiledMapServiceLayer;
import com.esri.map.FeatureLayer;
import com.esri.map.JMap;

/***
 * This sample shows how to perform an attribute query against a GeodatabaseFeatureServiceTable.
 * <p>
 * On application load, a GeodatabaseFeatureServiceTable is created from a feature service URL 
 * and layer ID, then a FeatureLayer is created from the GeodatabaseFeatureServiceTable to display 
 * the table's features in the map. The GeodatabaseFeatureServiceTable queries the service for 
 * features within the current map extent and caches those features locally in a feature table. 
 * As you pan and zoom the map, more features get added to this local feature cache.
 * <p>
 * In this application, pressing the 'Query Features' button calls GeodatabaseFeatureServiceTable's 
 * <code>queryFeatures</code> method. This method queries the table's locally cached features. The 
 * query results are highlighted in the feature layer in the query callback.
 * <p>
 * To instead query the service directly, you can create a QueryTask from the feature service layer 
 * URL and call its <code>execute</code> method.
 */
public class OnlineQueryApp {

  // resources
  final String URL_TILED_LAYER = "http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer";
  final String FEATURE_SERVICE_URL = "http://sampleserver6.arcgisonline.com/arcgis/rest/services/DamageAssessment/FeatureServer";

  // ArcGIS components
  private JMap map;
  private FeatureLayer featureLayer;
  private GeodatabaseFeatureServiceTable featureServiceTable;

  // query attributes
  private final String[] TYPE_DAMAGE = { "Minor", "Major", "Affected",
      "Inaccessible", "Destroyed" };
  private final String[] PRIM_CAUSE = { "Snow", "Rain", "Flood", "Fire",
      "Wind", "Earthquake", "Other" };

  // ------------------------------------------------------------------------
  // Core functionality
  // ------------------------------------------------------------------------
  /**
   * Executes a query. The query will get all features whose damage type and
   * primary cause matches this.
   * 
   * @param damageType
   *          Input field that has the Damage type.
   * @param damageType
   *          Input field that has the Damage primary cause.
   */
  private void executeQuery(String damageType, String causeType) {
    // clears previous selection
    featureLayer.clearSelection();

    // creates the query parameters
    QueryParameters queryParameters = new QueryParameters();
    queryParameters.setWhere("typdamage LIKE '" + damageType
        + "' AND primcause LIKE '" + causeType + "'");

    // executes the query.
    featureServiceTable.queryFeatures(queryParameters,
        new CallbackListener<FeatureResult>() {

      @Override
      public void onError(Throwable e) {
        JOptionPane.showMessageDialog(map, e.getLocalizedMessage() , "",
            JOptionPane.ERROR_MESSAGE);
      }

      @Override
      public void onCallback(FeatureResult results) {
        // if there are no matching records, then return.
        if (results.featureCount() < 1) {
          System.out.println(" No records found! ");
          return;
        }

        for (Object objFeature : results) {
          Feature feature = (Feature) objFeature;

          // highlight features
          featureLayer.selectFeature(feature.getId());
        }
      }
    });
  }

  // ------------------------------------------------------------------------
  // Static methods
  // ------------------------------------------------------------------------
  /**
   * Starting point of this application: creates the window, creates an 
   * instance of this application and calls method to create the UI.
   * 
   * @param args any arguments
   */
  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        try {
          // instance of this application
          OnlineQueryApp OnlineQueryApp = new OnlineQueryApp();

          // create the UI, including the map, for the application.
          JFrame appWindow = OnlineQueryApp.createWindow();
          appWindow.add(OnlineQueryApp.createUI());
          appWindow.setVisible(true);
        } catch (Exception e) {
          // on any error, display the stack trace.
          e.printStackTrace();
        }
      }
    });

  }

  // ------------------------------------------------------------------------
  // Public methods
  // ------------------------------------------------------------------------
  /**
   * Creates the map, labels, comboboxes and various 
   * Swing panels used in the application and more.
   */
  public JComponent createUI() throws Exception {
    // application content
    JComponent mapPane = createMapPane();

    // map
    map = createMap();
    map.setSize(1000, 700);

    // Focus on U.S.
    map.setExtent(new Envelope(-15967900, 1670500, -6360000, 8079000));

    // application title
    JTextArea lblTitle = new JTextArea("Damage Assessment Query: ");
    lblTitle.setEditable(false);
    lblTitle.setFont(new Font("Verdana", Font.BOLD, 11));
    lblTitle.setBackground(new Color(0, 0, 0, 150));
    lblTitle.setForeground(Color.WHITE);
    lblTitle.setBorder(BorderFactory.createEtchedBorder());
    lblTitle.setAlignmentX(Component.CENTER_ALIGNMENT);
    lblTitle.setMaximumSize(new Dimension(200, 30));
    lblTitle.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));

    // query damage label
    JTextArea lblDamage = new JTextArea("Extent of damage is: ");
    lblDamage.setEditable(false);
    lblDamage.setForeground(Color.WHITE);
    lblDamage.setBackground(Color.DARK_GRAY);
    lblDamage.setAlignmentX(Component.CENTER_ALIGNMENT);
    lblDamage.setMaximumSize(new Dimension(200, 25));

    // Input field 1. Create the typdamage combo box.
    final JComboBox<String> damageList = new JComboBox<>(TYPE_DAMAGE);
    damageList.setSelectedIndex(4);
    damageList.setAlignmentX(Component.CENTER_ALIGNMENT);
    damageList.setMaximumSize(new Dimension(200, 25));

    // query primary cause label
    JTextArea lblCause = new JTextArea(" AND primary cause is: ");
    lblCause.setEditable(false);
    lblCause.setForeground(Color.WHITE);
    lblCause.setBackground(Color.DARK_GRAY);
    lblCause.setAlignmentX(Component.CENTER_ALIGNMENT);
    lblCause.setMaximumSize(new Dimension(200, 20));

    // Input Field 2. Create the primary cause combo box.
    final JComboBox<String> causeList = new JComboBox<>(PRIM_CAUSE);
    causeList.setSelectedIndex(3);
    causeList.setAlignmentX(Component.CENTER_ALIGNMENT);
    causeList.setMaximumSize(new Dimension(200, 25));

    final JButton queryButton = new JButton("Query Features");
    queryButton.setAlignmentX(Component.CENTER_ALIGNMENT);
    queryButton.setEnabled(true);
    queryButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        executeQuery((String)damageList.getSelectedItem(), (String)causeList.getSelectedItem());
      }
    });
    queryButton.setMaximumSize(new Dimension(200, 25));

    // group the above UI items into a panel
    final JPanel controlPanel = new JPanel();
    BoxLayout boxLayout = new BoxLayout(controlPanel, BoxLayout.Y_AXIS);
    controlPanel.setLayout(boxLayout);
    controlPanel.setLocation(10, 10);
    controlPanel.setSize(200, 160);
    controlPanel.setBackground(new Color(0, 0, 0, 100));
    controlPanel.setBorder(new LineBorder(Color.BLACK, 3, false));
    controlPanel.add(lblTitle);
    controlPanel.add(Box.createVerticalStrut(5));
    controlPanel.add(lblDamage);
    controlPanel.add(Box.createVerticalStrut(5));
    controlPanel.add(damageList);
    controlPanel.add(Box.createVerticalStrut(5));
    controlPanel.add(lblCause);
    controlPanel.add(Box.createVerticalStrut(5));
    controlPanel.add(causeList);
    controlPanel.add(Box.createVerticalStrut(5));
    controlPanel.add(queryButton);

    // add the panel to the main window
    mapPane.add(controlPanel);
    mapPane.add(map);

    return mapPane;
  }

  // ------------------------------------------------------------------------
  // Private methods
  // ------------------------------------------------------------------------
  /**
   * Creates a window.
   * 
   * @return a window.
   */
  private JFrame createWindow() {
    JFrame window = new JFrame("Feature Layer - Query Application");
    window.setBounds(100, 100, 1000, 700);
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.getContentPane().setLayout(new BorderLayout(0, 0));
    window.addWindowListener(new WindowAdapter() {
      @Override
      public void windowClosing(WindowEvent windowEvent) {
        super.windowClosing(windowEvent);
        map.dispose();
      }
    });
    return window;
  }

  /**
   * Creates a map pane which will contain the map component and 
   * be able to display other components above the map in z-order, 
   * such as panels.
   * 
   * @return the map pane
   */
  private static JLayeredPane createMapPane() {
    JLayeredPane contentPane = new JLayeredPane();
    contentPane.setBounds(100, 100, 1000, 700);
    contentPane.setLayout(new BorderLayout(0, 0));
    contentPane.setVisible(true);
    return contentPane;
  }

  /**
   * Creates a map, tiled layer, GeodatabaseFeatureServiceTable and FeatureLayer.
   * 
   * @return a map.
   */
  private JMap createMap() {
    final JMap jMap = new JMap();
    ArcGISTiledMapServiceLayer tiledLayer = new ArcGISTiledMapServiceLayer(
        URL_TILED_LAYER);

    jMap.getLayers().add(tiledLayer);

    featureServiceTable = new GeodatabaseFeatureServiceTable(
        FEATURE_SERVICE_URL, 0);
    featureServiceTable.initialize(new CallbackListener<GeodatabaseFeatureServiceTable.Status>() {

      @Override
      public void onError(Throwable e) {
        JOptionPane.showMessageDialog(map, 
            wrap(e.getLocalizedMessage()), "",JOptionPane.ERROR_MESSAGE);     
      }

      @Override
      public void onCallback(Status status) {
        if (Status.INITIALIZED == status) {

          // feature Layer - this has the damage to residential building data
          featureLayer = new FeatureLayer(featureServiceTable);
          jMap.getLayers().add(featureLayer);
        }
      }
    });

    return jMap;
  }

  private String wrap(String str) {
    // create a HTML string that wraps text when longer
    return "<html><p style='width:200px;'>" + str + "</html>";
  }
}
Feedback on this topic?