package org.wikipedia.edit;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import org.wikipedia.captcha.CaptchaResult;
import org.wikipedia.dataclient.WikiSite;
import org.wikipedia.dataclient.mwapi.MwException;
import org.wikipedia.dataclient.retrofit.MwCachedService;
import org.wikipedia.dataclient.retrofit.WikiCachedService;
import org.wikipedia.page.PageTitle;
import java.io.IOException;
import retrofit2.Call;
import retrofit2.Response;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
class EditClient {
public interface Callback {
void success(@NonNull Call<Edit> call, @NonNull EditResult result);
void failure(@NonNull Call<Edit> call, @NonNull Throwable caught);
}
@NonNull private final WikiCachedService<Service> cachedService = new MwCachedService<>(Service.class);
@SuppressWarnings("checkstyle:parameternumber")
public Call<Edit> request(@NonNull WikiSite wiki, @NonNull PageTitle title, int section,
@NonNull String text, @NonNull String token, @NonNull String summary,
boolean loggedIn, @Nullable String captchaId, @Nullable String captchaWord,
@NonNull Callback cb) {
return request(cachedService.service(wiki), title, section, text, token, summary, loggedIn,
captchaId, captchaWord, cb);
}
@VisibleForTesting @SuppressWarnings("checkstyle:parameternumber")
Call<Edit> request(@NonNull Service service, @NonNull PageTitle title, int section,
@NonNull String text, @NonNull String token, @NonNull String summary,
boolean loggedIn, @Nullable String captchaId, @Nullable String captchaWord,
@NonNull final Callback cb) {
Call<Edit> call = service.edit(title.getPrefixedText(), section, text, token, summary,
loggedIn ? "user" : null, captchaId, captchaWord);
call.enqueue(new retrofit2.Callback<Edit>() {
@Override
public void onResponse(Call<Edit> call, Response<Edit> response) {
if (response.body().hasEditResult()) {
handleEditResult(response.body().edit(), call, cb);
} else if (response.body().hasError()) {
RuntimeException e = response.body().badLoginState()
? new UserNotLoggedInException()
: new MwException(response.body().getError());
cb.failure(call, e);
} else {
cb.failure(call, new IOException("An unknown error occurred."));
}
}
@Override
public void onFailure(Call<Edit> call, Throwable t) {
cb.failure(call, t);
}
});
return call;
}
private void handleEditResult(@NonNull Edit.Result result, @NonNull Call<Edit> call,
@NonNull Callback cb) {
if (result.editSucceeded()) {
cb.success(call, new EditSuccessResult(result.newRevId()));
} else if (result.hasEditErrorCode()) {
cb.success(call, new EditAbuseFilterResult(result.code(), result.info(), result.warning()));
} else if (result.hasSpamBlacklistResponse()) {
cb.success(call, new EditSpamBlacklistResult(result.spamblacklist()));
} else if (result.hasCaptchaResponse()) {
cb.success(call, new CaptchaResult(result.captchaId()));
} else {
cb.failure(call, new IOException("Received unrecognized edit response"));
}
}
@VisibleForTesting interface Service {
@FormUrlEncoded
@POST("w/api.php?action=edit&format=json&formatversion=2")
@SuppressWarnings("checkstyle:parameternumber")
Call<Edit> edit(@NonNull @Field("title") String title,
@Field("section") int section,
@NonNull @Field("text") String text,
@NonNull @Field("token") String token,
@NonNull @Field("summary") String summary,
@Nullable @Field("assert") String user,
@Nullable @Field("captchaid") String captchaId,
@Nullable @Field("captchaword") String captchaWord);
}
}