All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
nl.vpro.api.client.utils.PageUpdateApiUtil Maven / Gradle / Ivy
package nl.vpro.api.client.utils;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.io.StringWriter;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Optional;
import java.util.function.Function;
import javax.inject.Inject;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.ProcessingException;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.http.impl.execchain.RequestAbortedException;
import nl.vpro.api.client.pages.PageUpdateApiClient;
import nl.vpro.domain.classification.ClassificationService;
import nl.vpro.domain.media.MediaObject;
import nl.vpro.domain.page.Page;
import nl.vpro.domain.page.PageIdMatch;
import nl.vpro.domain.page.update.DeleteResult;
import nl.vpro.domain.page.update.PageUpdate;
import nl.vpro.jackson2.Jackson2Mapper;
import nl.vpro.rs.client.Utils;
/**
* @author Michiel Meeuwissen
* @since 1.0
*/
@Slf4j
public class PageUpdateApiUtil {
private static final Function STRING = String::valueOf;
private static final Function JACKSON = input -> {
StringWriter writer = new StringWriter();
try {
Jackson2Mapper.getInstance().writer().writeValue(writer, input);
} catch (IOException e) {
log.error(e.getMessage(), e);
}
return writer.toString();
};
private final PageUpdateApiClient pageUpdateApiClient;
private final PageUpdateRateLimiter limiter;
@Getter
@Setter
private boolean retryErrors = true;
@Inject
@lombok.Builder
public PageUpdateApiUtil(
PageUpdateApiClient client,
PageUpdateRateLimiter limiter) {
pageUpdateApiClient = client;
this.limiter = limiter == null ? PageUpdateRateLimiter.builder().build() : limiter;
}
public Result save(@NotNull @Valid PageUpdate update) {
return save(update, false);
}
public Result saveAndWait(@NotNull @Valid PageUpdate update) {
return save(update, true);
}
protected Result save(@NotNull @Valid PageUpdate update, boolean wait) {
while(true) {
limiter.acquire();
try {
Result result = handleResponse(
pageUpdateApiClient.getPageUpdateRestService().save(update, wait),
update, STRING, String.class
);
// temporary, later we may do Result
if (result.isOk()) {
log.info(result.getEntity());
return Result.builder().status(result.getStatus()).build();
} else {
if ((! retryErrors) || (! result.needsRetry())) {
log.warn(result.getErrors());
return Result.builder().status(result.getStatus()).errors(result.getErrors()).build();
}
}
limiter.setCurrentRateToMinRate();
log.warn("Retrying {}", update);
} catch (ProcessingException e) {
return exceptionToResult(e);
}
}
}
public PageUpdate get(@NotNull String url) {
limiter.acquire();
PageIdMatch match = url.startsWith("crid:") ? PageIdMatch.CRID : PageIdMatch.URL;
return Utils.wrapNotFound(() -> pageUpdateApiClient.getPageUpdateRestService().load(url, false, match)).orElse(null);
}
public Result delete(@NotNull String id) {
limiter.acquire();
PageIdMatch match = id.startsWith("crid:") ? PageIdMatch.CRID : PageIdMatch.URL;
try {
return handleResponse(
pageUpdateApiClient.getPageUpdateRestService()
.delete(id, false, 1, false, match, null, null), id, STRING, DeleteResult.class
);
} catch (ProcessingException e) {
return exceptionToResult(e);
}
}
public Result deleteWhereStartsWith(@NotNull String prefix) {
limiter.acquire();
PageIdMatch match = prefix.startsWith("crid:") ? PageIdMatch.CRID : PageIdMatch.URL;
int batchSize = 10000;
try {
DeleteResult result = null;
while (true) {
Result r = handleResponse(
pageUpdateApiClient.getPageUpdateRestService()
.delete(prefix, true, batchSize, true, match, null,null), prefix, STRING, DeleteResult.class
);
log.info("Batch deleted {}: {}", prefix, r);
if (result == null) {
result = r.getEntity();
} else {
result = result.and(r.getEntity());
}
if (r.isOk()) {
if (r.getEntity().getCount() == 0) {
return Result.builder()
.entity(result)
.status(Result.Status.SUCCESS)
.build();
}
}
}
} catch (ProcessingException e) {
return exceptionToResult(e);
}
}
public Optional getPublishedPage(String url) {
try {
return Optional.of(getPageUpdateApiClient().getProviderRestService().getPage(url));
} catch (NotFoundException nfe) {
return Optional.empty();
}
}
public Optional getMedia(String mid) {
return Optional.of(getPageUpdateApiClient().getProviderRestService().getMedia(mid));
}
public ClassificationService getClassificationService() {
return pageUpdateApiClient.getClassificationService();
}
public PageUpdateApiClient getPageUpdateApiClient() {
return pageUpdateApiClient;
}
protected Result exceptionToResult(Exception e) {
Throwable cause = ExceptionUtils.getRootCause(e);
try {
throw cause;
} catch (RequestAbortedException rae) {
return returnResult(Result.aborted(pageUpdateApiClient + ":" + cause.getClass().getName() + " " + cause.getMessage()));
} catch (SocketException se) {
return returnResult(Result.error(pageUpdateApiClient + ":" + cause.getClass().getName() + " " + cause.getMessage()));
} catch (ProcessingException | NullPointerException fatal) {
return returnResult(Result.fatal(pageUpdateApiClient + ":" + e.getClass().getName() + " " + e.getMessage(), e));
} catch (Throwable t) {
return returnResult(Result.error(pageUpdateApiClient + ":" + e.getClass().getName() + " " + e.getMessage()));
}
}
protected Result handleResponse(
Response response,
T input,
Function toString,
Class e) {
try (response) {
switch (response.getStatus()) {
case 200, 202 -> {
log.debug(pageUpdateApiClient + " " + response.getStatus());
try {
E entity = response.readEntity(e);
return returnResult(Result.success(entity));
} catch (Exception ex) {
log.error("For {}: {}", response.getEntity(), ex.getMessage(), ex);
throw ex;
}
}
case 400 -> {
String error = response.readEntity(String.class);
String s = pageUpdateApiClient + " " + response.getStatus() + " " + error;
return returnResult(Result.invalid(s));
}
case 404 -> {
String error = response.readEntity(String.class);
String s = pageUpdateApiClient + " " + response.getStatus() + " " + error;
return returnResult(Result.notfound(s));
}
case 403 -> {
String error = response.readEntity(String.class);
String s = pageUpdateApiClient + " " + response.getStatus() + " " + error;
return returnResult(Result.denied(s));
}
case 503 -> {
String string = pageUpdateApiClient + " " + response.getStatus() + " " + input.toString();
return returnResult(Result.error(string));
}
default -> {
MultivaluedMap headers = response.getHeaders();
if ("true".equals(headers.getFirst("validation-exception"))) {
if ("text/plain".equals(headers.getFirst("Content-Type"))) {
String string = response.readEntity(String.class);
return returnResult(Result.invalid(pageUpdateApiClient + ":" + string));
} else {
try {
String string = response.readEntity(String.class);
return returnResult(Result.invalid(pageUpdateApiClient + ":" + string));
} catch (Exception ex) {
return returnResult(Result.invalid(pageUpdateApiClient + ":" + new HashMap<>(headers) + "(" + ex.getMessage() + ")"));
}
}
} else {
String error = response.readEntity(String.class);
String string = pageUpdateApiClient + " " + response.getStatus() + " " + new HashMap<>(response.getStringHeaders()) + " " + error + " for: '" + toString.apply(input) + "'";
return returnResult(Result.error(string));
}
}
}
}
}
protected Result returnResult(Result result) {
if (result.needsRetry()) {
limiter.downRate();
}
if (result.isOk()) {
limiter.upRate();
} else {
log.debug(result.getErrors());
}
return result;
}
@Override
public String toString() {
return "PageUpdateApiUtil for " + pageUpdateApiClient.getDescription();
}
}