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

com.sap.cds.mtx.impl.AbstractSidecarAccess Maven / Gradle / Ivy

/*
 * ----------------------------------------------------------------
 * © 2019-2021 SAP SE or an SAP affiliate company. All rights reserved.
 * ----------------------------------------------------------------
 *
 */
package com.sap.cds.mtx.impl;

import static org.apache.http.HttpStatus.SC_BAD_GATEWAY;
import static org.apache.http.HttpStatus.SC_GATEWAY_TIMEOUT;
import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
import static org.apache.http.HttpStatus.SC_NOT_FOUND;
import static org.apache.http.HttpStatus.SC_NOT_MODIFIED;
import static org.apache.http.HttpStatus.SC_NO_CONTENT;
import static org.apache.http.HttpStatus.SC_OK;
import static org.apache.http.HttpStatus.SC_SERVICE_UNAVAILABLE;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.IntFunction;

import org.apache.http.HttpHeaders;

import com.google.common.base.Strings;
import com.sap.cds.CdsCommunicationException;
import com.sap.cds.mtx.ModelId;
import com.sap.cloud.mt.tools.api.RequestEnhancer;
import com.sap.cloud.mt.tools.api.ResilienceConfig;
import com.sap.cloud.mt.tools.api.ServiceCall;
import com.sap.cloud.mt.tools.api.ServiceEndpoint;
import com.sap.cloud.mt.tools.api.ServiceResponse;
import com.sap.cloud.mt.tools.exception.InternalException;
import com.sap.cloud.mt.tools.exception.ServiceException;

public abstract class AbstractSidecarAccess {
    protected static final String APPLICATION_JSON = "application/json";
    protected final ServiceEndpoint csnEndpoint;
    protected final ServiceEndpoint edmxEndpoint;
    protected final ServiceEndpoint i18nEndpoint;
    protected RequestEnhancer requestEnhancer;

    /**
     * @param requestEnhancer  Adds information to http request, for example for authentication and authority
     * @param resilienceConfig Parameters like number of retries, wait between
     *                         retries, ..
     */
    protected AbstractSidecarAccess(RequestEnhancer requestEnhancer,
            ResilienceConfig resilienceConfig) {
        Set retryCodes = getRetryCodes();
        try {
            csnEndpoint = ServiceEndpoint.create().destinationName(getDestinationName())
                    .path(getCsnPath()).returnCodeChecker(getCheckFunction()).retry().forReturnCodes(retryCodes)
                    .config(resilienceConfig).end();
            edmxEndpoint = ServiceEndpoint.create().destinationName(getDestinationName())
                    .path(getEdmxPath()).returnCodeChecker(getCheckFunction()).retry().forReturnCodes(retryCodes)
                    .config(resilienceConfig).end();
            i18nEndpoint = getI18nPath() != null ? ServiceEndpoint.create().destinationName(getDestinationName())
                    .path(getI18nPath()).returnCodeChecker(getCheckFunction()).retry().forReturnCodes(retryCodes)
                    .config(resilienceConfig).end() : null;
        } catch (InternalException e) {
            throw new CdsCommunicationException(e);
        }
        this.requestEnhancer = requestEnhancer;
    }

    private Set getRetryCodes() {
        Set retryCodes = new HashSet<>();
        retryCodes.add(SC_BAD_GATEWAY);
        retryCodes.add(SC_GATEWAY_TIMEOUT);
        retryCodes.add(SC_INTERNAL_SERVER_ERROR);
        retryCodes.add(SC_SERVICE_UNAVAILABLE);
        retryCodes.add(SC_NOT_FOUND);
        return retryCodes;
    }

    protected abstract String getDestinationName();

    protected Map getHeaderFields(String eTag) {
        Map headerFields = new HashMap<>();
        if (!Strings.isNullOrEmpty(eTag)) {
            headerFields.put(HttpHeaders.IF_NONE_MATCH, eTag);
        }
        headerFields.put(HttpHeaders.ACCEPT, APPLICATION_JSON);
        return headerFields;
    }

