All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jsunsoft.http.BasicResponseHandler Maven / Gradle / Ivy

There is a newer version: 3.3.1
Show newest version
/*
 * Copyright (c) 2017-2021. Benik Arakelyan
 *
 * 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 com.jsunsoft.http;

import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.message.HeaderGroup;

import java.lang.reflect.Type;
import java.net.URI;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * ResponseHandler objects are immutable they can be shared.
 *
 * @param  Type of deserialized content from response
 */

final class BasicResponseHandler implements ResponseHandler {

    private final int statusCode;
    private final T content;
    private final HeaderGroup headerGroup;
    private final String errorText;
    private final boolean isVoidType;
    private final ContentType contentType;
    private final URI uri;
    private final boolean success;
    private final ConnectionFailureType connectionFailureType;

    BasicResponseHandler(T content, int statusCode, String errorText, Type type, ContentType contentType, URI uri, ConnectionFailureType connectionFailureType) {
        this(content, statusCode, new HeaderGroup(), errorText, type, contentType, uri, connectionFailureType);
    }

    BasicResponseHandler(T content, int statusCode, HeaderGroup headerGroup, String errorText, Type type, ContentType contentType, URI uri) {
        this(content, statusCode, headerGroup, errorText, type, contentType, uri, BasicConnectionFailureType.NONE);
    }

    private BasicResponseHandler(T content, int statusCode, HeaderGroup headerGroup, String errorText, Type type, ContentType contentType, URI uri, ConnectionFailureType connectionFailureType) {
        this.statusCode = statusCode;
        this.content = content;
        this.headerGroup = headerGroup;
        this.errorText = errorText;
        this.isVoidType = HttpRequestUtils.isVoidType(type);
        this.contentType = contentType;
        this.uri = ArgsCheck.notNull(uri, "uri");
        this.success = HttpRequestUtils.isSuccess(statusCode);
        this.connectionFailureType = ArgsCheck.notNull(connectionFailureType, "connectionFailureType");
    }

    /**
     * @return {@code true} If content is present else {@code false}
     */
    @Override
    public boolean hasContent() {
        return content != null;
    }

    /**
     * @return {@code true} If hasn't content else {@code false}
     */
    @Override
    public boolean hasNotContent() {
        return content == null;
    }

    @Override
    public int getCode() {
        return statusCode;
    }

    /**
     * @param defaultValue value to return if content isn't present
     *
     * @return Deserialized Content from response. If content isn't present returns defaultValue.
     *
     * @throws UnsupportedOperationException if generic type is a Void
     */
    @Override
    public T orElse(T defaultValue) {
        check();
        return content == null ? defaultValue : content;
    }

    /**
     * @param defaultValue value to return if status code is success and hasn't body
     *
     * @return Deserialized Content from response. If hasn't body returns defaultValue.
     *
     * @throws UnexpectedStatusCodeException If status code is not success
     * @throws UnsupportedOperationException if generic type is a Void
     */
    @Override
    public T orElseThrow(T defaultValue) {
        check();
        if (isNonSuccess()) {
            throw new UnexpectedStatusCodeException(statusCode, errorText, uri);
        }
        return content == null ? defaultValue : content;
    }

    /**
     * @param exceptionFunction Instance of type {@link Function} by parameter this which returns exception to throw if status code isn't success.
     * @param                Type of the exception to be thrown
     *
     * @return Deserialized content from response. If hasn't body returns {@code null}.
     *
     * @throws X If status code isn't success.
     */
    @Override
    public  T orThrow(Function, X> exceptionFunction) throws X {
        check();
        if (isNonSuccess()) {
            throw exceptionFunction.apply(this);
        }
        return content;
    }

    /**
     * @param defaultValue      Value to return if content is {@code null}
     * @param exceptionFunction Instance of type {@link Function} by parameter this which returns exception to throw if status code isn't success.
     * @param                Type of the exception to be thrown
     *
     * @return Deserialized content from response. If hasn't body returns {@code defaultValue}.
     *
     * @throws X If status code isn't success.
     */
    @Override
    public  T orThrow(T defaultValue, Function, X> exceptionFunction) throws X {
        check();
        if (isNonSuccess()) {
            throw exceptionFunction.apply(this);
        }
        return content == null ? defaultValue : content;
    }

    /**
     * @param exceptionSupplier Instance of type {@link Supplier} which returns exception to throw if status code isn't success.
     * @param                Type of the exception to be thrown
     *
     * @return Deserialized content from response. If hasn't body returns {@code null}.
     *
     * @throws X If status code isn't success.
     */
    @Override
    public  T getOrThrow(Supplier exceptionSupplier) throws X {
        check();
        if (isNonSuccess()) {
            throw exceptionSupplier.get();
        }
        return content;
    }

