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;
 }
 
}