B.1 Implementing the Spatial Provider Class
The spatial provider class interface must be implemented.
The provider must implement the class interface shown in Custom Geometry Themes. Example B-1 contains the partial code for the spatial provider in the supplied demo. Note that this sample code is deliberately simplified; it is not optimized, and the provider does not create any spatial indexing mechanism.
After you have implemented the provider code, compile it and generate a jar file with this compiled class. The file spatialprovider.jar
in the demo directory contains the compiled version of this sample code, and you can use it directly. Copy this jar file to a directory that is part of the map visualization component's CLASSPATH definition, such as the web/WB-INF/lib
directory.
Example B-1 Implementing the Spatial Provider Class
package spatialprovider.samples; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.io.File; import java.util.ArrayList; import java.util.Properties; import java.util.StringTokenizer; import java.util.Vector; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import oracle.mapviewer.share.Field; import oracle.mapviewer.share.ext.SDataProvider; import oracle.mapviewer.share.ext.SDataSet; import oracle.mapviewer.share.ext.SObject; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import oracle.spatial.geometry.JGeometry; import oracle.spatial.util.GML; public class CustomSpatialProviderSample implements SDataProvider { ... /** * Constructor. */ public CustomSpatialProviderSample() { ... } /** * Returns the initialization parameters for the provider. * The "datadir" parameter should be registered in the map visualization component * configuration file and can be used to access the data. * @return */ public String[] getInitParameterNames() { return new String[]{ "datadir" }; } /** * Returns runtime parameter names. Runtime parameters are additional parameters * that the provider may use when retrieving the data objects. * @return */ public String[] getRuntimeParameterNames() { return new String[]{ "filename" }; } /** * Initializes the provider * @param params init properties * @return */ public boolean init(Properties params) { dataDirectory = null; if(params == null) return true; dataDirectory = params.getProperty("datadir"); if(dataDirectory == null || dataDirectory.trim().length() == 0) { // try upper case dataDirectory = params.getProperty("DATADIR"); if(dataDirectory == null || dataDirectory.trim().length() == 0) System.out.println("FINE: Init properties does not define \"datadir\" parameter."); } return true; } /** * Returns the data set (geometries plus attributes) that intersects the * query window. In this sample the data is parsed just once and * there is no spatial index for searching. The search is sequential. * @param queryWin search area * @param nonSpatialColumns attribute columns * @param params runtime properties * @return */ public SDataSet buildDataSet(Rectangle2D queryWin, String []nonSpatialColumns, Properties params) { if(!dataParsed) { dataParsed = parseData(params); if(!dataParsed) return null; } if(geometries.size() == 0) return null; SDataSet dataset = new SDataSet(); boolean fullExtent = isFullExtent(queryWin); if(fullExtent) { for(int i=0;i<geometries.size();i++) { JGeometry geom = (JGeometry)geometries.get(i); SObject obj = new SObject(geom,getGeometryAttributes(nonSpatialColumns,i)); dataset.addObject(obj); } } else { for(int i=0;i<geometries.size();i++) { JGeometry geom = (JGeometry)geometries.get(i); double []mbr = geom.getMBR(); if(mbr == null) continue; Rectangle2D.Double rect = new Rectangle2D.Double(mbr[0],mbr[1], mbr[2]-mbr[0], mbr[3]-mbr[1]); if(rect.getWidth() == 0. && rect.getHeight() == 0.) { Point2D.Double pt = new Point2D.Double(mbr[0],mbr[1]); if(queryWin.contains(pt)) { SObject obj = new SObject(geom,getGeometryAttributes(nonSpatialColumns,i)); dataset.addObject(obj); } } else if(queryWin.contains(rect) || queryWin.intersects(rect)) { SObject obj = new SObject(geom,getGeometryAttributes(nonSpatialColumns,i)); dataset.addObject(obj); } } } if(dataset.getSize() == 0) return null; return dataset; } /** * Returns the data provider attribute list. * @return */ public Field[] getAttributeList(Properties params) { if(!dataParsed) { dataParsed = parseData(params); if(!dataParsed) return null; } if(attributes.size() == 0) return null; return (Field[])attributes.toArray(new Field[attributes.size()]); } /** * Returns the data extents. * @return */ public Rectangle2D getDataExtents(Properties params) { if(!dataParsed) { dataParsed = parseData(params); if(!dataParsed) return null; } if(extents == null || extents.length < 4) return null; else return new Rectangle2D.Double(extents[0],extents[1], extents[2]-extents[0], extents[3]-extents[1]); } /** * Builds a spatial index for the data. In this sample there is no * spatial index. The data is loaded into memory when data is parsed. * @return */ public boolean buildSpatialIndex(Properties params) { return true; } }
Parent topic: Creating and Registering a Custom Spatial Data Provider