diff --git a/docs/release-notes.html b/docs/release-notes.html index 15c4b5e94..639ad7098 100644 --- a/docs/release-notes.html +++ b/docs/release-notes.html @@ -38,6 +38,22 @@

Version 6.0.11



+
  • + Added new BinarySizeUnit and DecimalSizeUnit enums that can be used when working + with data sizes in a variety of units, including bytes, kilobytes, megabytes, + gigabytes, terabytes, petabytes, exabytes, zettabytes, and yottabytes. These + enums provide methods for determining the number of bytes in a specified number + of instances of the given unit, determining the number of instances of a unit + represented by a given number of bytes, and generating a human-readable string + representation of a given number of bytes using the unit deemed most appropriate. + The BinarySizeUnit enum assumes that each unit is 1024 times larger than the next + smaller unit (e.g., so one kilobyte is 1024 bytes, one megabyte is 1024 + kilobytes, etc.), while the DecimalSizeUnit enum assumes that each unit is 1000 + times larger than the next smaller unit (e.g., so one kilobyte is 1000 bytes, one + megabyte is 1000 kilobytes, etc.). +

    +
  • +
  • Updated client-side support for the LDIF export administrative task in the Ping Identity Directory Server to allow requesting that the server invoke one or more diff --git a/messages/unboundid-ldapsdk-util.properties b/messages/unboundid-ldapsdk-util.properties index 14f691efe..224f55ded 100644 --- a/messages/unboundid-ldapsdk-util.properties +++ b/messages/unboundid-ldapsdk-util.properties @@ -1253,3 +1253,30 @@ ERR_GET_NON_FIPS_BC_CLASS_LOADER_NO_JARS_FOUND=Unable to create a class \ ERR_PROXY_SF_CANNOT_CREATE_UNCONNECTED_SOCKET=Unable to create an unconnected \ socket for communication through a proxy server when an SSLSocketFactory \ has been configured. +INFO_SIZE_UNIT_BYTES_SINGULAR=byte +INFO_SIZE_UNIT_BYTES_PLURAL=bytes +INFO_SIZE_UNIT_BYTES_ABBREVIATION=B +INFO_SIZE_UNIT_KILOBYTES_SINGULAR=kilobyte +INFO_SIZE_UNIT_KILOBYTES_PLURAL=kilobytes +INFO_SIZE_UNIT_KILOBYTES_ABBREVIATION=KB +INFO_SIZE_UNIT_MEGABYTES_SINGULAR=megabyte +INFO_SIZE_UNIT_MEGABYTES_PLURAL=megabytes +INFO_SIZE_UNIT_MEGABYTES_ABBREVIATION=MB +INFO_SIZE_UNIT_GIGABYTES_SINGULAR=gigabyte +INFO_SIZE_UNIT_GIGABYTES_PLURAL=gigabytes +INFO_SIZE_UNIT_GIGABYTES_ABBREVIATION=GB +INFO_SIZE_UNIT_TERABYTES_SINGULAR=terabyte +INFO_SIZE_UNIT_TERABYTES_PLURAL=terabytes +INFO_SIZE_UNIT_TERABYTES_ABBREVIATION=TB +INFO_SIZE_UNIT_PETABYTES_SINGULAR=petabyte +INFO_SIZE_UNIT_PETABYTES_PLURAL=petabytes +INFO_SIZE_UNIT_PETABYTES_ABBREVIATION=PB +INFO_SIZE_UNIT_EXABYTES_SINGULAR=exabyte +INFO_SIZE_UNIT_EXABYTES_PLURAL=exabytes +INFO_SIZE_UNIT_EXABYTES_ABBREVIATION=EB +INFO_SIZE_UNIT_ZETTABYTES_SINGULAR=zettabyte +INFO_SIZE_UNIT_ZETTABYTES_PLURAL=zettabytes +INFO_SIZE_UNIT_ZETTABYTES_ABBREVIATION=ZB +INFO_SIZE_UNIT_YOTTABYTES_SINGULAR=yottabyte +INFO_SIZE_UNIT_YOTTABYTES_PLURAL=yottabytes +INFO_SIZE_UNIT_YOTTABYTES_ABBREVIATION=YB diff --git a/src/com/unboundid/util/BinarySizeUnit.java b/src/com/unboundid/util/BinarySizeUnit.java new file mode 100644 index 000000000..e9f051b61 --- /dev/null +++ b/src/com/unboundid/util/BinarySizeUnit.java @@ -0,0 +1,519 @@ +/* + * Copyright 2023 Ping Identity Corporation + * All Rights Reserved. + */ +/* + * Copyright 2023 Ping Identity Corporation + * + * 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. + */ +/* + * Copyright (C) 2023 Ping Identity Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (GPLv2 only) + * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +package com.unboundid.util; + + + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.RoundingMode; + +import static com.unboundid.util.UtilityMessages.*; + + + +/** + * This enum defines a set of size units that can be used to represent data + * sizes in varying units (bytes, kilobytes, megabytes, gigabytes, etc.). This + * class uses binary-based values rather than decimal-based values, so each + * unit is 1024 times larger than the previous (for example, one kilobyte is + * interpreted as 1024 bytes rather than 1000 bytes). + */ +public enum BinarySizeUnit +{ + /** + * The size unit that represents bytes. + */ + BYTES(BigInteger.valueOf(1L), + INFO_SIZE_UNIT_BYTES_SINGULAR.get(), + INFO_SIZE_UNIT_BYTES_PLURAL.get(), + INFO_SIZE_UNIT_BYTES_ABBREVIATION.get()), + + + + /** + * The size unit that represents kilobytes. Each kilobyte is 1024 bytes. + */ + KILOBYTES(BigInteger.valueOf(1_024L), + INFO_SIZE_UNIT_KILOBYTES_SINGULAR.get(), + INFO_SIZE_UNIT_KILOBYTES_PLURAL.get(), + INFO_SIZE_UNIT_KILOBYTES_ABBREVIATION.get()), + + + + /** + * The size unit that represents megabytes. Each megabyte is 1024 kilobytes. + */ + MEGABYTES(BigInteger.valueOf(1_048_576L), + INFO_SIZE_UNIT_MEGABYTES_SINGULAR.get(), + INFO_SIZE_UNIT_MEGABYTES_PLURAL.get(), + INFO_SIZE_UNIT_MEGABYTES_ABBREVIATION.get()), + + + + /** + * The size unit that represents gigabytes. Each gigabyte is 1024 megabytes. + */ + GIGABYTES(BigInteger.valueOf(1_073_741_824L), + INFO_SIZE_UNIT_GIGABYTES_SINGULAR.get(), + INFO_SIZE_UNIT_GIGABYTES_PLURAL.get(), + INFO_SIZE_UNIT_GIGABYTES_ABBREVIATION.get()), + + + + /** + * The size unit that represents terabytes. Each terabyte is 1024 gigabytes. + */ + TERABYTES(BigInteger.valueOf(1_099_511_627_776L), + INFO_SIZE_UNIT_TERABYTES_SINGULAR.get(), + INFO_SIZE_UNIT_TERABYTES_PLURAL.get(), + INFO_SIZE_UNIT_TERABYTES_ABBREVIATION.get()), + + + + /** + * The size unit that represents petabyte. Each petabyte is 1024 terabytes. + */ + PETABYTES(BigInteger.valueOf(1_125_899_906_842_624L), + INFO_SIZE_UNIT_PETABYTES_SINGULAR.get(), + INFO_SIZE_UNIT_PETABYTES_PLURAL.get(), + INFO_SIZE_UNIT_PETABYTES_ABBREVIATION.get()), + + + + /** + * The size unit that represents exabytes. Each exabyte is 1024 petabytes. + */ + EXABYTES(new BigInteger("1152921504606846976"), + INFO_SIZE_UNIT_EXABYTES_SINGULAR.get(), + INFO_SIZE_UNIT_EXABYTES_PLURAL.get(), + INFO_SIZE_UNIT_EXABYTES_ABBREVIATION.get()), + + + + /** + * The size unit that represents zettabytes. Each zettabyte is 1024 exabytes. + */ + ZETTABYTES(new BigInteger("1180591620717411303424"), + INFO_SIZE_UNIT_ZETTABYTES_SINGULAR.get(), + INFO_SIZE_UNIT_ZETTABYTES_PLURAL.get(), + INFO_SIZE_UNIT_ZETTABYTES_ABBREVIATION.get()), + + + + /** + * The size unit that represents yottabytes. Each yottabyte is 1024 + * zettabytes. + */ + YOTTABYTES(new BigInteger("1208925819614629174706176"), + INFO_SIZE_UNIT_YOTTABYTES_SINGULAR.get(), + INFO_SIZE_UNIT_YOTTABYTES_PLURAL.get(), + INFO_SIZE_UNIT_YOTTABYTES_ABBREVIATION.get()); + + + + // The number of bytes per single instance of this unit. + @NotNull private final BigInteger numBytesPerUnit; + + // The abbreviation for the unit. + @NotNull private final String abbreviation; + + // The plural name for the unit. + @NotNull private final String pluralName; + + // The singular name for the unit. + @NotNull private final String singularName; + + + + /** + * Creates a new size unit with the provided information. + * + * @param numBytesPerUnit The number of bytes per single instance of this + * size unit. It must not be {@code null}. + * @param singularName The name for a single instance of this size unit. + * It must not be {@code null}. + * @param pluralName The name for multiple instances of this size unit. + * It must not be {@code null}. + * @param abbreviation The abbreviation for multiple instances of this + * size unit. It must not be {@code null}. + */ + BinarySizeUnit(@NotNull final BigInteger numBytesPerUnit, + @NotNull final String singularName, + @NotNull final String pluralName, + @NotNull final String abbreviation) + { + this.numBytesPerUnit = numBytesPerUnit; + this.singularName = singularName; + this.pluralName = pluralName; + this.abbreviation = abbreviation; + } + + + + /** + * Retrieves the number of bytes per single instance of this size unit. + * + * @return The number of bytes per single instance of this size unit. + */ + @NotNull() + public BigInteger getNumBytesPerUnit() + { + return numBytesPerUnit; + } + + + + /** + * Retrieves the singular name for this size unit. + * + * @return The singular name for this size unit. + */ + @NotNull() + public String getSingularName() + { + return singularName; + } + + + + /** + * Retrieves the plural name for this size unit. + * + * @return The plural name for this size unit. + */ + @NotNull() + public String getPluralName() + { + return pluralName; + } + + + + /** + * Retrieves the abbreviation for this size unit. + * + * @return The abbreviation for this size unit. + */ + @NotNull() + public String getAbbreviation() + { + return abbreviation; + } + + + + /** + * Retrieves the number of bytes in the specified number of instances of this + * size unit. + * + * @param value The number of instances of this unit to convert to bytes. + * + * @return The number of bytes in the specified number of instances of this + * size unit. + */ + @NotNull() + public BigInteger toBytes(final long value) + { + return toBytes(BigInteger.valueOf(value)); + } + + + + /** + * Retrieves the number of bytes in the specified number of instances of this + * size unit. + * + * @param value The number of instances of this unit to convert to bytes. + * It must not be {@code null}. + * + * @return The number of bytes in the specified number of instances of this + * size unit. + */ + @NotNull() + public BigInteger toBytes(@NotNull final BigInteger value) + { + return numBytesPerUnit.multiply(value); + } + + + + /** + * Retrieves the number of bytes in the specified number of instances of this + * size unit, rounded to the nearest integer. + * + * @param value The number of instances of this unit to convert to bytes. + * + * @return The number of bytes in the specified number of instances of this + * size unit. + */ + @NotNull() + public BigInteger toBytes(final double value) + { + return toBytes(BigDecimal.valueOf(value)); + } + + + + /** + * Retrieves the number of bytes in the specified number of instances of this + * size unit, rounded to the nearest integer. + * + * @param value The number of instances of this unit to convert to bytes. + * It must not be {@code null}. + * + * @return The number of bytes in the specified number of instances of this + * size unit. + */ + @NotNull() + public BigInteger toBytes(@NotNull final BigDecimal value) + { + final BigDecimal numBytesPerUnitAsBigDecimal = + new BigDecimal(numBytesPerUnit); + final BigDecimal numBytesBigDecimal = + numBytesPerUnitAsBigDecimal.multiply(value); + final BigDecimal roundedBigDecimal = + numBytesBigDecimal.setScale(0, RoundingMode.HALF_UP); + return roundedBigDecimal.toBigInteger(); + } + + + + /** + * Retrieves the number of instances of this unit represented by the + * specified number of bytes. + * + * @param numBytes The number of bytes to use to make the determination. + * + * @return The number of instances of this unit represented by the specified + * number of bytes. + */ + @NotNull() + public BigDecimal fromBytes(final long numBytes) + { + return fromBytes(BigInteger.valueOf(numBytes)); + } + + + + /** + * Retrieves the number of instances of this unit represented by the + * specified number of bytes. + * + * @param numBytes The number of bytes to use to make the determination. It + * must not be {@code null}. + * + * @return The number of instances of this unit represented by the specified + * number of bytes. + */ + @NotNull() + public BigDecimal fromBytes(@NotNull final BigInteger numBytes) + { + final BigDecimal numBytesPerUnitAsBigDecimal = + new BigDecimal(numBytesPerUnit); + final BigDecimal numBytesAsBigDecimal = new BigDecimal(numBytes); + return numBytesAsBigDecimal.divide(numBytesPerUnitAsBigDecimal); + } + + + + /** + * Retrieves a string that represents a human-readable representation of the + * specified number of bytes. The string representation will be constructed + * in accordance with the following rules: + * + * + * @param numBytes The number of bytes to represent as a human-readable + * size. It must be greater than or equal to zero. + * + * @return A string that represents a human-readable representation of the + * specified number of bytes. + */ + @NotNull() + public static String bytesToHumanReadableSize(final long numBytes) + { + return bytesToHumanReadableSize(BigInteger.valueOf(numBytes)); + } + + + + /** + * Retrieves a string that represents a human-readable representation of the + * specified number of bytes. The string representation will be constructed + * in accordance with the following rules: + * + * + * @param numBytes The number of bytes to represent as a human-readable + * size. It must not be {@code null}, and it must represent + * a value that is greater than or equal to zero. + * + * @return A string that represents a human-readable representation of the + * specified number of bytes. + */ + @NotNull() + public static String bytesToHumanReadableSize( + @NotNull final BigInteger numBytes) + { + Validator.ensureTrue((numBytes.compareTo(BigInteger.ZERO) >= 0), + "BinarySizeUnits.bytesToHumanReadableSize.numBytes must be greater " + + "than or equal to zero."); + + + // Find the smallest unit whose numBytesPerUnit is greater than or equal + // to the given value. + BinarySizeUnit selectedUnit = null; + final BinarySizeUnit[] values = values(); + for (int i=(values.length - 1); i >= 0; i--) + { + final BinarySizeUnit unit = values[i]; + if (numBytes.compareTo(unit.numBytesPerUnit) >= 0) + { + selectedUnit = unit; + break; + } + } + + + // Check to see if we ended up without a selected unit (which should only + // happen if the provided unit was zero). In that case, we'll default to + // a unit of bytes. + if (selectedUnit == null) + { + return numBytes + BYTES.abbreviation; + } + + + // Check to see if the provided value is an exact multiple of the number of + // bytes per instance of the selected unit. If so, then represent the value + // as an integer followed by the unit abbreviation. + if (numBytes.remainder(selectedUnit.numBytesPerUnit).equals( + BigInteger.ZERO)) + { + return numBytes.divide(selectedUnit.numBytesPerUnit) + + selectedUnit.abbreviation; + } + + + // Compute the number of instances of the given unit needed to represent + // the provided value. + final BigDecimal numBytesAsBigDecimal = new BigDecimal(numBytes); + final BigDecimal numBytesPerUnitAsBigDecimal = + new BigDecimal(selectedUnit.numBytesPerUnit); + final BigDecimal numUnitsPerValueAsBigDecimal = + numBytesAsBigDecimal.divide(numBytesPerUnitAsBigDecimal, 2, + RoundingMode.HALF_UP); + return numUnitsPerValueAsBigDecimal.toString() + selectedUnit.abbreviation; + } + + + + /** + * Retrieves the binary size unit value that has the given name as either its + * singular name, plural name, or abbreviation, in a case-insensitive manner. + * + * + * @param name The name for which to retrieve the binary size unit value. + * It must not be {@code null}. + * + * @return The binary size unit value for the given name, or {@code null} if + * no value has a singular name, plural name, or abbreviation that + * matches the provided name in a case-insensitive manner. + */ + @Nullable() + public static BinarySizeUnit forName(@NotNull final String name) + { + for (final BinarySizeUnit unit : values()) + { + if (name.equalsIgnoreCase(unit.name()) || + name.equalsIgnoreCase(unit.singularName) || + name.equalsIgnoreCase(unit.pluralName) || + name.equalsIgnoreCase(unit.abbreviation)) + { + return unit; + } + } + + return null; + } +} diff --git a/src/com/unboundid/util/DecimalSizeUnit.java b/src/com/unboundid/util/DecimalSizeUnit.java new file mode 100644 index 000000000..656d1e762 --- /dev/null +++ b/src/com/unboundid/util/DecimalSizeUnit.java @@ -0,0 +1,519 @@ +/* + * Copyright 2023 Ping Identity Corporation + * All Rights Reserved. + */ +/* + * Copyright 2023 Ping Identity Corporation + * + * 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. + */ +/* + * Copyright (C) 2023 Ping Identity Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (GPLv2 only) + * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +package com.unboundid.util; + + + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.RoundingMode; + +import static com.unboundid.util.UtilityMessages.*; + + + +/** + * This enum defines a set of size units that can be used to represent data + * sizes in varying units (bytes, kilobytes, megabytes, gigabytes, etc.). This + * class uses decimal-based values rather than binary-based values, so each + * unit is 1000 times larger than the previous (for example, one kilobyte is + * interpreted as 1000 bytes rather than 1024 bytes). + */ +public enum DecimalSizeUnit +{ + /** + * The size unit that represents bytes. + */ + BYTES(BigInteger.valueOf(1L), + INFO_SIZE_UNIT_BYTES_SINGULAR.get(), + INFO_SIZE_UNIT_BYTES_PLURAL.get(), + INFO_SIZE_UNIT_BYTES_ABBREVIATION.get()), + + + + /** + * The size unit that represents kilobytes. Each kilobyte is 1024 bytes. + */ + KILOBYTES(BigInteger.valueOf(1_000L), + INFO_SIZE_UNIT_KILOBYTES_SINGULAR.get(), + INFO_SIZE_UNIT_KILOBYTES_PLURAL.get(), + INFO_SIZE_UNIT_KILOBYTES_ABBREVIATION.get()), + + + + /** + * The size unit that represents megabytes. Each megabyte is 1024 kilobytes. + */ + MEGABYTES(BigInteger.valueOf(1_000_000L), + INFO_SIZE_UNIT_MEGABYTES_SINGULAR.get(), + INFO_SIZE_UNIT_MEGABYTES_PLURAL.get(), + INFO_SIZE_UNIT_MEGABYTES_ABBREVIATION.get()), + + + + /** + * The size unit that represents gigabytes. Each gigabyte is 1024 megabytes. + */ + GIGABYTES(BigInteger.valueOf(1_000_000_000L), + INFO_SIZE_UNIT_GIGABYTES_SINGULAR.get(), + INFO_SIZE_UNIT_GIGABYTES_PLURAL.get(), + INFO_SIZE_UNIT_GIGABYTES_ABBREVIATION.get()), + + + + /** + * The size unit that represents terabytes. Each terabyte is 1024 gigabytes. + */ + TERABYTES(BigInteger.valueOf(1_000_000_000_000L), + INFO_SIZE_UNIT_TERABYTES_SINGULAR.get(), + INFO_SIZE_UNIT_TERABYTES_PLURAL.get(), + INFO_SIZE_UNIT_TERABYTES_ABBREVIATION.get()), + + + + /** + * The size unit that represents petabyte. Each petabyte is 1024 terabytes. + */ + PETABYTES(BigInteger.valueOf(1_000_000_000_000_000L), + INFO_SIZE_UNIT_PETABYTES_SINGULAR.get(), + INFO_SIZE_UNIT_PETABYTES_PLURAL.get(), + INFO_SIZE_UNIT_PETABYTES_ABBREVIATION.get()), + + + + /** + * The size unit that represents exabytes. Each exabyte is 1024 petabytes. + */ + EXABYTES(new BigInteger("1000000000000000000"), + INFO_SIZE_UNIT_EXABYTES_SINGULAR.get(), + INFO_SIZE_UNIT_EXABYTES_PLURAL.get(), + INFO_SIZE_UNIT_EXABYTES_ABBREVIATION.get()), + + + + /** + * The size unit that represents zettabytes. Each zettabyte is 1024 exabytes. + */ + ZETTABYTES(new BigInteger("1000000000000000000000"), + INFO_SIZE_UNIT_ZETTABYTES_SINGULAR.get(), + INFO_SIZE_UNIT_ZETTABYTES_PLURAL.get(), + INFO_SIZE_UNIT_ZETTABYTES_ABBREVIATION.get()), + + + + /** + * The size unit that represents yottabytes. Each yottabyte is 1024 + * zettabytes. + */ + YOTTABYTES(new BigInteger("1000000000000000000000000"), + INFO_SIZE_UNIT_YOTTABYTES_SINGULAR.get(), + INFO_SIZE_UNIT_YOTTABYTES_PLURAL.get(), + INFO_SIZE_UNIT_YOTTABYTES_ABBREVIATION.get()); + + + + // The number of bytes per single instance of this unit. + @NotNull private final BigInteger numBytesPerUnit; + + // The abbreviation for the unit. + @NotNull private final String abbreviation; + + // The plural name for the unit. + @NotNull private final String pluralName; + + // The singular name for the unit. + @NotNull private final String singularName; + + + + /** + * Creates a new size unit with the provided information. + * + * @param numBytesPerUnit The number of bytes per single instance of this + * size unit. It must not be {@code null}. + * @param singularName The name for a single instance of this size unit. + * It must not be {@code null}. + * @param pluralName The name for multiple instances of this size unit. + * It must not be {@code null}. + * @param abbreviation The abbreviation for multiple instances of this + * size unit. It must not be {@code null}. + */ + DecimalSizeUnit(@NotNull final BigInteger numBytesPerUnit, + @NotNull final String singularName, + @NotNull final String pluralName, + @NotNull final String abbreviation) + { + this.numBytesPerUnit = numBytesPerUnit; + this.singularName = singularName; + this.pluralName = pluralName; + this.abbreviation = abbreviation; + } + + + + /** + * Retrieves the number of bytes per single instance of this size unit. + * + * @return The number of bytes per single instance of this size unit. + */ + @NotNull() + public BigInteger getNumBytesPerUnit() + { + return numBytesPerUnit; + } + + + + /** + * Retrieves the singular name for this size unit. + * + * @return The singular name for this size unit. + */ + @NotNull() + public String getSingularName() + { + return singularName; + } + + + + /** + * Retrieves the plural name for this size unit. + * + * @return The plural name for this size unit. + */ + @NotNull() + public String getPluralName() + { + return pluralName; + } + + + + /** + * Retrieves the abbreviation for this size unit. + * + * @return The abbreviation for this size unit. + */ + @NotNull() + public String getAbbreviation() + { + return abbreviation; + } + + + + /** + * Retrieves the number of bytes in the specified number of instances of this + * size unit. + * + * @param value The number of instances of this unit to convert to bytes. + * + * @return The number of bytes in the specified number of instances of this + * size unit. + */ + @NotNull() + public BigInteger toBytes(final long value) + { + return toBytes(BigInteger.valueOf(value)); + } + + + + /** + * Retrieves the number of bytes in the specified number of instances of this + * size unit. + * + * @param value The number of instances of this unit to convert to bytes. + * It must not be {@code null}. + * + * @return The number of bytes in the specified number of instances of this + * size unit. + */ + @NotNull() + public BigInteger toBytes(@NotNull final BigInteger value) + { + return numBytesPerUnit.multiply(value); + } + + + + /** + * Retrieves the number of bytes in the specified number of instances of this + * size unit, rounded to the nearest integer. + * + * @param value The number of instances of this unit to convert to bytes. + * + * @return The number of bytes in the specified number of instances of this + * size unit. + */ + @NotNull() + public BigInteger toBytes(final double value) + { + return toBytes(BigDecimal.valueOf(value)); + } + + + + /** + * Retrieves the number of bytes in the specified number of instances of this + * size unit, rounded to the nearest integer. + * + * @param value The number of instances of this unit to convert to bytes. + * It must not be {@code null}. + * + * @return The number of bytes in the specified number of instances of this + * size unit. + */ + @NotNull() + public BigInteger toBytes(@NotNull final BigDecimal value) + { + final BigDecimal numBytesPerUnitAsBigDecimal = + new BigDecimal(numBytesPerUnit); + final BigDecimal numBytesBigDecimal = + numBytesPerUnitAsBigDecimal.multiply(value); + final BigDecimal roundedBigDecimal = + numBytesBigDecimal.setScale(0, RoundingMode.HALF_UP); + return roundedBigDecimal.toBigInteger(); + } + + + + /** + * Retrieves the number of instances of this unit represented by the + * specified number of bytes. + * + * @param numBytes The number of bytes to use to make the determination. + * + * @return The number of instances of this unit represented by the specified + * number of bytes. + */ + @NotNull() + public BigDecimal fromBytes(final long numBytes) + { + return fromBytes(BigInteger.valueOf(numBytes)); + } + + + + /** + * Retrieves the number of instances of this unit represented by the + * specified number of bytes. + * + * @param numBytes The number of bytes to use to make the determination. It + * must not be {@code null}. + * + * @return The number of instances of this unit represented by the specified + * number of bytes. + */ + @NotNull() + public BigDecimal fromBytes(@NotNull final BigInteger numBytes) + { + final BigDecimal numBytesPerUnitAsBigDecimal = + new BigDecimal(numBytesPerUnit); + final BigDecimal numBytesAsBigDecimal = new BigDecimal(numBytes); + return numBytesAsBigDecimal.divide(numBytesPerUnitAsBigDecimal); + } + + + + /** + * Retrieves a string that represents a human-readable representation of the + * specified number of bytes. The string representation will be constructed + * in accordance with the following rules: + *
      + *
    • + * The string representation will use the abbreviation for the unit (e.g., + * "b" instead of "bytes", "KB" instead of kilobytes, etc.) + *
    • + *
    • + * If the provided value represents an exact multiple of the number of + * bytes for a given unit, then the string representation will be an + * integer followed by the abbreviation for the unit (e.g., a value of + * 123 will result in a string representation of "123b", a value of + * 524880 will result in a string representation of "5MB", a value of + * 7516192768 will result in a string representation of "7GB", etc.). + *
    • + *
    • + * If the provided value does not represent an exact multiple of the + * number of bytes for the given unit, then the string representation will + * use a floating-point number with two digits behind the decimal point. + * It will select the unit so that when possible, there will be between + * 1 and 3 digits before the decimal point (e.g., a value of 12345 will + * result in a string representation of "12.06KB", a value of + * 9876543210 will result in a string representation of "9.20GB", etc.). + *
    • + *
    + * + * @param numBytes The number of bytes to represent as a human-readable + * size. It must be greater than or equal to zero. + * + * @return A string that represents a human-readable representation of the + * specified number of bytes. + */ + @NotNull() + public static String bytesToHumanReadableSize(final long numBytes) + { + return bytesToHumanReadableSize(BigInteger.valueOf(numBytes)); + } + + + + /** + * Retrieves a string that represents a human-readable representation of the + * specified number of bytes. The string representation will be constructed + * in accordance with the following rules: + *
      + *
    • + * The string representation will use the abbreviation for the unit (e.g., + * "B" instead of "bytes", "KB" instead of kilobytes, etc.) + *
    • + *
    • + * The string representation + * The string representation will use the abbreviation for the unit (e.g., + * "B" instead of "bytes", "KB" instead of kilobytes, etc.) + *
    • + *
    • + * If the provided value represents an exact multiple of the number of + * bytes for the selected unit, then the string representation will be an + * integer followed by the abbreviation for the unit (e.g., a value of + * 123 will result in a string representation of "123B", a value of + * 524880 will result in a string representation of "5MB", a value of + * 7516192768 will result in a string representation of "7GB", etc.). + *
    • + *
    • + * If the provided value does not represent an exact multiple of the + * number of bytes for the selected unit, then the string representation + * will use a floating-point number with two digits behind the decimal + * point (e.g., a value of 12345 will result in a string representation of + * "12.06KB", a value of 9876543210 will result in a string representation + * of "9.20GB", etc.). + *
    • + *
    + * + * @param numBytes The number of bytes to represent as a human-readable + * size. It must not be {@code null}, and it must represent + * a value that is greater than or equal to zero. + * + * @return A string that represents a human-readable representation of the + * specified number of bytes. + */ + @NotNull() + public static String bytesToHumanReadableSize( + @NotNull final BigInteger numBytes) + { + Validator.ensureTrue((numBytes.compareTo(BigInteger.ZERO) >= 0), + "DecimalSizeUnits.bytesToHumanReadableSize.numBytes must be greater " + + "than or equal to zero."); + + + // Find the smallest unit whose numBytesPerUnit is greater than or equal + // to the given value. + DecimalSizeUnit selectedUnit = null; + final DecimalSizeUnit[] values = values(); + for (int i=(values.length - 1); i >= 0; i--) + { + final DecimalSizeUnit unit = values[i]; + if (numBytes.compareTo(unit.numBytesPerUnit) >= 0) + { + selectedUnit = unit; + break; + } + } + + + // Check to see if we ended up without a selected unit (which should only + // happen if the provided unit was zero). In that case, we'll default to + // a unit of bytes. + if (selectedUnit == null) + { + return numBytes + BYTES.abbreviation; + } + + + // Check to see if the provided value is an exact multiple of the number of + // bytes per instance of the selected unit. If so, then represent the value + // as an integer followed by the unit abbreviation. + if (numBytes.remainder(selectedUnit.numBytesPerUnit).equals( + BigInteger.ZERO)) + { + return numBytes.divide(selectedUnit.numBytesPerUnit) + + selectedUnit.abbreviation; + } + + + // Compute the number of instances of the given unit needed to represent + // the provided value. + final BigDecimal numBytesAsBigDecimal = new BigDecimal(numBytes); + final BigDecimal numBytesPerUnitAsBigDecimal = + new BigDecimal(selectedUnit.numBytesPerUnit); + final BigDecimal numUnitsPerValueAsBigDecimal = + numBytesAsBigDecimal.divide(numBytesPerUnitAsBigDecimal, 2, + RoundingMode.HALF_UP); + return numUnitsPerValueAsBigDecimal.toString() + selectedUnit.abbreviation; + } + + + + /** + * Retrieves the decimal size unit value that has the given name as either its + * singular name, plural name, or abbreviation, in a case-insensitive manner. + * + * + * @param name The name for which to retrieve the decimal size unit value. + * It must not be {@code null}. + * + * @return The decimal size unit value for the given name, or {@code null} if + * no value has a singular name, plural name, or abbreviation that + * matches the provided name in a case-insensitive manner. + */ + @Nullable() + public static DecimalSizeUnit forName(@NotNull final String name) + { + for (final DecimalSizeUnit unit : values()) + { + if (name.equalsIgnoreCase(unit.name()) || + name.equalsIgnoreCase(unit.singularName) || + name.equalsIgnoreCase(unit.pluralName) || + name.equalsIgnoreCase(unit.abbreviation)) + { + return unit; + } + } + + return null; + } +} diff --git a/tests/unit/src/com/unboundid/util/BinarySizeUnitTestCase.java b/tests/unit/src/com/unboundid/util/BinarySizeUnitTestCase.java new file mode 100644 index 000000000..9bcd0b254 --- /dev/null +++ b/tests/unit/src/com/unboundid/util/BinarySizeUnitTestCase.java @@ -0,0 +1,306 @@ +/* + * Copyright 2023 Ping Identity Corporation + * All Rights Reserved. + */ +/* + * Copyright 2023 Ping Identity Corporation + * + * 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. + */ +/* + * Copyright (C) 2023 Ping Identity Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (GPLv2 only) + * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +package com.unboundid.util; + + + +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import com.unboundid.ldap.sdk.LDAPSDKTestCase; + + + +/** + * This class provides a set of test cases for the {@code BinarySizeUnit} enum. + */ +public final class BinarySizeUnitTestCase + extends LDAPSDKTestCase +{ + /** + * Provides basic test coverage for the various enum methods. + * + * @throws Exception If an unexpected problem occurs. + */ + @Test() + public void testBasicEnumMethods() + throws Exception + { + for (final BinarySizeUnit unit : BinarySizeUnit.values()) + { + assertNotNull(unit.getSingularName()); + assertNotNull(unit.getPluralName()); + assertNotNull(unit.getAbbreviation()); + assertNotNull(unit.getNumBytesPerUnit()); + + assertEquals(BinarySizeUnit.forName(unit.name()), unit); + assertEquals(BinarySizeUnit.forName(unit.getSingularName()), unit); + assertEquals(BinarySizeUnit.forName(unit.getPluralName()), unit); + assertEquals(BinarySizeUnit.forName(unit.getAbbreviation()), unit); + + assertEquals(BinarySizeUnit.forName( + StaticUtils.toLowerCase(unit.name())), unit); + assertEquals(BinarySizeUnit.forName( + StaticUtils.toLowerCase(unit.getSingularName())), unit); + assertEquals(BinarySizeUnit.forName( + StaticUtils.toLowerCase(unit.getPluralName())), unit); + assertEquals(BinarySizeUnit.forName( + StaticUtils.toLowerCase(unit.getAbbreviation())), unit); + + assertEquals(BinarySizeUnit.forName( + StaticUtils.toUpperCase(unit.name())), unit); + assertEquals(BinarySizeUnit.forName( + StaticUtils.toUpperCase(unit.getSingularName())), unit); + assertEquals(BinarySizeUnit.forName( + StaticUtils.toUpperCase(unit.getPluralName())), unit); + assertEquals(BinarySizeUnit.forName( + StaticUtils.toUpperCase(unit.getAbbreviation())), unit); + + for (int i=1; i <= 999; i++) + { + final BigInteger numBytes = unit.getNumBytesPerUnit().multiply( + BigInteger.valueOf(i)); + + assertEquals(BinarySizeUnit.bytesToHumanReadableSize(numBytes), + i + unit.getAbbreviation()); + + assertEquals(unit.toBytes(i), numBytes); + assertEquals(unit.toBytes(i * 1.0d), numBytes); + + assertEquals(unit.fromBytes(numBytes), BigDecimal.valueOf(i)); + if (canRepresentAsLong(numBytes)) + { + assertEquals(unit.fromBytes(numBytes.longValue()), + BigDecimal.valueOf(i)); + } + } + } + } + + + + /** + * Ensures that the {@code forName} method returns {@code null} for an + * invalid or unrecognized name. + * + * @throws Exception If an unexpected problem occurs. + */ + @Test() + public void testForNameInvalid() + throws Exception + { + assertNull(BinarySizeUnit.forName("invalid")); + } + + + + /** + * Ensures that the {@code bytesToHumanReadableSize} method yields the + * expected output for the given value. + * + * @param numBytes + * The number of bytes to provide as an argument to the + * {@code bytesToHumanReadableSize} method. + * @param expectedStringRepresentation + * The expected string representation for the provided value. + * + * @throws Exception If an unexpected problem occurs. + */ + @Test(dataProvider = "BytesToHumanReadableSizeTestData") + public void testBytesToHumanReadableSize(final BigInteger numBytes, + final String expectedStringRepresentation) + throws Exception + { + assertEquals(BinarySizeUnit.bytesToHumanReadableSize(numBytes), + expectedStringRepresentation); + + if (canRepresentAsLong(numBytes)) + { + assertEquals( + BinarySizeUnit.bytesToHumanReadableSize(numBytes.longValue()), + expectedStringRepresentation); + } + } + + + + /** + * Retrieves data that may be used for testing the + * {@code bytesToHumanReadableDuration} method. + * + * @return Data that may be used for testing the + * {@code bytesToHumanReadableDuration} method. + * + * @throws Exception If an unexpected problem occurs. + */ + @DataProvider(name = "BytesToHumanReadableSizeTestData") + public Object[][] getBytesToHumanReadableSizeTestData() + throws Exception + { + return new Object[][] + { + new Object[] + { + BigInteger.valueOf(0L), + "0B" + }, + new Object[] + { + BigInteger.valueOf(1L), + "1B" + }, + new Object[] + { + BigInteger.valueOf(12L), + "12B" + }, + new Object[] + { + BigInteger.valueOf(123L), + "123B" + }, + new Object[] + { + BigInteger.valueOf(1024L), + "1KB" + }, + new Object[] + { + BigInteger.valueOf(1234L), + "1.21KB" + }, + new Object[] + { + BigInteger.valueOf(2048L), + "2KB" + }, + new Object[] + { + BigInteger.valueOf(12345L), + "12.06KB" + }, + new Object[] + { + BigInteger.valueOf(123456L), + "120.56KB" + }, + new Object[] + { + BigInteger.valueOf(1048576L), + "1MB" + }, + new Object[] + { + BigInteger.valueOf(1234567L), + "1.18MB" + }, + new Object[] + { + BigInteger.valueOf(6291456L), + "6MB" + }, + new Object[] + { + BigInteger.valueOf(12345678L), + "11.77MB" + }, + new Object[] + { + BigInteger.valueOf(123456789L), + "117.74MB" + }, + new Object[] + { + BigInteger.valueOf(1073741824L), + "1GB" + }, + new Object[] + { + BigInteger.valueOf(1234567890L), + "1.15GB" + }, + new Object[] + { + BigInteger.valueOf(12345678901L), + "11.50GB" + }, + new Object[] + { + BigInteger.valueOf(56908316672L), + "53GB" + }, + new Object[] + { + BigInteger.valueOf(123456789012L), + "114.98GB" + }, + new Object[] + { + BigInteger.valueOf(1099511627776L), + "1TB" + }, + new Object[] + { + BigInteger.valueOf(1234567890123L), + "1.12TB" + }, + new Object[] + { + BigInteger.valueOf(12345678901234L), + "11.23TB" + }, + }; + } + + + + /** + * Indicates whether the provided {@code BigInteger} value can be represented + * as a {@code long}. + * + * @param value The value for which to make the determination. + * + * @return {@code true} if the provided value can be represented as a + * {@code long}, or {@code false} if not. + */ + private static boolean canRepresentAsLong(final BigInteger value) + { + return value.equals(BigInteger.valueOf(value.longValue())); + } +} diff --git a/tests/unit/src/com/unboundid/util/DecimalSizeUnitTestCase.java b/tests/unit/src/com/unboundid/util/DecimalSizeUnitTestCase.java new file mode 100644 index 000000000..8a827792c --- /dev/null +++ b/tests/unit/src/com/unboundid/util/DecimalSizeUnitTestCase.java @@ -0,0 +1,306 @@ +/* + * Copyright 2023 Ping Identity Corporation + * All Rights Reserved. + */ +/* + * Copyright 2023 Ping Identity Corporation + * + * 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. + */ +/* + * Copyright (C) 2023 Ping Identity Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (GPLv2 only) + * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +package com.unboundid.util; + + + +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import com.unboundid.ldap.sdk.LDAPSDKTestCase; + + + +/** + * This class provides a set of test cases for the {@code DecimalSizeUnit} enum. + */ +public final class DecimalSizeUnitTestCase + extends LDAPSDKTestCase +{ + /** + * Provides basic test coverage for the various enum methods. + * + * @throws Exception If an unexpected problem occurs. + */ + @Test() + public void testBasicEnumMethods() + throws Exception + { + for (final DecimalSizeUnit unit : DecimalSizeUnit.values()) + { + assertNotNull(unit.getSingularName()); + assertNotNull(unit.getPluralName()); + assertNotNull(unit.getAbbreviation()); + assertNotNull(unit.getNumBytesPerUnit()); + + assertEquals(DecimalSizeUnit.forName(unit.name()), unit); + assertEquals(DecimalSizeUnit.forName(unit.getSingularName()), unit); + assertEquals(DecimalSizeUnit.forName(unit.getPluralName()), unit); + assertEquals(DecimalSizeUnit.forName(unit.getAbbreviation()), unit); + + assertEquals(DecimalSizeUnit.forName( + StaticUtils.toLowerCase(unit.name())), unit); + assertEquals(DecimalSizeUnit.forName( + StaticUtils.toLowerCase(unit.getSingularName())), unit); + assertEquals(DecimalSizeUnit.forName( + StaticUtils.toLowerCase(unit.getPluralName())), unit); + assertEquals(DecimalSizeUnit.forName( + StaticUtils.toLowerCase(unit.getAbbreviation())), unit); + + assertEquals(DecimalSizeUnit.forName( + StaticUtils.toUpperCase(unit.name())), unit); + assertEquals(DecimalSizeUnit.forName( + StaticUtils.toUpperCase(unit.getSingularName())), unit); + assertEquals(DecimalSizeUnit.forName( + StaticUtils.toUpperCase(unit.getPluralName())), unit); + assertEquals(DecimalSizeUnit.forName( + StaticUtils.toUpperCase(unit.getAbbreviation())), unit); + + for (int i=1; i <= 999; i++) + { + final BigInteger numBytes = unit.getNumBytesPerUnit().multiply( + BigInteger.valueOf(i)); + + assertEquals(DecimalSizeUnit.bytesToHumanReadableSize(numBytes), + i + unit.getAbbreviation()); + + assertEquals(unit.toBytes(i), numBytes); + assertEquals(unit.toBytes(i * 1.0d), numBytes); + + assertEquals(unit.fromBytes(numBytes), BigDecimal.valueOf(i)); + if (canRepresentAsLong(numBytes)) + { + assertEquals(unit.fromBytes(numBytes.longValue()), + BigDecimal.valueOf(i)); + } + } + } + } + + + + /** + * Ensures that the {@code forName} method returns {@code null} for an + * invalid or unrecognized name. + * + * @throws Exception If an unexpected problem occurs. + */ + @Test() + public void testForNameInvalid() + throws Exception + { + assertNull(DecimalSizeUnit.forName("invalid")); + } + + + + /** + * Ensures that the {@code bytesToHumanReadableSize} method yields the + * expected output for the given value. + * + * @param numBytes + * The number of bytes to provide as an argument to the + * {@code bytesToHumanReadableSize} method. + * @param expectedStringRepresentation + * The expected string representation for the provided value. + * + * @throws Exception If an unexpected problem occurs. + */ + @Test(dataProvider = "BytesToHumanReadableSizeTestData") + public void testBytesToHumanReadableSize(final BigInteger numBytes, + final String expectedStringRepresentation) + throws Exception + { + assertEquals(DecimalSizeUnit.bytesToHumanReadableSize(numBytes), + expectedStringRepresentation); + + if (canRepresentAsLong(numBytes)) + { + assertEquals( + DecimalSizeUnit.bytesToHumanReadableSize(numBytes.longValue()), + expectedStringRepresentation); + } + } + + + + /** + * Retrieves data that may be used for testing the + * {@code bytesToHumanReadableDuration} method. + * + * @return Data that may be used for testing the + * {@code bytesToHumanReadableDuration} method. + * + * @throws Exception If an unexpected problem occurs. + */ + @DataProvider(name = "BytesToHumanReadableSizeTestData") + public Object[][] getBytesToHumanReadableSizeTestData() + throws Exception + { + return new Object[][] + { + new Object[] + { + BigInteger.valueOf(0L), + "0B" + }, + new Object[] + { + BigInteger.valueOf(1L), + "1B" + }, + new Object[] + { + BigInteger.valueOf(12L), + "12B" + }, + new Object[] + { + BigInteger.valueOf(123L), + "123B" + }, + new Object[] + { + BigInteger.valueOf(1000L), + "1KB" + }, + new Object[] + { + BigInteger.valueOf(1234L), + "1.23KB" + }, + new Object[] + { + BigInteger.valueOf(2000L), + "2KB" + }, + new Object[] + { + BigInteger.valueOf(12345L), + "12.35KB" + }, + new Object[] + { + BigInteger.valueOf(123456L), + "123.46KB" + }, + new Object[] + { + BigInteger.valueOf(1000000L), + "1MB" + }, + new Object[] + { + BigInteger.valueOf(1234567L), + "1.23MB" + }, + new Object[] + { + BigInteger.valueOf(6000000L), + "6MB" + }, + new Object[] + { + BigInteger.valueOf(12345678L), + "12.35MB" + }, + new Object[] + { + BigInteger.valueOf(123456789L), + "123.46MB" + }, + new Object[] + { + BigInteger.valueOf(1000000000L), + "1GB" + }, + new Object[] + { + BigInteger.valueOf(1234567890L), + "1.23GB" + }, + new Object[] + { + BigInteger.valueOf(10000000000L), + "10GB" + }, + new Object[] + { + BigInteger.valueOf(53000000000L), + "53GB" + }, + new Object[] + { + BigInteger.valueOf(123456789012L), + "123.46GB" + }, + new Object[] + { + BigInteger.valueOf(1000000000000L), + "1TB" + }, + new Object[] + { + BigInteger.valueOf(1234567890123L), + "1.23TB" + }, + new Object[] + { + BigInteger.valueOf(12345678901234L), + "12.35TB" + }, + }; + } + + + + /** + * Indicates whether the provided {@code BigInteger} value can be represented + * as a {@code long}. + * + * @param value The value for which to make the determination. + * + * @return {@code true} if the provided value can be represented as a + * {@code long}, or {@code false} if not. + */ + private static boolean canRepresentAsLong(final BigInteger value) + { + return value.equals(BigInteger.valueOf(value.longValue())); + } +}