Interface Encoding<T>
- Type Parameters:
T- The associated Java type
- All Superinterfaces:
Comparator<T>,NaturalSortAware,Serializable
- All Known Implementing Classes:
AbstractEncoding,ArrayEncoding,Base64ArrayEncoding,BigDecimalEncoding,BigIntegerEncoding,BitSetEncoding,BooleanArrayEncoding,BooleanEncoding,ByteArrayEncoding,ByteEncoding,CharacterArrayEncoding,CharacterEncoding,Concat2Encoding,Concat3Encoding,Concat4Encoding,Concat5Encoding,ConvertedEncoding,DateEncoding,DoubleArrayEncoding,DoubleEncoding,DoubleSummaryStatisticsEncoding,DurationEncoding,EnumValueEncoding,FileEncoding,FloatArrayEncoding,FloatEncoding,Inet4AddressEncoding,Inet6AddressEncoding,InetAddressEncoding,InstantEncoding,IntegerArrayEncoding,IntegerEncoding,IntegralArrayEncoding,IntegralEncoding,InternetAddressEncoding,IntSummaryStatisticsEncoding,LocalDateEncoding,LocalDateTimeEncoding,LocalTimeEncoding,LongArrayEncoding,LongEncoding,LongSummaryStatisticsEncoding,MonthDayEncoding,NullSafeEncoding,NumberEncoding,ObjectArrayEncoding,ObjIdEncoding,OffsetDateTimeEncoding,OffsetTimeEncoding,PatternEncoding,PeriodEncoding,PrimitiveEncoding,PrimitiveWrapperEncoding,ReferenceEncoding,ShortArrayEncoding,ShortEncoding,StringConvertedEncoding,StringEncoding,Tuple2Encoding,Tuple3Encoding,Tuple4Encoding,Tuple5Encoding,TupleEncoding,UnsignedIntEncoding,URIEncoding,UUIDEncoding,VoidEncoding,YearEncoding,YearMonthEncoding,ZonedDateTimeEncoding,ZoneIdEncoding,ZoneOffsetEncoding
Encoding's are used to map between instances of some Java type and the byte[] encodings of those instances
stored in a Permazen database. The byte[] encoding defines the database sort order (via unsigned lexicographical
ordering), and this same ordering is reflected in Java via compare().
An Encoding also defines a mapping between Java instances and String values.
Instances may have an associated EncodingId, which is a globally unique URN-style identifier that allows the encoding
to be referred to by name (e.g., in an EncodingRegistry). Encodings with no EncodingId are called anonymous.
Encodings must satsify these requirements:
- Instances have an associated Java type which can represent any of the encoding's supported values (see
getTypeToken()). However, an encoding is not required to support every value of the Java type. For example, there could be an encoding of typeIntegerthat only supports non-negative values. - Instances totally order their supported Java values (see
compare()). If the associated Java type itself implementsComparable, then the two orderings do not necessarily have to agree, but they should if possible. In that case,sortsNaturally()should return true. nullmay or may not be a supported value (seesupportsNull()). If so, it must be fully supported value just like any other; for example, it must be handled bycompare()(typically null values sort last). Note that this is an additional requirement beyond whatComparatorstrictly requires.- There is a default value. For types that support null, the default value must be null,
and for types that don't support null, obviously the default value must not be null; however, an exception can be made
for encodings that don't support null but also don't need default values, e.g., anonymous encodings that are always
wrapped within a
NullSafeEncoding; for such encodings,getDefaultValue()should throw anUnsupportedOperationException. - All non-null values can be encoded/decoded into a
Stringwithout losing information (seetoString()andfromString()). These strings must contain characters that are valid in an XML document only. - All values, including null if supported, can be encoded/decoded into a self-delimiting binary string without
losing information (see
read()andwrite()). Moreover, these binary strings, when sorted lexicographically as unsigned values, sort consistently withcompare(). - An
Encoding's string and binary encodings and sort ordering is guaranteed to never change, unless theEncodingIdis also changed, which effectively defines a new encoding (in such scenarios, automatic schema migration is possible by adding the appropriate logic toconvert()).
Two Encoding instances should be equal according to equals() only when they behave identically
with respect to all of the above.
Instances must be stateless (and therefore also thread safe).
- See Also:
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final intThe maximum number of supported array dimensions (255). -
Method Summary
Modifier and TypeMethodDescriptionintOrder two values.default <S> Tdefault TDecode a valid from the given byte string.default ByteDataEncode the given value into abyte[]array.fromString(String string) Parse a non-null value previously encoded bytoString(T).Get the default value for this encoding.default ByteDataGet the default value for this encoding encoded as a byte string.Get the globally unique encoding ID that identifies this encoding, if any.Get the fixed width of this encoding, if any.Get the Java type corresponding to this encoding's values.booleanDetermine whether any of this encoding's encoded values start with a0x00byte.booleanDetermine whether any of this encoding's encoded values start with a0xffbyte.read(ByteData.Reader reader) Read a value from the given input.voidskip(ByteData.Reader reader) Read and discard an encoded value from the given input.booleanDetermine whether this encoding supports null values.Encode a non-null value as aStringfor later decoding byfromString().default TVerify the given object is a valid instance of thisEncoding's Java type and cast it to that type.default voidvalidateAndWrite(ByteData.Writer writer, Object obj) Convenience method that both validates and encodes a value.voidwrite(ByteData.Writer writer, T value) Write a value to the given output.Methods inherited from interface java.util.Comparator
equals, reversed, thenComparing, thenComparing, thenComparing, thenComparingDouble, thenComparingInt, thenComparingLongMethods inherited from interface io.permazen.util.NaturalSortAware
sortsNaturally
-
Field Details
-
MAX_ARRAY_DIMENSIONS
static final int MAX_ARRAY_DIMENSIONSThe maximum number of supported array dimensions (255).- See Also:
-
-
Method Details
-
getEncodingId
EncodingId getEncodingId()Get the globally unique encoding ID that identifies this encoding, if any.Once associated with a specific encoding, an encoding ID must never be changed or reused. If an
Encoding's behavior changes in any way, then its encoding ID must also change. This applies only to the encoding itself, and not the associated Java type. For example, anEncoding's associated Java type can change over time, e.g., if its class or package name changes.- Returns:
- this encoding's unique ID, or null if this encoding is anonymous
-
getTypeToken
Get the Java type corresponding to this encoding's values.- Returns:
- the Java type used to represent this encoding's values
-
read
Read a value from the given input.- Parameters:
reader- byte input- Returns:
- decoded value (possibly null)
- Throws:
IllegalArgumentException- if invalid input is encounteredIndexOutOfBoundsException- if input is truncatedIllegalArgumentException- ifreaderis null
-
write
Write a value to the given output.- Parameters:
writer- byte outputvalue- value to write (possibly null)- Throws:
IllegalArgumentException- ifvalueis null and this encoding does not support nullIllegalArgumentException- ifwriteris null
-
getDefaultValueBytes
Get the default value for this encoding encoded as a byte string.The implementation in
Encodingreturns the binary encoding of the value returned bygetDefaultValue().- Returns:
- encoded default value
- Throws:
UnsupportedOperationException- if this encoding does not have a default value
-
getDefaultValue
T getDefaultValue()Get the default value for this encoding.If this encoding supports null values, then this must return null.
- Returns:
- default value
- Throws:
UnsupportedOperationException- if this encoding does not have a default value
-
skip
Read and discard an encoded value from the given input.If the value skipped over is invalid, this method may, but is not required to, throw
IllegalArgumentException.If the value skipped over is truncated, this method must throw
IndexOutOfBoundsException.- Parameters:
reader- byte input- Throws:
IllegalArgumentException- if invalid input is encounteredIndexOutOfBoundsException- if input is truncatedIllegalArgumentException- ifreaderis null
-
toString
Encode a non-null value as aStringfor later decoding byfromString().Each of the characters in the returned
String, when decoded as 32-bit Unicode codepoints, must contain only valid XML characters (seeXMLUtil.isValidChar(int)).- Parameters:
value- actual value, never null- Returns:
- string encoding of
valueacceptable tofromString() - Throws:
IllegalArgumentException- ifvalueis null- See Also:
-
fromString
Parse a non-null value previously encoded bytoString(T).- Parameters:
string- non-null value previously encoded as aStringbytoString(T)- Returns:
- actual value
- Throws:
IllegalArgumentException- if the input is invalidIllegalArgumentException- ifstringis null
-
convert
Attempt to convert a value from the givenEncodinginto a value of thisEncoding.For a non-null
value, the implementation inEncodingfirst checks whether thevalueis already a valid value for this encoding; if so, the value is returned. Otherwise, it invokesencoding.toString(value)to convertvalueinto aString, and then attempts to parse that string viathis.fromString(); if the parse fails, anIllegalArgumentExceptionis thrown. Note this means that any value will convert successfully to aString, as long as it doesn't contain an invalid escape sequence (seeStringEncoding.toString(java.lang.String)).If
valueis null, the implementation inEncodingreturns null, unless this encoding does not support null values, in which case anIllegalArgumentExceptionis thrown.Permazen's built-in encodings include the following conversions:
- Non-boolean Primitive types:
- Convert from other non-boolean primitive types as if by the corresponding Java cast
- Convert from boolean by converting to zero (if false) or one (if true)
- Boolean: converts from other primitive types as if by
value != 0 - A
char[]array and aStringare convertible to each other - A
charand aStringof length one are convertible to each other (otherStrings are not) - Arrays: converted by converting each array element individually (if possible)
- Type Parameters:
S- source encoding- Parameters:
encoding- theEncodingofvaluevalue- the value to convert- Returns:
valueconverted to this instance's type- Throws:
IllegalArgumentException- if the conversion fails
- Non-boolean Primitive types:
-
validate
Verify the given object is a valid instance of thisEncoding's Java type and cast it to that type.Note that this method must throw
IllegalArgumentException, notClassCastExceptionorNullPointerException, ifobjdoes not have the correct type, or is an unsupported value - including null if null is not supported.This method is allowed to perform widening conversions of the object that lose no information, e.g., from
IntegertoLong.The implementation in
Encodingfirst verifies the value is not null if this instance does not allow null values, and then attempts to cast the value using this instance's raw Java type. Subclasses should override this method to implement any other restrictions.- Parameters:
obj- object to validate- Returns:
objcast to this encoding's type- Throws:
IllegalArgumentException- ifobjin not of type TIllegalArgumentException- ifobjis null and this encoding does not support null valuesIllegalArgumentException- ifobjis in any other way not supported by thisEncoding
-
compare
Order two values.This method must provide a total ordering of all supported Java values that is consistent with the database ordering, i.e., the unsigned lexicographical ordering of the corresponding
byte[]encoded values.If null is a supported Java value, then the this method must accept null parameters without throwing an exception (note, this is a stronger requirement than the
Comparatorinterface normally requires).Note: by convention, null values usually sort last.
- Specified by:
comparein interfaceComparator<T>- Throws:
IllegalArgumentException- ifvalue1orvalue2is null and this encoding does not support null
-
supportsNull
boolean supportsNull()Determine whether this encoding supports null values.- Returns:
- true if null is a valid value, otherwise false
-
hasPrefix0x00
boolean hasPrefix0x00()Determine whether any of this encoding's encoded values start with a0x00byte. Certain optimizations are possible when this is not the case. It is safe for this method to always return true.Note: changing the result of this method may result in an incompatible encoding if this encoding is wrapped in another class.
- Returns:
- true if an encoded value starting with
0x00exists
-
hasPrefix0xff
boolean hasPrefix0xff()Determine whether any of this encoding's encoded values start with a0xffbyte. Certain optimizations are possible when this is not the case. It is safe for this method to always return true.Note: changing the result of this method may result in an incompatible encoding if this encoding is wrapped in another class.
- Returns:
- true if an encoded value starting with
0xffexists
-
getFixedWidth
OptionalInt getFixedWidth()Get the fixed width of this encoding, if any.Some encodings encode every value into the same number of bytes. For such encodings, this method returns that number. For variable width encodings, this method must return empty.
- Returns:
- the number of bytes of every encoded value, or empty if the encoding length varies
-
validateAndWrite
Convenience method that both validates and encodes a value.Equivalent to:
this.write(writer, this.validate(obj))
- Parameters:
writer- byte outputobj- object to validate- Throws:
IllegalArgumentException- ifobjin not of type TIllegalArgumentException- ifobjis null and this encoding does not support null valuesIllegalArgumentException- ifobjis in any other way not supported by thisEncodingIllegalArgumentException- ifwriteris null
-
encode
Encode the given value into abyte[]array.The implementation in
Encodingcreates a temporaryByteData.Writerand then delegates towrite().- Parameters:
value- value to encode, possibly null- Returns:
- encoded value
- Throws:
IllegalArgumentException- ifobjis invalid
-
decode
Decode a valid from the given byte string.The implementation in
Encodingcreates a temporaryByteData.Readerand then delegates toread().- Parameters:
bytes- encoded value- Returns:
- decoded value, possibly null
- Throws:
IllegalArgumentException- ifbytesis null, invalid, or contains trailing garbage
-