@Override
        protected Void doInBackground(final Void... params) {
          final Waypoint waypoint = new Waypoint(name, type, own);
          waypoint.setGeocode(geocode);
          waypoint.setPrefix(prefix);
          waypoint.setLookup(lookup);
          waypoint.setCoords(coordsToSave);
          waypoint.setNote(noteText);
          waypoint.setVisited(visited);
          waypoint.setId(waypointId);

          final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
          if (cache == null) {
            finishHandler.sendEmptyMessage(SAVE_ERROR);
            return null;
          }
          final Waypoint oldWaypoint = cache.getWaypointById(waypointId);
          if (cache.addOrChangeWaypoint(waypoint, true)) {
            DataStore.saveCache(cache, EnumSet.of(SaveFlag.DB));
            if (!StaticMapsProvider.hasAllStaticMapsForWaypoint(geocode, waypoint)) {
              StaticMapsProvider.removeWpStaticMaps(oldWaypoint, geocode);
              if (Settings.isStoreOfflineWpMaps()) {
                StaticMapsProvider.storeWaypointStaticMap(cache, waypoint).subscribe();
              }
            }
            if (modifyLocal.isChecked() || modifyBoth.isChecked()) {
              if (!cache.hasUserModifiedCoords()) {
                final Waypoint origWaypoint =
                    new Waypoint(
                        CgeoApplication.getInstance()
                            .getString(R.string.cache_coordinates_original),
                        WaypointType.ORIGINAL,
                        false);
                origWaypoint.setCoords(cache.getCoords());
                cache.addOrChangeWaypoint(origWaypoint, false);
                cache.setUserModifiedCoords(true);
              }
              cache.setCoords(waypoint.getCoords());
              DataStore.saveChangedCache(cache);
            }
            if (modifyBoth.isChecked() && waypoint.getCoords() != null) {
              finishHandler.sendEmptyMessage(UPLOAD_START);

              if (cache.supportsOwnCoordinates()) {
                final boolean result = uploadModifiedCoords(cache, waypoint.getCoords());
                finishHandler.sendEmptyMessage(result ? SUCCESS : UPLOAD_ERROR);
              } else {
                showToast(getString(R.string.waypoint_coordinates_couldnt_be_modified_on_website));
                finishHandler.sendEmptyMessage(UPLOAD_NOT_POSSIBLE);
              }
            } else {
              finishHandler.sendEmptyMessage(SUCCESS);
            }
          } else {
            finishHandler.sendEmptyMessage(SAVE_ERROR);
          }
          return null;
        }
 @Override
 public Uri insertWaypoint(Waypoint waypoint) {
   waypoint.setId(-1L);
   return contentResolver.insert(WaypointsColumns.CONTENT_URI, createContentValues(waypoint));
 }
  @Override
  public Waypoint createWaypoint(Cursor cursor) {
    int idIndex = cursor.getColumnIndexOrThrow(WaypointsColumns._ID);
    int nameIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.NAME);
    int descriptionIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.DESCRIPTION);
    int categoryIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.CATEGORY);
    int iconIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.ICON);
    int trackIdIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.TRACKID);
    int typeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.TYPE);
    int lengthIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.LENGTH);
    int durationIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.DURATION);
    int startTimeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.STARTTIME);
    int startIdIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.STARTID);
    int stopIdIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.STOPID);
    int longitudeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.LONGITUDE);
    int latitudeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.LATITUDE);
    int timeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.TIME);
    int altitudeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.ALTITUDE);
    int accuracyIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.ACCURACY);
    int speedIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.SPEED);
    int bearingIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.BEARING);
    int totalDistanceIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.TOTALDISTANCE);
    int totalTimeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.TOTALTIME);
    int movingTimeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.MOVINGTIME);
    int maxSpeedIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.MAXSPEED);
    int minElevationIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.MINELEVATION);
    int maxElevationIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.MAXELEVATION);
    int elevationGainIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.ELEVATIONGAIN);
    int minGradeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.MINGRADE);
    int maxGradeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.MAXGRADE);

    Waypoint waypoint = new Waypoint();

    if (!cursor.isNull(idIndex)) {
      waypoint.setId(cursor.getLong(idIndex));
    }
    if (!cursor.isNull(nameIndex)) {
      waypoint.setName(cursor.getString(nameIndex));
    }
    if (!cursor.isNull(descriptionIndex)) {
      waypoint.setDescription(cursor.getString(descriptionIndex));
    }
    if (!cursor.isNull(categoryIndex)) {
      waypoint.setCategory(cursor.getString(categoryIndex));
    }
    if (!cursor.isNull(iconIndex)) {
      waypoint.setIcon(cursor.getString(iconIndex));
    }
    if (!cursor.isNull(trackIdIndex)) {
      waypoint.setTrackId(cursor.getLong(trackIdIndex));
    }
    if (!cursor.isNull(typeIndex)) {
      waypoint.setType(cursor.getInt(typeIndex));
    }
    if (!cursor.isNull(lengthIndex)) {
      waypoint.setLength(cursor.getFloat(lengthIndex));
    }
    if (!cursor.isNull(durationIndex)) {
      waypoint.setDuration(cursor.getLong(durationIndex));
    }
    if (!cursor.isNull(startIdIndex)) {
      waypoint.setStartId(cursor.getLong(startIdIndex));
    }
    if (!cursor.isNull(stopIdIndex)) {
      waypoint.setStopId(cursor.getLong(stopIdIndex));
    }

    Location location = new Location("");
    if (!cursor.isNull(longitudeIndex) && !cursor.isNull(latitudeIndex)) {
      location.setLongitude(((double) cursor.getInt(longitudeIndex)) / 1E6);
      location.setLatitude(((double) cursor.getInt(latitudeIndex)) / 1E6);
    }
    if (!cursor.isNull(timeIndex)) {
      location.setTime(cursor.getLong(timeIndex));
    }
    if (!cursor.isNull(altitudeIndex)) {
      location.setAltitude(cursor.getFloat(altitudeIndex));
    }
    if (!cursor.isNull(accuracyIndex)) {
      location.setAccuracy(cursor.getFloat(accuracyIndex));
    }
    if (!cursor.isNull(speedIndex)) {
      location.setSpeed(cursor.getFloat(speedIndex));
    }
    if (!cursor.isNull(bearingIndex)) {
      location.setBearing(cursor.getFloat(bearingIndex));
    }
    waypoint.setLocation(location);

    TripStatistics tripStatistics = new TripStatistics();
    boolean hasTripStatistics = false;
    if (!cursor.isNull(startTimeIndex)) {
      tripStatistics.setStartTime(cursor.getLong(startTimeIndex));
      hasTripStatistics = true;
    }
    if (!cursor.isNull(totalDistanceIndex)) {
      tripStatistics.setTotalDistance(cursor.getFloat(totalDistanceIndex));
      hasTripStatistics = true;
    }
    if (!cursor.isNull(totalTimeIndex)) {
      tripStatistics.setTotalTime(cursor.getLong(totalTimeIndex));
      hasTripStatistics = true;
    }
    if (!cursor.isNull(movingTimeIndex)) {
      tripStatistics.setMovingTime(cursor.getLong(movingTimeIndex));
      hasTripStatistics = true;
    }
    if (!cursor.isNull(maxSpeedIndex)) {
      tripStatistics.setMaxSpeed(cursor.getFloat(maxSpeedIndex));
      hasTripStatistics = true;
    }
    if (!cursor.isNull(minElevationIndex)) {
      tripStatistics.setMinElevation(cursor.getFloat(minElevationIndex));
      hasTripStatistics = true;
    }
    if (!cursor.isNull(maxElevationIndex)) {
      tripStatistics.setMaxElevation(cursor.getFloat(maxElevationIndex));
      hasTripStatistics = true;
    }
    if (!cursor.isNull(elevationGainIndex)) {
      tripStatistics.setTotalElevationGain(cursor.getFloat(elevationGainIndex));
      hasTripStatistics = true;
    }
    if (!cursor.isNull(minGradeIndex)) {
      tripStatistics.setMinGrade(cursor.getFloat(minGradeIndex));
      hasTripStatistics = true;
    }
    if (!cursor.isNull(maxGradeIndex)) {
      tripStatistics.setMaxGrade(cursor.getFloat(maxGradeIndex));
      hasTripStatistics = true;
    }

    if (hasTripStatistics) {
      waypoint.setTripStatistics(tripStatistics);
    }
    return waypoint;
  }