001/*
002 * Copyright 2022-2025 Revetware LLC.
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 */
016
017package com.soklet;
018
019import com.soklet.converter.ValueConverterRegistry;
020
021import javax.annotation.Nonnull;
022import java.util.List;
023
024/**
025 * Contract for determining parameter values to inject when invoking <em>Resource Methods</em>.
026 * <p>
027 * Standard implementations can also be acquired via these factory methods:
028 * <ul>
029 *   <li>{@link #withDefaults()} (sufficient for most applications)</li>
030 *   <li>{@link #with(InstanceProvider, ValueConverterRegistry, RequestBodyMarshaler)} </li>
031 * </ul>
032 * <p>
033 * However, should a custom implementation be necessary for your application, documentation is available at <a href="https://www.soklet.com/docs/request-handling#resource-method-parameter-injection">https://www.soklet.com/docs/request-handling#resource-method-parameter-injection</a>.
034 *
035 * @author <a href="https://www.revetkn.com">Mark Allen</a>
036 */
037@FunctionalInterface
038public interface ResourceMethodParameterProvider {
039        /**
040         * For the given {@code request} and {@code resourceMethod}, vends the list of parameters to use when invoking the
041         * underlying Java method located at {@link ResourceMethod#getMethod()}.
042         * <p>
043         * The size of the returned list of parameters must exactly match the number of parameters required by the Java method signature.
044         *
045         * @param request        the HTTP request
046         * @param resourceMethod the <em>Resource Method</em> associated with the HTTP request
047         * @return the list of parameters to use when performing Java method invocation, or the empty list if no parameters are necessary
048         */
049        @Nonnull
050        List<Object> parameterValuesForResourceMethod(@Nonnull Request request,
051                                                                                                                                                                                                @Nonnull ResourceMethod resourceMethod);
052
053        /**
054         * Acquires a basic {@link ResourceMethodParameterProvider} with sensible defaults.
055         * <p>
056         * Callers should not rely on reference identity; this method may return a new or cached instance.
057         *
058         * @return a {@code ResourceMethodParameterProvider} with default settings
059         */
060        @Nonnull
061        static ResourceMethodParameterProvider withDefaults() {
062                return DefaultResourceMethodParameterProvider.defaultInstance();
063        }
064
065        /**
066         * Acquires a basic {@link ResourceMethodParameterProvider} with sensible defaults.
067         * <p>
068         * Callers should not rely on reference identity; this method may return a new or cached instance.
069         *
070         * @param instanceProvider       controls how the parameter provider creates instances of objects
071         * @param valueConverterRegistry controls how the parameter provider converts values from strings to Java types expected by the <em>Resource Method</em>
072         * @param requestBodyMarshaler   controls how parameters annotated with {@link com.soklet.annotation.RequestBody} are converted to the Java type expected by the <em>Resource Method</em>
073         * @return a {@code ResourceMethodParameterProvider} with default settings
074         */
075        @Nonnull
076        static ResourceMethodParameterProvider with(@Nonnull InstanceProvider instanceProvider,
077                                                                                                                                                                                        @Nonnull ValueConverterRegistry valueConverterRegistry,
078                                                                                                                                                                                        @Nonnull RequestBodyMarshaler requestBodyMarshaler) {
079                return new DefaultResourceMethodParameterProvider(instanceProvider, valueConverterRegistry, requestBodyMarshaler);
080        }
081}