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.processor;
018
019import org.apache.camel.AsyncCallback;
020import org.apache.camel.Exchange;
021import org.apache.camel.Predicate;
022import org.apache.camel.Processor;
023import org.apache.camel.Traceable;
024import org.apache.camel.spi.IdAware;
025import org.apache.camel.util.ServiceHelper;
026import org.slf4j.Logger;
027import org.slf4j.LoggerFactory;
028
029/**
030 * The processor which implements the
031 * <a href="http://camel.apache.org/message-filter.html">Message Filter</a> EIP pattern.
032 *
033 * @version 
034 */
035public class FilterProcessor extends DelegateAsyncProcessor implements Traceable, IdAware {
036    private static final Logger LOG = LoggerFactory.getLogger(FilterProcessor.class);
037    private String id;
038    private final Predicate predicate;
039    private transient long filtered;
040
041    public FilterProcessor(Predicate predicate, Processor processor) {
042        super(processor);
043        this.predicate = predicate;
044    }
045
046    @Override
047    public boolean process(Exchange exchange, AsyncCallback callback) {
048        boolean matches = false;
049
050        try {
051            matches = matches(exchange);
052        } catch (Exception e) {
053            exchange.setException(e);
054        }
055
056        if (matches) {
057            return processor.process(exchange, callback);
058        } else {
059            callback.done(true);
060            return true;
061        }
062    }
063
064    public boolean matches(Exchange exchange) {
065        boolean matches = predicate.matches(exchange);
066
067        LOG.debug("Filter matches: {} for exchange: {}", matches, exchange);
068
069        // set property whether the filter matches or not
070        exchange.setProperty(Exchange.FILTER_MATCHED, matches);
071
072        if (matches) {
073            filtered++;
074        }
075
076        return matches;
077    }
078
079    @Override
080    public String toString() {
081        return "Filter[if: " + predicate + " do: " + getProcessor() + "]";
082    }
083
084    public String getId() {
085        return id;
086    }
087
088    public void setId(String id) {
089        this.id = id;
090    }
091
092    public String getTraceLabel() {
093        return "filter[if: " + predicate + "]";
094    }
095
096    public Predicate getPredicate() {
097        return predicate;
098    }
099
100    /**
101     * Gets the number of Exchanges that matched the filter predicate and therefore as filtered.
102     */
103    public long getFilteredCount() {
104        return filtered;
105    }
106
107    /**
108     * Reset counters.
109     */
110    public void reset() {
111        filtered = 0;
112    }
113
114    @Override
115    protected void doStart() throws Exception {
116        super.doStart();
117        // restart counter
118        reset();
119        ServiceHelper.startService(predicate);
120    }
121
122    @Override
123    protected void doStop() throws Exception {
124        ServiceHelper.stopService(predicate);
125        super.doStop();
126    }
127}