// Path: src/main/java/com/github/mkopylec/errorest/configuration/ErrorestProperties.java
// @ConfigurationProperties("errorest")
// public class ErrorestProperties {
// 
//     /**
//      * HTTP response body format.
//      */
//     private ResponseBodyFormat responseBodyFormat = FULL;
//     /**
//      * Properties responsible for handling validation errors.
//      */
//     private BeanValidationError beanValidationError = new BeanValidationError();
//     /**
//      * Properties responsible for handling 4xx HTTP errors.
//      */
//     private HttpClientError httpClientError = new HttpClientError();
// 
//     public ResponseBodyFormat getResponseBodyFormat() {
//         return responseBodyFormat;
//     }
// 
//     public void setResponseBodyFormat(ResponseBodyFormat responseBodyFormat) {
//         this.responseBodyFormat = responseBodyFormat;
//     }
// 
//     public BeanValidationError getBeanValidationError() {
//         return beanValidationError;
//     }
// 
//     public void setBeanValidationError(BeanValidationError beanValidationError) {
//         this.beanValidationError = beanValidationError;
//     }
// 
//     public HttpClientError getHttpClientError() {
//         return httpClientError;
//     }
// 
//     public void setHttpClientError(HttpClientError httpClientError) {
//         this.httpClientError = httpClientError;
//     }
// 
//     public enum ResponseBodyFormat {
//         WITHOUT_DESCRIPTIONS, FULL
//     }
// 
//     public static class BeanValidationError {
// 
//         /**
//          * Validation errors logging level.
//          */
//         private LoggingLevel loggingLevel = WARN;
// 
//         public LoggingLevel getLoggingLevel() {
//             return loggingLevel;
//         }
// 
//         public void setLoggingLevel(LoggingLevel loggingLevel) {
//             this.loggingLevel = loggingLevel;
//         }
//     }
// 
//     public static class HttpClientError {
// 
//         /**
//          * HTTP 4xx errors logging level.
//          */
//         private LoggingLevel loggingLevel = WARN;
// 
//         public LoggingLevel getLoggingLevel() {
//             return loggingLevel;
//         }
// 
//         public void setLoggingLevel(LoggingLevel loggingLevel) {
//             this.loggingLevel = loggingLevel;
//         }
//     }
// }
// 
// Path: src/main/java/com/github/mkopylec/errorest/handling/RequestAttributeSettingFilter.java
// public static final String REQUEST_HEADERS_ERROR_ATTRIBUTE = RequestAttributeSettingFilter.class.getName() + ".headers";


import com.github.mkopylec.errorest.configuration.ErrorestProperties;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.http.HttpStatus;
import org.springframework.web.context.request.WebRequest;
import javax.servlet.http.HttpServletRequest;
import static com.github.mkopylec.errorest.handling.RequestAttributeSettingFilter.REQUEST_HEADERS_ERROR_ATTRIBUTE;
import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
import static org.springframework.web.context.request.WebRequest.SCOPE_REQUEST;
package com.github.mkopylec.errorest.handling.errordata;




public abstract class ErrorDataProvider<T extends Throwable> {

    public static final String REQUEST_URI_ERROR_ATTRIBUTE = "path";
    public static final String NOT_AVAILABLE_DATA = "[N/A]";

    protected final ErrorestProperties errorestProperties;

    protected ErrorDataProvider(ErrorestProperties errorestProperties) {
        this.errorestProperties = errorestProperties;
    }

    public abstract ErrorData getErrorData(T ex, HttpServletRequest request);

    public abstract ErrorData getErrorData(T ex, HttpServletRequest request, HttpStatus defaultResponseStatus, ErrorAttributes errorAttributes, WebRequest webRequest);

    protected String getRequestUri(ErrorAttributes errorAttributes, WebRequest webRequest) {
        return errorAttributes.getErrorAttributes(webRequest, false).getOrDefault(REQUEST_URI_ERROR_ATTRIBUTE, NOT_AVAILABLE_DATA).toString();
    }

