Query by attribute

Download Sample Viewer

Description

This sample demonstrates performing an attribute query, adding the results to the map and a table, and zooming to the result. This uses 2 queries - one to get all state names, and another to get all attributes for a state. Additionally, this application also has a button, which when clicked will focus the map to the US extent.

Code snippet


    try {
        // execute the query.
        QueryTask task = new QueryTask(URL_STATES);
        FeatureSet queryResult = task.execute(query);
        for (Graphic graphic : queryResult.getGraphics()) {
            statesList.addItem(graphic.getAttributeValue("STATE_NAME"));
        }
    } catch (Exception ex) {
        // handle exception
    }
  

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.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Iterator;
import java.util.Map;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;

import com.esri.core.geometry.Envelope;
import com.esri.core.geometry.Geometry;
import com.esri.core.geometry.GeometryEngine;
import com.esri.core.geometry.SpatialReference;
import com.esri.core.map.Feature;
import com.esri.core.map.FeatureResult;
import com.esri.core.map.Graphic;
import com.esri.core.symbol.SimpleFillSymbol;
import com.esri.core.symbol.SimpleLineSymbol;
import com.esri.core.tasks.query.QueryParameters;
import com.esri.core.tasks.query.QueryTask;
import com.esri.map.ArcGISTiledMapServiceLayer;
import com.esri.map.GraphicsLayer;
import com.esri.map.JMap;
import com.esri.map.LayerList;
import com.esri.map.MapEvent;
import com.esri.map.MapEventListenerAdapter;

/***
 * This sample demonstrates performing an attribute query, adding the results to the map and a
 * table, and zooming to the result. This uses 2 queries - one to get all state names, and
 * another to get all attributes for a state. Additionally, this application also has a button, 
 * which when clicked will focus on the US extent.
 */
public class QueryAttributeApp {

  // symbology
  final static SimpleFillSymbol   SYM_STATE = new SimpleFillSymbol(
      new Color(128, 128, 128, 200), new SimpleLineSymbol(Color.WHITE, 1));

  // resources
  final String URL_USA_TOPO = "http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer";
  final String URL_STATES = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Census_USA/MapServer/5";

  // UI related
  final String INVALID_ITEM_STATES_LIST = "Select State...";
  private JPanel controlPanel;

  // JMap
  private JMap map;

  // our graphics layer for State graphics
  private GraphicsLayer graphicsLayer;

  // for zooming to a buffered geometry
  private static final double BUFFER_DISTANCE = 500000; // 500 km

  // ------------------------------------------------------------------------
  // Constructors
  // ------------------------------------------------------------------------
  public QueryAttributeApp() {
  }

