Merge pull request #4865 from osmandapp/osm_editing

Osm editing
This commit is contained in:
Pavel Ratushnyi 2017-12-20 11:11:39 +02:00 committed by GitHub
commit b7a539fc66
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 140 additions and 46 deletions

View file

@ -103,6 +103,7 @@ public abstract class Entity implements Serializable {
// lazy initializing
private Map<String, String> tags = null;
private Set<String> changedTags;
private final long id;
private boolean dataLoaded;
private int modify;
@ -125,6 +126,14 @@ public abstract class Entity implements Serializable {
this.dataLoaded = copy.dataLoaded;
}
public Set<String> getChangedTags() {
return changedTags;
}
public void setChangedTags(Set<String> changedTags) {
this.changedTags = changedTags;
}
public int getModify() {
return modify;
}

View file

@ -9,6 +9,7 @@ import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
@ -28,6 +29,8 @@ public class EditPoiData {
private boolean hasChangesBeenMade = false;
private Map<String, PoiType> allTranslatedSubTypes;
private PoiCategory category;
private Set<String> changedTags = new HashSet<>();
public EditPoiData(Node node, OsmandApplication app) {
allTranslatedSubTypes = app.getPoiTypes().getAllTranslatedNames(true);
@ -45,6 +48,7 @@ public class EditPoiData {
if(type != null && type != category) {
category = type;
tagValues.put(POI_TYPE_TAG, "");
changedTags.add(POI_TYPE_TAG);
}
}
@ -74,6 +78,7 @@ public class EditPoiData {
checkNotInEdit();
this.tagValues.clear();
this.tagValues.putAll(mp);
changedTags.clear();
retrieveType();
}
@ -112,6 +117,7 @@ public class EditPoiData {
isInEdit = true;
tagValues.remove(REMOVE_TAG_PREFIX+tag);
tagValues.put(tag, value);
changedTags.add(tag);
notifyDatasetChanged(tag);
} finally {
isInEdit = false;
@ -141,6 +147,7 @@ public class EditPoiData {
isInEdit = true;
tagValues.put(REMOVE_TAG_PREFIX+tag, REMOVE_TAG_VALUE);
tagValues.remove(tag);
changedTags.remove(tag);
notifyDatasetChanged(tag);
} finally {
isInEdit = false;
@ -154,8 +161,11 @@ public class EditPoiData {
public boolean isInEdit() {
return isInEdit;
}
public Set<String> getChangedTags() {
return changedTags;
}
private void notifyDatasetChanged(String tag) {
if (mListeners.size() > 0) {
hasChangesBeenMade = true;
@ -185,6 +195,7 @@ public class EditPoiData {
public void updateTypeTag(String string) {
tagValues.put(POI_TYPE_TAG, string);
changedTags.add(POI_TYPE_TAG);
retrieveType();
PoiType pt = getPoiTypeDefined();
if(pt != null) {
@ -192,6 +203,7 @@ public class EditPoiData {
tagValues.put(REMOVE_TAG_PREFIX+pt.getOsmTag2(), REMOVE_TAG_VALUE);
tagValues.remove(pt.getOsmTag());
tagValues.remove(pt.getOsmTag2());
changedTags.removeAll(Arrays.asList(pt.getOsmTag(), pt.getOsmTag2()));
category = pt.getCategory();
}
notifyDatasetChanged(POI_TYPE_TAG);

View file

@ -11,6 +11,7 @@ import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.design.widget.TextInputLayout;
import android.support.v4.app.DialogFragment;
@ -61,6 +62,7 @@ import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.BaseOsmAndDialogFragment;
import net.osmand.plus.osmedit.OsmPoint.Action;
import net.osmand.plus.osmedit.dialogs.PoiSubTypeDialogFragment;
import net.osmand.plus.osmedit.dialogs.PoiTypeDialogFragment;
import net.osmand.util.Algorithms;
@ -74,6 +76,7 @@ import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
public static final String TAG = "EditPoiDialogFragment";
@ -426,7 +429,7 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
Node original = editPoiData.getEntity();
final boolean offlineEdit = mOpenstreetmapUtil instanceof OpenstreetmapLocalUtil;
Node node = new Node(original.getLatitude(), original.getLongitude(), original.getId());
OsmPoint.Action action = node.getId() < 0 ? OsmPoint.Action.CREATE : OsmPoint.Action.MODIFY;
Action action = node.getId() < 0 ? Action.CREATE : Action.MODIFY;
for (Map.Entry<String, String> tag : editPoiData.getTagValues().entrySet()) {
if (!Algorithms.isEmpty(tag.getKey()) && !Algorithms.isEmpty(tag.getValue()) &&
!tag.getKey().equals(EditPoiData.POI_TYPE_TAG)) {
@ -451,7 +454,7 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
if (offlineEdit && !Algorithms.isEmpty(poiTypeTag)) {
node.putTagNoLC(EditPoiData.POI_TYPE_TAG, poiTypeTag);
}
String actionString = action == OsmPoint.Action.CREATE ? getString(R.string.default_changeset_add) : getString(R.string.default_changeset_edit);
String actionString = action == Action.CREATE ? getString(R.string.default_changeset_add) : getString(R.string.default_changeset_edit);
comment = actionString + " " + poiTypeTag;
}
commitNode(action, node, mOpenstreetmapUtil.getEntityInfo(node.getId()), comment, false,
@ -486,7 +489,7 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
return false;
}
}, getActivity(), mOpenstreetmapUtil);
}, getActivity(), mOpenstreetmapUtil, action == Action.MODIFY ? editPoiData.getChangedTags() : null);
}
private void dismissCheckForChanges() {
@ -506,15 +509,16 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
poiTypeEditText.setText(subCategory);
}
public static void commitNode(final OsmPoint.Action action,
public static void commitNode(final Action action,
final Node node,
final EntityInfo info,
final String comment,
final boolean closeChangeSet,
final CallbackWithObject<Node> postExecute,
final Activity activity,
final OpenstreetmapUtil openstreetmapUtil) {
if (info == null && OsmPoint.Action.CREATE != action && openstreetmapUtil instanceof OpenstreetmapRemoteUtil) {
final OpenstreetmapUtil openstreetmapUtil,
@Nullable final Set<String> changedTags) {
if (info == null && Action.CREATE != action && openstreetmapUtil instanceof OpenstreetmapRemoteUtil) {
Toast.makeText(activity, activity.getResources().getString(R.string.poi_error_info_not_loaded), Toast.LENGTH_LONG).show();
return;
}
@ -529,7 +533,7 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
@Override
protected Node doInBackground(Void... params) {
return openstreetmapUtil.commitNodeImpl(action, node, info, comment, closeChangeSet);
return openstreetmapUtil.commitNodeImpl(action, node, info, comment, closeChangeSet, changedTags);
}
@Override
@ -757,7 +761,7 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
private void deleteNode(final Node n, final String c, final boolean closeChangeSet) {
final boolean isLocalEdit = openstreetmapUtil instanceof OpenstreetmapLocalUtil;
commitNode(OsmPoint.Action.DELETE, n, openstreetmapUtil.getEntityInfo(n.getId()), c, closeChangeSet,
commitNode(Action.DELETE, n, openstreetmapUtil.getEntityInfo(n.getId()), c, closeChangeSet,
new CallbackWithObject<Node>() {
@Override
@ -776,7 +780,7 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
}
return false;
}
}, activity, openstreetmapUtil);
}, activity, openstreetmapUtil, null);
}
}

View file

@ -2,6 +2,8 @@ package net.osmand.plus.osmedit;
import net.osmand.PlatformUtil;
import net.osmand.data.Amenity;
import net.osmand.osm.AbstractPoiType;
import net.osmand.osm.MapPoiTypes;
import net.osmand.osm.PoiType;
import net.osmand.osm.edit.EntityInfo;
import net.osmand.osm.edit.Node;
@ -13,6 +15,8 @@ import org.apache.commons.logging.Log;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class OpenstreetmapLocalUtil implements OpenstreetmapUtil {
@ -42,12 +46,14 @@ public class OpenstreetmapLocalUtil implements OpenstreetmapUtil {
}
@Override
public Node commitNodeImpl(OsmPoint.Action action, Node n, EntityInfo info, String comment, boolean closeChangeSet){
public Node commitNodeImpl(OsmPoint.Action action, Node n, EntityInfo info, String comment,
boolean closeChangeSet, Set<String> changedTags){
Node newNode = n;
if (n.getId() == -1) {
newNode = new Node(n, Math.min(-2, plugin.getDBPOI().getMinID() - 1)); // generate local id for the created node
}
OpenstreetmapPoint p = new OpenstreetmapPoint();
newNode.setChangedTags(changedTags);
p.setEntity(newNode);
p.setAction(action);
p.setComment(comment);
@ -86,6 +92,16 @@ public class OpenstreetmapLocalUtil implements OpenstreetmapUtil {
entity.putTagNoLC(OSMTagKey.OPENING_HOURS.getValue(), n.getOpeningHours());
}
for (Map.Entry<String, String> entry : n.getAdditionalInfo().entrySet()) {
AbstractPoiType abstractPoi = MapPoiTypes.getDefault().getAnyPoiAdditionalTypeByKey(entry.getKey());
if (abstractPoi != null && abstractPoi instanceof PoiType) {
PoiType p = (PoiType) abstractPoi;
if (!p.isNotEditableOsm() && !Algorithms.isEmpty(p.getOsmTag())) {
entity.putTagNoLC(p.getOsmTag(), entry.getValue());
}
}
}
// check whether this is node (because id of node could be the same as relation)
if(entity != null && MapUtils.getDistance(entity.getLatLon(), n.getLocation()) < 50){
return entity;

View file

@ -1,20 +1,7 @@
package net.osmand.plus.osmedit;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.text.MessageFormat;
import java.util.LinkedHashMap;
import java.util.Map;
import android.util.Xml;
import android.widget.Toast;
import net.osmand.PlatformUtil;
import net.osmand.data.Amenity;
@ -37,8 +24,22 @@ import org.apache.commons.logging.Log;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import android.util.Xml;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.text.MessageFormat;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil {
@ -250,7 +251,7 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil {
@Override
public Node commitNodeImpl(OsmPoint.Action action, final Node n, EntityInfo info, String comment,
boolean closeChangeSet) {
boolean closeChangeSet, Set<String> changedTags) {
if (isNewChangesetRequired()) {
changeSetId = openChangeSet(comment);
changeSetTimeStamp = System.currentTimeMillis();
@ -330,7 +331,7 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil {
Node entity = (Node) st.getRegisteredEntities().get(id);
// merge non existing tags
for (String rtag : entity.getTagKeySet()) {
if (!n.getTagKeySet().contains(rtag)) {
if (!deletedTag(n, rtag) && (!containsTag(n, rtag) || !tagChanged(n, rtag))) {
n.putTagNoLC(rtag, entity.getTag(rtag));
}
}
@ -352,6 +353,18 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil {
return null;
}
private boolean deletedTag(Node node, String tag) {
return node.getTagKeySet().contains(EditPoiData.REMOVE_TAG_PREFIX + tag);
}
private boolean containsTag(Node node, String tag) {
return node.getTagKeySet().contains(tag);
}
private boolean tagChanged(Node node, String tag) {
return node.getChangedTags() != null && node.getChangedTags().contains(tag);
}
@Override
public Node loadNode(Amenity n) {
if (n.getId() % 2 == 1) {

View file

@ -1,16 +1,20 @@
package net.osmand.plus.osmedit;
import android.support.annotation.Nullable;
import net.osmand.data.Amenity;
import net.osmand.osm.edit.EntityInfo;
import net.osmand.osm.edit.Node;
import java.util.Set;
public interface OpenstreetmapUtil {
public EntityInfo getEntityInfo(long id);
EntityInfo getEntityInfo(long id);
public Node commitNodeImpl(OsmPoint.Action action, Node n, EntityInfo info, String comment, boolean closeChangeSet);
Node commitNodeImpl(OsmPoint.Action action, Node n, EntityInfo info, String comment, boolean closeChangeSet, @Nullable Set<String> changedTags);
public void closeChangeSet();
void closeChangeSet();
public Node loadNode(Amenity n);
Node loadNode(Amenity n);
}

View file

@ -9,13 +9,16 @@ import net.osmand.osm.edit.Node;
import net.osmand.util.Algorithms;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
public class OpenstreetmapsDbHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 4;
private static final int DATABASE_VERSION = 5;
public static final String OPENSTREETMAP_DB_NAME = "openstreetmap"; //$NON-NLS-1$
private static final String OPENSTREETMAP_TABLE_NAME = "openstreetmaptable"; //$NON-NLS-1$
private static final String OPENSTREETMAP_COL_ID = "id"; //$NON-NLS-1$
@ -24,11 +27,12 @@ public class OpenstreetmapsDbHelper extends SQLiteOpenHelper {
private static final String OPENSTREETMAP_COL_TAGS = "tags"; //$NON-NLS-1$
private static final String OPENSTREETMAP_COL_ACTION = "action"; //$NON-NLS-1$
private static final String OPENSTREETMAP_COL_COMMENT = "comment"; //$NON-NLS-1$
private static final String OPENSTREETMAP_COL_CHANGED_TAGS = "changed_tags";
private static final String OPENSTREETMAP_TABLE_CREATE = "CREATE TABLE " + OPENSTREETMAP_TABLE_NAME + " (" + //$NON-NLS-1$ //$NON-NLS-2$
OPENSTREETMAP_COL_ID + " bigint,"+
OPENSTREETMAP_COL_LAT + " double," + OPENSTREETMAP_COL_LON + " double," +
OPENSTREETMAP_COL_TAGS + " VARCHAR(2048)," +
OPENSTREETMAP_COL_ACTION + " TEXT, " + OPENSTREETMAP_COL_COMMENT + " TEXT);"; //$NON-NLS-1$ //$NON-NLS-2$
OPENSTREETMAP_COL_ACTION + " TEXT, " + OPENSTREETMAP_COL_COMMENT + " TEXT, " + OPENSTREETMAP_COL_CHANGED_TAGS + " TEXT);";
List<OpenstreetmapPoint> cache = null;
public OpenstreetmapsDbHelper(Context context) {
@ -46,6 +50,9 @@ public class OpenstreetmapsDbHelper extends SQLiteOpenHelper {
db.execSQL("DROP TABLE IF EXISTS " + OPENSTREETMAP_TABLE_NAME);
db.execSQL(OPENSTREETMAP_TABLE_CREATE);
}
if (oldVersion < 5) {
db.execSQL("ALTER TABLE " + OPENSTREETMAP_TABLE_NAME + " ADD " + OPENSTREETMAP_COL_CHANGED_TAGS + " TEXT");
}
}
public List<OpenstreetmapPoint> getOpenstreetmapPoints() {
@ -70,12 +77,30 @@ public class OpenstreetmapsDbHelper extends SQLiteOpenHelper {
tags.append("$$$");
}
}
Set<String> chTags = p.getEntity().getChangedTags();
StringBuilder changedTags = new StringBuilder();
if (chTags != null) {
Iterator<String> iterator = chTags.iterator();
while (iterator.hasNext()) {
changedTags.append(iterator.next());
if (iterator.hasNext()) {
changedTags.append("$$$");
}
}
}
db.execSQL("DELETE FROM " + OPENSTREETMAP_TABLE_NAME +
" WHERE " + OPENSTREETMAP_COL_ID + " = ?", new Object[] { p.getId() }); //$NON-NLS-1$ //$NON-NLS-2$
" WHERE " + OPENSTREETMAP_COL_ID + " = ?", new Object[]{p.getId()});
db.execSQL("INSERT INTO " + OPENSTREETMAP_TABLE_NAME +
" (" + OPENSTREETMAP_COL_ID + ", " + OPENSTREETMAP_COL_LAT + ", " + OPENSTREETMAP_COL_LON + ", " + OPENSTREETMAP_COL_TAGS + ", " + OPENSTREETMAP_COL_ACTION + "," + OPENSTREETMAP_COL_COMMENT + ")" +
" VALUES (?, ?, ?, ?, ?, ?)",
new Object[] { p.getId(),p.getLatitude(), p.getLongitude(), tags.toString() , OsmPoint.stringAction.get(p.getAction()), p.getComment(), }); //$NON-NLS-1$ //$NON-NLS-2$
" (" + OPENSTREETMAP_COL_ID + ", " +
OPENSTREETMAP_COL_LAT + ", " +
OPENSTREETMAP_COL_LON + ", " +
OPENSTREETMAP_COL_TAGS + ", " +
OPENSTREETMAP_COL_ACTION + ", " +
OPENSTREETMAP_COL_COMMENT + ", " +
OPENSTREETMAP_COL_CHANGED_TAGS + ")" +
" VALUES (?, ?, ?, ?, ?, ?, ?)",
new Object[]{p.getId(), p.getLatitude(), p.getLongitude(), tags.toString(),
OsmPoint.stringAction.get(p.getAction()), p.getComment(), chTags == null ? null : changedTags.toString()});
db.close();
checkOpenstreetmapPoints();
return true;
@ -102,8 +127,15 @@ public class OpenstreetmapsDbHelper extends SQLiteOpenHelper {
SQLiteDatabase db = getReadableDatabase();
List<OpenstreetmapPoint> points = new ArrayList<OpenstreetmapPoint>();
if (db != null) {
Cursor query = db.rawQuery("SELECT " + OPENSTREETMAP_COL_ID + ", " + OPENSTREETMAP_COL_LAT + "," + OPENSTREETMAP_COL_LON + "," + OPENSTREETMAP_COL_ACTION + "," + OPENSTREETMAP_COL_COMMENT + "," + OPENSTREETMAP_COL_TAGS+ " FROM " + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
OPENSTREETMAP_TABLE_NAME, null);
Cursor query = db.rawQuery("SELECT " +
OPENSTREETMAP_COL_ID + ", " +
OPENSTREETMAP_COL_LAT + "," +
OPENSTREETMAP_COL_LON + "," +
OPENSTREETMAP_COL_ACTION + "," +
OPENSTREETMAP_COL_COMMENT + "," +
OPENSTREETMAP_COL_TAGS + "," +
OPENSTREETMAP_COL_CHANGED_TAGS +
" FROM " + OPENSTREETMAP_TABLE_NAME, null);
if (query.moveToFirst()) {
do {
OpenstreetmapPoint p = new OpenstreetmapPoint();
@ -115,6 +147,10 @@ public class OpenstreetmapsDbHelper extends SQLiteOpenHelper {
for(int i=0; i<split.length - 1; i+= 2){
entity.putTagNoLC(split[i].trim(), split[i+1].trim());
}
String changedTags = query.getString(6);
if (changedTags != null) {
entity.setChangedTags(new HashSet<>(Arrays.asList(changedTags.split("\\$\\$\\$"))));
}
p.setEntity(entity);
p.setAction(query.getString(3));
p.setComment(query.getString(4));

View file

@ -240,7 +240,7 @@ public class OsmEditsLayer extends OsmandMapLayer implements ContextMenuLayer.IC
protected Node doInBackground(Void... params) {
Node node = objectInMotion.getEntity();
return mOpenstreetmapUtil.commitNodeImpl(objectInMotion.getAction(), node,
mOpenstreetmapUtil.getEntityInfo(node.getId()), "", false);
mOpenstreetmapUtil.getEntityInfo(node.getId()), "", false, null);
}
@Override

View file

@ -56,7 +56,7 @@ public class UploadOpenstreetmapPointAsyncTask
entityInfo = remotepoi.loadNode(p.getEntity());
}
Node n = remotepoi.commitNodeImpl(p.getAction(), p.getEntity(), entityInfo,
p.getComment(), false);
p.getComment(), false, null);
if (n != null) {
uploaded = true;
plugin.getDBPOI().deletePOI(p);

View file

@ -157,7 +157,7 @@ public class AddPOIAction extends QuickAction {
return false;
}
}, activity, mOpenstreetmapUtil);
}, activity, mOpenstreetmapUtil, null);
}
}