    /**
     * @param defaultValue      Value to return if content is {@code null}
     * @param exceptionSupplier Instance of type {@link Supplier} which returns exception to throw if status code isn't success.
     * @param                Type of the exception to be thrown
     *
     * @return Deserialized content from response. If hasn't body returns {@code defaultValue}.
     *
     * @throws X If status code isn't success.
     */
    @Override
    public  T getOrThrow(T defaultValue, Supplier exceptionSupplier) throws X {
        check();
        if (isNonSuccess()) {
            throw exceptionSupplier.get();
        }
        return content == null ? defaultValue : content;
    }

    /**
     * @return Content from response. Returns null if hasn't body
     *
     * @throws UnexpectedStatusCodeException If response code is not success
     * @throws UnsupportedOperationException if generic type is a Void
     */
    @Override
    public T orElseThrow() {
        check();
        if (isSuccess()) {
            return content;
        }
        throw new UnexpectedStatusCodeException(statusCode, errorText, uri);
    }

    /**
     * Strongly recommend call get method after check content is present.
     * For example
     * 
     *     if(responseHandler.hasContent()){
     *         responseHandler.get()
     *     }
     * 
* * @return Deserialized content from response. * * @throws NoSuchContentException If content is not present * @throws UnsupportedOperationException if generic type is a Void * @see BasicResponseHandler#orElse(Object) * @see BasicResponseHandler#ifHasContent(Consumer) */ @Override public T get() { check(); if (content == null) { throw new NoSuchContentException("Content is not present: Response code: [" + statusCode + ']'); } return content; } @Override public Optional getAsOptional() { check(); return Optional.ofNullable(content); } @Override public Optional getAsOptionalOrThrow() { check(); if (isSuccess()) { return Optional.ofNullable(content); } throw new UnexpectedStatusCodeException(statusCode, errorText, uri); } /** * @return Returns the error text if the connection failed but the server sent useful data nonetheless. * * @throws NoSuchElementException If error text is not present * @throws UnsupportedOperationException if generic type is a Void */ @Override public String getErrorText() { if (errorText == null) { throw new IllegalStateException("Error text is not available: Response code: [" + statusCode + ']'); } return errorText; } /** * @return Returns the connection URI */ @Override public URI getURI() { return uri; } /** * @return Content type of response */ @Override public ContentType getContentType() { return contentType; } /** * @return Returns true if status code contains [200, 300) else false */ @Override public boolean isSuccess() { return success; } /** * @return Returns true if status code isn't contains [200, 300) else false */ @Override public boolean isNonSuccess() { return !isSuccess(); } /** * If has a content, invoke the specified consumer with the content, otherwise do nothing. * * @param consumer block to be executed if has a content * * @throws IllegalArgumentException if {@code consumer} is null */ @Override public void ifHasContent(Consumer consumer) { ArgsCheck.notNull(consumer, "consumer"); if (content != null) { consumer.accept(content); } } /** * If status code is success , invoke the specified consumer with the responseHandler and returns {@code OtherwiseSupport} with ignore else {@code OtherwiseSupport} with not ignore. * * @param consumer block to be executed if status code is success. * * @return OtherwiseSupport instance to support action otherwise. * * @see OtherwiseSupport#otherwise(Consumer) */ @Override public OtherwiseSupport ifSuccess(Consumer> consumer) { ArgsCheck.notNull(consumer, "consumer"); OtherwiseSupport otherwiseSupportResult; if (success) { consumer.accept(this); otherwiseSupportResult = OtherwiseSupport.createIgnored(this); } else { otherwiseSupportResult = OtherwiseSupport.createNotIgnored(this); } return otherwiseSupportResult; } /** * If status code is success , invoke the specified consumer with the responseHandler. * * @param consumer block to be executed if status code is not success. */ @Override public void ifNotSuccess(Consumer> consumer) { ArgsCheck.notNull(consumer, "consumer"); if (!success) { consumer.accept(this); } } @Override public FilterSupport filter(Predicate> predicate) { return FilterSupport.create(this, predicate); } @Override public boolean containsHeader(String name) { return headerGroup.containsHeader(name); } @Override public Header[] getHeaders(String name) { return headerGroup.getHeaders(name); } @Override public Header getFirstHeader(String name) { return headerGroup.getFirstHeader(name); } @Override public Header getLastHeader(String name) { return headerGroup.getLastHeader(name); } @Override public Header[] getHeaders() { return headerGroup.getHeaders(); } /** * @return connectionFailureType. * * @see ConnectionFailureType */ //todo rename and make public ConnectionFailureType getConnectionFailureType() { return connectionFailureType; } @Override public String toString() { return "ResponseHandler{" + "statusCode=" + statusCode + ", content=" + content + ", errorText='" + errorText + '\'' + ", uri=" + uri + ", connectionFailureType=" + connectionFailureType + '}'; } private void check() { if (isVoidType) { throw new UnsupportedOperationException("Content is not available. Generic type is a Void"); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy