Migrating Projects to gvSIG 2.0
Issues to consider when migrating a project from gvSIG 1.x to gvSIG 2.0
- Introduction
- Project name
- Migrating to maven and the new project structure
- Package nomenclature
- Logging
- Moving to Java >= 1.5
- Dependencies
- Persistence
- Cloning objects
- Initialisation of Libraries
- Extension points
- Fmap
- appgvSIG
- Installer
- Recommendations
- FAQs
- Where is MapControl's addMapTool method?
- What is equivalent to the FieldDescription class in version 2.0?
- What has happened to FLyrVect's getRecordset and getSource methods?
- Can't locate the View class?
- Where can I find the ViewPort's getAdjustedExtent method?
- How can I convert a geometry to JTS?
- Can't find getModel in the View class?
- How do I get an extension point?
- The createLayer method of the LayerFactory class is deprecated. How do I create a raster layer?
Introduction
The following sections describe some of the main issues to consider when migrating a project (library or extension) from gvSIG 1.9 to gvSIG 2.0. These instructions will be largely applicable to projects being migrated from earlier versions as well.
Project name
A new project nomenclature should be defined, which should coincide with the main java package of the project, with the base names for jars that are generated or, also, with the artifactID of the maven project.
An example of this nomenclature would be:
extQuickInfo -> org.gvsig.quickinfo
Migrating to maven and the new project structure
gvSIG 2.0 has been migrated from ant to maven as a tool for constructing projects. Therefore, the ant build.xml file should be replaced with a maven pom.xml file.
Documentation on the pom.xml file format, as well as general maven documentation, can be found on the maven project website.
There is also a brief introduction and description of how to use maven in the gvSIG 2.0 development guide.
In addition, maven has a default project structure that allows the most common construction operations to be performed with a minimum of configuration. Adapting the project structure for migrating to the default maven structure is therefore quite convenient.
On the other hand, it is more convenient to create a new project from the maven templates or archetypes, and then to migrate the content from the old to the newly created project, rather than trying to convert the old project directory to the maven format.
These maven project templates (archetypes) allow us to create a simple project with everything needed to start working. There are many archetypes available:
If it is an internal project, use the create library or create extension archetype, according to the type of project required.
If the project to be migrated is an extension, then the correspondence between locations in the old and the maven directory is as follows:
- Sources: src -> src/main/java
- Source tests: src-test -> src/test/java
- Multilingual texts: config -> src/main/resources/locale
- config.xml: config -> src/main/resources/config
- Images: images -> src/main/resources/images
- about.htm: config -> src/main/resources/about
- build.number: [RAÍZ] -> src/main/resources
If this is an external project, follow the instructions in the document Creating our project to create the initial project structure.
Note
The external multi-module project archetype must still be created and documented.
Package nomenclature
Virtually all the code base of gvSIG projects has been migrated to the package nomenclature of org.gvsig.xxx.
When migrating a project, imports should be updated in the same class. Eclipse provides tools to easily make the necessary changes.
A quick way of doing this, for example, is in the package manager to select all classes in the project, right-click on them and then select Source > Organize Imports.
On the other hand, if the project being migrated belongs to the gvSIG project itself, the packages should be renamed to also begin with org.gvsig.
Logging
The logging API to use in gvSIG 2.0 is the SLF4J library. If the project being migrated is using another logging API, such as Log4J or java.util.logging, then it needs to be replaced with the SLF4J logging API. You can find more information on SLF4J in the section on logging in the development guide
In general, the steps needed to migrate from Log4J to SLF4J are:
1.- Replace the Log4J import classes with those of SLF4J:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// substituting the import of Log4j ...
// import org.apache.log4j.Logger;
2.- Change the Logger definition:
private static final Logger LOG = Logger.getLogger(MyClasser.class);
...
To:
private static final Logger LOG = LoggerFactory.getLogger(MyClass.class);
...
3.- Use message parameters where appropriate. For example:
LOG.debug("Point values: X = " + point.getX() + ", Y = " + point.getY());
...
To:
LOG.debug("Point values: X = {}, Y = {}", point.getX(), point.getY());
...
Moving to Java >= 1.5
gvSIG 2.0 supports Java version 1.5 or higher, except in joint projects with gvSIG mobile.
When migrating a project, we need to decide if we want the code to work on gvSIG mobile or not. If so, it is usually not all the code that needs to be compatible, only the library or the library API. It is therefore advisable to have these in a project separate from the rest and then to validate, unless the project compiles to Java ME CDC.
If the project does not need to be compatible with gvSIG mobile, or a part thereof, it is compiled with Java 1.5 or higher.
Due to the compilation with Java 1.5, it is advisable to remove the warnings that could appear in the code in Eclipse, such as the use of the classes of collections without the use of generics.
Dependencies
Dependencies in gvSIG 2.0 projects are managed from maven.
In addition to this change, there are a number of developments that affect how dependencies are defined in gvSIG:
- All dependencies are defined with their version.
- External dependencies are registered with their version in the pom.xml root configuration for all projects (see project org.gvsig.maven.base.pom). Therefore, a project only has to define its dependencies without indicating the version, as these have already been defined in the configuration project.
- All dependencies should be available in the official repositories of maven or osgeo. If not, they can be uploaded from the gvSIG repository.
- Dependencies with other gvSIG projects are defined in the same way as for any external project, indicating the groupId, artifactId and version.
- Some of the projects in gvSIG 2.0 have been divided in turn into other projects (for example, the libFMap project), so we must determine what our actual dependencies in gvSIG 2.0 are.
- Many projects begin to generate separate jars of their API, SPI, implementation, providers, etc. In general we rely solely on the API or SPI jars to build, and rely on the others only for performing tests.
Note
Every time dependencies are modified in the pom.xml file, the eclipse project has to be regenerated because the eclipse project configuration needs to be updated with said dependencies.
You can find more information about the management of dependencies in the section How to add or update a dependency in the gvSIG 2.0. development guide.
Persistence
In gvSIG object persistence is used, amongst other things, to save the project, symbols, etc.
In gvSIG 2.0 a new API and persistence implementation has been developed. It is compatible with Java ME CDC for use in the gvSIG Mobile project and completely replaces the previous API.
Therefore, we have to migrate all uses of persistence in our project so that they use the new API, which is available in the org.gvsig.tools.persistence package of the org.gvsig.tools project.
For more information about using the new persistence API, you can consult the persistence development guide.
Based on experience gained from migrating projects to date, we recommend that when migrating a project you don't rely on persistence as implemented with the old API, as it is often closely linked to the conditions leading to the earlier persistence, assumed a lot more work, besides making assumptions about the flow of persistence.
Instead we recommend that the migration of persistence be addressed as if it were being implemented for the first time, looking only at the class to be persisted, and which of its attributes to persist.
With the new API it is much easier to persist objects, since most of the time the attributes of the classes can be persisted directly, without having to manage their conversion between object and String.
Cloning objects
In versions prior to gvSIG 2.0, a common practice when implementing object cloning was to use persistence. An object was persisted and then 'unpersisted' to obtain a copy.
However, in gvSIG 2.0 this method will probably not work, as the new persistence API takes control of object references to avoid duplicating objects already loaded on the system, and so you may not get the desired results.
To implement object cloning a new API has been defined in org.gvsig.tools, as well as a development guide that shows how to implement and use cloning.
Initialisation of Libraries
There is often the need for some kind of initialisation when loading library projects. Up until now, every project has carried out this initialization on their own using different mechanisms.
To standardise and unify the operation of all projects, a library initialization mechanism has been defined in gvSIG 2.0, for which there is a short development guide showing how to use it in our projects.
Extension points
Extension points have undergone two major changes in gvSIG 2.0:
- Changes to the API.
- Project change, will now be in the org.gvsig.tools project.
You can find more information in the developer documentation on extension points.
Fmap
Introduction
The old libFMap project was divided into a number of subprojects which provided the core functionality. These projects, in turn, generated various artefacts or .jar files, which also affect the dependencies that we will include in our projects.
The main projects that have emerged from the former FMap are:
- org.gvsig.fmap.geometry (libFMap_geometries)
- org.gvsig.fmap.dal (libFMap_dal)
- org.gvsig.fmap.dal.file (libFMap_dalfile)
- org.gvsig.fmap.dal.db (libFMap_daldb)
- org.gvsig.fmap.dal.index.spatial (libFMap_dalindex)
- org.gvsig.fmap.mapcontext (libFmap_mapcontext)
- org.gvsig.symbology
- org.gvsig.fmap.control (libFMap_controls)
The following section discusses some of the major changes in functionality.
Geometries
In gvSIG 2.0 a separate project for geometry libraries has been constructed. It has evolved from what was in previous libraries and provides a separation between the API, implementation and operations on geometries.
There is development documentation available on the library, where we can see major changes at the API level, and a description of the model geometry that defines the library.
One of the major changes is that classes such as FShape have disappeared, and will be substituted by the interfaces available in the geometry library, such as Geometry and GeometryManager.
For example, where constant shape types were used to define the FShape class, there are now two options:
- Using geometry operations, we can associate types and/or subtypes of geometries.
- Using constant types and subtypes that are defined in the Geometry.TYPES and Geometry.SUBTYPES interfaces. This option has a big problem, in that these types and subtypes do not cover all possibilities, but only those defined initially as defaults. From now on libraries or extensions can be registered on their own, so if you use this option, instead of registering operations, our functionality won't function properly with these other geometry types.
In any case, if we choose the latter option, then we have a table showing the equivalents between the types of shapes and types of geometries of the new library:
FShape | Geometry.TYPES |
NULL | NULL |
POINT | POINT |
LINE | CURVE |
POLYGON | SURFACE |
TEXT | TEXT |
MULTI | GEOMETRY |
MULTIPOINT | MULTIPOINT |
CIRCLE | CIRCLE |
ARC | ARC |
ELLIPSE | ELLIPSE |
Z | (*) |
(*) In the gvSIG 2.0 geometry library, any geometry may be 2D, 3D, 2DM, etc. This feature is managed through the subtype of a geometry (see Geometry.SUBTYPES for predefined subtypes), so there is no equivalent for this constant in Geometry.TYPES.
Data access
One of the main changes in the development of gvSIG 2.0 has been the replacement of all previous data access methods with a new API and implementation, namely the DAL (Data Access Library).
This API combines access to both tabular and geometric data, in addition to defining a common core API between vector and raster data.
For more information about using the API, as well as the development of data providers, consult the DAL development guide.
Mapcontext, symbology and labelling
All code related to Mapcontext, symbology and labelling has been moved to a separate project: org.gvsig.fmap.mapcontext (libFMap_mapcontext). Those parts relating directly to mapcontext, the viewport, layers, etc. have not changed much since the previous version, except for changes required to conform to the rest of gvSIG 2.0.
The main change has been to extract the symbology and labelling API, as this API and the rest of mapcontext are a joint project between gvSIG desktop and gvSIG mobile.
The implementation of symbology and labelling now has its own project: org.gvsig.symbology. This is the implementation that is used in gvSIG desktop; gvSIG mobile has developed its own implementation.
Therefore, when a project is migrated to gvSIG 2.0 it will be affected mainly by:
- The extraction of the symbology and labelling API. These APIs have hardly been modified. The main change is that there are now managers for obtaining, creating and registering symbols, legends and labelling strategies. The entry point for accessing these managers will be the MapContextLocator.
- The introduction of new symbols, legends and labelling strategies. We use the previous managers to register them.
- A few changes to the rest of mapcontext, especially those related to data access, and issues such as InfoByPoint.
- Renamed all the starting packages with:
- org.gvsig.fmap.mapcontext: main package of the org.gvsig.fmap.mapcontext project (libFMap_mapcontext).
- org.gvsig.symbology: main package of the symboloy and labelling implementation project org.gvsig.symbology.
At the moment the development guide doesn't have any documentation available on this development.
Mapcontrol
A new project has been created where all the code related to MapControl is located: org.gvsig.fmap.control (libFMap_controls). This project also contains other graphical controls that depend on the other FMAP APIs, such as DAL.
For example, swing components, used from the gvSIG document table, have been created to display Feature tables. But now it is very easy to create applications outside of gvSIG, or to include other use cases that aren't from the document table, that show Feature data in tabular form.
Apart from the general changes to packages, and the adaptation to the other changes, this project has a few changes affecting the API. Some examples are:
- Rename the addCombinedTool method to addCombinedBehavior
- ...
appgvSIG
TODO
Changes to the project API and documents:
- View -> IView
Installer
TODO
Recommendations
Use the org.gvsig.i18n API directly. That is, instead of:
String text = PluginServices.getText(this, "Coordinates");
Use:
String text = Messages.getText("Coordinates");
Maintain a separation between the API, SPI, implementation and providers.
FAQs
Where is MapControl's addMapTool method?
Version 1.9 had an addMapTool method in the MapControl class but Version 2.0 doesn't.
Where can it be found?
The addMapTool method has simply been renamed addBehavior.
What is equivalent to the FieldDescription class in version 2.0?
In version 1.9 the FieldDescription class was used to query the attributes of a field in a table.
How is this done now?
In version 2.0 all data access has changed. To query the attributes that describe a field in a table you have to make use of the FeatureAttributeDescriptor class.
A vector layer has a FeatureStore, which in turn has a defaultFeatureType, that defines the structure of the feature by means of the FeatureAttributeDescriptor.
What has happened to FLyrVect's getRecordset and getSource methods?
The getSource and getRecordset methods were used to access a layer's data.
What is used now?
In version 2.0 the vector layers have a getFeatureStore method that returns a FeatureStore and provides access to both spatial and alphanumeric data.
If you just want to get all the layer's features you can invoke the getFeatureSet method of FeatureStore.
Can't locate the View class?
Some parts of my Extension were cast to the View class in order to access the view window.
Where is this class now?
The View class has been renamed and should not be used for casting. If you do need it, it will probably be sufficient to cast the IView interface.
Where can I find the ViewPort's getAdjustedExtent method?
How can I find the extent of the view port?
There is no longer a getAdjustedExtent method.
There has been a systematic elimination of all the methods that worked with an Extent. These have been replaced by methods for managing an Envelope. Operations on the gvSIG extent treated it as a 2D rectangle, which, with the emergence of more complex geometries, is no longer correct.
The methods that used to work on an Extent now work with an Envelope, and so have been renamed.
The getAdjustedExtent method has now become getAdjustedEnvelope.
How can I convert a geometry to JTS?
I have code that works with geometries that follow the JTS model.
How can I convert a gvSIG Geometry to JTS format?
You can do this by invoking:
Geometry geom;
com.vividsolutions.jts.geom.Geometry jtsGeom;
jtsGeom = (com.vividsolutions.jts.geom.Geometry) geom.invokeOperation(ToJTS.CODE, null);
Can't find getModel in the View class?
I have a variable of type View and would like to access the getModel method. Where I can find it in 2.0?
The code in 1.x was something like:
IWindow window;
MapContext mapa = ((View) window).getModel().getMapContext()
The code in 2.0 is:
IWindow window;
MapContext mapa = ((IView) window).getViewDocument().getMapContext();
How do I get an extension point?
To get an extension point:
The code in 1.x was something like this:
ExtensionPoint pe;
String name;
pe = (ExtensionPoint) ExtensionPointsSingleton.getInstance().get(name);
In 2.0 the code is:
ExtensionPoint pe;
String name;
pe = ToolsLocator.getExtensionPointManager().get(name);
The createLayer method of the LayerFactory class is deprecated. How do I create a raster layer?
The createLayer method of the LayerFactory class is deprecated. How do I create a raster layer?
The code in 1.x was something like this:
String filename;
BaseView view;
FLayer newLayer = LayerFactory.createLayer(filename, "gvSIG Image Driver",new File(filename), view.getProjection());
In 2.0 the code is:
String filename;
IView view;
DataStoreParameters parameters = DALLocator.getDataManager().createStoreParameters(RasterStoreProvider.NAME);
parameters.setDynValue("filename", filename);
parameters.setDynValue("srs", view.getViewDocument().getMapContext().getProjection());
FLayer newLayer = MapContextLocator.getMapContextManager().createLayer(filename, parameters);