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