    private IntFunction getCheckFunction() {
        return c -> {
            if (c != SC_OK && c != SC_NOT_MODIFIED && c != SC_NO_CONTENT) {
                String message = MessageFormat.format("Sidecar returned with status {0}", c);
                return new CdsCommunicationException(message, c);
            } else {
                return null;
            }
        };
    }

    /**
     * Returns csn model as string, as returned by sidecar
     *
     * @param id   the model identifier
     * @param eTag entity tag
     * @return the {@link SidecarResponse}
     * @throws CdsCommunicationException
     */
    public SidecarResponse getCsn(ModelId id, String eTag) throws CdsCommunicationException {
        try {
            ServiceCall call = createCsnCall(id, eTag);
            ServiceResponse response = call.execute(String.class);
            return csnSidecarResponse(response, eTag);
        } catch (InternalException e) {
            throw new CdsCommunicationException(e);
        } catch (ServiceException e) {
            if (e.getCause() instanceof CdsCommunicationException) {
                throw (CdsCommunicationException) e.getCause();
            }
            throw new CdsCommunicationException(e);
        }
    }

    protected abstract String getCsnPath();

    protected abstract ServiceCall createCsnCall(ModelId id, String eTag) throws InternalException;

    protected SidecarResponse csnSidecarResponse(ServiceResponse response, String eTag) throws InternalException {
        return modelInfo(response, eTag);
    }

    /**
     * Returns edmx model as string, as returned by sidecar
     *
     * @param id   the model identifier
     * @param eTag entity tag
     * @return the {@link SidecarResponse}
     * @throws CdsCommunicationException
     */
    public SidecarResponse getEdmx(ModelId id, String eTag) throws CdsCommunicationException {
        try {
            ServiceCall call = createEdmxCall(id, eTag);
            ServiceResponse response = call.execute(String.class);
            return edmxSidecarResponse(response, eTag);
        } catch (InternalException e) {
            throw new CdsCommunicationException(e);
        } catch (ServiceException e) {
            if (e.getCause() instanceof CdsCommunicationException) {
                throw (CdsCommunicationException) e.getCause();
            }
            throw new CdsCommunicationException(e);
        }
    }

    protected SidecarResponse edmxSidecarResponse(ServiceResponse response, String eTag) throws InternalException {
        return modelInfo(response, eTag);
    }

    private SidecarResponse modelInfo(ServiceResponse response, String eTag) throws InternalException {
        if (response.getHttpStatusCode() == SC_NOT_MODIFIED) {
            return new SidecarResponse(null, eTag, true);
        } else {
            String value = response.getPayload().orElse("");
            return new SidecarResponse(value, response.getETag().orElse(eTag), false);
        }
    }

    protected abstract String getEdmxPath();

    protected abstract ServiceCall createEdmxCall(ModelId id, String eTag) throws InternalException;

    /**
     * Returns i18n resources as string, as returned by sidecar
     *
     * @param id   the model identifier
     * @param eTag entity tag
     * @return the {@link SidecarResponse}
     * @throws CdsCommunicationException
     */
    public SidecarResponse getI18n(ModelId id, String eTag) throws CdsCommunicationException {
        try {
            ServiceCall call = createI18nCall(id, eTag);
            ServiceResponse response = call.execute(String.class);
            return i18nSidecarResponse(response, eTag);
        } catch (InternalException e) {
            throw new CdsCommunicationException(e);
        } catch (ServiceException e) {
            if (e.getCause() instanceof CdsCommunicationException) {
                throw (CdsCommunicationException) e.getCause();
            }
            throw new CdsCommunicationException(e);
        }
    }


    protected SidecarResponse i18nSidecarResponse(ServiceResponse response, String eTag) throws InternalException {
        return modelInfo(response, eTag);
    }

    protected abstract String getI18nPath();

    protected abstract ServiceCall createI18nCall(ModelId id, String eTag) throws InternalException;
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy