The Logic Library
The logic part of our development is divided into two projects:
- org.gvsig.viewer.lib.api
- org.gvsig.viewer.lib.impl
In the API project we find mostly interfaces. These interfaces make up the API of the logic components to be developed. The class model of the example is shown in the following diagram:
We have the following entities:
VisorLibrary, which represents the object Library. In this note class methods:
doRegistration, which runs to load the library and tells what kind of library is, in our case the definition of an API as well as what other libraries are required initialized before this, the library of data access, and geometry. The code doing this is:
public void doRegistration() { this.registerAs(VisorLibrary.class, Library.TYPE.API); this.require(DALLibrary.class); this.require(GeometryLibrary.class); }
doPostInitialize, which is executed when all bookstores have been initialized. In our case checks to verify that at least one implementation API has been registered. The code that does this is:
protected void doPostInitialize() throws LibraryException { // Validate if there are any implementation registered. VisorManager manager = VisorLocator.getManager(); if (manager == null) { throw new ReferenceNotRegisteredException( VisorLocator.MANAGER_NAME, VisorLocator.getInstance() ); } }
VisorLocator, is the locator of our library, responsible for give us the instance of our manager. This is a class with methods static to register implementations of this API and an implementation him.
VisorManager. A interface. The manager of the bookstore. Defines methods to obtain the blocks and plots as well as locating an apple given a point. It is the entrance to the various entities in our model.
VisorBlock An interface that represents a block, and provides methods for geometry that defines the block or for the parcels are.
VisorProperty. An interface that represents a cadastral parcel. It has methods for geometry that defines it, your code or municipality.
Let's see what we are in the implementation part. Observe that while in the normal API interfaces has been found in the implementation we find classes. Classes that implement the various interfaces that defined in the API. By convention, the implementation of the various interfaces that appear in the API will call the API like prepending the prefix Default.
The class model of implementation for our example is:
Let us see the most relevant parts of the implementation.
VisorDefaultImplLibrary. As in the API, this class is responsible for initialize the library implementation. In this note class methods:
doRegistration, which is responsible for registering the library as an implementation API. VisorLibrary Should you have other dependencies other than those marked on the API, would be added here to make sure these libraries are initialized before this, but it is the case of our example. When you register this library as an implementation of VisorLibrary, cover two functions. On one side the library API will always initialized before this implementation, and secondly when some other library dependencies with the API set, the initialization mechanism library is responsible for initializing the implementation along with the API ensure you have an implementation of the API that we required. The code you need to put in our example is:
public void doRegistration() { this.registerAsImplementationOf(VisorLibrary.class); }
doInitialize, que se encarga de registrar en el locator del API la implementación del manager que tenemos en esta librería. El código que hace esto es:
protected void doInitialize() throws LibraryException { VisorLocator.registerManager(DefaultVisorManager.class); }
DefaultVisorManager. De esta clase conviene resaltar principalmente:
El método getBlock. Podemos ver cómo realizar una busqueda de un registro filtrando por una condición espacial:
try { String attrGeomName = blocks.getDefaultFeatureType().getDefaultGeometryAttributeName(); FeatureQuery query = blocks.createFeatureQuery(); query.setFilter( new IntersectsEvaluator(attrGeomName,point) ); set = blocks.getFeatureSet(query); if( set.isEmpty() ) { return null; } it = set.fastiterator(); Feature f = (Feature) it.next(); VisorBlock block = new DefaultVisorBlock(this,f.getGeometry(attrGeomName)); return block; } catch (DataException e) { ... } finally { if( it != null ) { it.dispose(); } if( set != null ) { set.dispose(); } }
Tip
You can find information on the mechanisms available for querying the data access Guide to the developer of the Data Access Library (DAL)
From this point out:
- We can find out which attribute of the features is the one that contains the geometry through the getDefaultGeometryAttributeName from feature type of our store.
- To perform a search for features in a store we will invoke the method Passed as parameter getFeatureSet an instance of FeatureQuery in which specify the filter conditions. It can also be specified order or attributes that we want to recover in our query.
- The filter condition is specified by providing a method setFilter Evaluator of our query.
- We take care of releasing objects that we, like iterators o feature sets. Keep in mind that depending on the type of * store * with which we are working they may have reserved resources and connections to databases, recordsets or connections remote servers.
The openShape method. Here's how to open a store based on existing shapes:
parameters = manager.createStoreParameters("Shape"); parameters.setDynValue("shpfile", shape); parameters.setDynValue("crs", "EPSG:23030"); return (FeatureStore) manager.openStore("Shape", parameters);
Note that, to open a store we will do this in two phases. On the one hand create a structure to house the parameters needed to open our store the initialized with the appropriate values and invoke the openStore method from the data access manager within those parameters.
Each type of store will have a set of parameters specific to it. To open a shape, we indicate at least the name of the file and the reference system in which is located.
IntersectsEvaluator. This is the class that evaluates the condition used in the filter. This field class checks if the specified geometry intersects a given feature specific geometry. In its construction will provide the field containing the feature geometry and geometry to check whether there are intersecting. In this class should be emphasized:
The evaluate method, responsible for conducting the test:
Geometry op1geom = (Geometry) data.getDataValue(this.op2attrname); return new Boolean(this.op1geom.intersects(op1geom));
Knowing how to call the attribute that contains the geometry we can get this through the getDataValue method. Once we have the two geometries intersecs invoke * method * of the geometry to see if intersect.
The getCQL method. getCQL This method returns a string in the format of a where of sql to use as a filter in stores that attack to the database sql. The filter can be returned not be exactly the same as that implemented by the method code Evaluate, acting as a filter prior to this if the store supports it.
DefaultVisorBlock. Represents a block from our domain. Stores geometry that gives shape to the block. The most important of this class is the getProperties method that returns all parcels that are on the block:
List<VisorProperty> properties = new ArrayList<VisorProperty>(); FeatureStore store = this.manager.getProperties(); String attrGeomName = store.getDefaultFeatureType().getDefaultGeometryAttributeName(); FeatureQuery query = store.createFeatureQuery(); query.setFilter( new IntersectsEvaluator(attrGeomName, this.shape) ); set = this.manager.getProperties().getFeatureSet(query); if( set.isEmpty() ) { return null; } it = set.fastiterator(); while( it.hasNext() ) { Feature f = (Feature) it.next(); VisorProperty property = new DefaultVisorProperty( this.manager, f.getString(PROPERTIES_CODE), f.getGeometry(attrGeomName), f.getInt(PROPERTIES_CREATIONDATE), f.getInt(PROPERTIES_MUNICODE) ); properties.add(property); } return properties;
We can see that the same mechanism used to filter the plots use the manager to retrieve an apple. In this case once you get the set the plots, runs, retrieving data from these and creating plot objects.
DefaultVisorProperty. This is the class that represents a plot. In our example is not only logical, merely exposing the data store by geters.