Feature attachment editing

Download Sample Viewer

Description

This application shows how to use the toolkit's attachment editor (JAttachmentEditor). The attachment editor is created with a JMap instance and feature layer, once the feature layer has successfully initialized. Attachments - such as text files, images and so on - are associated with a feature in the feature layer, and the attachment editor provides UI elements to list, view, add, and delete attachments.

Code snippet


    featureLayer = new FeatureLayer(featureTable);
    // create attachment editor when FeatureLayer is initialized
    featureLayer.addLayerInitializeCompleteListener(new LayerInitializeCompleteListener() {
      attachmentEditor = new JAttachmentEditor(jMap, featureLayer);
  
      @Override
      public void layerInitializeComplete(LayerInitializeCompleteEvent e) {
        if (e.getLayer().getStatus() == LayerStatus.INITIALIZED) {
          SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
              // scroll pane for the attachment editor
              JScrollPane scrollPane = new JScrollPane();

              // create attachment editor
              attachmentEditor = new JAttachmentEditor(jMap, featureLayer);
              scrollPane.setViewportView(attachmentEditor);

              jPanel.add(scrollPane, BorderLayout.WEST);
            }
          });
        }
      }
    });
    map.getLayers().add(featureLayer);
    contentPane.add(map, BorderLayout.CENTER);
  

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.editing;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

import com.esri.core.geodatabase.Geodatabase;
import com.esri.core.geodatabase.GeodatabaseFeatureTable;
import com.esri.core.geometry.Envelope;
import com.esri.core.geometry.Point;
import com.esri.map.ArcGISTiledMapServiceLayer;
import com.esri.map.FeatureLayer;
import com.esri.map.JMap;
import com.esri.map.Layer.LayerStatus;
import com.esri.map.LayerInitializeCompleteEvent;
import com.esri.map.LayerInitializeCompleteListener;
import com.esri.map.LayerList;
import com.esri.map.MapEvent;
import com.esri.map.MapEventListenerAdapter;
import com.esri.runtime.ArcGISRuntime;
import com.esri.toolkit.attachments.JAttachmentEditor;

/***
 * This application shows how to use the toolkit's attachment editor 
 * ({@link JAttachmentEditor}). The attachment editor is created 
 * with a JMap instance and feature layer, once the feature layer has 
 * successfully initialized. Attachments - such as text files, images 
 * and so on - are associated with a feature in the feature layer, and 
 * the attachment editor provides UI elements to list, view, add, and 
 * delete attachments.
 */
public class AttachmentEditor extends MapEventListenerAdapter {

  private FeatureLayer featureLayer;
  private JAttachmentEditor attachmentEditor;
  private JPanel jPanel;
  private JMap jMap;
  private Geodatabase geodatabase;
  private static final String FSP = System.getProperty("file.separator");
  private static final String RELATIVE_PATH = 
      "disconnected" + FSP + "geodatabase" + FSP + "water.geodatabase";
  private static final String GEODATABASE_PATH = getPathSampleData() + FSP + RELATIVE_PATH;

