// Path: src/main/java/com/hantsylabs/restexample/springmvc/ApiErrors.java
// public class ApiErrors {
// 
//     private static final String PREFIX = "errors.";
// 
//     public static final String INVALID_REQUEST = PREFIX + "INVALID_REQUEST";
// 
//     private ApiErrors() {}
// 
// }
// 
// Path: src/main/java/com/hantsylabs/restexample/springmvc/exception/InvalidRequestException.java
// public class InvalidRequestException extends RuntimeException {
// 
//     private BindingResult errors;
// 
//     public InvalidRequestException(BindingResult errors) {
//         this.errors = errors;
//     }
// 
//     public BindingResult getErrors() {
//         return errors;
//     }
// 
// }
// 
// Path: src/main/java/com/hantsylabs/restexample/springmvc/exception/ResourceNotFoundException.java
// public class ResourceNotFoundException extends RuntimeException {
// 
//     private static final long serialVersionUID = 1L;
// 
//     private Long id;
// 
//     public ResourceNotFoundException(Long id) {
//         super(String.format("resource %s was not found", id));
//         this.id = id;
//     }
// 
//     public ResourceNotFoundException(String message) {
//         super(message);
//     }
//     
//     public Long getId() {
//         return id;
//     }
// }
// 
// Path: src/main/java/com/hantsylabs/restexample/springmvc/exception/UsernameAlreadyUsedException.java
// public class UsernameAlreadyUsedException extends RuntimeException {
// 
//     private static final long serialVersionUID = 1L;
// 
//     private String username;
// 
//     public UsernameAlreadyUsedException(String username) {
//         this.username = username;
//     }
// 
//     public String getUsername() {
//         return username;
//     }
//     
// }
// 
// Path: src/main/java/com/hantsylabs/restexample/springmvc/model/ResponseMessage.java
// public class ResponseMessage {
// 
//     public enum Type {
//         success, warning, danger, info;
//     }
// 
//     private Type type;
//     private String text;
//     private String code;
// 
//     public ResponseMessage(Type type, String text) {
//         this.type = type;
//         this.text = text;
//     }
// 
//     public ResponseMessage(Type type, String code, String message) {
//         this.type = type;
//         this.code = code;
//         this.text = message;
//     }
// 
//     public String getText() {
//         return text;
//     }
// 
//     public Type getType() {
//         return type;
//     }
// 
//     public String getCode() {
//         return code;
//     }
//     
//     public static ResponseMessage success(String text) {
//         return new ResponseMessage(Type.success, text);
//     }
// 
//     public static ResponseMessage warning(String text) {
//         return new ResponseMessage(Type.warning, text);
//     }
// 
//     public static ResponseMessage danger(String text) {
//         return new ResponseMessage(Type.danger, text);
//     }
// 
//     public static ResponseMessage info(String text) {
//         return new ResponseMessage(Type.info, text);
//     }
// 
//     private List<Error> errors = new ArrayList<Error>();
// 
//     public List<Error> getErrors() {
//         return errors;
//     }
// 
//     public void setErrors(List<Error> errors) {
//         this.errors = errors;
//     }
// 
//     public void addError(String field, String code, String message) {
//         this.errors.add(new Error(field, code, message));
//     }
// 
//     class Error {
// 
//         private String code;
//         private String message;
//         private String field;
// 
//         private Error(String field, String code, String message) {
//             this.field = field;
//             this.code = code;
//             this.message = message;
//         }
// 
//         public String getCode() {
//             return code;
//         }
// 
//         public void setCode(String code) {
//             this.code = code;
//         }
// 
//         public String getMessage() {
//             return message;
//         }
// 
//         public void setMessage(String message) {
//             this.message = message;
//         }
// 
//         public String getField() {
//             return field;
//         }
// 
//         public void setField(String field) {
//             this.field = field;
//         }
// 
//     }
// 
// }


import com.hantsylabs.restexample.springmvc.ApiErrors;
import com.hantsylabs.restexample.springmvc.exception.InvalidRequestException;
import com.hantsylabs.restexample.springmvc.exception.ResourceNotFoundException;
import com.hantsylabs.restexample.springmvc.exception.UsernameAlreadyUsedException;
import com.hantsylabs.restexample.springmvc.model.ResponseMessage;
import java.util.List;
import javax.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
package com.hantsylabs.restexample.springmvc.api;


/**
 * Called when an exception occurs during request processing. Transforms exception message into JSON format.
 */
@RestControllerAdvice()
public class RestExceptionHandler {

    private static final Logger log = LoggerFactory.getLogger(RestExceptionHandler.class);

    @Inject
    private MessageSource messageSource;

