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.
Encoding
s 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 typeInteger
that 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. null
may 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 whatComparator
strictly 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
String
without 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 theEncodingId
is 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
Modifier and TypeFieldDescriptionstatic final int
The maximum number of supported array dimensions (255). -
Method Summary
Modifier and TypeMethodDescriptionint
Order two values.default <S> T
default T
Decode a valid from the given byte string.default ByteData
Encode 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 ByteData
Get 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.boolean
Determine whether any of this encoding's encoded values start with a0x00
byte.boolean
Determine whether any of this encoding's encoded values start with a0xff
byte.read
(ByteData.Reader reader) Read a value from the given input.void
skip
(ByteData.Reader reader) Read and discard an encoded value from the given input.boolean
Determine whether this encoding supports null values.Encode a non-null value as aString
for later decoding byfromString()
.default T
Verify the given object is a valid instance of thisEncoding
's Java type and cast it to that type.default void
validateAndWrite
(ByteData.Writer writer, Object obj) Convenience method that both validates and encodes a value.void
write
(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, thenComparingLong
Methods 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
- ifreader
is null
-
write
Write a value to the given output.- Parameters:
writer
- byte outputvalue
- value to write (possibly null)- Throws:
IllegalArgumentException
- ifvalue
is null and this encoding does not support nullIllegalArgumentException
- ifwriter
is null
-
getDefaultValueBytes
Get the default value for this encoding encoded as a byte string.The implementation in
Encoding
returns 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
- ifreader
is null
-
toString
Encode a non-null value as aString
for 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
value
acceptable tofromString()
- Throws:
IllegalArgumentException
- ifvalue
is null- See Also:
-
fromString
Parse a non-null value previously encoded bytoString(T)
.- Parameters:
string
- non-null value previously encoded as aString
bytoString(T)
- Returns:
- actual value
- Throws:
IllegalArgumentException
- if the input is invalidIllegalArgumentException
- ifstring
is null
-
convert
Attempt to convert a value from the givenEncoding
into a value of thisEncoding
.For a non-null
value
, the implementation inEncoding
first checks whether thevalue
is already a valid value for this encoding; if so, the value is returned. Otherwise, it invokesencoding.
toString(value)
to convertvalue
into aString
, and then attempts to parse that string viathis.
fromString()
; if the parse fails, anIllegalArgumentException
is 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
value
is null, the implementation inEncoding
returns null, unless this encoding does not support null values, in which case anIllegalArgumentException
is 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 aString
are convertible to each other - A
char
and aString
of length one are convertible to each other (otherString
s are not) - Arrays: converted by converting each array element individually (if possible)
- Type Parameters:
S
- source encoding- Parameters:
encoding
- theEncoding
ofvalue
value
- the value to convert- Returns:
value
converted 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
, notClassCastException
orNullPointerException
, ifobj
does 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
Integer
toLong
.The implementation in
Encoding
first 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:
obj
cast to this encoding's type- Throws:
IllegalArgumentException
- ifobj
in not of type TIllegalArgumentException
- ifobj
is null and this encoding does not support null valuesIllegalArgumentException
- ifobj
is 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
Comparator
interface normally requires).Note: by convention, null values usually sort last.
- Specified by:
compare
in interfaceComparator<T>
- Throws:
IllegalArgumentException
- ifvalue1
orvalue2
is 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 a0x00
byte. 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
0x00
exists
-
hasPrefix0xff
boolean hasPrefix0xff()Determine whether any of this encoding's encoded values start with a0xff
byte. 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
0xff
exists
-
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
- ifobj
in not of type TIllegalArgumentException
- ifobj
is null and this encoding does not support null valuesIllegalArgumentException
- ifobj
is in any other way not supported by thisEncoding
IllegalArgumentException
- ifwriter
is null
-
encode
Encode the given value into abyte[]
array.The implementation in
Encoding
creates a temporaryByteData.Writer
and then delegates towrite()
.- Parameters:
value
- value to encode, possibly null- Returns:
- encoded value
- Throws:
IllegalArgumentException
- ifobj
is invalid
-
decode
Decode a valid from the given byte string.The implementation in
Encoding
creates a temporaryByteData.Reader
and then delegates toread()
.- Parameters:
bytes
- encoded value- Returns:
- decoded value, possibly null
- Throws:
IllegalArgumentException
- ifbytes
is null, invalid, or contains trailing garbage
-