// **********************************************************************
//
// <copyright>
//
// BBN Technologies
// 10 Moulton Street
// Cambridge, MA 02138
// (617) 873-8000
//
// Copyright (C) BBNT Solutions LLC. All rights reserved.
//
// </copyright>
// **********************************************************************
//
// $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/plugin/esri/EsriLayer.java,v $
// $RCSfile: EsriLayer.java,v $
// $Revision: 1.10 $
// $Date: 2006/08/25 15:36:16 $
// $Author: dietrick $
//
// **********************************************************************
package com.bbn.openmap.plugin.esri;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Properties;
import com.bbn.openmap.dataAccess.shape.DbfTableModel;
import com.bbn.openmap.dataAccess.shape.EsriGraphicList;
import com.bbn.openmap.dataAccess.shape.EsriPointList;
import com.bbn.openmap.dataAccess.shape.EsriPolygonList;
import com.bbn.openmap.dataAccess.shape.EsriPolylineList;
import com.bbn.openmap.dataAccess.shape.ShapeConstants;
import com.bbn.openmap.layer.OMGraphicHandlerLayer;
import com.bbn.openmap.omGraphics.DrawingAttributes;
import com.bbn.openmap.omGraphics.OMGraphic;
import com.bbn.openmap.omGraphics.OMGraphicList;
import com.bbn.openmap.util.Debug;
import com.bbn.openmap.util.PropUtils;
/**
* EsriLayer loads Esri shape file sets from web servers or local file
* systems, and it enables the creation of shape file sets.
*
* To create a shape file set from a remote location: <code><pre>
* URL dbf = new URL("http://www.webserver.com/file.dbf");URL shp = new URL("http://www.webserver.com/file.shp");
* URL shx = new URL("http://www.webserver.com/file.shx");
* EsriLayer layer = new EsriLayer("name", dbf, shp, shx);
*
* </pre></code>
*
* To open a shape file set from the local file system: <code><pre>
* String dbf = "c:/data/file.dbf";String shp = "c:/data/file.shp";
* String shx = "c:/data/file.shx";
* EsriLayer layer = new EsriLayer("name", dbf, shp, shx, DrawingAttributes.DEFAULT);
*
* </pre></code>
* <code>
*
* To create a zero content shape file set from which the user can add shapes at runtime:
* <code><pre>
* EsriLayer layer = new EsriLayer("name", EsriLayer.TYPE_POLYLINE);
* </pre></code>
* <code>
*
* To add features to an EsriLayer:
* <code><pre>
* </pre></code>
* OMGraphicList shapeData = new OMGraphicList();
* ArrayList tabularData = new ArrayList();
* float[] part0 = new float[]{35.0f, -120.0f, -25.0f, -95.0f, 56.0f, -30.0f};
* float[] part1 = new float[]{-15.0f, -110.0f, 13.0f, -80.0f, -25.0f, 10.0f};
* OMPoly poly0 = new OMPoly(part0, OMGraphic.DECIMAL_DEGREES, OMGraphic.LINETYPE_RHUMB);
* OMPoly poly1 = new OMPoly(part1, OMGraphic.DECIMAL_DEGREES, OMGraphic.LINETYPE_RHUMB);
* shapeData.add(poly0); //part 1
* shapeData.add(poly1); //part 2
* shapeData.generate(_mapBean.getProjection());
* tabularData.add(0, "a value");
* layer.addRecord(shapeData, tabularData);
* layer.repaint();
* </pre></code>
*
* To configure an EsriLayer through a properties file, specify file references
* in terms of resources, files or URLs.
*
* To reference a file on Windows 2000:
* <code><pre>
* esri.class = com.bbn.openmap.plugin.esri.EsriLayer
* esri.prettyName = Esri Example
* esri.dbf = file:///c:/data/shapefile.dbf
* esri.shp = file:///c:/data/shapefile.shp
* esri.shx = file:///c:/data/shapefile.shx
* </pre></code>
*
* To reference a file on RedHat Linux 6.2:
* <code><pre>
* esri.class = com.bbn.openmap.plugin.esri.EsriLayer
* esri.prettyName = Esri Example
* esri.dbf = /home/dvanauke/resources/shapefile.dbf
* esri.shp = /home/dvanauke/resources/shapefile.shp
* esri.shx = /home/dvanauke/resources/shapefile.shx
* </pre></code>
*
* To reference a file on a web server:
* <code><pre>
* esri.class = com.bbn.openmap.plugin.esri.EsriLayer
* esri.prettyName = Esri Example
* esri.dbf = http://www.webserver.com/shapefile.dbf
* esri.shp = http://www.webserver.com/shapefile.shp
* esri.shx = http://www.webserver.com/shapefile.shx
* </pre></code>
* @author Doug Van Auken
*/
public class EsriLayer extends OMGraphicHandlerLayer implements ShapeConstants {
/**
*
*/
private static final long serialVersionUID = 1L;
protected DbfTableModel _model = null;
protected String dbf;
protected String shx;
protected String shp;
protected DrawingAttributes drawingAttributes = DrawingAttributes.getDefaultClone();
/**
* Creates an EsriLayer that will be configured through the
* <code>setProperties()</code> method
*/
public EsriLayer() {}
/**
* Creates an empty EsriLayer, usable for adding features at
* run-time
*
* @param name The name of the layer
* @param type The type of layer
* @param columnCount The number of columns in the dbf model
*/
public EsriLayer(String name, int type, int columnCount) throws Exception {
setName(name);
switch (type) {
case SHAPE_TYPE_POINT:
setList(new EsriPointList());
break;
case SHAPE_TYPE_POLYGON:
setList(new EsriPolygonList());
break;
case SHAPE_TYPE_POLYLINE:
setList(new EsriPolylineList());
break;
default:
}
_model = new DbfTableModel(columnCount);
}
/**
* Creates an EsriLayer from a set of shape files
*
* @param name The name of the layer that may be used to reference
* the layer
* @param dbf The url referencing the dbf extension file
* @param shp The url referencing the shp extension file
* @param shx The url referencing the shx extension file
*/
public EsriLayer(String name, String dbf, String shp, String shx,
DrawingAttributes da) throws MalformedURLException {
this(name,
PropUtils.getResourceOrFileOrURL(dbf),
PropUtils.getResourceOrFileOrURL(shp),
PropUtils.getResourceOrFileOrURL(shx),
da);
}
/**
* Creates an EsriLayer from a set of shape files
*
* @param name The name of the layer that may be used to reference
* the layer
* @param dbf The url referencing the dbf extension file
* @param shp The url referencing the shp extension file
* @param shx The url referencing the shx extension file
*/
public EsriLayer(String name, URL dbf, URL shp, URL shx) {
this(name, dbf, shp, shx, DrawingAttributes.getDefaultClone());
}
/**
* Creates an EsriLayer from a set of shape files
*
* @param name The name of the layer that may be used to reference
* the layer
* @param dbf The url referencing the dbf extension file
* @param shp The url referencing the shp extension file
* @param shx The url referencing the shx extension file
* @param da DrawingAttributes to use to render the layer
* contents.
*/
public EsriLayer(String name, URL dbf, URL shp, URL shx,
DrawingAttributes da) {
setName(name);
drawingAttributes = da;
setModel(DbfTableModel.getDbfTableModel(dbf));
setList(EsriGraphicList.getEsriGraphicList(shp,
drawingAttributes,
getModel(), coordTransform));
}
/**
* Handles adding records to the geometry list and the
* DbfTableModel
*
* @param graphic An OMGraphic to add the graphics list
* @param record A record to add to the DbfTableModel
*/
public void addRecord(OMGraphic graphic, ArrayList<Object> record) {
OMGraphicList _list = getList();
// Associate the record directly in the OMGraphic
graphic.putAttribute(SHAPE_DBF_INFO_ATTRIBUTE, record);
if (_list != null) {
_list.add(graphic);
}
if (_model != null) {
_model.addRecord(record);
}
}
/**
* Returns the EsriGraphicList for this layer
*
* @return The EsriGraphicList for this layer
*/
public EsriGraphicList getEsriGraphicList() {
return (EsriGraphicList) getList();
}
/**
* Returns the associated table model for this layer
*
* @return The associated table model for this layer
*/
public DbfTableModel getModel() {
return _model;
}
/**
* Returns whether this layer is of type 0 (point), 3 (polyline),
* or 5(polygon)
*
* @return An int representing the type of layer, as specified in
* Esri's shape file format specification
*/
public int getType() {
EsriGraphicList egl = getEsriGraphicList();
if (egl != null) {
return egl.getType();
}
return -1;
}
/**
* Filters the DbfTableModel given a SQL like string
*
* @param query A SQL like string to filter the DbfTableModel
*/
public void query(String query) {
//to be implemented
}
/**
* Sets the DbfTableModel
*
* @param model The DbfModel to set for this layer
*/
public void setModel(DbfTableModel model) {
_model = model;
}
/**
* Sets the properties for the <code>Layer</code>.
*
* @param prefix the token to prefix the property names
* @param properties the <code>Properties</code> object
*/
public void setProperties(String prefix, Properties properties) {
super.setProperties(prefix, properties);
drawingAttributes.setProperties(prefix, properties);
prefix = PropUtils.getScopedPropertyPrefix(prefix);
shp = properties.getProperty(prefix + PARAM_SHP);
shx = properties.getProperty(prefix + PARAM_SHX);
dbf = properties.getProperty(prefix + PARAM_DBF);
if (shp != null) {
if ((shx == null || shx.length() == 0)) {
shx = shp.substring(0, shp.lastIndexOf('.') + 1) + PARAM_SHX;
}
if ((dbf == null || dbf.length() == 0)) {
dbf = shp.substring(0, shp.lastIndexOf('.') + 1) + PARAM_DBF;
}
try {
setModel(DbfTableModel.getDbfTableModel(PropUtils.getResourceOrFileOrURL(dbf)));
setList(EsriGraphicList.getEsriGraphicList(PropUtils.getResourceOrFileOrURL(shp),
drawingAttributes,
getModel(), coordTransform));
} catch (Exception exception) {
Debug.error("EsriLayer(" + getName()
+ ") exception reading Shape files:\n "
+ exception.getMessage());
}
}
}
/**
* PropertyConsumer method.
*
* @param properties the <code>Properties</code> object
* @return the <code>Properties</code> object
*/
public Properties getProperties(Properties properties) {
properties = super.getProperties(properties);
String prefix = PropUtils.getScopedPropertyPrefix(this);
properties.setProperty(prefix + PARAM_DBF, PropUtils.unnull(dbf));
properties.setProperty(prefix + PARAM_SHX, PropUtils.unnull(shx));
properties.setProperty(prefix + PARAM_SHP, PropUtils.unnull(shp));
// Need to make sure they line up.
drawingAttributes.setPropertyPrefix(getPropertyPrefix());
drawingAttributes.getProperties(properties);
return properties;
}
/**
* Method to fill in a Properties object with values reflecting
* the properties able to be set on this PropertyConsumer. The key
* for each property should be the raw property name (without a
* prefix) with a value that is a String that describes what the
* property key represents, along with any other information about
* the property that would be helpful (range, default value,
* etc.).
*
* @param list a Properties object to load the PropertyConsumer
* properties into. If getList equals null, then a new
* Properties object should be created.
* @return Properties object containing PropertyConsumer property
* values. If getList was not null, this should equal
* getList. Otherwise, it should be the Properties object
* created by the PropertyConsumer.
*/
public Properties getPropertyInfo(Properties list) {
list = super.getPropertyInfo(list);
list.put(PARAM_DBF, "Location URL of the dbf file.");
list.put(PARAM_DBF + ScopedEditorProperty,
"com.bbn.openmap.util.propertyEditor.FUPropertyEditor");
list.put(PARAM_SHX, "Location URL of the shx file.");
list.put(PARAM_SHX + ScopedEditorProperty,
"com.bbn.openmap.util.propertyEditor.FUPropertyEditor");
list.put(PARAM_SHP, "Location URL of the shp file.");
list.put(PARAM_SHP + ScopedEditorProperty,
"com.bbn.openmap.util.propertyEditor.FUPropertyEditor");
drawingAttributes.getPropertyInfo(list);
list.put(initPropertiesProperty, PARAM_SHP + " " + PARAM_SHX + " "
+ PARAM_DBF + " " + drawingAttributes.getInitPropertiesOrder());
return list;
}
}