    protected String getRequestHeaders(WebRequest webRequest) {
// Path: src/main/java/com/github/mkopylec/errorest/configuration/ErrorestProperties.java
// @ConfigurationProperties("errorest")
// public class ErrorestProperties {
// 
//     /**
//      * HTTP response body format.
//      */
//     private ResponseBodyFormat responseBodyFormat = FULL;
//     /**
//      * Properties responsible for handling validation errors.
//      */
//     private BeanValidationError beanValidationError = new BeanValidationError();
//     /**
//      * Properties responsible for handling 4xx HTTP errors.
//      */
//     private HttpClientError httpClientError = new HttpClientError();
// 
//     public ResponseBodyFormat getResponseBodyFormat() {
//         return responseBodyFormat;
//     }
// 
//     public void setResponseBodyFormat(ResponseBodyFormat responseBodyFormat) {
//         this.responseBodyFormat = responseBodyFormat;
//     }
// 
//     public BeanValidationError getBeanValidationError() {
//         return beanValidationError;
//     }
// 
//     public void setBeanValidationError(BeanValidationError beanValidationError) {
//         this.beanValidationError = beanValidationError;
//     }
// 
//     public HttpClientError getHttpClientError() {
//         return httpClientError;
//     }
// 
//     public void setHttpClientError(HttpClientError httpClientError) {
//         this.httpClientError = httpClientError;
//     }
// 
//     public enum ResponseBodyFormat {
//         WITHOUT_DESCRIPTIONS, FULL
//     }
// 
//     public static class BeanValidationError {
// 
//         /**
//          * Validation errors logging level.
//          */
//         private LoggingLevel loggingLevel = WARN;
// 
//         public LoggingLevel getLoggingLevel() {
//             return loggingLevel;
//         }
// 
//         public void setLoggingLevel(LoggingLevel loggingLevel) {
//             this.loggingLevel = loggingLevel;
//         }
//     }
// 
//     public static class HttpClientError {
// 
//         /**
//          * HTTP 4xx errors logging level.
//          */
//         private LoggingLevel loggingLevel = WARN;
// 
//         public LoggingLevel getLoggingLevel() {
//             return loggingLevel;
//         }
// 
//         public void setLoggingLevel(LoggingLevel loggingLevel) {
//             this.loggingLevel = loggingLevel;
//         }
//     }
// }
// 
// Path: src/main/java/com/github/mkopylec/errorest/handling/RequestAttributeSettingFilter.java
// public static final String REQUEST_HEADERS_ERROR_ATTRIBUTE = RequestAttributeSettingFilter.class.getName() + ".headers";


// Path: src/main/java/com/github/mkopylec/errorest/handling/errordata/ErrorDataProvider.java
import com.github.mkopylec.errorest.configuration.ErrorestProperties;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.http.HttpStatus;
import org.springframework.web.context.request.WebRequest;
import javax.servlet.http.HttpServletRequest;
import static com.github.mkopylec.errorest.handling.RequestAttributeSettingFilter.REQUEST_HEADERS_ERROR_ATTRIBUTE;
import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
import static org.springframework.web.context.request.WebRequest.SCOPE_REQUEST;

package com.github.mkopylec.errorest.handling.errordata;




public abstract class ErrorDataProvider<T extends Throwable> {

    public static final String REQUEST_URI_ERROR_ATTRIBUTE = "path";
    public static final String NOT_AVAILABLE_DATA = "[N/A]";

    protected final ErrorestProperties errorestProperties;

    protected ErrorDataProvider(ErrorestProperties errorestProperties) {
        this.errorestProperties = errorestProperties;
    }

    public abstract ErrorData getErrorData(T ex, HttpServletRequest request);

    public abstract ErrorData getErrorData(T ex, HttpServletRequest request, HttpStatus defaultResponseStatus, ErrorAttributes errorAttributes, WebRequest webRequest);

    protected String getRequestUri(ErrorAttributes errorAttributes, WebRequest webRequest) {
        return errorAttributes.getErrorAttributes(webRequest, false).getOrDefault(REQUEST_URI_ERROR_ATTRIBUTE, NOT_AVAILABLE_DATA).toString();
    }

    protected String getRequestHeaders(WebRequest webRequest) {
        return getAttribute(REQUEST_HEADERS_ERROR_ATTRIBUTE, webRequest);