blob: 50a31a122382eecb1e27a7addae9f4c022525fd2 [file] [log] [blame]
// Copyright 2007, 2008 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package org.apache.tapestry5.ioc.util;
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Used to represent a period of time, specifically as a configuration value. This is often used to specify timeouts.
* <p/>
* TimePeriods are parsed from strings.
* <p/>
* The string specifys a number of terms. The values of all the terms are summed together to form the total time period.
* Each term consists of a number followed by a unit. Units (from largest to smallest) are: <dl> <dt>y <dd>year <dt>d
* <dd>day <dt>h <dd>hour <dt>m <dd>minute <dt>s <dd>second <dt>ms <dd>millisecond </dl> <p> Example: "2 h 30 m". By
* convention, terms are specified largest to smallest. A term without a unit is assumed to be milliseconds. Units are
* case insensitive ("h" or "H" are treated the same).
*/
public class TimeInterval
{
private static final Map<String, Long> UNITS = CollectionFactory.newCaseInsensitiveMap();
private static final long MILLISECOND = 1000l;
static
{
UNITS.put("ms", 1l);
UNITS.put("s", MILLISECOND);
UNITS.put("m", 60 * MILLISECOND);
UNITS.put("h", 60 * UNITS.get("m"));
UNITS.put("d", 24 * UNITS.get("h"));
UNITS.put("y", 365 * UNITS.get("d"));
}
private static final Pattern PATTERN = Pattern.compile("\\s*(\\d+)\\s*([a-z]*)", Pattern.CASE_INSENSITIVE);
private final long milliseconds;
/**
* Creates a TimeInterval for a string.
*
* @param input the string specifying the amount of time in the period
*/
public TimeInterval(String input)
{
milliseconds = parseMilliseconds(input);
}
public long milliseconds()
{
return milliseconds;
}
public long seconds()
{
return milliseconds / MILLISECOND;
}
static long parseMilliseconds(String input)
{
long milliseconds = 0l;
Matcher matcher = PATTERN.matcher(input);
matcher.useAnchoringBounds(true);
// TODO: Notice non matching characters and reject input, including at end
int lastMatchEnd = -1;
while (matcher.find())
{
int start = matcher.start();
if (lastMatchEnd + 1 < start)
{
String invalid = input.substring(lastMatchEnd + 1, start);
throw new RuntimeException(UtilMessages.invalidTimeIntervalInput(invalid, input));
}
lastMatchEnd = matcher.end();
long count = Long.parseLong(matcher.group(1));
String units = matcher.group(2);
if (units.length() == 0)
{
milliseconds += count;
continue;
}
Long unitValue = UNITS.get(units);
if (unitValue == null)
throw new RuntimeException(UtilMessages.invalidTimeIntervalUnit(units, input, UNITS.keySet()));
milliseconds += count * unitValue;
}
if (lastMatchEnd + 1 < input.length())
{
String invalid = input.substring(lastMatchEnd + 1);
throw new RuntimeException(UtilMessages.invalidTimeIntervalInput(invalid, input));
}
return milliseconds;
}
@Override
public String toString()
{
return String.format("TimeInterval[%d ms]", milliseconds);
}
@Override
public boolean equals(Object obj)
{
if (obj == null) return false;
if (obj instanceof TimeInterval)
{
TimeInterval tp = (TimeInterval) obj;
return milliseconds == tp.milliseconds;
}
return false;
}
}