Java tutorial
// ///////////////////////////////////////////////////////// // This file is part of Propel. // // Propel is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Propel 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 Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with Propel. If not, see <http://www.gnu.org/licenses/>. // ///////////////////////////////////////////////////////// // Authored by: Nikolaos Tountas -> salam.kaser-at-gmail.com // ///////////////////////////////////////////////////////// package propel.core.utils; import java.math.BigDecimal; import java.math.BigInteger; import java.nio.charset.Charset; import java.util.Calendar; import java.util.Formatter; import java.util.GregorianCalendar; import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; import lombok.Predicate; import lombok.Validate; import lombok.Validate.NotNull; import lombok.val; import org.joda.time.DateTime; import org.joda.time.Duration; import org.joda.time.LocalDateTime; import org.joda.time.Period; import propel.core.collections.maps.avl.AvlHashtable; import propel.core.common.CONSTANT; import propel.core.userTypes.Int128; import propel.core.userTypes.SignedByte; import propel.core.userTypes.UnsignedByte; import propel.core.userTypes.UnsignedInteger; import propel.core.userTypes.UnsignedLong; import propel.core.userTypes.UnsignedShort; /** * Class aiding in casting, encoding/decoding and converting */ public final class ConversionUtils { /** * Used to convert Durations into milliseconds */ private static final Calendar ZERO_AD = new GregorianCalendar(0, 0, 0, 0, 0, 0); /** * Packs two 32-bit integers into a 64-bit long (a,b => ab) */ public static long pack64(int a, int b) { long c1 = (((long) a) << 32); long c2 = ((long) b) & 0xFFFFFFFFL; long num = c1 | c2; return num; } /** * Reversed the pack64() function */ public static int[] unpack64(long num) { int a = (int) (num >>> 32); int b = (int) num; return new int[] { a, b }; } /** * Conversion utility method, allows for a C# unsigned byte to be converted to a Java signed byte. */ public static byte byteDotNetToJvm(int i) { if (i > 127) { return (byte) (i - 256); } else { return (byte) i; } } /** * Conversion utility method, allows for a Java signed byte to be converted to a C# unsigned byte. */ public static int byteJvmToDotNet(byte b) { return b & 0xFF; } /** * .NET-style Convert.ChangeType functionality. Works for most built-in types. Attempts to use casting for others. * * @throws NullPointerException An argument is null. * @throws IllegalArgumentException An incompatible argument was passed (e.g. an array or annotation) * @throws NumberFormatException An invalid input value was given that does not parse to the specified target type * @throws ClassCastException A class cast failed */ @Validate @SuppressWarnings("unchecked") public static <T> T changeType(@NotNull final Object value, @NotNull final Class<T> targetType) throws InstantiationException, IllegalAccessException { val sourceType = value.getClass(); // check that we're not working with incompatible types if (sourceType.isAnnotation() || targetType.isAnnotation()) throw new IllegalArgumentException("This conversion process does not support annotations."); if (sourceType.isArray() || targetType.isArray()) throw new IllegalArgumentException("This conversion process does not support arrays."); // handle conversion to String if (targetType.equals(String.class)) return (T) value.toString(); // handle parsing from String if (sourceType.equals(String.class)) return (T) changeTypeParseFromString(value, targetType); // handle simple casting scenario if (sourceType.isAssignableFrom(targetType)) return targetType.cast(value); // handle number conversion if (value instanceof Number) return (T) changeTypeFromNumber(value, targetType); // handle primitive conversion PrimitiveType primitiveType = ReflectionUtils.getPrimitiveType(sourceType); if (primitiveType != PrimitiveType.NotPrimitive) return (T) changeTypeFromPrimitive(value, primitiveType, targetType); // handle number-like Character and Boolean conversion (these don't implement Number) if (value instanceof Character) return (T) changeTypeFromCharacter(value, targetType); if (value instanceof Boolean) return (T) changeTypeFromBoolean(value, targetType); // all attempts have failed throw new IllegalArgumentException("The provided object of type '" + sourceType.getSimpleName() + "' could not be converted to '" + targetType.getSimpleName()); } // JODA, XML data types, etc. /** * Converts an XML Gregorian Calendar data type to a Joda LocalDateTime */ @Validate public static LocalDateTime fromXMLGregorianCalendar(@NotNull final XMLGregorianCalendar value) { return new LocalDateTime(value.getYear(), value.getMonth(), value.getDay(), value.getHour(), value.getMinute(), value.getSecond(), value.getMillisecond()); } /** * Converts an XML Duration data type to a Joda Duration */ @Validate public static Duration fromXMLDuration(@NotNull final javax.xml.datatype.Duration value) { return new Duration(value.getTimeInMillis(ZERO_AD)); } /** * Converts a Joda LocalDateTime object to an XML Gregorian Calendar data type */ @Validate public static XMLGregorianCalendar toXMLGregorianCalendar(@NotNull final LocalDateTime value) throws DatatypeConfigurationException { val gc = new GregorianCalendar(value.getYear(), value.getMonthOfYear() - 1, value.getDayOfMonth(), value.getHourOfDay(), value.getMinuteOfHour(), value.getSecondOfMinute()); gc.set(Calendar.MILLISECOND, value.getMillisOfSecond()); return DatatypeFactory.newInstance().newXMLGregorianCalendar(gc); } /** * Converts a Joda Duration object to an XML Duration data type */ @Validate public static javax.xml.datatype.Duration toXMLDuration(@NotNull final Duration value) throws DatatypeConfigurationException { return DatatypeFactory.newInstance().newDuration(value.getMillis()); } // BINARY conversions /** * Converts a number to binary, e.g. 255 -> 11111111. Binary representations can be endian dependent. */ @Validate public static String toBinary(@NotNull final UnsignedLong num, boolean padLeft) { return !padLeft ? toBinary(num) : StringUtils.padLeft(toBinary(num), 64, CONSTANT.ZERO_CHAR); } /** * Converts a number to binary, e.g. 255 -> 11111111. Binary representations can be endian dependent. */ public static String toBinary(UnsignedLong num) { return num.bigIntegerValue().toString(2); } /** * Converts a number to binary, e.g. 255 -> 11111111. Binary representations can be endian dependent. */ public static String toBinary(long num, boolean padLeft) { return !padLeft ? toBinary(num) : StringUtils.padLeft(toBinary(num), 64, CONSTANT.ZERO_CHAR); } /** * Converts a number to binary, e.g. 255 -> 11111111. Binary representations can be endian dependent. */ public static String toBinary(long num) { return Long.toBinaryString(num); } /** * Converts a number to binary, e.g. 255 -> 11111111. Binary representations can be endian dependent. */ @Validate public static String toBinary(@NotNull final UnsignedInteger num, boolean padLeft) { return !padLeft ? toBinary(num) : StringUtils.padLeft(toBinary(num), 32, CONSTANT.ZERO_CHAR); } /** * Converts a number to binary, e.g. 255 -> 11111111. Binary representations can be endian dependent. */ @Validate public static String toBinary(@NotNull final UnsignedInteger num) { return num.bigIntegerValue().toString(2); } /** * Converts a number to binary, e.g. 255 -> 11111111. Binary representations can be endian dependent. */ public static String toBinary(int num, boolean padLeft) { return !padLeft ? toBinary(num) : StringUtils.padLeft(toBinary(num), 32, CONSTANT.ZERO_CHAR); } /** * Converts a number to binary, e.g. 255 -> 11111111. Binary representations can be endian dependent. */ public static String toBinary(int num) { return Integer.toBinaryString(num); } /** * Converts a number to binary, e.g. 255 -> 11111111. Binary representations can be endian dependent. */ @Validate public static String toBinary(@NotNull final UnsignedShort num, boolean padLeft) { return !padLeft ? toBinary(num) : StringUtils.padLeft(toBinary(num), 16, CONSTANT.ZERO_CHAR); } /** * Converts a number to binary, e.g. 255 -> 11111111. Binary representations can be endian dependent. */ public static String toBinary(UnsignedShort num) { return num.bigIntegerValue().toString(2); } /** * Converts a number to binary, e.g. 255 -> 11111111. Binary representations can be endian dependent. */ public static String toBinary(short num, boolean padLeft) { return !padLeft ? toBinary(num) : StringUtils.padLeft(toBinary(num), 16, CONSTANT.ZERO_CHAR); } /** * Converts a number to binary, e.g. 255 -> 11111111. Binary representations can be endian dependent. */ public static String toBinary(short num) { return Integer.toBinaryString(num); } /** * Converts a number to binary, e.g. 255 -> 11111111. Binary representations can be endian dependent. */ @Validate public static String toBinary(@NotNull final UnsignedByte num, boolean padLeft) { return !padLeft ? toBinary(num) : StringUtils.padLeft(toBinary(num), 8, CONSTANT.ZERO_CHAR); } /** * Converts a number to binary, e.g. 255 -> 11111111. Binary representations can be endian dependent. */ public static String toBinary(UnsignedByte num) { return num.bigIntegerValue().toString(2); } /** * Converts a number to binary, e.g. 255 -> 11111111. Binary representations can be endian dependent. */ public static String toBinary(byte num, boolean padLeft) { return !padLeft ? toBinary(num) : StringUtils.padLeft(toBinary(num), 8, CONSTANT.ZERO_CHAR); } /** * Converts a number to binary */ public static String toBinary(byte num) { return Integer.toBinaryString(num); } /** * Converts a byte array to a binary string. Binary representations can be endian dependent. * * @throws NullPointerException An argument is null. */ @Validate public static String toBinary(@NotNull final byte[] bytes) { val sb = new StringBuilder(bytes.length * 8); for (byte b : bytes) sb.append(toBinary(b, true)); return sb.toString(); } /** * Converts a byte array to a binary string. Binary representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws IndexOutOfBoundsException An index is out of bounds. * @throws IllegalArgumentException An argument is out of range. */ @Validate public static String toBinary(@NotNull final byte[] bytes, int startIndex, int length) { if (startIndex < 0 || startIndex > bytes.length) throw new IndexOutOfBoundsException("startIndex=" + startIndex + " bytesLen=" + bytes.length); if (length < 0 || length + startIndex > bytes.length || length + startIndex < 0) throw new IllegalArgumentException( "startIndex=" + startIndex + " length=" + length + " bytesLen=" + bytes.length); StringBuilder sb = new StringBuilder(bytes.length * 8); for (int i = startIndex; i < startIndex + length; i++) sb.append(toBinary(bytes[i], true)); return sb.toString(); } /** * Converts a binary back to an int. Binary representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static int fromBinaryToInt32(@NotNull final String binary) { return Integer.parseInt(binary, 2); } /** * Converts a binary back to an uint. Binary representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static UnsignedInteger fromBinaryToUInt32(@NotNull final String binary) { return new UnsignedInteger(new BigInteger(binary, 2)); } /** * Converts a binary back to a long. Binary representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static long fromBinaryToInt64(@NotNull final String binary) { return Long.parseLong(binary, 2); } /** * Converts a binary back to a ulong. Binary representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static UnsignedLong fromBinaryToUInt64(@NotNull final String binary) { return new UnsignedLong(new BigInteger(binary, 2)); } /** * Converts a binary back to a short. Binary representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static short fromBinaryToInt16(@NotNull final String binary) { return Short.parseShort(binary, 2); } /** * Converts a binary back to a ushort. Binary representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static UnsignedShort fromBinaryToUInt16(@NotNull final String binary) { return new UnsignedShort(new BigInteger(binary, 2)); } /** * Converts a binary back to a byte. Binary representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static byte fromBinaryToByte(@NotNull final String binary) { return Byte.parseByte(binary, 2); } /** * Converts a binary back to an unsigned byte. Binary representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static UnsignedByte fromBinaryToUInt8(@NotNull final String binary) { return new UnsignedByte(new BigInteger(binary, 2)); } /** * Converts a binary back to a byte[]. Binary representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws IllegalArgumentException An argument is out of range. * @throws NumberFormatException A number could not be parsed. */ @Validate public static byte[] fromBinaryToByteArray(@NotNull final String binary) { return fromBinaryToByteArray(binary, 0, binary.length()); } /** * Converts a binary back to a byte[]. Binary representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws IndexOutOfBoundsException An index is out of bounds. * @throws IllegalArgumentException An argument is out of range. * @throws NumberFormatException A number could not be parsed. */ @Validate public static byte[] fromBinaryToByteArray(@NotNull final String binary, int startIndex, int length) { if (startIndex < 0 || startIndex > binary.length()) throw new IndexOutOfBoundsException("startIndex=" + startIndex + " binaryLen=" + binary.length()); if (length < 0 || length + startIndex > binary.length() || length + startIndex < 0) throw new IllegalArgumentException( "startIndex=" + startIndex + " length=" + length + " binaryLen=" + binary.length()); if (binary.length() == 0 || binary.length() % 8 != 0) throw new IllegalArgumentException( "The binary string should use 8 digits per byte: " + binary.length()); byte[] result = new byte[length / 8]; for (int i = startIndex; i < startIndex + length; i += 8) result[i / 8 - startIndex / 8] = fromBinaryToByte(binary.substring(i, 8)); return result; } // DECIMAL conversions /** * Converts a string back to a uint * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static UnsignedInteger fromStringToUInt32(@NotNull final String value) { return new UnsignedInteger(value); } /** * Converts a string back to an int * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static int fromStringToInt32(@NotNull final String value) { return Integer.parseInt(value, 10); } /** * Converts a string back to a ulong * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static UnsignedLong fromStringToUInt64(@NotNull final String value) { return new UnsignedLong(value); } /** * Converts a string back to a long * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static long fromStringToInt64(@NotNull final String value) { return Long.parseLong(value, 10); } /** * Converts a string back to a ushort * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static UnsignedShort fromStringToUInt16(@NotNull final String value) { return new UnsignedShort(value); } /** * Converts a string back to a short * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static short fromStringToInt16(@NotNull final String value) { return Short.parseShort(value, 10); } /** * Converts a string back to an unsigned byte * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static UnsignedByte fromStringToUInt8(@NotNull final String value) { return new UnsignedByte(value); } /** * Converts a string back to a byte * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static byte fromStringToByte(@NotNull final String value) { return Byte.parseByte(value, 10); } // HEX conversions /** * Converts a number to hex, e.g. 255 -> FF. Hex representations can be endian dependent. */ @Validate public static String toHex(@NotNull final UnsignedLong num) { return num.bigIntegerValue().toString(16); } /** * Converts a number to hex, e.g. 255 -> FF Hex representations can be endian dependent. */ @Validate public static String toHex(@NotNull final UnsignedLong num, boolean padLeft) { return !padLeft ? num.bigIntegerValue().toString(16) : StringUtils.padLeft(num.bigIntegerValue().toString(16), 16, CONSTANT.ZERO_CHAR); } /** * Converts a number to hex, e.g. 255 -> FF. Hex representations can be endian dependent. */ public static String toHex(long num) { return Long.toHexString(num); } /** * Converts a number to hex, e.g. 255 -> FF Hex representations can be endian dependent. */ public static String toHex(long num, boolean padLeft) { return !padLeft ? Long.toHexString(num) : StringUtils.padLeft(Long.toHexString(num), 16, CONSTANT.ZERO_CHAR); } /** * Converts a number to hex, e.g. 255 -> FF. Hex representations can be endian dependent. */ @Validate public static String toHex(@NotNull final UnsignedInteger num) { return num.bigIntegerValue().toString(16); } /** * Converts a number to hex, e.g. 255 -> FF Hex representations can be endian dependent. */ @Validate public static String toHex(@NotNull final UnsignedInteger num, boolean padLeft) { return !padLeft ? num.bigIntegerValue().toString(16) : StringUtils.padLeft(num.bigIntegerValue().toString(16), 8, CONSTANT.ZERO_CHAR); } /** * Converts a number to hex, e.g. 255 -> FF Hex representations can be endian dependent. */ public static String toHex(int num) { return Integer.toHexString(num); } /** * Converts a number to hex, e.g. 255 -> FF Hex representations can be endian dependent. */ public static String toHex(int num, boolean padLeft) { return !padLeft ? Integer.toHexString(num) : StringUtils.padLeft(Integer.toHexString(num), 8, CONSTANT.ZERO_CHAR); } /** * Converts a number to hex, e.g. 255 -> FF. Hex representations can be endian dependent. */ @Validate public static String toHex(@NotNull final UnsignedShort num) { return num.bigIntegerValue().toString(16); } /** * Converts a number to hex, e.g. 255 -> FF Hex representations can be endian dependent. */ @Validate public static String toHex(@NotNull final UnsignedShort num, boolean padLeft) { return !padLeft ? num.bigIntegerValue().toString(16) : StringUtils.padLeft(num.bigIntegerValue().toString(16), 4, CONSTANT.ZERO_CHAR); } /** * Converts a number to hex, e.g. 255 -> FF Hex representations can be endian dependent. */ public static String toHex(short num) { return Integer.toHexString(num); } /** * Converts a number to hex, e.g. 255 -> FF Hex representations can be endian dependent. */ public static String toHex(short num, boolean padLeft) { return !padLeft ? Integer.toHexString(num) : StringUtils.padLeft(Integer.toHexString(num), 4, CONSTANT.ZERO_CHAR); } /** * Converts a number to hex, e.g. 255 -> FF. Hex representations can be endian dependent. */ @Validate public static String toHex(@NotNull final UnsignedByte num) { return num.bigIntegerValue().toString(16); } /** * Converts a number to hex, e.g. 255 -> FF Hex representations can be endian dependent. */ @Validate public static String toHex(@NotNull final UnsignedByte num, boolean padLeft) { return !padLeft ? num.bigIntegerValue().toString(16) : StringUtils.padLeft(num.bigIntegerValue().toString(16), 2, CONSTANT.ZERO_CHAR); } /** * Converts a number to hex, e.g. 255 -> FF Hex representations can be endian dependent. */ public static String toHex(byte num) { return toHex(new byte[] { num }); } /** * Converts a number to hex, e.g. 255 -> FF Hex representations can be endian dependent. */ public static String toHex(byte num, boolean padLeft) { return !padLeft ? toHex(new byte[] { num }) : StringUtils.padLeft(toHex(new byte[] { num }), 2, CONSTANT.ZERO_CHAR); } /** * Converts a byte array to hex Hex representations can be endian dependent. * * @throws NullPointerException An argument is null. */ @Validate public static String toHex(@NotNull final byte[] ba) { return toHex(ba, 0, ba.length); } /** * Converts a byte array to hex Hex representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws IndexOutOfBoundsException An index is out of bounds. * @throws IllegalArgumentException An argument is out of range. */ @Validate public static String toHex(@NotNull final byte[] ba, int offset, int length) { if (offset < 0 || offset > ba.length) throw new IndexOutOfBoundsException("offset=" + offset + " baLen=" + ba.length); if (length < 0 || offset + length > ba.length || offset + length < 0) throw new IndexOutOfBoundsException("offset=" + offset + " length=" + length + " baLen=" + ba.length); final String HEX = "0123456789ABCDEF"; StringBuilder hex = new StringBuilder(2 * ba.length); for (int i = offset; i < offset + length; i++) hex.append(HEX.charAt((ba[i] & 0xF0) >> 4)).append(HEX.charAt((ba[i] & 0x0F))); return hex.toString(); } /** * Converts a hex string to a byte array Hex representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws IllegalArgumentException An argument is out of range. * @throws NumberFormatException A number could not be parsed. */ public static byte[] fromHexToByteArray(String hex) { return fromHexToByteArray(hex, 0, hex.length()); } /** * Converts a hex string to a byte array Hex representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws IndexOutOfBoundsException An index is out of bounds. * @throws IllegalArgumentException An argument is out of range. * @throws NumberFormatException A number could not be parsed. */ @Validate public static byte[] fromHexToByteArray(@NotNull final String hex, int startIndex, int length) { if (startIndex < 0 || startIndex > hex.length()) throw new IndexOutOfBoundsException("startIndex=" + startIndex + " hexLen=" + hex.length()); if (length < 0 || length + startIndex > hex.length() || length + startIndex < 0) throw new IllegalArgumentException( "startIndex=" + startIndex + " length=" + length + " hexLen=" + hex.length()); if (length == 0 || length % 2 != 0) throw new IllegalArgumentException("The hex string should use two digits per byte: " + hex.length()); byte[] result = new byte[hex.length() / 2]; for (int i = 0; i < result.length; i++) { int index = i * 2; int v = Integer.parseInt(hex.substring(index, index + 2), 16); result[i] = (byte) v; } return result; } /** * Converts a hex back to a ulong Hex representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static UnsignedLong fromHexToUInt64(@NotNull final String hex) { return new UnsignedLong(new BigInteger(hex, 16)); } /** * Converts a hex back to a long Hex representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static long fromHexToInt64(@NotNull final String hex) { return Long.parseLong(hex, 16); } /** * Converts a hex back to a uint Hex representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static UnsignedInteger fromHexToUInt32(@NotNull final String hex) { return new UnsignedInteger(new BigInteger(hex, 16)); } /** * Converts a hex back to an int Hex representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static int fromHexToInt32(@NotNull final String hex) { return Integer.parseInt(hex, 16); } /** * Converts a hex back to a ushort Hex representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static UnsignedInteger fromHexToUInt16(@NotNull final String hex) { return new UnsignedInteger(new BigInteger(hex, 16)); } /** * Converts a hex back to a short Hex representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ public static short fromHexToInt16(@NotNull final String hex) { int i = Integer.parseInt(hex, 16); if (i < Short.MIN_VALUE || i > Short.MAX_VALUE) throw new NumberFormatException("The hex string '" + hex + "' cannot be represented as a Short."); return (short) i; } /** * Converts a hex back to a ushort Hex representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static UnsignedByte fromHexToUInt8(@NotNull final String hex) { return new UnsignedByte(new BigInteger(hex, 16)); } /** * Converts a hex back to a byte Hex representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static byte fromHexToByte(@NotNull final String hex) { int i = Integer.parseInt(hex, 16); if (i < Byte.MIN_VALUE || i > Byte.MAX_VALUE) throw new NumberFormatException("The hex string '" + hex + "' cannot be represented as a Byte."); return (byte) i; } // BASE64 conversions /** * Converts a number to Base64. Base64 representations can be endian dependent. */ public static String toBase64(UnsignedLong num) { return Base64.encodeBytes(ByteArrayUtils.getBytes(num)); } /** * Converts a number to Base64. Base64 representations can be endian dependent. */ public static String toBase64(long num) { return Base64.encodeBytes(ByteArrayUtils.getBytes(num)); } /** * Converts a number to Base64. Base64 representations can be endian dependent. */ public static String toBase64(UnsignedInteger num) { return Base64.encodeBytes(ByteArrayUtils.getBytes(num)); } /** * Converts a number to Base64. Base64 representations can be endian dependent. */ public static String toBase64(int num) { return Base64.encodeBytes(ByteArrayUtils.getBytes(num)); } /** * Converts a number to Base64. Base64 representations can be endian dependent. */ public static String toBase64(UnsignedShort num) { return Base64.encodeBytes(ByteArrayUtils.getBytes(num)); } /** * Converts a number to Base64. Base64 representations can be endian dependent. */ public static String toBase64(short num) { return Base64.encodeBytes(ByteArrayUtils.getBytes(num)); } /** * Converts a number to Base64. Base64 representations can be endian dependent. */ public static String toBase64(byte num) { return Base64.encodeBytes(new byte[] { num }); } /** * Converts a byte array to Base64. Base64 representations can be endian dependent. * * @throws NullPointerException An argument is null. */ public static String toBase64(byte[] array) { return Base64.encodeBytes(array); } /** * Converts a byte array to Base64. Base64 representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws IndexOutOfBoundsException An index is out of bounds. * @throws IllegalArgumentException An argument is out of range. */ @Validate public static String toBase64(@NotNull final byte[] array, int offset, int length) { return Base64.encodeBytes(array, offset, length); } /** * Converts a Base64 back to a long. Base64 representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static long fromBase64ToInt64(@NotNull final String base64) { try { return ByteArrayUtils.toInt64(Base64.decode(base64)); } catch (Throwable e) { throw new NumberFormatException( "The base64 string '" + base64 + "' could not be parsed as a Long: " + e.getMessage()); } } /** * Converts a Base64 back to a ulong. Base64 representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static UnsignedLong fromBase64ToUInt64(@NotNull final String base64) { try { return ByteArrayUtils.toUInt64(Base64.decode(base64)); } catch (Throwable e) { throw new NumberFormatException( "The base64 string '" + base64 + "' could not be parsed as a ULong: " + e.getMessage()); } } /** * Converts a Base64 back to an int. Base64 representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static int fromBase64ToInt32(@NotNull final String base64) { try { return ByteArrayUtils.toInt32(Base64.decode(base64)); } catch (Throwable e) { throw new NumberFormatException( "The base64 string '" + base64 + "' could not be parsed as an Int: " + e.getMessage()); } } /** * Converts a Base64 back to a uint. Base64 representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static UnsignedInteger fromBase64ToUInt32(@NotNull final String base64) { try { return ByteArrayUtils.toUInt32(Base64.decode(base64)); } catch (Throwable e) { throw new NumberFormatException( "The base64 string '" + base64 + "' could not be parsed as a UInt: " + e.getMessage()); } } /** * Converts a Base64 back to a short. Base64 representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static short fromBase64ToInt16(@NotNull final String base64) { try { return ByteArrayUtils.toInt16(Base64.decode(base64)); } catch (Throwable e) { throw new NumberFormatException( "The base64 string '" + base64 + "' could not be parsed as an Short: " + e.getMessage()); } } /** * Converts a Base64 back to a ushort. Base64 representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static UnsignedShort fromBase64ToUInt16(@NotNull final String base64) { try { return ByteArrayUtils.toUInt16(Base64.decode(base64)); } catch (Throwable e) { throw new NumberFormatException( "The base64 string '" + base64 + "' could not be parsed as an Short: " + e.getMessage()); } } /** * Converts a Base64 back to a byte. Base64 representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws NumberFormatException A number could not be parsed. */ @Validate public static byte fromBase64ToByte(@NotNull final String base64) { try { short s = ByteArrayUtils.toInt16(Base64.decode(base64)); if (s < Byte.MIN_VALUE || s > Byte.MAX_VALUE) throw new Exception("Byte value is out of valid range."); return (byte) s; } catch (Throwable e) { throw new NumberFormatException( "The base64 string '" + base64 + "' could not be parsed as a Byte: " + e.getMessage()); } } /** * Converts a Base64 representation to a byte array. Base64 representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws IllegalArgumentException An argument is out of range. * @throws NumberFormatException A number could not be parsed. */ @Validate public static byte[] fromBase64ToByteArray(@NotNull final String base64) { try { return Base64.decode(base64); } catch (Throwable e) { throw new IllegalArgumentException("The specified base64 string could not be decoded.", e); } } /** * Converts a Base64 representation to a byte array. Base64 representations can be endian dependent. * * @throws NullPointerException An argument is null. * @throws IndexOutOfBoundsException An index is out of range. * @throws IllegalArgumentException An argument is out of range. * @throws NumberFormatException A number could not be parsed. */ @Validate public static byte[] fromBase64ToByteArray(@NotNull final String base64, int startIndex, int length) { if (startIndex < 0 || startIndex > base64.length()) throw new IndexOutOfBoundsException("startIndex=" + startIndex + " baseLen=" + base64.length()); if (length < 0 || startIndex + length > base64.length() || startIndex + length < 0) throw new IllegalArgumentException( "startIndex=" + startIndex + " length=" + length + " base64Len=" + base64.length()); try { return Base64.decode(base64.substring(startIndex, startIndex + length)); } catch (Throwable e) { throw new IllegalArgumentException("The specified base64 string could not be decoded.", e); } } // Alphanumeric conversions /** * Converts a number to alphanumeric, e.g. 0 -> 0, 16 -> G, 61 -> z, 62 -> 10. Only works for positive numbers. */ @Validate public static String toAlphanumeric(@NotNull final UnsignedLong num) { if (num.bigIntegerValue().equals(BigInteger.ZERO)) return CONSTANT.ZERO; StringBuilder sb = new StringBuilder(16); BigInteger sixtyTwo = new BigInteger("62"); BigInteger value = num.bigIntegerValue(); // this algorithm gives us the alphanumeric number in reverse order while (value.compareTo(BigInteger.ZERO) > 0) { int remainder = value.mod(sixtyTwo).intValue(); sb.append(CONSTANT.ALPHANUMERIC_DIGITS[remainder]); value = value.divide(sixtyTwo); } // reverse result return StringUtils.reverse(sb.toString()); } /** * Converts a number to alphanumeric, e.g. 0 -> 0, 16 -> G, 61 -> z, 62 -> 10 */ @Validate public static String toAlphanumeric(@NotNull final UnsignedLong num, boolean padLeft) { return !padLeft ? toAlphanumeric(num) : StringUtils.padLeft(toAlphanumeric(num), 11, CONSTANT.ZERO_CHAR); } /** * Converts a byte array to alphanumeric * * @throws NullPointerException An argument is null. */ @Validate public static String toAlphanumeric(@NotNull final byte[] ba) { return toAlphanumeric(ba, 0, ba.length); } /** * Converts a byte array to alphanumeric * * @throws NullPointerException An argument is null. * @throws IndexOutOfBoundsException An index is out of bounds. * @throws IllegalArgumentException An argument is out of range. */ @Validate public static String toAlphanumeric(@NotNull final byte[] ba, int offset, int length) { if (offset < 0 || offset > ba.length) throw new IndexOutOfBoundsException("offset=" + offset + " baLen=" + ba.length); if (length < 0 || length + offset > ba.length || length + offset < 0) throw new IllegalArgumentException("length=" + length + " offset=" + offset + " baLen=" + ba.length); if (length == 0 || length % 8 != 0) throw new IllegalArgumentException("Length should be divisible by 8: " + length); // convert blocks to alphanumerics StringBuilder sb = new StringBuilder(16); for (int i = offset; i < offset + length; i += 8) { byte[] ulBytes = ByteArrayUtils.subarray(ba, i, 8); UnsignedLong num = ByteArrayUtils.toUInt64(ulBytes); sb.append(toAlphanumeric(num, true)); } return sb.toString(); } /** * Converts an alphanumeric string to a byte array * * @throws NullPointerException An argument is null. * @throws IllegalArgumentException An argument is out of range. * @throws NumberFormatException A number could not be parsed. */ @Validate public static byte[] fromAlphanumericToByteArray(@NotNull final String alphanumeric) { return fromAlphanumericToByteArray(alphanumeric, 0, alphanumeric.length()); } /** * Converts an alphanumeric string to a byte array * * @throws NullPointerException An argument is null. * @throws IndexOutOfBoundsException An index is out of bounds. * @throws IllegalArgumentException An argument is out of range. * @throws NumberFormatException A number could not be parsed. */ @Validate public static byte[] fromAlphanumericToByteArray(@NotNull final String alphanumeric, int startIndex, int length) { if (startIndex < 0 || startIndex > alphanumeric.length()) throw new IndexOutOfBoundsException("startIndex=" + startIndex + " alphaLen=" + alphanumeric.length()); if (length < 0 || length + startIndex > alphanumeric.length() || length + startIndex < 0) throw new IllegalArgumentException( "length=" + length + " startIndex=" + startIndex + " alphaLen=" + alphanumeric.length()); if (length == 0 || alphanumeric.length() % 11 != 0) throw new NumberFormatException( "The alphanumeric string should use 11 digits per word: " + alphanumeric.length()); byte[] result = new byte[alphanumeric.length() / 11 * 8]; int j = 0; for (int i = 0; i < alphanumeric.length(); i += 11) { UnsignedLong num = fromAlphanumericToUInt64(alphanumeric.substring(i, i + 11)); byte[] bytes = ByteArrayUtils.getBytes(num); System.arraycopy(bytes, 0, result, j, 8); j += 8; } return result; } /** * Converts an alphanumeric back to a ulong * * @throws NullPointerException An argument is null * @throws NumberFormatException A number could not be parsed. */ @Validate public static UnsignedLong fromAlphanumericToUInt64(@NotNull final String alphanumeric) { if (alphanumeric.equals(CONSTANT.ZERO)) return new UnsignedLong(BigInteger.ZERO); UnsignedLong result = new UnsignedLong(BigInteger.ZERO); BigInteger sixtyTwo = new BigInteger("62"); int len = alphanumeric.length(); for (int i = 0; i < len; i++) { char ch = alphanumeric.charAt(i); if (!StringUtils.contains(CONSTANT.ALPHANUMERIC_DIGITS, ch)) throw new NumberFormatException( "The digit does not belong to the alphanumeric number structure: " + ch); // add and check for overflows int pos = len - i - 1; int charIndex = StringUtils.indexOf(CONSTANT.ALPHANUMERIC_DIGITS, ch); BigInteger added = sixtyTwo.pow(pos).multiply(new BigInteger(charIndex + "")); result = new UnsignedLong(result.bigIntegerValue().add(added)); } return result; } /* * TODO: implement these * * // Human-readable values // TODO: these are locale sensitive date formats * * /// <summary> /// Built-in date/time ToString styles. /// </summary> public enum DateTimeStyle { /// <summary> /// Displays e.g. * 15/04/2008 for en-GB, 04/15/2008 for en-US, 4/15/2008 for en-NZ, 15.04.2008 for de-DE, etc. /// </summary> ShortDate, /// <summary> /// * Displays e.g. Thursday, April 10, 2008 for en-GB, quinta-feira, 10 de abril de 2008 for pt-BR, jueves, 10 de abril de 2008 for es-MX * /// </summary> LongDate, /// <summary> /// Displays e.g. Thursday, April 10, 2008 6:30 AM for en-US, jeudi 10 avril 2008 06:30 for * fr-FR /// </summary> FullDateShortTime, /// <summary> /// Displays e.g. Thursday, April 10, 2008 6:30:00 AM for en-US, jeudi 10 avril * 2008 06:30:00 for fr-FR /// </summary> FullDateLongTime, /// <summary> /// Displays e.g. 4/10/2008 6:30 AM for en-US, 10/04/2008 6:30 * for fr-BE /// </summary> GeneralDateShortTime, /// <summary> /// Displays e.g. 4/10/2008 6:30:00 AM for en-US, 10/04/2008 6:30:00 for * nl-BE /// </summary> GeneralDateLongTime, /// <summary> /// Displays e.g. April 10 for en-US, 10 April for ms-MY /// </summary> * MonthDay, /// <summary> /// Displays e.g. 2008-04-10T06:30:00.0000000 for a DateTime, 2008-04-10T06:30:00.0000000-07:00 for a * DateTimeOffset /// </summary> RoundTrip, /// <summary> /// Displays e.g. Thu, 10 Apr 2008 13:30:00 GMT /// </summary> Rfc1123, /// * <summary> /// Displays e.g. 2008-04-10T06:30:00 /// </summary> Sortable, /// <summary> /// Displays e.g. 6:30 AM for en-US, 6:30 for * es-ES /// </summary> ShortTime, /// <summary> /// Displays e.g. 6:30:00 AM for en-US, 6:30:00 AM for es-ES /// </summary> LongTime, /// * <summary> /// Displays e.g. 2008-04-10 13:30:00Z /// </summary> UniversalSortable, /// <summary> /// Displays e.g. Thursday, April 10, * 2008 1:30:00 PM for en-US, den 10 april 2008 13:30:00 for sv-FI /// </summary> UniversalFull, /// <summary> /// Displays e.g. April, * 2008 for en-US, April 2008 for af-ZA /// </summary> YearMonth } */ @Validate public static String toHumanReadable(@NotNull final Period p) { return toHumanReadable(p.toStandardDuration()); } /** * Returns the value of the given timespan in a human-readable form, appending the suffix. * * <pre> * Example: 10 seconds become "less than a minute". * Example: 1.1 minutes become "about a minute from now". * Example: 50 minutes become "50 minutes". * Example: 13 hours, 10 minutes become "about 13 hours". * The suffix " ago" or " from now" is appended depending on the sign of the timespan. * </pre> */ @Validate public static String toHumanReadable(@NotNull Duration ts) { String suffix = " ago"; if (ts.getMillis() < 0.0) { // negate ts = new Duration(-ts.getMillis()); // indicate this is suffix = " from now"; } return toHumanReadable(ts, suffix); } /** * Returns the value of the given timespan in a human-readable form, appending the suffix. Example: 10 seconds become * "less than a minute". Example: 1.1 minutes become "about a minute". Example: 50 minutes become "50 minutes". Example: 13 hours, 10 * minutes become "about 13 hours". The suffix can be used to describe the event's position in time, use e.g. " ago" or " from now" */ @Validate public static String toHumanReadable(@NotNull final Duration ts, @NotNull final String suffix) { val values = new AvlHashtable<Double, String>(Double.class, String.class); long totalSeconds = Math.abs(ts.getStandardSeconds()); final double totalMinutes = Math.round(totalSeconds / 60); double totalHours = Math.round(totalMinutes / 60); double totalDays = Math.floor(totalHours / 24); double totalMonths = Math.floor(totalDays / 30); double totalYears = Math.floor(totalMonths / 12); values.add(0.75d, "less than a minute"); values.add(1.5d, "about a minute"); values.add(45d, String.format("%d minutes", (int) totalMinutes)); values.add(90d, "about an hour"); values.add(1440d, String.format("about %d hours", (int) totalHours)); // 60 * 24 values.add(2880d, "a day"); // 60 * 48 values.add(43200d, String.format("%d days", (int) totalDays)); // 60 * 24 * 30 values.add(86400d, "about a month"); // 60 * 24 * 60 values.add(525600d, String.format("%d months", (int) totalMonths)); // 60 * 24 * 365 values.add(1051200d, "about a year"); // 60 * 24 * 365 * 2 values.add(Double.MAX_VALUE, String.format("%d years", (int) totalYears)); Double key = Linq.first(values.getKeys(), keyGreaterThan(totalMinutes)); return values.get(key) + suffix; } @Predicate private static boolean keyGreaterThan(Double key, final double _totalMinutes) { return _totalMinutes < key; } /** * Returns the value of the given number in a human-readable form. Example: 1000 becomes 1,000 (UK) or 1.000 (US). */ public static String toHumanReadable(long number) { return new Formatter().format("%,d", number).toString(); } /** * Returns the value of the given number in a human-readable form. Example: 1000 becomes 1,000 (UK) or 1.000 (US). */ public static String toHumanReadable(int number) { return new Formatter().format("%,d", number).toString(); } /** * Returns the value of the given number in a human-readable form. Example: 1000 becomes 1,000 (UK) or 1.000 (US). */ public static String toHumanReadable(short number) { return new Formatter().format("%,d", number).toString(); } /** * Returns the value of the given number in a human-readable form. Example: 1000 becomes 1,000 (UK) or 1.000 (US). */ public static String toHumanReadable(byte number) { return new Formatter().format("%,d", number).toString(); } /** * Returns the value of the given number in a human-readable form. Example: 1000 becomes 1,000 (UK) or 1.000 (US). */ public static String toHumanReadable(float number) { return new Formatter().format("%,f", number).toString(); } /** * Returns the value of the given number in a human-readable form. Example: 1000 becomes 1,000 (UK) or 1.000 (US). * * @throws IllegalArgumentException An argument was invalid */ public static String toHumanReadable(float number, int decimalPlaces) { if (decimalPlaces < 0) throw new IllegalArgumentException("decimalPlaces=" + decimalPlaces); return new Formatter().format("%,." + decimalPlaces + "f", number).toString(); } /** * Returns the value of the given number in a human-readable form. Example: 1000 becomes 1,000 (UK) or 1.000 (US). */ public static String toHumanReadable(double number) { return new Formatter().format("%,f", number).toString(); } /** * Returns the value of the given number in a human-readable form. Example: 1000 becomes 1,000 (UK) or 1.000 (US). * * @throws IllegalArgumentException An argument was invalid */ public static String toHumanReadable(double number, int decimalPlaces) { if (decimalPlaces < 0) throw new IllegalArgumentException("decimalPlaces=" + decimalPlaces); return new Formatter().format("%,." + decimalPlaces + "f", number).toString(); } /** * Returns the value of the given number in a human-readable form. Example: 1000 becomes 1,000 (UK) or 1.000 (US). * * @throws NullPointerException An argument is null */ @Validate public static String toHumanReadable(@NotNull final BigDecimal number) { return new Formatter().format("%,f", number).toString(); } /** * Returns the value of the given number in a human-readable form. Example: 1000 becomes 1,000 (UK) or 1.000 (US). * * @throws NullPointerException An argument is null * @throws IllegalArgumentException An argument was invalid */ @Validate public static String toHumanReadable(@NotNull final BigDecimal number, int decimalPlaces) { return new Formatter().format("%,." + decimalPlaces + "f", number).toString(); } // TODO: implement these /* * /// <summary> /// Returns the date/time value in a human-readable and standard form, /// as specified by the given style selection. * Uses current thread locale. /// </summary> public static String ToHumanReadable(DateTime dateTime, DateTimeStyle style) { return * ToHumanReadable(dateTime, style, CultureInfo.CurrentCulture); } /// <summary> /// Returns the date/time value in a human-readable and * standard form, /// as specified by the given style selection. Uses current specified locale. /// </summary> /// <exception * cref="ArgumentException">Unrecognized date/time style used.</exception> public static String ToHumanReadable(DateTime dateTime, * DateTimeStyle style, CultureInfo cultureInfo) { switch(style) { case DateTimeStyle.ShortDate: return dateTime.ToString("d", * cultureInfo); case DateTimeStyle.LongDate: return dateTime.ToString("D", cultureInfo); case DateTimeStyle.FullDateShortTime: return * dateTime.ToString("f", cultureInfo); case DateTimeStyle.FullDateLongTime: return dateTime.ToString("F", cultureInfo); case * DateTimeStyle.GeneralDateShortTime: return dateTime.ToString("g", cultureInfo); case DateTimeStyle.GeneralDateLongTime: return * dateTime.ToString("G", cultureInfo); case DateTimeStyle.MonthDay: return dateTime.ToString("m", cultureInfo); case * DateTimeStyle.RoundTrip: return dateTime.ToString("o", cultureInfo); case DateTimeStyle.Rfc1123: return dateTime.ToString("r", * cultureInfo); case DateTimeStyle.Sortable: return dateTime.ToString("s", cultureInfo); case DateTimeStyle.ShortTime: return * dateTime.ToString("t", cultureInfo); case DateTimeStyle.LongTime: return dateTime.ToString("T", cultureInfo); case * DateTimeStyle.UniversalSortable: return dateTime.ToString("u", cultureInfo); case DateTimeStyle.UniversalFull: return * dateTime.ToString("U", cultureInfo); case DateTimeStyle.YearMonth: return dateTime.ToString("y", cultureInfo); default: throw new * ArgumentException("Unrecognized date/time format: " + style); } } */ // Text <-> Byte-array conversions /** * Converts a UTF8-encoded string to a byte[] * * @throws NullPointerException An argument is null. * @throws RuntimeException The UTF8 encoding is not supported. */ @Validate public static byte[] toByteArray(@NotNull final String text) { try { return text.getBytes(CONSTANT.UTF8); } catch (Throwable e) { throw new RuntimeException("UTF8 encoding is not supported by this JVM.", e); } } /** * Converts a UTF8-encoded string to a byte[] * * @throws NullPointerException An argument is null. * @throws IndexOutOfBoundsException An index is out of bounds * @throws IllegalArgumentException An argument is out of range * @throws RuntimeException The UTF8 encoding is not supported */ @Validate public static byte[] toByteArray(@NotNull final String text, int index, int count) { if (index < 0 || index > text.length()) throw new IndexOutOfBoundsException("index=" + index + " textLen=" + text.length()); if (count < 0 || index + count > text.length() || index + count < 0) throw new IllegalArgumentException("count=" + count + " index=" + index + " textLen=" + text.length()); return toByteArray(text.substring(index, index + count)); } /** * Converts a string to a byte[] * * @throws NullPointerException An argument is null. */ @Validate public static byte[] toByteArray(@NotNull final String text, @NotNull final Charset encoding) { return text.getBytes(encoding); } /** * Converts a string to a byte[] * * @throws NullPointerException An argument is null. * @throws IndexOutOfBoundsException An index is out of bounds * @throws IllegalArgumentException An argument is out of range * @throws RuntimeException The UTF8 encoding is not supported */ @Validate public static byte[] toByteArray(@NotNull final String text, @NotNull final Charset encoding, int index, int count) { if (index < 0 || index > text.length()) throw new IndexOutOfBoundsException("index=" + index + " textLen=" + text.length()); if (count < 0 || index + count > text.length() || index + count < 0) throw new IllegalArgumentException("count=" + count + " index=" + index + " textLen=" + text.length()); return text.substring(index, index + count).getBytes(encoding); } /** * Converts a byte array to a UTF8-encoded string */ @Validate public static String toString(@NotNull final byte[] ba) { return new String(ba); } /** * Converts a byte array to a UTF8-encoded string * * @throws NullPointerException An argument is null. * @throws IndexOutOfBoundsException An index is out of bounds * @throws IllegalArgumentException An argument is out of range */ @Validate public static String toString(@NotNull final byte[] ba, int index, int count) { if (index < 0 || index > ba.length) throw new IndexOutOfBoundsException("index=" + index + " baLen=" + ba.length); if (count < 0 || index + count > ba.length || index + count < 0) throw new IllegalArgumentException("count=" + count + " index=" + index + " baLen=" + ba.length); return new String(ba, index, count); } /** * Converts a byte array to an encoded string * * @throws NullPointerException An argument is null. */ @Validate public static String toString(@NotNull final byte[] ba, @NotNull final Charset encoding) { return new String(ba, encoding); } /** * Converts a byte array to an encoded string * * @throws NullPointerException An argument is null. * @throws IndexOutOfBoundsException An index is out of bounds * @throws IllegalArgumentException An argument is out of range */ @Validate public static String toString(@NotNull final byte[] ba, @NotNull final Charset encoding, int index, int count) { if (index < 0 || index > ba.length) throw new IndexOutOfBoundsException("index=" + index + " baLen=" + ba.length); if (count < 0 || index + count > ba.length || index + count < 0) throw new IllegalArgumentException("count=" + count + " index=" + index + " baLen=" + ba.length); return new String(ba, index, count, encoding); } private static Object changeTypeFromPrimitive(Object value, PrimitiveType sourceType, Class<?> targetType) { switch (sourceType) { case Boolean: return changeTypeFromBoolean(Boolean.valueOf(value.toString()), targetType); case Char: if (StringUtils.isNullOrEmpty(value.toString())) throw new IllegalArgumentException("Cannot change primitive to Char, because it is null or empty."); return changeTypeFromCharacter(Character.valueOf(value.toString().charAt(0)), targetType); case Byte: return changeTypeFromNumber(Byte.valueOf(value.toString()), targetType); case Short: return changeTypeFromNumber(Short.valueOf(value.toString()), targetType); case Int: return changeTypeFromNumber(Integer.valueOf(value.toString()), targetType); case Long: return changeTypeFromNumber(Long.valueOf(value.toString()), targetType); case Double: return changeTypeFromNumber(Double.valueOf(value.toString()), targetType); case Float: return changeTypeFromNumber(Float.valueOf(value.toString()), targetType); default: throw new IllegalArgumentException("Unexpected source type: " + sourceType); } } private static Object changeTypeFromNumber(Object value, Class<?> targetType) { Number number = (Number) value; // dispatch to appropriate constructor method if (targetType.equals(Byte.class)) return new Byte(number.byteValue()); if (targetType.equals(Boolean.class)) return number.longValue() == 0 ? new Boolean(false) : new Boolean(true); if (targetType.equals(Short.class)) return new Short(number.shortValue()); if (targetType.equals(Integer.class)) return new Integer(number.intValue()); if (targetType.equals(Long.class)) return new Long(number.longValue()); if (targetType.equals(Float.class)) return new Float(number.floatValue()); if (targetType.equals(Double.class)) return new Double(number.doubleValue()); if (targetType.equals(Character.class)) return new Character((char) number.shortValue()); if (targetType.equals(byte.class)) return number.byteValue(); if (targetType.equals(boolean.class)) return number.longValue() == 0 ? false : true; if (targetType.equals(char.class)) return (char) number.shortValue(); if (targetType.equals(short.class)) return number.shortValue(); if (targetType.equals(int.class)) return number.intValue(); if (targetType.equals(long.class)) return number.longValue(); if (targetType.equals(float.class)) return number.floatValue(); if (targetType.equals(double.class)) return number.doubleValue(); if (targetType.equals(LocalDateTime.class)) return new LocalDateTime(number.longValue()); if (targetType.equals(DateTime.class)) return new DateTime(number.longValue()); if (targetType.equals(BigDecimal.class)) return new BigDecimal(number.toString()); if (targetType.equals(Duration.class)) return new Duration(number.longValue()); if (targetType.equals(Period.class)) return new Period(number.longValue()); if (targetType.equals(Int128.class)) return new Int128(number.toString()); if (targetType.equals(UnsignedByte.class)) return new UnsignedByte((short) (number.byteValue() & 0xFF)); if (targetType.equals(UnsignedShort.class)) return new UnsignedShort((int) (number.shortValue() & 0xFFFF)); if (targetType.equals(UnsignedInteger.class)) return new UnsignedInteger((long) (number.intValue() & 0xFFFFFFFF)); if (targetType.equals(UnsignedLong.class)) { // perform similar operation as above to get rid of the negative values long ln = new BigInteger(number.toString()).longValue(); return new UnsignedLong(new BigInteger("0" + toBinary(ln))); } if (targetType.equals(SignedByte.class)) return new SignedByte(number.byteValue()); if (targetType.equals(BigInteger.class)) return new BigInteger(number.toString()); if (targetType.equals(propel.core.userTypes.BigInteger.class)) { propel.core.userTypes.BigInteger bi = new propel.core.userTypes.BigInteger(); bi.setCurrentValue(number.toString()); return bi; } throw new IllegalArgumentException("The provided Number could not be converted to type '" + targetType.getSimpleName() + "': " + value); } private static Object changeTypeFromCharacter(Object value, Class<?> targetType) { char ch = ((Character) value).charValue(); // dispatch to appropriate construction method if (targetType.equals(Byte.class)) return new Byte((byte) ch); if (targetType.equals(Boolean.class)) return ch == 0 ? new Boolean(false) : new Boolean(true); if (targetType.equals(Short.class)) return new Short((short) ch); if (targetType.equals(Integer.class)) return new Integer(ch); if (targetType.equals(Long.class)) return new Long(ch); if (targetType.equals(Float.class)) return new Float(ch); if (targetType.equals(Double.class)) return new Double(ch); if (targetType.equals(byte.class)) return (byte) ch; if (targetType.equals(boolean.class)) return ch == 0 ? false : true; if (targetType.equals(char.class)) return ch; if (targetType.equals(short.class)) return (short) ch; if (targetType.equals(int.class)) return (int) ch; if (targetType.equals(long.class)) return (long) ch; if (targetType.equals(float.class)) return (float) ch; if (targetType.equals(double.class)) return (double) ch; if (targetType.equals(LocalDateTime.class)) return new LocalDateTime((long) ch); if (targetType.equals(DateTime.class)) return new DateTime((long) ch); if (targetType.equals(BigDecimal.class)) return new BigDecimal(ch); if (targetType.equals(Duration.class)) return new Duration((long) ch); if (targetType.equals(Period.class)) return new Period((long) ch); if (targetType.equals(Int128.class)) return new Int128(Integer.valueOf(ch).toString()); if (targetType.equals(UnsignedByte.class)) return new UnsignedByte((byte) ch); if (targetType.equals(UnsignedShort.class)) return new UnsignedShort(ch); if (targetType.equals(UnsignedInteger.class)) return new UnsignedInteger(ch); if (targetType.equals(UnsignedLong.class)) return new UnsignedLong(new Integer(ch).toString()); if (targetType.equals(SignedByte.class)) return new SignedByte((byte) ch); if (targetType.equals(BigInteger.class)) return new BigInteger(Integer.valueOf(ch).toString()); if (targetType.equals(propel.core.userTypes.BigInteger.class)) { propel.core.userTypes.BigInteger bi = new propel.core.userTypes.BigInteger(); bi.setCurrentValue(Integer.valueOf(ch).toString()); return bi; } throw new IllegalArgumentException("The provided Character could not be converted to type '" + targetType.getSimpleName() + "': " + value); } private static Object changeTypeFromBoolean(Object value, Class<?> targetType) { boolean bool = ((Boolean) value).booleanValue(); // dispatch to appropriate construction method if (targetType.equals(Byte.class)) return bool ? new Byte((byte) 1) : new Byte((byte) 0); if (targetType.equals(Character.class)) return bool ? new Character((char) 0) : new Character((char) 1); if (targetType.equals(Short.class)) return bool ? new Short((short) 1) : new Short((short) 0); if (targetType.equals(Integer.class)) return bool ? new Integer(1) : new Integer(0); if (targetType.equals(Long.class)) return bool ? new Long(1) : new Long(0); if (targetType.equals(Float.class)) return bool ? new Float(1) : new Float(0); if (targetType.equals(Double.class)) return bool ? new Double(1) : new Double(0); if (targetType.equals(byte.class)) return bool ? (byte) 1 : (byte) 0; if (targetType.equals(boolean.class)) return bool; if (targetType.equals(char.class)) return bool ? (char) 1 : (char) 0; if (targetType.equals(short.class)) return bool ? (short) 1 : (short) 0; if (targetType.equals(int.class)) return bool ? (int) 1 : (int) 0; if (targetType.equals(long.class)) return bool ? (long) 1 : (long) 0; if (targetType.equals(float.class)) return bool ? (float) 1.0 : (float) 0.0; if (targetType.equals(double.class)) return bool ? (double) 1.0 : (double) 0.0; if (targetType.equals(LocalDateTime.class)) return bool ? new LocalDateTime(1) : new LocalDateTime(0); if (targetType.equals(DateTime.class)) return bool ? new DateTime(1) : new DateTime(0); if (targetType.equals(BigDecimal.class)) return bool ? new BigDecimal(1) : new BigDecimal(0); if (targetType.equals(Duration.class)) return bool ? new Duration(1) : new Duration(0); if (targetType.equals(Period.class)) return bool ? new Period(1) : new Period(0); if (targetType.equals(Int128.class)) return bool ? new Int128("1") : new Int128("0"); if (targetType.equals(UnsignedByte.class)) return bool ? new UnsignedByte((byte) 1) : new UnsignedByte((byte) 0); if (targetType.equals(UnsignedShort.class)) return bool ? new UnsignedShort(1) : new UnsignedShort(0); if (targetType.equals(UnsignedInteger.class)) return bool ? new UnsignedInteger(1) : new UnsignedInteger(0); if (targetType.equals(UnsignedLong.class)) return bool ? new UnsignedLong("1") : new UnsignedLong("0"); if (targetType.equals(SignedByte.class)) return bool ? new SignedByte("1") : new SignedByte("0"); if (targetType.equals(BigInteger.class)) return bool ? new BigInteger("1") : new BigInteger("0"); if (targetType.equals(propel.core.userTypes.BigInteger.class)) { propel.core.userTypes.BigInteger bi = new propel.core.userTypes.BigInteger(); bi.setCurrentValue(bool ? "1" : "0"); return bi; } throw new IllegalArgumentException("The provided Boolean could not be converted to type '" + targetType.getSimpleName() + "': " + value); } private static Object changeTypeParseFromString(Object value, Class<?> targetType) { String str = value.toString(); // dispatch to appropriate parser method if (targetType.equals(Byte.class)) return new Byte(StringUtils.parseInt8(str)); if (targetType.equals(Boolean.class)) return new Boolean(StringUtils.parseBool(str)); if (targetType.equals(Character.class)) return new Character(StringUtils.parseChar(str)); if (targetType.equals(Short.class)) return new Short(StringUtils.parseInt16(str)); if (targetType.equals(Integer.class)) return new Integer(StringUtils.parseInt32(str)); if (targetType.equals(Long.class)) return new Long(StringUtils.parseInt64(str)); if (targetType.equals(Float.class)) return new Float(StringUtils.parseFloat(str)); if (targetType.equals(Double.class)) return new Double(StringUtils.parseDouble(str)); if (targetType.equals(byte.class)) return StringUtils.parseInt8(str); if (targetType.equals(boolean.class)) return StringUtils.parseBool(str); if (targetType.equals(char.class)) return StringUtils.parseChar(str); if (targetType.equals(short.class)) return StringUtils.parseInt16(str); if (targetType.equals(int.class)) return StringUtils.parseInt32(str); if (targetType.equals(long.class)) return StringUtils.parseInt64(str); if (targetType.equals(float.class)) return StringUtils.parseFloat(str); if (targetType.equals(double.class)) return StringUtils.parseDouble(str); if (targetType.equals(LocalDateTime.class)) return StringUtils.parseDateTime(str); if (targetType.equals(DateTime.class)) return StringUtils.parseDateTime(str).toDateTime(); if (targetType.equals(BigDecimal.class)) return StringUtils.parseDecimal(str); if (targetType.equals(Duration.class)) return StringUtils.parseTimeSpan(str); if (targetType.equals(Period.class)) return StringUtils.parseTimeSpan(str).toPeriod(); if (targetType.equals(Int128.class)) return StringUtils.parseInt128(str); if (targetType.equals(UnsignedByte.class)) return new UnsignedByte(str); if (targetType.equals(UnsignedShort.class)) return new UnsignedShort(str); if (targetType.equals(UnsignedInteger.class)) return new UnsignedInteger(str); if (targetType.equals(UnsignedLong.class)) return new UnsignedLong(str); if (targetType.equals(SignedByte.class)) return new SignedByte(str); if (targetType.equals(BigInteger.class)) return new BigInteger(str); if (targetType.equals(propel.core.userTypes.BigInteger.class)) { propel.core.userTypes.BigInteger bi = new propel.core.userTypes.BigInteger(); bi.setCurrentValue(str); return bi; } throw new IllegalArgumentException("The provided object could not be converted to type '" + targetType.getSimpleName() + "': " + value); } private ConversionUtils() { } }