Opened 10 years ago
Closed 10 years ago
#12198 closed enhancement (wontfix)
Create a possibility to attach plug-in specific data to an OSMPrimitive
| Reported by: | Owned by: | team | |
|---|---|---|---|
| Priority: | normal | Milestone: | |
| Component: | Plugin | Version: | |
| Keywords: | OSMPrimitive extend | Cc: |
Description
I'm working on a Plug-in that compares buildings and addresses in OSM to their counterparts in the official Dutch government registry for buildings and addresses (BAG). The differences are shown using a stylesheet and the plug-in assists the user in updating the OSM data for objects he/she selects.
For this to work, I need a way to reference an object (building or address node) in the imported data from the related OSMPrimitive on the OSM layer. Currently, the only way to achieve this is with a HashMap, mapping the OSMPrimitive to the related object in the imported data.
It would be a great improvement if there was a way to add a reference directly from the OSMPrimitive.
The ideal way to achieve this would be to implement a Node or Way interface, but these are Objects in stead of interfaces.
The second-best way would be to extend the Node, Way or Relation, but these classes are final and therefore can not be extended. Simply removing the 'final' modifier from these classes wouldn't work either, because the collections were not written with this possibility in mind. For example the method setNodes() in Way is written as setNodes(List<Node>) in stead of setNodes(List<? extends Node).
There is however a relatively simple way to extend the OSMPrimitives without breaking the rest of the code.
Just add the following methods to the IPrimitive interface and implement them in the Abstract primitive class with a map:
Object getPluginData(Class<? extends Plugin> plugin); void setPluginData(Class<? extends Plugin>, Object data);
Using the plugin class as a key prevents interference between plug-ins. The data object could contain anything. It's up to the plug-in whether and how to use it.
The implementation could be as simple as this:
private Map<Class<? extends Plugin>, Object data> pluginData;
@Override
Object getPluginData(Class<? extends Plugin> plugin) {
if (pluginData == null) return null;
return pluginData.get(plugin);
}
@Override
void setPluginData(Class<? extends Plugin> plugin, Object data) {
if (pluginData == null) {
// To save memory, don't create the map unless we need it.
pluginData = new HashMap<>();
}
pluginData.put(plugin, data);
}
Attachments (0)
Change History (3)
comment:1 by , 10 years ago
comment:2 by , 10 years ago
I was curious to see if more people would consider this to be an improvement. For me, it would make my code more straight-forward and I expect a performance improvement. But if I'm the only one who could use this, I'll stick with the HashMap solution.
comment:3 by , 10 years ago
| Resolution: | → wontfix |
|---|---|
| Status: | new → closed |
Adding one additional reference field to the OsmPrimitive class increases the memory cost for each primitive. It isn't much, but it scales with the number of objects and affects everyone.
So far I am not convinced, there is an advantage that goes beyond coding style. If this data field turns out to be required to achieve a certain functional goal, then let's reconsider.



Why do you think a
HashMapis not a sufficient solution? Performance-wise it should be perfectly fine. One advantage of having the data in the Primitive object is that the mapping/data automatically dies when the object is garbage collected. However, data is rarely removed, but usually only added, so I don't see the point at the moment.