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.util.HashMap;
020import java.util.Map;
021import java.util.Set;
022
023import org.apache.camel.Exchange;
024import org.apache.camel.Processor;
025import org.apache.camel.impl.ScheduledPollConsumer;
026import org.apache.camel.util.ObjectHelper;
027import org.slf4j.Logger;
028import org.slf4j.LoggerFactory;
029
030/**
031 * Abstract base class for API Component Consumers.
032 */
033public abstract class AbstractApiConsumer<E extends Enum<E> & ApiName, T>
034    extends ScheduledPollConsumer implements PropertyNamesInterceptor, PropertiesInterceptor, ResultInterceptor {
035
036    // logger
037    protected final Logger log = LoggerFactory.getLogger(getClass());
038
039    // API Endpoint
040    protected final AbstractApiEndpoint<E, T> endpoint;
041
042    // API method to invoke
043    protected final ApiMethod method;
044
045    // split Array or Collection API method results into multiple Exchanges
046    private boolean splitResult = true;
047
048    public AbstractApiConsumer(AbstractApiEndpoint<E, T> endpoint, Processor processor) {
049        super(endpoint, processor);
050
051        this.endpoint = endpoint;
052        this.method = ApiConsumerHelper.findMethod(endpoint, this);
053    }
054
055    @Override
056    public boolean isGreedy() {
057        // make this consumer not greedy to avoid making too many calls
058        return false;
059    }
060
061    @Override
062    protected int poll() throws Exception {
063        // invoke the consumer method
064        final Map<String, Object> args = new HashMap<>();
065        args.putAll(endpoint.getEndpointProperties());
066
067        // let the endpoint and the Consumer intercept properties
068        endpoint.interceptProperties(args);
069        interceptProperties(args);
070
071        try {
072
073            Object result = doInvokeMethod(args);
074            return ApiConsumerHelper.getResultsProcessed(this, result, isSplitResult());
075
076        } catch (Throwable t) {
077            throw ObjectHelper.wrapRuntimeCamelException(t);
078        }
079    }
080
081    @Override
082    public void interceptPropertyNames(Set<String> propertyNames) {
083        // do nothing by default
084    }
085
086    @Override
087    public void interceptProperties(Map<String, Object> properties) {
088        // do nothing by default
089    }
090
091    /**
092     * Invoke the API method.
093     * This method can be overridden, for example to synchronize API calls for thread-unsafe proxies.
094     * Derived class MUST call super.doInvokeMethod() to invoke the API method.
095     * @param args method arguments from endpoint parameters.
096     * @return method invocation result.
097     */
098    protected Object doInvokeMethod(Map<String, Object> args) {
099        return ApiMethodHelper.invokeMethod(endpoint.getApiProxy(method, args), method, args);
100    }
101
102    @Override
103    public Object splitResult(Object result) {
104        return result;
105    }
106
107    @Override
108    public void interceptResult(Object result, Exchange resultExchange) {
109        // do nothing by default
110    }
111
112    public final boolean isSplitResult() {
113        return splitResult;
114    }
115
116    public final void setSplitResult(boolean splitResult) {
117        this.splitResult = splitResult;
118    }
119}