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