  // ------------------------------------------------------------------------
  // Core functionality
  // ------------------------------------------------------------------------
  /**
   * <pre>
   * This method
   * <li> Queries to get the information of a state.
   * <li> Zooms the map to the state.
   * <li> Highlights the state by adding it to the graphics layer.
   * </pre>
   * @param jMap map.
   * @param newStateName The state name which will be used to query, zoom, and highlight.
   * @param tblModelStateInfo Result of the query for the input state.
   */
  private void onStateNameChanged(
      final JMap jMap,
      String newStateName,
      DefaultTableModel tblModelStateInfo) {

    // return if state name is not valid
    if (newStateName == null ||
        newStateName.isEmpty() ||
        newStateName.equals(INVALID_ITEM_STATES_LIST)) {
      return;
    }

    // initialize the result - add the column headers if not already present,
    // and clear existing rows.
    if (tblModelStateInfo.getColumnCount() == 0) {
      tblModelStateInfo.addColumn("No.");
      tblModelStateInfo.addColumn("Name");
      tblModelStateInfo.addColumn("Value");
    }
    tblModelStateInfo.setRowCount(0);

    // -----------------------------------------------------------------------------------------
    // Query to get attributes of a state
    // -----------------------------------------------------------------------------------------
    // create query parameters
    QueryParameters query = new QueryParameters();

    // specify * to fetch all attributes.
    query.setOutFields(new String[] {"*"});
    // get information of the input state only.
    query.setWhere("STATE_NAME='" + newStateName + "'");

    Feature selectedState = null;

    try {
      // execute the query
      QueryTask task = new QueryTask(URL_STATES);
      FeatureResult queryResult = task.execute(query);

      // query result should have only 1 record per state
      if (queryResult.featureCount() != 1) {
        System.err.println("Error! There should be exactly 1 record per state.");
        return;
      }
      selectedState = (Feature) queryResult.iterator().next();

      // get all attributes of the state and add them as rows to the table
      int attrIndex = 1;
      for (Map.Entry<String, Object> attr : selectedState.getAttributes().entrySet()) {
        tblModelStateInfo.addRow(new Object[] {Integer.valueOf(attrIndex++), attr.getKey(), attr.getValue()});
      }

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

    if (selectedState != null) {
      // -----------------------------------------------------------------------------------------
      // Zoom to selected state, with neighbouring states within extent zoomed to
      // -----------------------------------------------------------------------------------------
      // since the coordinates system used by states layer is different from the one used
      // by the base layer, convert one to the other.
      Geometry selectedStateOnBaseMap = GeometryEngine.project(
          selectedState.getGeometry(),
          SpatialReference.create(4269),
          jMap.getSpatialReference());
      // calculate a buffer around the state geometry
      Geometry geometryForZoom = GeometryEngine.buffer(
          selectedStateOnBaseMap, map.getSpatialReference(), BUFFER_DISTANCE, map.getSpatialReference().getUnit());
      // zoom to this buffered geometry
      jMap.zoomTo(geometryForZoom);

      // -----------------------------------------------------------------------------------------
      // Add a graphic for the selected State to the graphics layer
      // -----------------------------------------------------------------------------------------
      graphicsLayer.removeAll();
      Graphic stateGraphic = new Graphic(selectedStateOnBaseMap, SYM_STATE);
      graphicsLayer.addGraphic(stateGraphic);
    }
  }

  /**
   * Executes a query to get the list of states.
   * @param statesList A combo box to which the list of states will be added.
   */
  private void populateStatesList(JComboBox<String> statesList) {
    // create a query that gets all states name.
    QueryParameters query = new QueryParameters();
    // specify STATE_NAME as the attribute to be fetched.
    query.setOutFields(new String[] {"STATE_NAME"});
    // the geometry of the state is not required here. this will reduce the amount of data
    // retrieved from the server.
    query.setReturnGeometry(false);
    // select all records.
    query.setWhere("1=1");

    try {
      // execute the query.
      QueryTask task = new QueryTask(URL_STATES);
      FeatureResult queryResult = task.execute(query);

      // add the query result to the list.
      Iterator<Object> it = queryResult.iterator();
      while (it.hasNext()) {
        Object o = it.next();
        if (o instanceof Feature) {
          Feature feature = (Feature) o;
          if (String.class.isInstance(feature.getAttributeValue("STATE_NAME"))) {
            String stateName = (String) feature.getAttributeValue("STATE_NAME");
            if (stateName != null && stateName.length() > 0) {
              statesList.addItem((String)feature.getAttributeValue("STATE_NAME"));
            }
          }
        }
      }
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }

  // ------------------------------------------------------------------------
  // Static methods
  // ------------------------------------------------------------------------
  /**
   * Starting point of this application.
   * @param args arguments to this application.
   */
  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        try {
          // instance of this application
          QueryAttributeApp queryAttributeApp = new QueryAttributeApp();

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

  // ------------------------------------------------------------------------
  // Public methods
  // ------------------------------------------------------------------------

  /**
   * Creates and displays the UI, including the map, for this application.
   */
  public JComponent createUI() throws Exception {

    // content pane
    JComponent contentPane = new JPanel();
    contentPane.setLayout(new BorderLayout(1, 0));
    contentPane.setBackground(Color.DARK_GRAY);

    // map
    map = createMap();

    Dimension preferredSize = new Dimension(250, 30);
    // button - when clicked, focus on the U.S. extent
    JButton btnShowUS = new JButton("Zoom to U.S.");
    btnShowUS.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        map.setExtent(new Envelope(-15000000, 2000000, -7000000, 8000000));
      }
    });
    btnShowUS.setPreferredSize(preferredSize);
    btnShowUS.setMaximumSize(preferredSize);
    btnShowUS.setMinimumSize(preferredSize);

    // label for the states list
    JLabel lblStatesList = new JLabel("  Query all attributes of a State.  ");
    lblStatesList.setPreferredSize(preferredSize);
    lblStatesList.setMinimumSize(preferredSize);
    lblStatesList.setMaximumSize(preferredSize);
    lblStatesList.setForeground(Color.BLACK);
    lblStatesList.setBackground(Color.WHITE);

    // scrollable-table to display a state's information
    final DefaultTableModel tblModelStateInfo = new DefaultTableModel();
    JTable stateInfoTable = new JTable(tblModelStateInfo);
    JScrollPane tblStateInfoScrollable = new JScrollPane(stateInfoTable);

    // drop-down list for the states
    JComboBox<String> cbxStatesList = new JComboBox<>();
    cbxStatesList.addItem(INVALID_ITEM_STATES_LIST);
    cbxStatesList.setPreferredSize(preferredSize);
    // populate the states list by querying
    populateStatesList(cbxStatesList);
    // add a hook for the action to be taken when selected state changes
    cbxStatesList.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        String selected = (String)((JComboBox<String>) e.getSource()).getSelectedItem();
        // execute when button is pressed.
        onStateNameChanged(map, selected, tblModelStateInfo);
      }
    });

    JPanel topPanel = new JPanel();
    topPanel.setBackground(Color.WHITE);
    topPanel.setLayout(new BorderLayout());
    topPanel.add(btnShowUS, BorderLayout.NORTH);
    topPanel.add(lblStatesList, BorderLayout.SOUTH);

    JPanel bottomPanel = new JPanel();
    bottomPanel.setLayout(new BorderLayout());
    bottomPanel.add(cbxStatesList, BorderLayout.NORTH);
    bottomPanel.add(tblStateInfoScrollable, BorderLayout.CENTER);

    // group the above UI items into a panel
    controlPanel = new JPanel();
    controlPanel.setLayout(new BorderLayout());
    controlPanel.setPreferredSize(new Dimension(250, 550));
    controlPanel.setDoubleBuffered(true);

    controlPanel.add(topPanel, BorderLayout.NORTH);
    controlPanel.add(bottomPanel, BorderLayout.CENTER);

    // add the panel and map to our content pane
    contentPane.add(controlPanel, BorderLayout.WEST);
    contentPane.add(map, BorderLayout.CENTER);

    return contentPane;
  }

  // ------------------------------------------------------------------------
  // Private methods
  // ------------------------------------------------------------------------
  /**
   * Creates a window.
   * @return a window.
   */
  private JFrame createWindow() {
    JFrame window = new JFrame("Query Attribute 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.
   * @return a map.
   */
  private JMap createMap() throws Exception {
    final JMap jMap = new JMap();
    // -----------------------------------------------------------------------------------------
    // Base Layer - with US topology, focus on U.S by default
    // -----------------------------------------------------------------------------------------
    final ArcGISTiledMapServiceLayer baseLayer = new ArcGISTiledMapServiceLayer(URL_USA_TOPO);
    jMap.setExtent(new Envelope(-15000000, 2000000, -7000000, 8000000));

    jMap.addMapEventListener(new MapEventListenerAdapter() {
      @Override
      public void mapReady(final MapEvent arg0) {
        SwingUtilities.invokeLater(new Runnable() {
          @Override
          public void run() {
            controlPanel.setVisible(true);
          }
        });
      }
    });
    LayerList layers = jMap.getLayers();
    layers.add(baseLayer);

    // -----------------------------------------------------------------------------------------
    // Graphics Layer - to highlight a selected feature
    // -----------------------------------------------------------------------------------------
    graphicsLayer = new GraphicsLayer();
    layers.add(graphicsLayer);

    return jMap;
  }

}
Feedback on this topic?