This page is part of the MapGuide Future section, where ideas are proposed and refined before being turned into RFCs (or discarded). Visit the Future page to view more!
Overview
This page is a living proposal for adding extra convenience methods to the MapGuide API
Motivation
There are common scenarios in MapGuide application development where there is still lots of boilerplate code required to achieve desired tasks. Some of these scenarios are described below
Simplifying feature manipulation
Inserting features
The current process of inserting features is currently:
- Create a MgFeatureCommandCollection
- Create a MgPropertyCollection
- Populate the property collection with desired property values
- Create a MgInsertFeatures
- Add the property collection to the MgInsertFeatures command
- Add the MgInsertFeatures command to the MgFeatureCommandCollection
- Execute MgFeatureService::UpdateFeatures passing in the feature source id and the command collection and to specify whether this should be transactional or not
- Process each individual result of the UpdateFeatures() call, taking note of any thrown exceptions (non-transactional) and open feature readers
There is a lot of object creation and setup to insert a feature. Inserting multiple features increases the number of objects created and boilerplate code.
mg-desktop provides a simplified API for inserting features, that should also be brought over to the MapGuide API:
class MG_PLATFORMBASE_API MgFeatureService : public MgService { PUBLISHED_API: MgFeatureReader* InsertFeatures(MgResourceIdentifier* resource, CREFSTRING className, MgPropertyCollection* props); MgFeatureReader* InsertFeatures(MgResourceIdentifier* resource, CREFSTRING className, MgPropertyCollection* props, MgTransaction* trans); MgPropertyCollection* InsertFeatures(MgResourceIdentifier* resource, CREFSTRING className, MgBatchPropertyCollection* batchPropertyValues); MgPropertyCollection* InsertFeatures(MgResourceIdentifier* resource, CREFSTRING className, MgBatchPropertyCollection* batchPropertyValues, MgTransaction* trans); }; class MG_PLATFORMBASE_API MgLayerBase : public MgNamedSerializable { PUBLISHED_API: MgFeatureReader* InsertFeatures(MgPropertyCollection* props); MgFeatureReader* InsertFeatures(MgPropertyCollection* props, MgTransaction* trans); MgPropertyCollection* InsertFeatures(MgBatchPropertyCollection* batchPropertyValues); MgPropertyCollection* InsertFeatures(MgBatchPropertyCollection* batchPropertyValues, MgTransaction* trans); };
Under this simplified API, the process is now.
- Create a MgPropertyCollection or MgBatchPropertyCollection
- Load it up with the desired property values
- Execute InsertFeatures(), passing in the feature source, the property collection and optionally a transaction.
- Close the open feature reader, or process the property collection (if using a MgBatchPropertyCollection)
Updating features
The current process of update features is similarly complex:
- Create a MgFeatureCommandCollection
- Create a MgPropertyCollection
- Populate the property collection with desired property values to update
- Create a MgUpdateFeatures
- Add the property collection to the MgUpdateFeatures command
- Specify the update filter for the MgUpdateFeatures command
- Add the MgUpdateFeaturescommand to the MgFeatureCommandCollection
- Execute MgFeatureService::UpdateFeatures passing in the feature source id and the command collection and to specify whether this should be transactional or not
- Process each individual result of the UpdateFeatures() call, taking note of any thrown exceptions (non-transactional) and open feature readers
There is a lot of object creation and setup to insert a feature. Inserting multiple features increases the number of objects created and boilerplate code.
mg-desktop provides a simplified API for updating features, that should also be brought over to the MapGuide API:
class MG_PLATFORMBASE_API MgFeatureService : public MgService { PUBLISHED_API: INT32 UpdateFeatures(MgResourceIdentifier* resource, CREFSTRING className, MgPropertyCollection* props, CREFSTRING filter); INT32 UpdateFeatures(MgResourceIdentifier* resource, CREFSTRING className, MgPropertyCollection* props, CREFSTRING filter, MgTransaction* trans); }; class MG_PLATFORMBASE_API MgLayerBase : public MgNamedSerializable { PUBLISHED_API: INT32 UpdateFeatures(MgPropertyCollection* props, CREFSTRING filter); INT32 UpdateFeatures(MgPropertyCollection* props, CREFSTRING filter, MgTransaction* trans); };
Under this simplified API, the process is now.
- Create a MgPropertyCollection
- Load it up with the desired property values to update with
- Execute UpdateFeatures(), passing in the feature source, the property collection, update filter and optionally a transaction.
Deleting Features
Querying transformed features
This API is currently not implemented in MapGuide
class MG_PLATFORMBASE_API MgFeatureService : public MgService { PUBLISHED_API: virtual MgFeatureReader* SelectFeatures(MgResourceIdentifier* resource, CREFSTRING className, MgFeatureQueryOptions* options, CREFSTRING coordinateSystem) = 0; };
Having this API implemented would be very useful. Along the same theme of convenience, MgLayerBase should have a shortcut form of the above API:
class MG_PLATFORMBASE_API MgLayerBase : public MgNamedSerializable { PUBLISHED_API: virtual MgFeatureReader* SelectFeatures(MgFeatureQueryOptions* options, CREFSTRING coordinateSystem); };
Getting a layer icon
The process to get the legend image icon for a given MgLayer instance is especially cumbersome as a lot of boilerplate code is required in fetching the associated layer definition and walking through its styles to get the matching geometry type and theme category required for a MgMappingService::GenerateLegendImage() call.
Since MgLayer possesses most of this knowledge, it makes sense to have convenience APIs in MgLayer itself:
class MG_MAPGUIDE_API MgLayer : public MgLayerBase { PUBLISHED_API: //Gets the list of geometry type styles for this layer at the map's current scale. Returns NULL if there are no applicable geometry types MgIntCollection* GetGeometryTypeStyles(); //Gets the number of theme categories for this layer at the map's current scale for the given geometry type style. A count greater than 1 indicates a themed layer. Returns -1 if there are no applicable styles at the current scale INT32 GetThemeCategoryCount(INT32 geomType); //Gets the legend image icon for this layer at the at the map's current scale for the given geometry type style and theme category. Returns NULL if there is no applicable icon at the given scale/geomType/themeCategory MgByteReader* GenerateLegendImage(INT32 width, INT32 height, CREFSTRING format, INT32 geomType, INT32 themeCategory); //Gets the list of geometry type styles for this layer at the given scale. Returns NULL if there are not applicable geometry types MgIntCollection* GetGeometryTypeStyles(double scale); //Gets the number of theme categories for this layer at the given scale for the given geometry type style. A count greater than 1 indicates a themed layer. Returns -1 if there are no applicable styles at the given scale INT32 GetThemeCategoryCount(double scale, INT32 geomType); //Gets the legend image icon for this layer at the at the given scale for the given geometry type style and theme category. Returns NULL if there is no applicable icon at the given scale/geomType/themeCategory MgByteReader* GenerateLegendImage(double scale, INT32 width, INT32 height, CREFSTRING format, INT32 geomType, INT32 themeCategory); };