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

org.glassfish.jersey.microprofile.restclient.RestClientModel Maven / Gradle / Ivy

/*
 * Copyright (c) 2019, 2022 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2019 Payara Foundation and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.jersey.microprofile.restclient;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;

import jakarta.ws.rs.client.WebTarget;

/**
 * Model of the rest client interface.
 *
 * @author David Kral
 * @author Patrik Dudits
 */
class RestClientModel {

    private final InterfaceModel interfaceModel;
    private final Map methodModels;

    /**
     * Creates new instance of the {@link RestClientModel} base on interface class.
     *
     * @param context RestClient data context
     * @return new instance
     */
    static RestClientModel from(RestClientContext context) {
        InterfaceModel interfaceModel = InterfaceModel.from(context);
        return new Builder()
                .interfaceModel(interfaceModel)
                .methodModels(parseMethodModels(interfaceModel))
                .build();
    }

    private RestClientModel(Builder builder) {
        this.interfaceModel = builder.classModel;
        this.methodModels = builder.methodModels;
    }

    /**
     * Invokes desired rest client method.
     *
     * @param baseWebTarget path to endpoint
     * @param method        desired method
     * @param args          actual method parameters
     * @return method return value
     */
     Object invokeMethod(WebTarget baseWebTarget, Method method, Object[] args) {
        WebTarget classLevelTarget = baseWebTarget.path(interfaceModel.getPath());
        MethodModel methodModel = methodModels.get(method);
        if (methodModel != null) {
            return new InterceptorInvocationContext(classLevelTarget, methodModel, method, args).proceed();
        }
        try {
            if (method.isDefault()) {
                T instance = (T) ReflectionUtil.createProxyInstance(interfaceModel.getRestClientClass());
                return method.invoke(instance, args);
            } else {
                throw new UnsupportedOperationException("This method is not supported!");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static Map parseMethodModels(InterfaceModel classModel) {
        Map methodMap = new HashMap<>();
        for (Method method : classModel.getRestClientClass().getMethods()) {
            if (method.isDefault() || Modifier.isStatic(method.getModifiers())) {
                continue;
            }
            //Skip method processing if method does not have HTTP annotation
            //and is not sub resource (does not have Path annotation)
            methodMap.put(method, MethodModel.from(classModel, method));
        }
        return methodMap;
    }

    private static class Builder {

        private InterfaceModel classModel;
        private Map methodModels;

        private Builder() {
        }

        /**
         * Rest client class converted to {@link InterfaceModel}
         *
         * @param classModel {@link InterfaceModel} instance
         * @return Updated Builder instance
         */
        Builder interfaceModel(InterfaceModel classModel) {
            this.classModel = classModel;
            return this;
        }

        /**
         * Rest client class methods converted to {@link Map} of {@link MethodModel}
         *
         * @param methodModels Method models
         * @return Updated Builder instance
         */
        Builder methodModels(Map methodModels) {
            this.methodModels = methodModels;
            return this;
        }

        /**
         * Creates new RestClientModel instance.
         *
         * @return new instance
         */
        public RestClientModel build() {
            return new RestClientModel(this);
        }
    }

    @Override
    public String toString() {
        return interfaceModel.getRestClientClass().getName();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy