Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/time/temporal/ValueRange.java
38918 views
/*1* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26* This file is available under and governed by the GNU General Public27* License version 2 only, as published by the Free Software Foundation.28* However, the following notice accompanied the original version of this29* file:30*31* Copyright (c) 2011-2012, Stephen Colebourne & Michael Nascimento Santos32*33* All rights reserved.34*35* Redistribution and use in source and binary forms, with or without36* modification, are permitted provided that the following conditions are met:37*38* * Redistributions of source code must retain the above copyright notice,39* this list of conditions and the following disclaimer.40*41* * Redistributions in binary form must reproduce the above copyright notice,42* this list of conditions and the following disclaimer in the documentation43* and/or other materials provided with the distribution.44*45* * Neither the name of JSR-310 nor the names of its contributors46* may be used to endorse or promote products derived from this software47* without specific prior written permission.48*49* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS50* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT51* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR52* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR53* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,54* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,55* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR56* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF57* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING58* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS59* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.60*/61package java.time.temporal;6263import java.io.IOException;64import java.io.InvalidObjectException;65import java.io.ObjectInputStream;66import java.io.Serializable;67import java.time.DateTimeException;6869/**70* The range of valid values for a date-time field.71* <p>72* All {@link TemporalField} instances have a valid range of values.73* For example, the ISO day-of-month runs from 1 to somewhere between 28 and 31.74* This class captures that valid range.75* <p>76* It is important to be aware of the limitations of this class.77* Only the minimum and maximum values are provided.78* It is possible for there to be invalid values within the outer range.79* For example, a weird field may have valid values of 1, 2, 4, 6, 7, thus80* have a range of '1 - 7', despite that fact that values 3 and 5 are invalid.81* <p>82* Instances of this class are not tied to a specific field.83*84* @implSpec85* This class is immutable and thread-safe.86*87* @since 1.888*/89public final class ValueRange implements Serializable {9091/**92* Serialization version.93*/94private static final long serialVersionUID = -7317881728594519368L;9596/**97* The smallest minimum value.98*/99private final long minSmallest;100/**101* The largest minimum value.102*/103private final long minLargest;104/**105* The smallest maximum value.106*/107private final long maxSmallest;108/**109* The largest maximum value.110*/111private final long maxLargest;112113/**114* Obtains a fixed value range.115* <p>116* This factory obtains a range where the minimum and maximum values are fixed.117* For example, the ISO month-of-year always runs from 1 to 12.118*119* @param min the minimum value120* @param max the maximum value121* @return the ValueRange for min, max, not null122* @throws IllegalArgumentException if the minimum is greater than the maximum123*/124public static ValueRange of(long min, long max) {125if (min > max) {126throw new IllegalArgumentException("Minimum value must be less than maximum value");127}128return new ValueRange(min, min, max, max);129}130131/**132* Obtains a variable value range.133* <p>134* This factory obtains a range where the minimum value is fixed and the maximum value may vary.135* For example, the ISO day-of-month always starts at 1, but ends between 28 and 31.136*137* @param min the minimum value138* @param maxSmallest the smallest maximum value139* @param maxLargest the largest maximum value140* @return the ValueRange for min, smallest max, largest max, not null141* @throws IllegalArgumentException if142* the minimum is greater than the smallest maximum,143* or the smallest maximum is greater than the largest maximum144*/145public static ValueRange of(long min, long maxSmallest, long maxLargest) {146return of(min, min, maxSmallest, maxLargest);147}148149/**150* Obtains a fully variable value range.151* <p>152* This factory obtains a range where both the minimum and maximum value may vary.153*154* @param minSmallest the smallest minimum value155* @param minLargest the largest minimum value156* @param maxSmallest the smallest maximum value157* @param maxLargest the largest maximum value158* @return the ValueRange for smallest min, largest min, smallest max, largest max, not null159* @throws IllegalArgumentException if160* the smallest minimum is greater than the smallest maximum,161* or the smallest maximum is greater than the largest maximum162* or the largest minimum is greater than the largest maximum163*/164public static ValueRange of(long minSmallest, long minLargest, long maxSmallest, long maxLargest) {165if (minSmallest > minLargest) {166throw new IllegalArgumentException("Smallest minimum value must be less than largest minimum value");167}168if (maxSmallest > maxLargest) {169throw new IllegalArgumentException("Smallest maximum value must be less than largest maximum value");170}171if (minLargest > maxLargest) {172throw new IllegalArgumentException("Minimum value must be less than maximum value");173}174return new ValueRange(minSmallest, minLargest, maxSmallest, maxLargest);175}176177/**178* Restrictive constructor.179*180* @param minSmallest the smallest minimum value181* @param minLargest the largest minimum value182* @param maxSmallest the smallest minimum value183* @param maxLargest the largest minimum value184*/185private ValueRange(long minSmallest, long minLargest, long maxSmallest, long maxLargest) {186this.minSmallest = minSmallest;187this.minLargest = minLargest;188this.maxSmallest = maxSmallest;189this.maxLargest = maxLargest;190}191192//-----------------------------------------------------------------------193/**194* Is the value range fixed and fully known.195* <p>196* For example, the ISO day-of-month runs from 1 to between 28 and 31.197* Since there is uncertainty about the maximum value, the range is not fixed.198* However, for the month of January, the range is always 1 to 31, thus it is fixed.199*200* @return true if the set of values is fixed201*/202public boolean isFixed() {203return minSmallest == minLargest && maxSmallest == maxLargest;204}205206//-----------------------------------------------------------------------207/**208* Gets the minimum value that the field can take.209* <p>210* For example, the ISO day-of-month always starts at 1.211* The minimum is therefore 1.212*213* @return the minimum value for this field214*/215public long getMinimum() {216return minSmallest;217}218219/**220* Gets the largest possible minimum value that the field can take.221* <p>222* For example, the ISO day-of-month always starts at 1.223* The largest minimum is therefore 1.224*225* @return the largest possible minimum value for this field226*/227public long getLargestMinimum() {228return minLargest;229}230231/**232* Gets the smallest possible maximum value that the field can take.233* <p>234* For example, the ISO day-of-month runs to between 28 and 31 days.235* The smallest maximum is therefore 28.236*237* @return the smallest possible maximum value for this field238*/239public long getSmallestMaximum() {240return maxSmallest;241}242243/**244* Gets the maximum value that the field can take.245* <p>246* For example, the ISO day-of-month runs to between 28 and 31 days.247* The maximum is therefore 31.248*249* @return the maximum value for this field250*/251public long getMaximum() {252return maxLargest;253}254255//-----------------------------------------------------------------------256/**257* Checks if all values in the range fit in an {@code int}.258* <p>259* This checks that all valid values are within the bounds of an {@code int}.260* <p>261* For example, the ISO month-of-year has values from 1 to 12, which fits in an {@code int}.262* By comparison, ISO nano-of-day runs from 1 to 86,400,000,000,000 which does not fit in an {@code int}.263* <p>264* This implementation uses {@link #getMinimum()} and {@link #getMaximum()}.265*266* @return true if a valid value always fits in an {@code int}267*/268public boolean isIntValue() {269return getMinimum() >= Integer.MIN_VALUE && getMaximum() <= Integer.MAX_VALUE;270}271272/**273* Checks if the value is within the valid range.274* <p>275* This checks that the value is within the stored range of values.276*277* @param value the value to check278* @return true if the value is valid279*/280public boolean isValidValue(long value) {281return (value >= getMinimum() && value <= getMaximum());282}283284/**285* Checks if the value is within the valid range and that all values286* in the range fit in an {@code int}.287* <p>288* This method combines {@link #isIntValue()} and {@link #isValidValue(long)}.289*290* @param value the value to check291* @return true if the value is valid and fits in an {@code int}292*/293public boolean isValidIntValue(long value) {294return isIntValue() && isValidValue(value);295}296297/**298* Checks that the specified value is valid.299* <p>300* This validates that the value is within the valid range of values.301* The field is only used to improve the error message.302*303* @param value the value to check304* @param field the field being checked, may be null305* @return the value that was passed in306* @see #isValidValue(long)307*/308public long checkValidValue(long value, TemporalField field) {309if (isValidValue(value) == false) {310throw new DateTimeException(genInvalidFieldMessage(field, value));311}312return value;313}314315/**316* Checks that the specified value is valid and fits in an {@code int}.317* <p>318* This validates that the value is within the valid range of values and that319* all valid values are within the bounds of an {@code int}.320* The field is only used to improve the error message.321*322* @param value the value to check323* @param field the field being checked, may be null324* @return the value that was passed in325* @see #isValidIntValue(long)326*/327public int checkValidIntValue(long value, TemporalField field) {328if (isValidIntValue(value) == false) {329throw new DateTimeException(genInvalidFieldMessage(field, value));330}331return (int) value;332}333334private String genInvalidFieldMessage(TemporalField field, long value) {335if (field != null) {336return "Invalid value for " + field + " (valid values " + this + "): " + value;337} else {338return "Invalid value (valid values " + this + "): " + value;339}340}341342//-----------------------------------------------------------------------343/**344* Restore the state of an ValueRange from the stream.345* Check that the values are valid.346*347* @param s the stream to read348* @throws InvalidObjectException if349* the smallest minimum is greater than the smallest maximum,350* or the smallest maximum is greater than the largest maximum351* or the largest minimum is greater than the largest maximum352* @throws ClassNotFoundException if a class cannot be resolved353*/354private void readObject(ObjectInputStream s)355throws IOException, ClassNotFoundException, InvalidObjectException356{357s.defaultReadObject();358if (minSmallest > minLargest) {359throw new InvalidObjectException("Smallest minimum value must be less than largest minimum value");360}361if (maxSmallest > maxLargest) {362throw new InvalidObjectException("Smallest maximum value must be less than largest maximum value");363}364if (minLargest > maxLargest) {365throw new InvalidObjectException("Minimum value must be less than maximum value");366}367}368369//-----------------------------------------------------------------------370/**371* Checks if this range is equal to another range.372* <p>373* The comparison is based on the four values, minimum, largest minimum,374* smallest maximum and maximum.375* Only objects of type {@code ValueRange} are compared, other types return false.376*377* @param obj the object to check, null returns false378* @return true if this is equal to the other range379*/380@Override381public boolean equals(Object obj) {382if (obj == this) {383return true;384}385if (obj instanceof ValueRange) {386ValueRange other = (ValueRange) obj;387return minSmallest == other.minSmallest && minLargest == other.minLargest &&388maxSmallest == other.maxSmallest && maxLargest == other.maxLargest;389}390return false;391}392393/**394* A hash code for this range.395*396* @return a suitable hash code397*/398@Override399public int hashCode() {400long hash = minSmallest + (minLargest << 16) + (minLargest >> 48) +401(maxSmallest << 32) + (maxSmallest >> 32) + (maxLargest << 48) +402(maxLargest >> 16);403return (int) (hash ^ (hash >>> 32));404}405406//-----------------------------------------------------------------------407/**408* Outputs this range as a {@code String}.409* <p>410* The format will be '{min}/{largestMin} - {smallestMax}/{max}',411* where the largestMin or smallestMax sections may be omitted, together412* with associated slash, if they are the same as the min or max.413*414* @return a string representation of this range, not null415*/416@Override417public String toString() {418StringBuilder buf = new StringBuilder();419buf.append(minSmallest);420if (minSmallest != minLargest) {421buf.append('/').append(minLargest);422}423buf.append(" - ").append(maxSmallest);424if (maxSmallest != maxLargest) {425buf.append('/').append(maxLargest);426}427return buf.toString();428}429430}431432433