package com.boardgamegeek.tasks; import android.content.ContentProviderOperation; import android.content.Context; import android.database.Cursor; import android.os.AsyncTask; import android.support.annotation.NonNull; import com.boardgamegeek.R; import com.boardgamegeek.provider.BggContract; import com.boardgamegeek.provider.BggContract.PlayPlayers; import com.boardgamegeek.provider.BggContract.PlayerColors; import com.boardgamegeek.provider.BggContract.Plays; import com.boardgamegeek.service.SyncService; import com.boardgamegeek.util.ResolverUtils; import com.boardgamegeek.util.SelectionBuilder; import org.greenrobot.eventbus.EventBus; import java.util.ArrayList; import java.util.List; import timber.log.Timber; /** * Change a player name (either a GeekBuddy or named player), updating and syncing all plays. */ public class RenamePlayerTask extends AsyncTask<Void, Void, String> { private static final String SELECTION = "play_players." + PlayPlayers.NAME + "=? AND (" + PlayPlayers.USER_NAME + "=? OR " + PlayPlayers.USER_NAME + " IS NULL)"; private final Context context; private final String oldName; private final String newName; private final long startTime; private final ArrayList<ContentProviderOperation> batch; public RenamePlayerTask(Context context, String oldName, String newName) { this.context = (context == null ? null : context.getApplicationContext()); this.oldName = oldName; this.newName = newName; startTime = System.currentTimeMillis(); batch = new ArrayList<>(); } @NonNull @Override protected String doInBackground(Void... params) { if (context == null) return ""; batch.clear(); updatePlays(); updatePlayers(); updateColors(); ResolverUtils.applyBatch(context, batch); SyncService.sync(context, SyncService.FLAG_SYNC_PLAYS_UPLOAD); return context.getString(R.string.msg_play_player_change, oldName, newName); } private void updatePlays() { List<Long> internalIds = ResolverUtils.queryLongs(context.getContentResolver(), Plays.buildPlayersByPlayUri(), Plays._ID, "(" + SELECTION + ") AND " + SelectionBuilder.whereZeroOrNull(Plays.UPDATE_TIMESTAMP) + " AND " + SelectionBuilder.whereZeroOrNull(Plays.DELETE_TIMESTAMP) + " AND " + SelectionBuilder.whereZeroOrNull(Plays.DIRTY_TIMESTAMP), new String[] { oldName, "" }); if (internalIds.size() > 0) { for (Long internalId : internalIds) { if (internalId != BggContract.INVALID_ID) { batch.add(ContentProviderOperation .newUpdate(Plays.buildPlayUri(internalId)) .withValue(Plays.UPDATE_TIMESTAMP, startTime) .build()); } } } } private void updatePlayers() { batch.add(ContentProviderOperation .newUpdate(Plays.buildPlayersByPlayUri()) .withValue(PlayPlayers.NAME, newName) .withSelection(SELECTION, new String[] { oldName, "" }) .build()); } private void updateColors() { Cursor cursor = context.getContentResolver().query(PlayerColors.buildPlayerUri(oldName), new String[] { PlayerColors.PLAYER_COLOR, PlayerColors.PLAYER_COLOR_SORT_ORDER }, null, null, null); try { if (cursor != null) { while (cursor.moveToNext()) { batch.add(ContentProviderOperation .newInsert(PlayerColors.buildPlayerUri(newName)) .withValue(PlayerColors.PLAYER_COLOR, cursor.getString(0)) .withValue(PlayerColors.PLAYER_COLOR_SORT_ORDER, cursor.getInt(1)) .build()); } Timber.i("Updated %,d colors", cursor.getCount()); } else { Timber.i("No colors to update"); } } finally { if (cursor != null) cursor.close(); } batch.add(ContentProviderOperation.newDelete(PlayerColors.buildPlayerUri(oldName)).build()); } @Override protected void onPostExecute(String result) { EventBus.getDefault().post(new Event(newName, result)); } public class Event { private final String playerName; private final String message; public Event(String playerName, String message) { this.playerName = playerName; this.message = message; } public String getPlayerName() { return playerName; } public String getMessage() { return message; } } }