=Binding=
Binding is a mechanism for mapping a Java Class to a Datatype.
For example, take a java.lang.Double. The instance is a container (private final double value;
) for the data and its Binding (DoubleBinding) is a way to access the data (.valueOf()
, .getDouble()
).
Java Object + Binding = Databoard Value
Bindings have the exact same composition tree structure as its respective Datatype
- structural types have structural Bindings, and primitive types a single binding. To acquire a binding, the developer can use a utility that creates one using Java reflection functions.
Binding binding = Binding.getBinding( Double.class );Sometimes classes cannot bound using automatic tool, for instance when using 3rd party classes which cannot be modified. The developer must then write binding self by sub-classing on of the 13 base binding classes (There is a base binding class for each Datatype).
Binding binding = new RecordBinding() { ... };'''[../javadoc/org/simantics/databoard/binding|org.simantics.databoard.binding]'''. {| style="background-color: #f9f9f9; border: 1px solid #aaaaaa; " |- style="background-color: #e9e9e9; " | | '''Class''' || '''Description''' |- | [../javadoc/org/simantics/databoard/binding/DataBinding.html|DataBinding] | Base class for all data Bindings |- | [../javadoc/org/simantics/databoard/binding/RecordBinding.html|RecordBinding] | Record |- | [../javadoc/org/simantics/databoard/binding/ArrayBinding.html|ArrayBinding] | Array - an ordered sequence of elements of one value. |- | [../javadoc/org/simantics/databoard/binding/MapBinding.html|MapBinding] | Map - an ''ordered'' map of keys to values. |- | [../javadoc/org/simantics/databoard/binding/UnionBinding.html|UnionBinding] | Union |- | [../javadoc/org/simantics/databoard/binding/BooleanBinding.html|BooleanBinding],[../javadoc/org/simantics/databoard/binding/IntBinding.html|IntBinding],[../javadoc/org/simantics/databoard/binding/LongBinding.html|LongBinding],[../javadoc/org/simantics/databoard/binding/FloatBinding.html|FloatBinding],[../javadoc/org/simantics/databoard/binding/DoubleBinding.html|DoubleBinding] | Primitive and numeric Bindings |- | [../javadoc/org/simantics/databoard/binding/StringBinding.html|StringBinding] | String |- | [../javadoc/org/simantics/databoard/binding/OptionalBinding.html|OptionalBinding] | Optional value |- | [../javadoc/org/simantics/databoard/binding/VariantBinding.html|VariantBinding] | Variant value |} Binding can be acquired or created using one of the following methods: * Constructor * Constant * Reflection-Read from a Class * Created using [../javadoc/org/simantics/databoard/bindingscheme/BindingScheme.html|BindingScheme]
Binding binding = new DoubleBinding( doubleType ); Binding binding = new RecordBinding() { ... }; Binding binding = Bindings.DOUBLE; Binding binding = Binding.getBinding( Double.class ); Binding binding = Binding.getBinding( Datatypes.DOUBLE );==Reflection== '''Data Type and Binding can be read automatically from a Class by utility.'''
Datatype type = Datatypes.getDatatype( Foo.class ); Binding binding = Bindings.getBinding( Foo.class );Bindings for generics classes can be created by passing arguments.
Binding e = Bindings.getBinding(List.class, String.class); ListEven cascading generics...list = (List ) e.createRandom(5); Binding binding = Bindings.getBinding( Map.class, Integer.class, Integer.class ); Map value = (Map ) binding.createDefault();
Binding e = Bindings.getBinding(List.class, List.class, String.class); List'''Classes are RecordTypes'''> listList = (List
>) e.createRandom(5);
class Foo { public int x, y, z; }Is a binding to the following Datatype
type Foo = { x : Integer, y : Integer, z : Integer }'''There are three types of classes supported, and therefore three ways how objects are constructed.''' If you create binding for your class with Bindings#getBinding( clazz ), the class must adhere one of these format. You may have to add annotations such as @Recursive, @Optional, @Arguments. ''Record-like classes:''
class Foo { public String name; public Object value; }''Immutable classes:''
class Foo { private String name; private Object value; public Foo(String name, Object value) { this.name = name; this.value = value; } public String getName() { return name; } public Object getValue() { return value; } }''Bean-like classes:''
class Foo { private String name; private Object value; public void setName(String name) { this.name = name; } public void setValue(Object value) { this.value = value; } public String getName() { return name; } public Object getValue() { return value; } }static final long serialVersionUID = -3387516993124229943L; transient int hashCode; '''Enumerations are Union Types'''
enum Cars { Ferrari, Porche, Lamborghini, Jaguar }is interpreted as union type type Cars = | Ferrari | Porche | Lamborghini | Jaguar If you cannot modify the class, you have to create binding for it by subclassing base binding classes, eg. RecordBinding. '''Other exceptions:''' *
java.lang.Object
is Variant.
*java.lang.Set
is Map(T, {}).
*java.lang.TreeSet
is Map(T, {}).
*java.lang.HashSet
is Map(T, {}). (Note HashSet binding has very low performance.)
*java.lang.Map
is Map(K, V).
*java.lang.TreeMap
is Map(K, V).
*java.lang.HashMap
is Map(K, V). (Note HashMap binding has very low performance.)
*java.lang.List
is Array(T).
*java.lang.ArrayList
is Array(T).
*java.lang.LinkedList
is Array(T).
*void
is {}.
*The stacktrace of Exception.class
is omited.
===Annotations===
Java Classes / Fields can be annotated with the following annotations ('''[../javadoc/org/simantics/databoard/annotations/|org.simantics.databoard.annotations]]''').
'''UnionTypes are abstract classes or interfaces with @Union
annotation.'''
@Union({A.class, B.class}) interface Union1 { } class A implements Union1 { public int value; } class B implements Union1 { public String name; }'''
@Referable
denotes that the class has recursion and is a referable record.'''
public @Referable class Node { public Node[] children; }'''Fields that can have null value have
@Optional
annotation.'''
@Optional String name;'''String valid values are set with
@Pattern
as regular expression. ([http://en.wikipedia.org/wiki/Regular_expression])'''
String @Pattern("(19|20)\\d\\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])") date; type Date = String( Pattern = "(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])" )'''String content type is set with a
@MIMEType
. ([http://en.wikipedia.org/wiki/Mime_type MIME Type])'''
@MIMEType("text/xml") String document;'''Array size restricted with @Length.'''
@Length("[0..10]") int[] array; @Length({"[320]", "[240]"}) int[][] image;'''Valid numeric range is set with @Range.'''
@Range("[0..100]") double alpha; @Range("[0..]" double length;'''Range and Length notation:''' *Exact Value "0" *Exclude all "()" *Unlimited "[..]" *Inclusive range "[0..100]" *Exclusive range "(0..100)" *Inclusive lower bound and exclusive upper bound "[0..100)" '''Engineering unit type is given with @Unit.'''
@Unit("km/h") double maxVelocity;'''The serializer generated with reflection can be overriden with @SpecializedSerializer'''
@SpecializedSerializer(MySerializer.class) public class MyRecord { ... }== Mapping Scheme == A ''binding scheme'' associates some data types with a unique binding. The mapping of types to bindings is bijective, there is one binding for each type and vice-versa.
DefaultBindingScheme
is a scheme that converts any datatype to a binding. It prefers java.lang.X primitives.
The Class mapping for each type is listed below.
{| style="background-color: #f9f9f9; border: 1px solid #aaaaaa; "
|- style="background-color: #e9e9e9;
| '''Type''' || '''Class'''
|-
| BooleanType
|| Boolean.class
|-
| ByteType
|| Byte.class
|-
| FloatType
|| Float.class
|-
| DoubleType
|| eDouble.class
|-
| IntegerType
|| Integer.class
|-
| LongType
|| Long.class
|-
| StringType
|| String.class
|-
| UnionType
|| TaggedObject.class
|-
| OptionType
|| ValueContainer.class
|-
| RecordType
|| Object[].class
|-
| ArrayType
|| ArrayList.class
|-
| Array(Byte)
|| byte[].class
|-
| MapType
|| TreeMap.class
|-
| VariantType
|| Variant.class
|}
MutableBindingScheme
is a scheme that provides a fully implementing mutable binding for all data types.
The Class mapping for each type is listed below.
{| style="background-color: #f9f9f9; border: 1px solid #aaaaaa; "
|- style="background-color: #e9e9e9; " |
| '''Type''' || '''Class'''
|-
| BooleanType
|| MutableBoolean.class
|-
| ByteType
|| MutableByte.class
|-
| FloatType
|| MutableFloat.class
|-
| DoubleType
|| MutableDouble.class
|-
| IntegerType
|| MutableInt.class
|-
| LongType
|| MutableLong.class
|-
| StringType
|| MutableString.class
|-
| UnionType
|| TaggedObject.class
|-
| OptionType
|| ValueContainer.class
|-
| RecordType
|| Object[].class
|-
| ArrayType
|| ArrayList.class
|-
| MapType
|| TreeMap.class
|-
| VariantType
|| Variant.class
|}
===Serialization===
[../javadoc/org/simantics/databoard/serialization/binary/Serializer.html|Serializer] is a class that serializes Values into and from binary serialization format. It follows the Databoard [Databoard_Specification#Binary_File_Format|Binary File Format].
Binding binding = Bindings.DOUBLE; Serializer serializer = Bindings.getSerializer( binding ); byte[] data = serializer.serialize( new Double( 100.0 ) ); Double value = (Double) serializer.deserialize( data );Files can be partially accessed using BinaryAccessor, see [accessor|Accessors]. This is useful when handling larger than memory files. ===Validation=== '''Value''' can be ''well-formed'' or ''valid''. The domain of valid values are defined with restrictions in data types, and
@Length
, @Range
, @Pattern
and @MIMEType
Annotations in Classes
Validation mechanism in Binding asserts that the instance is a valid value of the respective Data Type.
try { Binding.assertInstaceIsValid( object ); } catch( BindingException e ) { // In-valid object }===Other Notes=== *Binding is a Comparator, all data values are comparable, the order is defined in [[Databoard_Specification#Comparison|Specification]]. *Binding#createDefault() creates a valid instance of the Datatype. *Binding#createRandom(int) creates a valid instance with random values. Useful for unit tests. *Binding#clone(Object) creates a new instance with same content. *Binding#readFrom(Object, Binding, Binding) copies contents from another object of same type. ===Parsing & Printing=== Data values are printed and parsed of the [[Databoard_Specification|Text notation]] with the following
Binding
methods:
String text = binding.printValue( value, true ); Object value = binding.parseValue( text );And also to value definitions ''name : type = value''
StringBuilder sb = new StringBuilder(); DataValueRepository repo = new DataValueRepository(); repo.put( "temp", binding, value ); binding.printValue( value, sb, repo, true ); String text = sb.toString(); Object value = binding.parseValueDefinition( text );