Schema Annotations
TimeBase Schema Annotations are used to annotate source/target language classes with TimeBase metadata. Annotations are used in class binding (when reading messages from TimeBase streams) and for introspection to create TimeBase schema for given classes in the source language.
Property Binding
TimeBase Schema Annotation can be used for classes in POJO and Java Beans notations. We use the following approach to bind TimeBase schema fields to the class/entity properties:
- Search for the public Property with
<name>
(case insensitive search). - If public Property is not found, then search for the Property with
SchemaElement
annotation that has a<name>
tag. - If Property is not found, then binding considered as ignored and is for nullable fields only. It is considered as an Error for non-nullable data types.
- Each property may have additional methods with predefined names:
has<Property>
andnullify<Property>
. If both methods are defined, use them to manage NULL values. - All verifications should be done on accessors methods to make sure that data types are compatible.
info
Refer to Binding Algorithm for more information.
SchemaElement Annotation
The SchemaElement
annotation is used to specify that a persistent property or field is mapped to a specific schema field. SchemaElement
is also used to map entities (classes or ENUM) to Record Class Descriptor with a specified name
. Default values apply in case SchemaElement
annotation is not present.
name
(Optional) - The mapped schema field name. Field's/property's name is used if empty.title
(Optional) - The title of the schema field. Not specified if empty.description
(Optional) - The description of the schema field. Not specified if empty.
tip
name
should be specified only when it overrides the default class name or field/property name.
public @interface SchemaElement {
String name() default "";
String title() default "";
String description() default "";
}
@SchemaElement(name = "deltix.timebase.api.messages.BarMessage", title = "Bar Message")
public class BarMessage extends MarketMessage implements BarMessageInterface {
...
}
@SchemaElement
public boolean isNational() {
return isNational == 1;
}
@SchemaElement(name = "deltix.custom.Status")
public enum Status {
@SchemaElement(name = "Closed")
CLOSED,
@SchemaElement(name = "Open")
OPEN
}
Schema Data Types
SchemaDataType
ENUM defines the list of supported TimeBase Data Types by Persistence Provider.
Data Type | Description | Supported Encodings | Java Types | .NET Types |
---|---|---|---|---|
CHAR | The CHAR data type represents a single Unicode character | String, CharSequence, StringBuilder | String, StringBuilder, MutableString | |
VARCHAR | The VARCHAR data type represents a variable size string (text). An empty string is different from the NULL value | UTF8, ALPHANUMERIC(N) | String, CharSequence, StringBuilder, long for ALPHANUMERIC | String, StringBuilder, MutableString, long for ALPHANUMERIC |
BOOLEAN | The BOOLEAN data type represents a Boolean (logical) value, which is one of TRUE or FALSE | int, boolean | int, bool | |
BINARY | The BINARY data type can be used for storing arbitrary raw data. | byte[] | byte[] | |
INTEGER | The INTEGER data type represents an integer number. The INTEGER type can be constrained by specifying the minimum and maximum values. | SIGNED(N), N=8,16,32,48,64, UNSIGNED (M), M=30,61, INTERVAL | byte, short, int, long | byte, short, int, long |
FLOAT | The FLOAT data type represents a floating-point number. The FLOAT type can be constrained by specifying the minimum and maximum values. | BINARY (32), BINARY (64), DECIMAL, DECIMAL64, DECIMAL (n) | decimal, double, float, long for DECIMAL64 | decimal, double, float, long for DECIMAL64 |
TIMESTAMP | The TIMESTAMP data type represents an absolute, time zone-independent, number of millisecond passed from 1/1/1970 | long | DateTime | |
TIME_OF_DAY | The TIMEOFDAY data type represents a time of day in millisecond resolution. | long, int | DateTime | |
OBJECT | The Object type defines a structure, consisting of a determined sequence of fields. | Object | Object | |
ENUM | The enumerated type defines its values as a set of named constants. | int, short | int, short | |
DEFAULT | Type from field/property will be used. |
INTEGER
TimeBase offers a rich choice of encodings for the INTEGER data type:
Encoding | # Bytes | Min | Max | Description |
---|---|---|---|---|
SIGNED (8) | 1 | -127 | 127 | A signed 8-bit value. |
SIGNED (16) | 2 | -32,767 | 32,767 | A signed 16-bit value. |
SIGNED (32) | 4 | -231 | 231 | A signed 32-bit value. |
SIGNED (48) | 6 | -247 | 247 | A signed 48-bit value. |
SIGNED (64) | 8 | -263 | 263 | A signed 64-bit value. This encoding can be omitted in field specifications, because it is the default for the INTEGER data type. |
UNSIGNED (30) | 1 .. 4 | 0 | 230 - 2 | A packed unsigned 30-bit value. The smaller the number, the less space it occupies. |
UNSIGNED (61) | 1 .. 8 | 0 | 261 - 2 | A packed unsigned 61-bit value. The smaller the number, the less space it occupies. |
INTERVAL | 1 .. 5 | 1 | 231 | A non-zero value between 1 and 231, with optimal encoding for representing time intervals in milliseconds. |
FLOAT
TimeBase offers a rich choice of encodings for the FLOAT data type:
Encoding | # Bytes | ~Range | Description |
---|---|---|---|
BINARY (32) | 4 | ±3.4 * 1038 | Single-precision number, encoded according to IEEE 754 binary32 format. |
BINARY (64) | 8 | ±1.8 * 10308 | Double-precision number, encoded according to IEEE 754 binary64 format. This encoding can be omitted in field specifications, because it is the default for the FLOAT data type. |
DECIMAL | 2 .. 9 | ±1.8 * 10308 | A decimal floating-point number, encoded with automatically chosen precision. This encoding works best with smaller decimal numbers, such as24.25 or 1234.5556. |
DECIMAL (n) | 2 .. 9 | ±1.8 * 10308 | A decimal floating-point number, encoded with user-defined precision n, where n represents the number of fractional digits. This encoding works best with smaller decimal numbers, such as24.25 or 1234.5556. Numbers are rounded at encoding time to the specified number of fractional decimal digits. n can be between0 .. 14, inclusively. |
VARCHAR
TimeBase offers a rich choice of encodings for the VARCHAR data type:
Name | Max Length | # Bytes | Description |
---|---|---|---|
UTF8 | 64,534 | 2 + length * (1 .. 4) | A Unicode string up to 64,534 characters long, encoded in UTF8. This encoding can be omitted in field specifications, because it is the default for the VARCHAR data type. |
ALPHANUMERIC (n) | n | ~0.75 * n | This encoding is highly optimized for storing small alphanumeric codes, such as typical currency or exchange codes. Strings that can be represented by this encoding are limited in length to n and can only be composed of characters whose ASCII codes are between 0x20 and 0x5F, inclusively. This includes the space character, [A-Z], [0-9] and !"#$%&'()*+,-./:;<=>?@[\]^_. Note that lower-case letters are not supported. |
ALPHANUMERIC | 10 | 8 | Equivalent to ALPHANUMERIC (10). |
Default Type Mappings
Java Type | .NET Type | TimeBase Type |
---|---|---|
String | String | VARCHAR |
CharSequence | MutableString | VARCHAR |
StringBuilder | StringBuilder | VARCHAR |
boolean | bool | BOOLEAN |
byte | bool? | BOOLEAN, [NULLABLE] |
byte | byte | INTEGER, SIGNED(8) |
byte | byte? | INTEGER, SIGNED(8), [NULLABLE] |
short | short | INTEGER, SIGNED(16) |
int | int | INTEGER, SIGNED(32) |
int | int? | INTEGER, SIGNED(64), [NULLABLE] |
long | long | INTEGER, SIGNED(64) , FLOAT DECIMAL64 |
long | long? | INTEGER, SIGNED(64) , FLOAT DECIMAL64, [NULLABLE] |
float | float | FLOAT, BINARY (32) |
float | float? | FLOAT, BINARY (32), [NULLABLE] |
double | double | FLOAT |
double | double? | FLOAT, [NULLABLE] |
decimal | FLOAT | |
enum | enum | ENUM |
enum | enum? | ENUM, [NULLABLE] |
byte[] | byte[] | BINARY |
Object | Object | OBJECT |
SchemaType Annotation
SchemaType
annotation is used to specify a field's/property's data type in TimeBase. If SchemaType
annotation is not present - then default values apply according to the field/property type.
dataType
(Optional) - Data type specification. If omitted, default type will be used.encoding
(Optional) - Data type Encoding.isNullable
(Optional) - Nullability specification.minimum
(Optional) - Left bound for numeric data types.maximum
(Optional) - Right bound for numeric data types.nestedTypes
(Optional) - Polymorphic type specification for OBJECTs.
public @interface SchemaType
{
SchemaDataType dataType() default SchemaDataType.DEFAULT;
String encoding() default "";
boolean isNullable() default true;
String minimum() default "";
String maximum() default "";
Class[] nestedTypes() default { };
}
@SchemaElement()
@SchemaType(encoding = "SIGNED(8)", dataType = SchemaDataType.INTEGER, minimum = "1", maximum = "
12")
public byte getContractMonth() {
return contractMonth;
}
SchemaIgnore Annotation
SchemaIgnore
annotation is used to specify that field/property is excluded from mapping.
SchemaStaticType Annotation
public @interface SchemaStaticType {
String value()
SchemaDataType dataType() default SchemaDataType.DEFAULT;
}
SchemaStaticType
annotation is used to specify static persistent field/property.
PrimaryKey Annotation
PrimaryKey
annotation is used to specify that persistent field/property is a part of the message's primary key.
RelativeTo Annotation
public @interface RelativeTo {
String value()
}
@RelativeTo("close")
public double getHigh() {
return high;
}
RelativeTo
annotation is used to specify that persistent field/property decoding depends on another field/property value.
Applicable for numeric types only.
- value (Required) - Name of the TimeBase field.
TimeBase supports so-called relative encoding. Consider a typical financial event - the price bar. The one-minute price bar, for example, contains the open, high, low and close values of the price of a security for every one-minute interval. To optimize performance, it makes sense to store close as a number, and open, high, and low as a delta from close. This approach saves space and increases the reading speed. In TimeBase, the relative encoding mode is a generic part of the type system and can be used with any user-defined data structure, not only price bars.
OldElementName Annotation
public @interface OldElementName {
String value()
}
@SchemaType(encoding = "ALPHANUMERIC(10)", dataType = SchemaDataType.VARCHAR)
@SchemaElement(title = "Exchange Code")
@OldElementName("exchangeCode")
public long getExchangeId() {
return exchangeId;
}
OldElementName
annotation is used to specify backwards compatible TimeBase fields' names for the persistent field/property and entity. This annotation is used for automatic schema migration.
Bitmask Annotation
public @interface Bitmask {
String value()
}
Bitmask
annotation is used to specify that ENUM values should have bitmask numeric codes.
SchemaArrayType Annotation
public @interface SchemaArrayType
{
boolean isNullable() default true;
boolean isElementNullable() default true;
SchemaDataType elementDataType() default SchemaDataType.DEFAULT;
String elementMinimum() default "";
String elementMaximum() default "";
lass[] elementTypes() default { };
}
@SchemaArrayType(elementTypes = {Level2Action.class} )
@SchemaElement
public ObjectArrayList<Level2ActionInfo> getActions() {
return actions;
}
@SchemaArrayType(elementDataType = SchemaDataType.TIMESTAMP)
@SchemaElement(title = "Coupon Dates")
public LongArrayList getCouponDates() {
return couponDates;
}
SchemaArrayType
annotation is used to specify TimeBase Array Type of the field/property.
If SchemaType
annotation is not present - then default values apply according to the field/property type.
isNullable
(Optional) - Nullability specification.isElementNullable
(Optional) - Nullability specification for the Array elements.elementMinimum
(Optional) - Array elements left bound for numeric data types.elementMaximum
(Optional) - Array elements right bound for numeric data types.elementTypes
(Optional) - Types specification for the ARRAY of OBJECT data types.
Known restrictions for the field/property mapped to SchemaArrayType:
- Java primitive data types: BooleanArrayList, CharacterArrayList, ShortArrayList, IntegerArrayList, LongArrayList, DoubleArrayList, FloatArrayList, BinaryArray, ByteArrayList
- Java objects: ObjectArrayList and ArrayList implementations
- .NET: supported any implementation of the List
Supported Array Mappings
Java Type | .NET Type | TimeBase Type DLL Notation |
---|---|---|
BinaryArray | BinaryArray | ARRAY(INTEGER SIGNED (8)) |
BooleanArrayList | IList bool | ARRAY(BOOLEAN) |
ShortArrayList | IList short | ARRAY(INTEGER SIGNED(16)) |
IntegerArrayList | IList int | ARRAY(INTEGER SIGNED(32)) |
LongArrayList | IList long | ARRAY(INTEGER SIGNED(64)) |
FloatArrayList | IList float | ARRAY(INTEGER FLOAT BINARY (32)) |
DoubleArrayList | IList double | ARRAY(INTEGER FLOAT) |
CharacterArrayList | IList char | ARRAY(VARCHAR) |
ObjectArrayList | IList Object | ARRAY(OBJECT) |
Binding Algorithms
CLASS Binding Algorithm
Input:
- TimeBase schema class with declared fields.
- Non-abstract Java class extends InstrumentMessage.
Algorithm will bind each schema field to the appropriate public class field/property. For each schema field <dataField>
having <name>
do:
Search for the public
<field>
annotated with<SchemaElement>
:Conditions:
toLowerCase(<name>)
=toLowerCase(<SchemaElement>.name)
AND- not annotated with
<SchemaIgnore>
Search for the public
<field>
:Conditions:
toLowerCase(<name>)
=toLowerCase(<field>.name)
AND- not annotated with
<SchemaIgnore>
Search for the public
<property>
annotated with<SchemaElement>
:Conditions:
toLowerCase(<name>)
=toLowerCase(<SchemaElement>.name)
AND- not annotated with
<SchemaIgnore>
Search for the public
<property>
:Conditions:
toLowerCase(<name>)
=toLowerCase(<property>.name)
AND- not annotated with
<SchemaIgnore>
if (<field> == null && <property> == null && NOT(<dataField>.nullable))
throw Error
if (<field> already bind)
throw Error
if (<property> already bind)
throw Error
Validate returned property/field types according to the table below.
Search for additional hasers and nullifiers methods.
TimeBase Type | Java Type |
---|---|
VARCHAR | String, CharSequence, StringBuilder |
VARCHAR , ALPHANUMERIC | long |
BOOLEAN | boolean, byte |
TIMESTAMP | long |
TIME_OF_DAY | int, long |
INTEGER, SIGNED(8) | byte, short, int, long |
INTEGER, SIGNED(16) | short, int, long |
INTEGER, SIGNED(32) | int, long |
INTEGER, SIGNED(64) | long |
FLOAT, BINARY (32) | float, double |
FLOAT | double |
FLOAT, DECIMAL64 | long, double |
ENUM | enum |
BINARY | byte[], BinaryArray |
OBJECT | Object |
ENUM Binding Algorithm
Input:
- TimeBase enum schema with declared elements.
- Non-abstract Enum class.
For each schema element with <name>
do:
Search for the public enum
<value>
annotated with<SchemaElement>
:Conditions:
toLowerCase(<value>)
=toLowerCase(<SchemaElement>.name)
AND- not annotated with
<SchemaIgnore>
Search for the public enum
<value>
:Conditions:
toLowerCase(<value>)
=toLowerCase(<field>.name)
AND- not annotated with
<SchemaIgnore>
if (<value> == null)
throw Error
if (<value> already bound)
throw Error
Notes
Properties
use public getter and setter methods that are typically named after the Entity's class instance variable names. There is a getter method getProperty
and setter method setProperty
for every Entity Type persistent property
. If the property
is a Boolean
, you may use isProperty
instead of getProperty
.