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.impl;
018
019import java.util.ArrayList;
020import java.util.List;
021
022import org.apache.camel.Consumer;
023import org.apache.camel.Endpoint;
024import org.apache.camel.Navigate;
025import org.apache.camel.Processor;
026import org.apache.camel.RouteAware;
027import org.apache.camel.Service;
028import org.apache.camel.SuspendableService;
029import org.apache.camel.spi.IdAware;
030import org.apache.camel.spi.RouteContext;
031import org.apache.camel.util.EndpointHelper;
032
033/**
034 * A {@link DefaultRoute} which starts with an
035 * <a href="http://camel.apache.org/event-driven-consumer.html">Event Driven Consumer</a>
036 * <p/>
037 * Use the API from {@link org.apache.camel.CamelContext} to control the lifecycle of a route,
038 * such as starting and stopping using the {@link org.apache.camel.CamelContext#startRoute(String)}
039 * and {@link org.apache.camel.CamelContext#stopRoute(String)} methods.
040 *
041 * @version 
042 */
043public class EventDrivenConsumerRoute extends DefaultRoute {
044    private final Processor processor;
045    private Consumer consumer;
046
047    public EventDrivenConsumerRoute(RouteContext routeContext, Endpoint endpoint, Processor processor) {
048        super(routeContext, endpoint);
049        this.processor = processor;
050    }
051
052    @Override
053    public String toString() {
054        return "EventDrivenConsumerRoute[" + getEndpoint() + " -> " + processor + "]";
055    }
056
057    public Processor getProcessor() {
058        return processor;
059    }
060
061    /**
062     * Factory method to lazily create the complete list of services required for this route
063     * such as adding the processor or consumer
064     */
065    @Override
066    protected void addServices(List<Service> services) throws Exception {
067        Endpoint endpoint = getEndpoint();
068        consumer = endpoint.createConsumer(processor);
069        if (consumer != null) {
070            services.add(consumer);
071            if (consumer instanceof RouteAware) {
072                ((RouteAware) consumer).setRoute(this);
073            }
074        }
075        Processor processor = getProcessor();
076        if (processor instanceof Service) {
077            services.add((Service)processor);
078        }
079    }
080
081    @SuppressWarnings("unchecked")
082    public Navigate<Processor> navigate() {
083        Processor answer = getProcessor();
084
085        // we want navigating routes to be easy, so skip the initial channel
086        // and navigate to its output where it all starts from end user point of view
087        if (answer instanceof Navigate) {
088            Navigate<Processor> nav = (Navigate<Processor>) answer;
089            if (nav.next().size() == 1) {
090                Object first = nav.next().get(0);
091                if (first instanceof Navigate) {
092                    return (Navigate<Processor>) first;
093                }
094            }
095            return (Navigate<Processor>) answer;
096        }
097        return null;
098    }
099
100    @SuppressWarnings("unchecked")
101    public List<Processor> filter(String pattern) {
102        List<Processor> match = new ArrayList<Processor>();
103        doFilter(pattern, navigate(), match);
104        return match;
105    }
106
107    @SuppressWarnings("unchecked")
108    private void doFilter(String pattern, Navigate<Processor> nav, List<Processor> match) {
109        List<Processor> list = nav.next();
110        if (list != null) {
111            for (Processor proc : list) {
112                String id = null;
113                if (proc instanceof IdAware) {
114                    id = ((IdAware) proc).getId();
115                }
116                if (EndpointHelper.matchPattern(id, pattern)) {
117                    match.add(proc);
118                }
119                if (proc instanceof Navigate) {
120                    Navigate<Processor> child = (Navigate<Processor>) proc;
121                    doFilter(pattern, child, match);
122                }
123            }
124        }
125    }
126
127    public Consumer getConsumer() {
128        return consumer;
129    }
130
131    public boolean supportsSuspension() {
132        return consumer instanceof SuspendableService;
133    }
134}