    @ExceptionHandler(value = {Exception.class, RuntimeException.class})
    //@ResponseBody
    public ResponseEntity<ResponseMessage> handleGenericException(Exception ex, WebRequest request) {
        if (log.isDebugEnabled()) {
            log.debug("handling exception...");
        }
        return new ResponseEntity<>(new ResponseMessage(ResponseMessage.Type.danger, ex.getMessage()), HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(value = {ResourceNotFoundException.class})
    //@ResponseBody
    public ResponseEntity<ResponseMessage> handleResourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
        if (log.isDebugEnabled()) {
            log.debug("handling ResourceNotFoundException...");
        }
        return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    }

// Path: src/main/java/com/hantsylabs/restexample/springmvc/ApiErrors.java
// public class ApiErrors {
// 
//     private static final String PREFIX = "errors.";
// 
//     public static final String INVALID_REQUEST = PREFIX + "INVALID_REQUEST";
// 
//     private ApiErrors() {}
// 
// }
// 
// Path: src/main/java/com/hantsylabs/restexample/springmvc/exception/InvalidRequestException.java
// public class InvalidRequestException extends RuntimeException {
// 
//     private BindingResult errors;
// 
//     public InvalidRequestException(BindingResult errors) {
//         this.errors = errors;
//     }
// 
//     public BindingResult getErrors() {
//         return errors;
//     }
// 
// }
// 
// Path: src/main/java/com/hantsylabs/restexample/springmvc/exception/ResourceNotFoundException.java
// public class ResourceNotFoundException extends RuntimeException {
// 
//     private static final long serialVersionUID = 1L;
// 
//     private Long id;
// 
//     public ResourceNotFoundException(Long id) {
//         super(String.format("resource %s was not found", id));
//         this.id = id;
//     }
// 
//     public ResourceNotFoundException(String message) {
//         super(message);
//     }
//     
//     public Long getId() {
//         return id;
//     }
// }
// 
// Path: src/main/java/com/hantsylabs/restexample/springmvc/exception/UsernameAlreadyUsedException.java
// public class UsernameAlreadyUsedException extends RuntimeException {
// 
//     private static final long serialVersionUID = 1L;
// 
//     private String username;
// 
//     public UsernameAlreadyUsedException(String username) {
//         this.username = username;
//     }
// 
//     public String getUsername() {
//         return username;
//     }
//     
// }
// 
// Path: src/main/java/com/hantsylabs/restexample/springmvc/model/ResponseMessage.java
// public class ResponseMessage {
// 
//     public enum Type {
//         success, warning, danger, info;
//     }
// 
//     private Type type;
//     private String text;
//     private String code;
// 
//     public ResponseMessage(Type type, String text) {
//         this.type = type;
//         this.text = text;
//     }
// 
//     public ResponseMessage(Type type, String code, String message) {
//         this.type = type;
//         this.code = code;
//         this.text = message;
//     }
// 
//     public String getText() {
//         return text;
//     }
// 
//     public Type getType() {
//         return type;
//     }
// 
//     public String getCode() {
//         return code;
//     }
//     
//     public static ResponseMessage success(String text) {
//         return new ResponseMessage(Type.success, text);
//     }
// 
//     public static ResponseMessage warning(String text) {
//         return new ResponseMessage(Type.warning, text);
//     }
// 
//     public static ResponseMessage danger(String text) {
//         return new ResponseMessage(Type.danger, text);
//     }
// 
//     public static ResponseMessage info(String text) {
//         return new ResponseMessage(Type.info, text);
//     }
// 
//     private List<Error> errors = new ArrayList<Error>();
// 
//     public List<Error> getErrors() {
//         return errors;
//     }
// 
//     public void setErrors(List<Error> errors) {
//         this.errors = errors;
//     }
// 
//     public void addError(String field, String code, String message) {
//         this.errors.add(new Error(field, code, message));
//     }
// 
//     class Error {
// 
//         private String code;
//         private String message;
//         private String field;
// 
//         private Error(String field, String code, String message) {
//             this.field = field;
//             this.code = code;
//             this.message = message;
//         }
// 
//         public String getCode() {
//             return code;
//         }
// 
//         public void setCode(String code) {
//             this.code = code;
//         }
// 
//         public String getMessage() {
//             return message;
//         }
// 
//         public void setMessage(String message) {
//             this.message = message;
//         }
// 
//         public String getField() {
//             return field;
//         }
// 
//         public void setField(String field) {
//             this.field = field;
//         }
// 
//     }
// 
// }


// Path: src/main/java/com/hantsylabs/restexample/springmvc/api/RestExceptionHandler.java
import com.hantsylabs.restexample.springmvc.ApiErrors;
import com.hantsylabs.restexample.springmvc.exception.InvalidRequestException;
import com.hantsylabs.restexample.springmvc.exception.ResourceNotFoundException;
import com.hantsylabs.restexample.springmvc.exception.UsernameAlreadyUsedException;
import com.hantsylabs.restexample.springmvc.model.ResponseMessage;
import java.util.List;
import javax.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;

package com.hantsylabs.restexample.springmvc.api;


/**
 * Called when an exception occurs during request processing. Transforms exception message into JSON format.
 */
@RestControllerAdvice()
public class RestExceptionHandler {

    private static final Logger log = LoggerFactory.getLogger(RestExceptionHandler.class);

    @Inject
    private MessageSource messageSource;

    @ExceptionHandler(value = {Exception.class, RuntimeException.class})
    //@ResponseBody
    public ResponseEntity<ResponseMessage> handleGenericException(Exception ex, WebRequest request) {
        if (log.isDebugEnabled()) {
            log.debug("handling exception...");
        }
        return new ResponseEntity<>(new ResponseMessage(ResponseMessage.Type.danger, ex.getMessage()), HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(value = {ResourceNotFoundException.class})
    //@ResponseBody
    public ResponseEntity<ResponseMessage> handleResourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
        if (log.isDebugEnabled()) {
            log.debug("handling ResourceNotFoundException...");
        }
        return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(value = {UsernameAlreadyUsedException.class})