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", "name", String.class);
034 *
035 *         private ApiMethodImpl apiMethod;
036 *
037 *         private HelloWorldMethods(Class<?> resultType, String name, Object... 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, Object... args) throws IllegalArgumentException {
061        this.name = name;
062        this.resultType = resultType;
063
064        if (args.length % 2 != 0) {
065            throw new IllegalArgumentException("Invalid parameter list, "
066                + "must be of the form 'Class arg1, String arg1Name, Class arg2, String arg2Name...");
067        }
068        int nArgs = args.length / 2;
069        this.argNames = new ArrayList<String>(nArgs);
070        this.argTypes = new ArrayList<Class<?>>(nArgs);
071        for (int i = 0; i < nArgs; i++) {
072            this.argTypes.add((Class<?>) args[i * 2]);
073            this.argNames.add((String) args[i * 2 + 1]);
074        }
075
076        // find method in Proxy type
077        try {
078            this.method = proxyType.getMethod(name, argTypes.toArray(new Class[nArgs]));
079        } catch (NoSuchMethodException e) {
080            throw new IllegalArgumentException(
081                String.format("Missing method %s %s", name, argTypes.toString().replace('[', '(').replace(']', ')')),
082                e);
083        }
084    }
085
086    @Override
087    public String getName() {
088        return name;
089    }
090
091    @Override
092    public Class<?> getResultType() {
093        return resultType;
094    }
095
096    @Override
097    public List<String> getArgNames() {
098        return Collections.unmodifiableList(argNames);
099    }
100
101    @Override
102    public List<Class<?>> getArgTypes() {
103        return Collections.unmodifiableList(argTypes);
104    }
105
106    @Override
107    public Method getMethod() {
108        return method;
109    }
110
111    @Override
112    public String toString() {
113        StringBuilder builder = new StringBuilder();
114        builder.append("{")
115            .append("name=").append(name)
116            .append(", resultType=").append(resultType)
117            .append(", argNames=").append(argNames)
118            .append(", argTypes=").append(argTypes)
119            .append("}");
120        return builder.toString();
121    }
122}