001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.camel.util.component;
018
019import java.lang.reflect.Method;
020import java.util.ArrayList;
021import java.util.Collections;
022import java.util.List;
023
024/**
025 * Delegate class for {@link ApiMethod}.
026 * This class is instantiated by Enumerations for Api Proxy types.
027 * <p>
028 *     For example:
029 * </p>
030 * <pre>
031 * {@code
032 *     public enum HelloWorldMethod implements ApiMethod {
033 *         SAYHI(String.class, "sayHi", ApiMethodArg.from(String.class, "name");
034 *
035 *         private ApiMethodImpl apiMethod;
036 *
037 *         private HelloWorldMethods(Class<?> resultType, String name, ApiMethodArg... args) throws IllegalArgumentException {
038 *             this.apiMethod = new ApiMethod(HelloWorld.class, resultType, name, args);
039 *         }
040 *
041 *         // implement ApiMethod interface
042 *         String getName() { return apiMethod.getName(); }
043 *         Class<?> getResultType() {return apiMethod.getResultType(); }
044 *         List<String> getArgNames() { return apiMethod.getArgNames(); }
045 *         List<Class<?>> getArgTypes() {return apiMethod.getArgTypes(); }
046 *         Method getMethod() { return apiMethod.getMethod(); }
047 *     }
048 * }
049 * </pre>
050 */
051public final class ApiMethodImpl implements ApiMethod {
052
053    // name, result class, ordered argument names and classes, and Method to invoke
054    private final String name;
055    private final Class<?> resultType;
056    private final List<String> argNames;
057    private final List<Class<?>> argTypes;
058    private final Method method;
059
060    public ApiMethodImpl(Class<?> proxyType, Class<?> resultType, String name, ApiMethodArg... args) throws IllegalArgumentException {
061        this.name = name;
062        this.resultType = resultType;
063
064        final List<String> tmpArgNames = new ArrayList<>(args.length);
065        final List<Class<?>> tmpArgTypes = new ArrayList<>(args.length);
066        for (ApiMethodArg arg : args) {
067            tmpArgTypes.add(arg.getType());
068            tmpArgNames.add(arg.getName());
069        }
070
071        this.argNames = Collections.unmodifiableList(tmpArgNames);
072        this.argTypes = Collections.unmodifiableList(tmpArgTypes);
073
074        // find method in Proxy type
075        try {
076            this.method = proxyType.getMethod(name, argTypes.toArray(new Class[args.length]));
077        } catch (NoSuchMethodException e) {
078            throw new IllegalArgumentException(
079                String.format("Missing method %s %s", name, argTypes.toString().replace('[', '(').replace(']', ')')),
080                e);
081        }
082    }
083
084    @Override
085    public String getName() {
086        return name;
087    }
088
089    @Override
090    public Class<?> getResultType() {
091        return resultType;
092    }
093
094    @Override
095    public List<String> getArgNames() {
096        return argNames;
097    }
098
099    @Override
100    public List<Class<?>> getArgTypes() {
101        return argTypes;
102    }
103
104    @Override
105    public Method getMethod() {
106        return method;
107    }
108
109    @Override
110    public String toString() {
111        StringBuilder builder = new StringBuilder();
112        builder.append("{")
113            .append("name=").append(name)
114            .append(", resultType=").append(resultType)
115            .append(", argNames=").append(argNames)
116            .append(", argTypes=").append(argTypes)
117            .append("}");
118
119        return builder.toString();
120    }
121}