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.model;
018
019import java.util.Locale;
020import java.util.concurrent.TimeUnit;
021
022import javax.xml.bind.annotation.XmlAccessType;
023import javax.xml.bind.annotation.XmlAccessorType;
024import javax.xml.bind.annotation.XmlAttribute;
025import javax.xml.bind.annotation.XmlRootElement;
026import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
027
028import org.apache.camel.Processor;
029import org.apache.camel.builder.xml.TimeUnitAdapter;
030import org.apache.camel.processor.SamplingThrottler;
031import org.apache.camel.spi.Metadata;
032import org.apache.camel.spi.RouteContext;
033
034/**
035 * Extract a sample of the messages passing through a route
036 *
037 * @version 
038 */
039@Metadata(label = "eip,routing")
040@XmlRootElement(name = "sample")
041@XmlAccessorType(XmlAccessType.FIELD)
042public class SamplingDefinition extends OutputDefinition<SamplingDefinition> {
043
044    // use Long to let it be optional in JAXB so when using XML the default is 1 second
045
046    // TODO: Camel 3.0 Should extend NoOutputDefinition
047
048    @XmlAttribute @Metadata(defaultValue = "1")
049    private Long samplePeriod;
050    @XmlAttribute
051    private Long messageFrequency;
052    @XmlAttribute
053    @XmlJavaTypeAdapter(TimeUnitAdapter.class) @Metadata(defaultValue = "SECONDS")
054    private TimeUnit units;
055
056    public SamplingDefinition() {
057    }
058
059    public SamplingDefinition(long samplePeriod, TimeUnit units) {
060        this.samplePeriod = samplePeriod;
061        this.units = units;
062    }
063
064    public SamplingDefinition(long messageFrequency) {
065        this.messageFrequency = messageFrequency;
066    }
067    
068    @Override
069    public String toString() {
070        return "Sample[" + description() + " -> " + getOutputs() + "]";
071    }
072    
073    protected String description() {
074        if (messageFrequency != null) {
075            return "1 Exchange per " + getMessageFrequency() + " messages received";
076        } else {
077            TimeUnit tu = getUnits() != null ? getUnits() : TimeUnit.SECONDS;
078            return "1 Exchange per " + getSamplePeriod() + " " + tu.toString().toLowerCase(Locale.ENGLISH);
079        }
080    }
081
082    @Override
083    public String getLabel() {
084        return "sample[" + description() + "]";
085    }
086
087    @Override
088    public Processor createProcessor(RouteContext routeContext) throws Exception {
089        Processor childProcessor = this.createChildProcessor(routeContext, true);
090        
091        if (messageFrequency != null) {
092            return new SamplingThrottler(childProcessor, messageFrequency);
093        } else {
094            // should default be 1 sample period
095            long time = getSamplePeriod() != null ? getSamplePeriod() : 1L;
096            // should default be in seconds
097            TimeUnit tu = getUnits() != null ? getUnits() : TimeUnit.SECONDS;
098            return new SamplingThrottler(childProcessor, time, tu);
099        }
100    }
101
102    // Fluent API
103    // -------------------------------------------------------------------------
104
105    /**
106     * Sets the sample message count which only a single {@link org.apache.camel.Exchange} will pass through after this many received.
107     *
108     * @param messageFrequency 
109     * @return the builder
110     */
111    public SamplingDefinition sampleMessageFrequency(long messageFrequency) {
112        setMessageFrequency(messageFrequency);
113        return this;
114    }
115    
116    /**
117     * Sets the sample period during which only a single {@link org.apache.camel.Exchange} will pass through.
118     *
119     * @param samplePeriod the period
120     * @return the builder
121     */
122    public SamplingDefinition samplePeriod(long samplePeriod) {
123        setSamplePeriod(samplePeriod);
124        return this;
125    }
126
127    /**
128     * Sets the time units for the sample period, defaulting to seconds.
129     *
130     * @param units the time unit of the sample period.
131     * @return the builder
132     */
133    public SamplingDefinition timeUnits(TimeUnit units) {
134        setUnits(units);
135        return this;
136    }
137
138    // Properties
139    // -------------------------------------------------------------------------
140
141    public Long getSamplePeriod() {
142        return samplePeriod;
143    }
144
145    /**
146     * Sets the sample period during which only a single Exchange will pass through.
147     */
148    public void setSamplePeriod(Long samplePeriod) {
149        this.samplePeriod = samplePeriod;
150    }
151
152    public Long getMessageFrequency() {
153        return messageFrequency;
154    }
155
156    /**
157     * Sets the sample message count which only a single Exchange will pass through after this many received.
158     */
159    public void setMessageFrequency(Long messageFrequency) {
160        this.messageFrequency = messageFrequency;
161    }
162
163    /**
164     * Sets the time units for the sample period, defaulting to seconds.
165     */
166    public void setUnits(String units) {
167        this.units = TimeUnit.valueOf(units);
168    }
169
170    /**
171     * Sets the time units for the sample period, defaulting to seconds.
172     */
173    public void setUnits(TimeUnit units) {
174        this.units = units;
175    }
176
177    public TimeUnit getUnits() {
178        return units;
179    }
180}