  // ------------------------------------------------------------------------
  // Core functionality
  // ------------------------------------------------------------------------
  /**
   * Creates and displays the UI, including the map, feature layer, and 
   * attachment editor for this application.
   * 
   * @throws FileNotFoundException if there is no geodatabase at the specified location 
   */
  public JPanel createUI() throws FileNotFoundException {
    jPanel = new JPanel();
    jPanel.setLayout(new BorderLayout());

    // add map
    jMap = new JMap();
    jPanel.add(jMap, BorderLayout.CENTER);
    jMap.setMinimumSize(new Dimension(512, 512));

    // set default extent to Naperville Area
    jMap.setExtent(new Envelope(-9823085, 5125318, -9803978, 5134251));
    jMap.addMapEventListener(new MapEventListenerAdapter() {

      @Override
      public void mapReady(MapEvent event) {
        jMap.zoom(0.125);
        jMap.panTo(new Point(-9812978.056800043, 5128501.028743427));
      }
    });

    // add data to the map
    LayerList layers = jMap.getLayers();
    layers.add(new ArcGISTiledMapServiceLayer(
        "http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"));

    // add feature data to the map
    geodatabase = new Geodatabase(GEODATABASE_PATH);
    GeodatabaseFeatureTable table = geodatabase.getGeodatabaseFeatureTableByLayerId(4);
    featureLayer = new FeatureLayer(table);
    // create attachment editor when FeatureLayer is initialized
    featureLayer.addLayerInitializeCompleteListener(new LayerInitializeCompleteListener() {

      @Override
      public void layerInitializeComplete(LayerInitializeCompleteEvent e) {
        if (e.getLayer().getStatus() == LayerStatus.INITIALIZED) {
          SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
              // scroll pane for the attachment editor
              JScrollPane scrollPane = new JScrollPane();

              // create attachment editor
              attachmentEditor = new JAttachmentEditor(jMap, featureLayer);
              scrollPane.setViewportView(attachmentEditor);

              jPanel.add(scrollPane, BorderLayout.WEST);
            }
          });
        }
      }
    });
    layers.add(featureLayer);

    return jPanel;
  }

  /**
   * Creates the application window, calls dispose on the map and geodatabase 
   * on application exit.
   * @return a window.
   */
  private JFrame createWindow() {
    JFrame window = new JFrame();
    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);
        if (jMap!=null) jMap.dispose();
        if (geodatabase!=null) geodatabase.dispose();
      }
    });
    return window;
  }
  
  // ------------------------------------------------------------------------
  // 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 {
          AttachmentEditor attachmentEditorApp = new AttachmentEditor();
          JFrame window = attachmentEditorApp.createWindow();
          window.add(attachmentEditorApp.createUI());
          window.setVisible(true);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    });
  }

  // ------------------------------------------------------------------------
  // Private methods
  // ------------------------------------------------------------------------
  private static String getPathSampleData() {
    String dataPath = null;
    String javaPath = ArcGISRuntime.getInstallDirectory();
    if (javaPath != null) {
      if (!(javaPath.endsWith("/") || javaPath.endsWith("\\"))){
        javaPath += FSP;
      }
      dataPath = javaPath + "sdk" + FSP + "samples" + FSP + "data" + FSP;
    }
    File dataDir = new File(dataPath);
    if (!dataDir.exists()) { 
      dataPath = ".." + FSP + "data" + FSP;
      dataDir = new File(dataPath);
    }

    return copyIfNoCreateFileAccess(dataDir, RELATIVE_PATH);
  }

  /**
   * Copies file to java.io.tmpdir if the user does not have permission to create file
   * in the current dataDir.
   * @param dataDir directory containing the file to be copied.
   * @param relativeFilePath path of file to be copied relative to the dataDir.
   * @return the path of directory that contains the file copied. This will be in the java.io.tmpdir
   * if copied, otherwise it will be same as input dataDir.
   */
  private static String copyIfNoCreateFileAccess(File dataDir, String relativeFilePath) {
    // check if can create a file in the data directory.
    // can't use File.canWrite() because create is considered different from write. 
    File tempFolder = null;
    try {
      tempFolder = new File(dataDir.getAbsolutePath() + FSP + "temp");
      if (tempFolder.exists()) {
        tempFolder.delete();
      }
      tempFolder.mkdir();
    } catch (Exception ex) {
      ex.printStackTrace();
    }
    if (tempFolder != null && tempFolder.exists()) {
      tempFolder.delete();
      return dataDir.getAbsolutePath();
    }

    // no permission to create a new file in the existing data folder.
    // so copy the data file to the java.io.tmpdir folder.
    String tempDataDir = System.getProperty("java.io.tmpdir") + FSP + 
        "ArcGIS SDKs" + FSP + "java" + ArcGISRuntime.getAPIVersion() + 
        FSP + "sdk" + FSP + "samples" + FSP + "data";

    String fromFilePath = dataDir + FSP + relativeFilePath;
    String toFilePath = tempDataDir + FSP + relativeFilePath;
    FileInputStream in = null;
    FileOutputStream out = null;
    try {
      File toFile = new File(toFilePath);
      if (toFile.exists()) {
        return tempDataDir;
      }
      toFile.getParentFile().mkdirs();
      toFile.createNewFile();
      System.out.println("Copying file from " + fromFilePath + " to " + toFile.getAbsolutePath());
      in = new FileInputStream(fromFilePath);
      out = new FileOutputStream(toFile);
      byte[] byteBuf = new byte[4096]; 
      int numBytesRead;
      while ((numBytesRead = in.read(byteBuf)) != -1) {
        out.write(byteBuf, 0, numBytesRead);
      }
    } catch (Exception ex) {
      JOptionPane.showMessageDialog(null, wrap(ex.getMessage()));
    } finally {
      if (in != null) {
        try {
          in.close();
        } catch (IOException ex) {
          ex.printStackTrace();
        }
      }
      if (out != null) {
        try {
          out.close();
        } catch (IOException ex) {
          ex.printStackTrace();
        }
      }
    }
    System.out.println("Copy completed.");
    return tempDataDir;
  }
  
  private static 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?