private void duplicate(int id) { Uri splitMarkerSetUri = createSplitMarkerSetUri(id); final ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(); Cursor splitMarkerSetCursor = null; Cursor splitMarkerCursor = null; try { splitMarkerSetCursor = getContentResolver().query(splitMarkerSetUri, null, null, null, null); if (splitMarkerSetCursor.getCount() != 1) { LOG.error( "Wrong number of split marker sets found. Expected 1 but found [{}].", splitMarkerSetCursor.getCount()); onNonTerminalError(); } else { splitMarkerSetCursor.moveToFirst(); final String name = splitMarkerSetCursor.getString( splitMarkerSetCursor.getColumnIndex( TrackLoggerData.SplitMarkerSet.COLUMN_NAME_NAME)); String newName = TrackLoggerDataUtil.createUniqueSplitMarkerSetName( getContentResolver(), name + " Copy"); if (newName == null) { onNonTerminalError(); } else if (!TrackLoggerDataUtil.isValidSplitMarkerSetName(newName)) { LOG.error("[{}] is an invalid split marker set name.", newName); onNonTerminalError(); } else { operations.add( ContentProviderOperation.newInsert(TrackLoggerData.SplitMarkerSet.CONTENT_URI) .withValue(TrackLoggerData.SplitMarkerSet.COLUMN_NAME_NAME, newName) .build()); splitMarkerCursor = getContentResolver() .query( TrackLoggerData.SplitMarker.CONTENT_URI, null, TrackLoggerData.SplitMarker.COLUMN_NAME_SPLIT_MARKER_SET_ID + " = ?", new String[] {String.valueOf(id)}, null); splitMarkerCursor.moveToFirst(); final int nameIndex = splitMarkerCursor.getColumnIndex(TrackLoggerData.SplitMarker.COLUMN_NAME_NAME); final int latIndex = splitMarkerCursor.getColumnIndex(TrackLoggerData.SplitMarker.COLUMN_NAME_LATITUDE); final int lonIndex = splitMarkerCursor.getColumnIndex(TrackLoggerData.SplitMarker.COLUMN_NAME_LONGITUDE); while (!splitMarkerCursor.isAfterLast()) { operations.add( ContentProviderOperation.newInsert(TrackLoggerData.SplitMarker.CONTENT_URI) // Back reference to the set insertion .withValueBackReference( TrackLoggerData.SplitMarker.COLUMN_NAME_SPLIT_MARKER_SET_ID, 0) // Index can be size - 1 because the set is always the first element in the list .withValue( TrackLoggerData.SplitMarker.COLUMN_NAME_ORDER_INDEX, operations.size() - 1) .withValue( TrackLoggerData.SplitMarker.COLUMN_NAME_NAME, splitMarkerCursor.getString(nameIndex)) .withValue( TrackLoggerData.SplitMarker.COLUMN_NAME_LATITUDE, splitMarkerCursor.getDouble(latIndex)) .withValue( TrackLoggerData.SplitMarker.COLUMN_NAME_LONGITUDE, splitMarkerCursor.getDouble(lonIndex)) .build()); splitMarkerCursor.move(1); } getContentResolver().applyBatch(TrackLoggerData.AUTHORITY, operations); Toast.makeText( this, getString(R.string.split_marker_set_list_duplicated_notification, name, newName), Toast.LENGTH_LONG) .show(); } } } catch (Exception e) { LOG.error( "Error applying batch operations for split marker set clone. Operations included [" + operations + "].", e); onNonTerminalError(); } finally { if (splitMarkerSetCursor != null) { splitMarkerSetCursor.close(); } if (splitMarkerCursor != null) { splitMarkerCursor.close(); } } }