<commit_before>/**
 *    Retz
 *    Copyright (C) 2016 Nautilus Technologies, Inc.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package io.github.retz.web.feign;

import java.io.IOException;
import java.util.Optional;
import java.util.function.Function;

import com.fasterxml.jackson.databind.ObjectMapper;

import feign.FeignException;
import feign.Response;
import feign.codec.ErrorDecoder;
import io.github.retz.protocol.ErrorResponse;

public class ErrorResponseDecoder implements ErrorDecoder {

    private final ObjectMapper mapper;

    private final ErrorDecoder delegate;

    private final Function<String, Optional<String>> extractor;

    public ErrorResponseDecoder(ObjectMapper mapper) {
        this(mapper, new ErrorDecoder.Default(), ErrorResponseDecoder::extract);
    }

    public ErrorResponseDecoder(
            ObjectMapper mapper,
            ErrorDecoder delegate,
            Function<String, Optional<String>> extractor) {
        this.mapper = mapper;
        this.delegate = delegate;
        this.extractor = extractor;
    }

    @Override
    public Exception decode(String methodKey, Response response) {
        Exception ex = delegate.decode(methodKey, response);
        if (ex instanceof ErrorResponseException) {
            return ex;
        } else if (ex instanceof FeignException) {
            FeignException fex = (FeignException) ex;
            return extractor.apply(fex.getMessage())
                    .map(value -> {
                        try {
                            return new ErrorResponseException(
                                    fex.status(), fex.getMessage(),
                                    mapper.readValue(value, ErrorResponse.class));
                        } catch (IOException e) {
                            return ex;
                        }
                    })
                    .orElseGet(() -> ex);
        } else {
            return ex;
        }
    }

    private static final String SEPARATOR = "; content:\n";

    private static Optional<String> extract(String message) {
        int idx = message.indexOf(SEPARATOR);<commit_msg>Create ErrorResponseException even if the ErrorResponse couldn't be built from the response body.<commit_after>/**
 *    Retz
 *    Copyright (C) 2016 Nautilus Technologies, Inc.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package io.github.retz.web.feign;

import java.io.IOException;
import java.util.Optional;
import java.util.function.Function;

import com.fasterxml.jackson.databind.ObjectMapper;

import feign.FeignException;
import feign.Response;
import feign.codec.ErrorDecoder;
import io.github.retz.protocol.ErrorResponse;

public class ErrorResponseDecoder implements ErrorDecoder {

    private final ObjectMapper mapper;

    private final ErrorDecoder delegate;

    private final Function<String, Optional<String>> extractor;

    public ErrorResponseDecoder(ObjectMapper mapper) {
        this(mapper, new ErrorDecoder.Default(), ErrorResponseDecoder::extract);
    }

    public ErrorResponseDecoder(
            ObjectMapper mapper,
            ErrorDecoder delegate,
            Function<String, Optional<String>> extractor) {
        this.mapper = mapper;
        this.delegate = delegate;
        this.extractor = extractor;
    }

    @Override
    public Exception decode(String methodKey, Response response) {
        Exception ex = delegate.decode(methodKey, response);
        if (ex instanceof ErrorResponseException) {
            return ex;
        } else if (ex instanceof FeignException) {
            FeignException fex = (FeignException) ex;
            return extractor.apply(fex.getMessage())
                    .map(value -> {
                        try {
                            return new ErrorResponseException(
                                    fex.status(), fex.getMessage(),
                                    mapper.readValue(value, ErrorResponse.class));
                        } catch (IOException e) {
                            return new ErrorResponseException(
                                    fex.status(), fex.getMessage(),
                                    new ErrorResponse(value));
                        }
                    })
                    .orElseGet(() -> new ErrorResponseException(
                            fex.status(), fex.getMessage(),
                            new ErrorResponse(fex.toString())));
        } else {
            return ex;
        }
    }

    private static final String SEPARATOR = "; content:\n";

    private static Optional<String> extract(String message) {
        int idx = message.indexOf(SEPARATOR);
{'fraction_non_alphanumeric': 0.0796583580268433, 'fraction_numerical': 0.002788914066585323, 'mean_word_length': 2.1235710397387044, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3318708', 'n_tokens_mistral': 1406, 'n_tokens_neox': 1356, 'n_words': 431}