001/**
002 * Copyright (C) 2006-2024 Talend Inc. - www.talend.com
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.talend.sdk.component.runtime.manager.service.http;
017
018import static java.util.stream.Collectors.toMap;
019
020import java.util.Collection;
021import java.util.Map;
022import java.util.Optional;
023import java.util.function.BiFunction;
024import java.util.function.Function;
025
026import org.talend.sdk.component.api.service.http.Configurer;
027
028import lombok.AllArgsConstructor;
029import lombok.Data;
030import lombok.EqualsAndHashCode;
031
032@Data
033@AllArgsConstructor()
034@EqualsAndHashCode(exclude = "bodyCache")
035public class HttpRequest {
036
037    private static final Object[] EMPTY_ARRAY = new Object[0];
038
039    private static final Configurer.ConfigurerConfiguration EMPTY_CONFIGURER_OPTIONS =
040            new Configurer.ConfigurerConfiguration() {
041
042                @Override
043                public Object[] configuration() {
044                    return EMPTY_ARRAY;
045                }
046
047                @Override
048                public <T> T get(final String name, final Class<T> type) {
049                    return null;
050                }
051            };
052
053    private final String url;
054
055    private final String methodType;
056
057    private final Collection<String> queryParams;
058
059    private final Map<String, String> headers;
060
061    private final Configurer configurer;
062
063    private final Map<String, Function<Object[], Object>> configurerOptions;
064
065    private final BiFunction<String, Object[], Optional<byte[]>> payloadProvider;
066
067    private final Object[] params;
068
069    private volatile Optional<byte[]> bodyCache;
070
071    /**
072     * encode payload only when requested
073     *
074     * @return bytes encoded payload
075     */
076    public Optional<byte[]> getBody() {
077        if (bodyCache != null) {
078            return bodyCache;
079        }
080        synchronized (this) {
081            if (bodyCache != null) {
082                return bodyCache;
083            }
084            return bodyCache = doGetBody();
085        }
086    }
087
088    private Optional<byte[]> doGetBody() {
089        if (payloadProvider == null) {
090            return Optional.empty();
091        }
092        return payloadProvider.apply(headers.get("content-type"), params);
093    }
094
095    public Configurer.ConfigurerConfiguration getConfigurationOptions() {
096        final Map<String, Object> options = configurerOptions
097                .entrySet()
098                .stream()
099                .collect(toMap(Map.Entry::getKey, e -> e.getValue().apply(params)));
100
101        return configurerOptions.isEmpty() ? EMPTY_CONFIGURER_OPTIONS : new Configurer.ConfigurerConfiguration() {
102
103            @Override
104            public Object[] configuration() {
105                return options.values().toArray(new Object[0]);
106            }
107
108            @Override
109            public <T> T get(final String name, final Class<T> type) {
110                return type.cast(options.get(name));
111            }
112        };
113    }
114}