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     */
017    package org.apache.camel.converter;
018    
019    import java.util.regex.Matcher;
020    import java.util.regex.Pattern;
021    
022    import org.apache.camel.Converter;
023    import org.slf4j.Logger;
024    import org.slf4j.LoggerFactory;
025    
026    @Converter
027    public final class TimePatternConverter {   
028        private static final Logger LOG = LoggerFactory.getLogger(TimePatternConverter.class);
029        private static final String NUMBERS_ONLY_STRING_PATTERN = "^[-]?(\\d)+$";
030        private static final String REPLACEMENT_PATTERN = "[our|inute|econd](s)?";
031        private static final String HOUR_REGEX_PATTERN = "((\\d)*(\\d))[h|H]";
032        private static final String MINUTES_REGEX_PATTERN = "((\\d)*(\\d))[m|M]";
033        private static final String SECONDS_REGEX_PATTERN = "((\\d)*(\\d))[s|S]";
034    
035        /**
036         * Utility classes should not have a public constructor.
037         */
038        private TimePatternConverter() {
039        }
040        
041        @Converter
042        public static long toMilliSeconds(String source) throws IllegalArgumentException {
043            long milliseconds = 0;
044            boolean foundFlag = false;
045            Matcher matcher;
046    
047            matcher = createMatcher(NUMBERS_ONLY_STRING_PATTERN, source);
048            if (matcher.find()) {
049                // Note: This will also be used for regular numeric strings. 
050                //       This String -> long converter will be used for all strings.
051                milliseconds = Long.valueOf(source).longValue();
052            } else {            
053                matcher = createMatcher(REPLACEMENT_PATTERN, source);
054                String replacedSource = matcher.replaceAll(""); 
055                
056                LOG.trace("Replaced original source {} to {}", source, replacedSource);
057                
058                matcher = createMatcher(HOUR_REGEX_PATTERN, replacedSource);
059                if (matcher.find()) {
060                    milliseconds = milliseconds + (3600000 * Long.valueOf(matcher.group(1)).longValue());
061                    foundFlag = true;
062                }
063                
064                matcher = createMatcher(MINUTES_REGEX_PATTERN, replacedSource);            
065                if (matcher.find()) {
066                    long minutes = Long.valueOf(matcher.group(1)).longValue();
067                    if ((minutes > 59) && foundFlag) {
068                        throw new IllegalArgumentException("Minutes should contain a valid value between 0 and 59: " + source);
069                    }
070                    foundFlag = true;
071                    milliseconds = milliseconds + (60000 * minutes);
072                }
073                   
074                matcher = createMatcher(SECONDS_REGEX_PATTERN, replacedSource);
075                if (matcher.find()) {
076                    long seconds = Long.valueOf(matcher.group(1)).longValue();
077                    if ((seconds > 59) && foundFlag) {
078                        throw new IllegalArgumentException("Seconds should contain a valid value between 0 and 59: " + source);
079                    }
080                    foundFlag = true;
081                    milliseconds = milliseconds + (1000 * seconds);
082                }      
083                
084                // No pattern matched... initiating fallback check and conversion (if required). 
085                // The source at this point may contain illegal values or special characters 
086                if (!foundFlag) {
087                    milliseconds = Long.valueOf(source).longValue();
088                }
089            }       
090            
091            LOG.trace("source: {} milliseconds: ", source, milliseconds);
092            
093            return milliseconds;
094        }
095    
096        private static Matcher createMatcher(String regexPattern, String source) {
097            Pattern pattern = Pattern.compile(regexPattern, Pattern.CASE_INSENSITIVE);
098            return pattern.matcher(source);        
099        }    
100    }