TimeBase schema annotations and data bindings overview

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:

  1. Search for the public Property with <name> (case insensitive search).
  2. If public Property is not found, then search for the Property with SchemaElement annotation that has a <name> tag.
  3. 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.
  4. Each property may have additional methods with predefined names: has<Property> and nullify<Property>. If both methods are defined, use them to manage NULL values.
  5. All verifications should be done on accessors methods to make sure that data types are compatible.

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.
public @interface SchemaElement {
	String name() default "";
	String title() default "";
	String description() default "";
}

// Example Java

@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.

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 { };
	}

Example Java 

@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()
}


Example Java 

@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()
}


Example Java 

@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 SchemaType

	{
		boolean isNullable() default true;
		boolean isElementNullable() default true;
   		SchemaDataType elementDataType() default SchemaDataType.DEFAULT;
		String elementMinimum() default "";
		String elementMaximum() default "";
		lass[] elementTypes() default { };
	}
Example Java 

@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:

  1. Search for the public <field> annotated with <SchemaElement>:
    Conditions:
    • toLowerCase(<name>) = toLowerCase(<SchemaElement>.name) AND
    • not annotated with <SchemaIgnore>
  2. Search for the public <field>:
    Conditions:
    • toLowerCase(<name>) = toLowerCase(<field>.name) AND
    • not annotated with <SchemaIgnore>
  3. Search for the public <property> annotated with <SchemaElement>:
    Conditions:
    • toLowerCase(<name>) = toLowerCase(<SchemaElement>.name) AND
    • not annotated with <SchemaIgnore>
  4. Search for the public <property>:
    Conditions:
    • toLowerCase(<name>) = toLowerCase(<property>.name) AND
    • not annotated with <SchemaIgnore>
  5. if (<field> == null && <property> == null && NOT(<dataField>.nullable)) throw Error

  6. if (<field> already bind) throw Error

  7. if (<property> already bind) throw Error

  8. Validate returned property/field types according to the table below.

  9. 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:

  1. Search for the public enum <value> annotated with <SchemaElement>:
    Conditions:
    • toLowerCase(<value>) = toLowerCase(<SchemaElement>.name) AND
    • not annotated with <SchemaIgnore>
  2. Search for the public enum <value>:
    Conditions:
    • toLowerCase(<value>) = toLowerCase(<field>.name) AND
    • not annotated with <SchemaIgnore>
  3. if (<value> == null) throw Error

  4. 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.