package compositions;
import com.fasterxml.jackson.databind.JsonNode;
import exceptions.ErrorResponse;
import exceptions.PoseidonException;
import play.libs.F;
import play.libs.Json;
import play.mvc.Action;
import play.mvc.Http;
import play.mvc.Result;
import play.mvc.With;
import javax.persistence.EntityExistsException;
import javax.persistence.PersistenceException;
import static play.mvc.Http.Status.*;
import static play.libs.Jsonp.jsonp;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public class ErrorHandlingComposition {
private static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ErrorHandlingComposition.class);
@With(ErrorHandlingAction.class)
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ErrorHandling {
String value() default "*";
}
public static class ErrorHandlingAction extends Action<ErrorHandling> {
private static final String STANDARD_DB_ERROR_MESSAGE = "En feil oppstod under kommunikasjon med databasen. Feilen har blitt logget";
private static final String DB_ERROR_UNIQUE_CONSTRAINT = "En av de oppgitte verdiene er ikke unik";
public F.Promise<Result> call(Http.Context context) throws Throwable {
F.Promise<Result> res;
try {
res = delegate.call(context);
} catch (PoseidonException e) {
logError(e);
ErrorResponse errorResponse = new ErrorResponse(e.getErrorCode(), e.getMessage());
String callback = resolveCallback(context);
Result result;
if ( e.getErrorCode() == BAD_REQUEST){
result = badRequesJsonp(callback, Json.toJson(errorResponse));
}
else if ( e.getErrorCode() == NOT_FOUND){
result = notFoundJsonp(callback, Json.toJson(errorResponse));
}
else if ( e.getErrorCode() == UNAUTHORIZED){
result = unauthorizedJsonp(callback, Json.toJson(errorResponse));
}
else if ( e.getErrorCode() == FORBIDDEN){
result = forbiddenJsonp(callback, Json.toJson(errorResponse));
}
else result = internalServerErrorJsonp(callback,Json.toJson(errorResponse));
return F.Promise.pure(result);
}
catch (EntityExistsException e){
logError(e);
String callback = resolveCallback(context);
String msg = DB_ERROR_UNIQUE_CONSTRAINT;
ErrorResponse response = new ErrorResponse(INTERNAL_SERVER_ERROR,msg);
return F.Promise.pure(badRequesJsonp(callback,Json.toJson(response)));
}
catch (PersistenceException e){
logError(e);
String callback = resolveCallback(context);
String msg = STANDARD_DB_ERROR_MESSAGE;
if ( e.getMessage().toLowerCase().contains("unique")){
msg = DB_ERROR_UNIQUE_CONSTRAINT;
}
ErrorResponse response = new ErrorResponse(INTERNAL_SERVER_ERROR,msg);
return F.Promise.pure(internalServerErrorJsonp(callback,Json.toJson(response)));
}
catch (Exception e){
logError(e);
String callback = resolveCallback(context);
ErrorResponse response = new ErrorResponse(INTERNAL_SERVER_ERROR,e.getMessage());
return F.Promise.pure(internalServerErrorJsonp(callback,Json.toJson(response)));
}
return res;
}
private void logError(Exception e) {
logger.error("REST call failed exception message " + e.getMessage(),e);
if ( e.getCause() != null) {
logger.error("REST call failed with cause " + e.getCause().getMessage());
}
}
private String resolveCallback(Http.Context context) {
String[] callbackmap = context.request().queryString().get("callback");
String callback = null;
if (callbackmap != null && callbackmap.length > 0) {
callback = callbackmap[0];
}
return callback;
}
private static Result badRequesJsonp(String callback, JsonNode jsonOutput){
return callback == null ? badRequest(jsonOutput) : badRequest(jsonp(callback, jsonOutput));
}
private static Result notFoundJsonp(String callback, JsonNode jsonOutput){
return callback == null ? notFound(jsonOutput) : notFound(jsonp(callback, jsonOutput));
}
private static Result internalServerErrorJsonp(String callback, JsonNode jsonOutput){
return callback == null ? internalServerError(jsonOutput) : internalServerError(jsonp(callback, jsonOutput));
}
private static Result unauthorizedJsonp(String callback, JsonNode jsonOutput){
return callback == null ? unauthorized(jsonOutput) : unauthorized(jsonp(callback, jsonOutput));
}
private static Result forbiddenJsonp(String callback, JsonNode jsonOutput){
return callback == null ? forbidden(jsonOutput) : forbidden(jsonp(callback, jsonOutput));
}
}
}