// License: GPL. For details, see LICENSE file.
package org.openstreetmap.hot.sds;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.actions.UploadAction;
import org.openstreetmap.josm.data.osm.INode;
import org.openstreetmap.josm.data.osm.IPrimitive;
import org.openstreetmap.josm.data.osm.IRelation;
import org.openstreetmap.josm.data.osm.IWay;
import org.openstreetmap.josm.data.osm.OsmPrimitive;
import org.openstreetmap.josm.data.osm.visitor.PrimitiveVisitor;
import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
import org.openstreetmap.josm.io.OsmReader;
import org.openstreetmap.josm.io.OsmServerWriter;
import org.openstreetmap.josm.io.OsmWriterFactory;
import org.openstreetmap.josm.plugins.Plugin;
import org.openstreetmap.josm.plugins.PluginInformation;
/**
*
* Plugin that loads extra data from HOT separate data store.
*
* @author Frederik Ramm <frederik.ramm@geofabrik.de>
*/
public class SeparateDataStorePlugin extends Plugin {
public final Map<Long, IPrimitive> originalNodes = new HashMap<>();
public final Map<Long, IPrimitive> originalWays = new HashMap<>();
public final Map<Long, IPrimitive> originalRelations = new HashMap<>();
public List<QueueItem> uploadQueue = new ArrayList<>();
private PrimitiveVisitor learnVisitor = new PrimitiveVisitor() {
@Override
public void visit(INode i) {
originalNodes.put(i.getId(), i);
}
@Override
public void visit(IWay i) {
originalWays.put(i.getId(), i);
}
@Override
public void visit(IRelation i) {
originalRelations.put(i.getId(), i);
}
};
static class QueueItem {
public final IPrimitive primitive;
public final Map<String, String> tags;
public final boolean sdsOnly;
public boolean processed;
QueueItem(IPrimitive p, HashMap<String, String> t, boolean s) {
primitive = p;
tags = t;
sdsOnly = s;
processed = false;
}
}
/**
* Creates the plugin
*/
public SeparateDataStorePlugin(PluginInformation info) {
super(info);
// this lets us see what JOSM load from the server, and augment it with our data
OsmReader.registerPostprocessor(new ReadPostprocessor(this));
// this makes sure that our data is never written to the OSM server on a low level
OsmWriterFactory.setDefaultFactory(new SdsOsmWriterFactory(this));
// this lets us see what JOSM is planning to upload, and prepare our own uploads accordingly
UploadAction.registerUploadHook(new DetermineSdsModificationsUploadHook(this));
// this lets us perform our own uploads after JOSM has succeeded
OsmServerWriter.registerPostprocessor(new WritePostprocessor(this));
// add menu
new SdsMenu(this);
}
public String getIgnorePrefix() {
return Main.pref.get("sds-server.tag-prefix", "hot:");
}
public IPrimitive getOriginalPrimitive(IPrimitive other) {
switch (other.getType()) {
case NODE: return originalNodes.get(other.getId());
case WAY: return originalWays.get(other.getId());
case RELATION: return originalRelations.get(other.getId());
default: throw new AssertionError("unexpected case: " + other.getType());
}
}
protected void enqueueForUpload(IPrimitive prim, HashMap<String, String> tags, boolean onlySds) {
uploadQueue.add(new QueueItem(prim, tags, onlySds));
}
/**
* Stores the given primitive in the plugin's cache in order to
* determine changes later.
*/
protected void learn(IPrimitive prim) {
if (prim instanceof OsmPrimitive) {
((OsmPrimitive) prim).save().accept(learnVisitor);
} else {
prim.accept(learnVisitor);
}
}
/**
* removes all elements from the upload queue that have the processed flag set.
*/
protected void clearQueue() {
ArrayList<QueueItem> newQueue = new ArrayList<>();
for (QueueItem q : uploadQueue) {
if (!q.processed) newQueue.add(q);
}
uploadQueue = newQueue;
}
/**
* reset the processed flag for all elements of the queue.
*/
protected void resetQueue() {
for (QueueItem q : uploadQueue) {
q.processed = false;
}
}
@Override
public PreferenceSetting getPreferenceSetting() {
return new SdsPluginPreferences();
}
}