All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.micrometer.core.instrument.config.validate.DurationValidator Maven / Gradle / Ivy

There is a newer version: 1.13.0
Show newest version
/**
 * Copyright 2020 VMware, Inc.
 * 

* 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 *

* https://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 io.micrometer.core.instrument.config.validate; import io.micrometer.core.annotation.Incubating; import io.micrometer.core.instrument.util.StringUtils; import io.micrometer.core.lang.Nullable; import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; /** * Validator for {@link Duration}. * * @author Jon Schneider * @since 1.5.0 */ @Incubating(since = "1.5.0") public enum DurationValidator { /** * Human readable formatting, for example '1s'. */ SIMPLE("^\\s*(([\\+]?\\d+)(\\.\\d*)?)\\s*([a-zA-Z]{0,2})\\s*", "^\\s*([\\+]?\\d{0,3}([_,]?\\d{3})*(\\.\\d*)?)\\s*([a-zA-Z]{0,2})\\s*") { @Override protected Validated doParse(String property, String value) { Matcher matcher = patterns.get(0).matcher(value.toLowerCase().replaceAll("[,_\\s]", "")); if (!matcher.matches()) { return Validated.invalid(property, value, "must be a valid duration", InvalidReason.MALFORMED); } String unit = matcher.group(4); if (StringUtils.isBlank(unit)) { return Validated.invalid(property, value, "must have a valid duration unit", InvalidReason.MALFORMED); } int e = 0; Double amount = Double.valueOf(matcher.group(1)); while (e < 18 && Math.abs(amount - amount.longValue()) > 1e-10) { amount *= 10; e++; } long multipliedResult = amount.longValue(); long multipliedFactor = (long) Math.pow(10, e); return validateChronoUnit(property, value, unit) .map(cu -> Duration.of(multipliedResult, cu).dividedBy(multipliedFactor)); } }, ISO8601("^[\\+\\-]?P.*$") { @Override protected Validated doParse(String property, String value) { try { return Validated.valid(property, Duration.parse(value)); } catch (Exception ex) { return Validated.invalid(property, value, "must be a valid ISO-8601 duration like 'PT10S'", InvalidReason.MALFORMED, ex); } } }; protected final List patterns; DurationValidator(String... patterns) { this.patterns = Arrays.stream(patterns).map(Pattern::compile).collect(Collectors.toList()); } /** * Detect the style then parse the value to return a duration. * * @param property The configuration property this duration belongs to * @param value The value to parse * @return the parsed duration */ public static Validated validate(String property, @Nullable String value) { return value == null ? Validated.valid(property, null) : detect(property, value).flatMap(validator -> validator.doParse(property, value)); } /** * Parse the given value to a duration. * * @param property The configuration property this duration belongs to * @param value The value to parse * @return a duration */ protected abstract Validated doParse(String property, String value); /** * Detect the style from the given source value. * * @param value the source value * @return the duration style */ private static Validated detect(String property, @Nullable String value) { if (value == null || StringUtils.isBlank(value)) { return Validated.invalid(property, value, "must be a valid duration value", value == null ? InvalidReason.MISSING : InvalidReason.MALFORMED); } for (DurationValidator candidate : values()) { if (candidate.patterns.stream().anyMatch(p -> p.matcher(value).matches())) { return Validated.valid(property, candidate); } } return Validated.invalid(property, value, "must be a valid duration value", InvalidReason.MALFORMED); } public static Validated validateTimeUnit(String property, @Nullable String unit) { return validateChronoUnit(property, unit, unit) .flatMap(cu -> toTimeUnit(property, cu)); } /** * Validate a unit that is potentially part of a larger string including the magnitude of time. * * @param property The property that is a {@link Duration} or unit. * @param value The whole string including magnitude. * @param unit The unit portion of the string. * @return A validated unit. */ public static Validated validateChronoUnit(String property, @Nullable String value, @Nullable String unit) { if (unit == null) { return Validated.valid(property, null); } switch (unit.toLowerCase()) { case "ns": case "nanoseconds": case "nanosecond": case "nanos": return Validated.valid(property, ChronoUnit.NANOS); case "us": case "microseconds": case "microsecond": case "micros": return Validated.valid(property, ChronoUnit.MICROS); case "ms": case "milliseconds": case "millisecond": case "millis": return Validated.valid(property, ChronoUnit.MILLIS); case "s": case "seconds": case "second": case "secs": case "sec": return Validated.valid(property, ChronoUnit.SECONDS); case "m": case "minutes": case "minute": case "mins": case "min": return Validated.valid(property, ChronoUnit.MINUTES); case "h": case "hours": case "hour": return Validated.valid(property, ChronoUnit.HOURS); case "d": case "days": case "day": return Validated.valid(property, ChronoUnit.DAYS); default: return Validated.invalid(property, value, "must contain a valid time unit", InvalidReason.MALFORMED); } } private static Validated toTimeUnit(String property, @Nullable ChronoUnit chronoUnit) { if (chronoUnit == null) { return Validated.valid(property, null); } switch (chronoUnit) { case NANOS: return Validated.valid(property, TimeUnit.NANOSECONDS); case MICROS: return Validated.valid(property, TimeUnit.MICROSECONDS); case MILLIS: return Validated.valid(property, TimeUnit.MILLISECONDS); case SECONDS: return Validated.valid(property, TimeUnit.SECONDS); case MINUTES: return Validated.valid(property, TimeUnit.MINUTES); case HOURS: return Validated.valid(property, TimeUnit.HOURS); case DAYS: return Validated.valid(property, TimeUnit.DAYS); default: return Validated.invalid(property, chronoUnit.toString(), "must be a valid time unit", InvalidReason.MALFORMED); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy