]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src-isv/doc/binding.mediawiki
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.databoard / src-isv / doc / binding.mediawiki
1 =Binding=\r
2 Binding is a mechanism for mapping a Java Class to a Datatype.\r
3 For example, take a java.lang.Double. The instance is a container (<code>private final double value;</code>) for the data and its Binding (DoubleBinding) is a way to access the data (<code>.valueOf()</code>, <code>.getDouble()</code>). \r
4     Java Object + Binding = Databoard Value\r
5 \r
6 Bindings have the exact same composition tree structure as its respective <code>Datatype</code> - 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.\r
7 <pre class="code">\r
8     Binding binding = Binding.getBinding( Double.class );\r
9 </pre>\r
10 \r
11 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). \r
12 <pre class="code">\r
13     Binding binding = new RecordBinding() { ... };\r
14 </pre>\r
15 \r
16 '''[../javadoc/org/simantics/databoard/binding|org.simantics.databoard.binding]'''.\r
17 {| style="background-color: #f9f9f9; border: 1px solid #aaaaaa; "\r
18 |- style="background-color: #e9e9e9; " |\r
19 | '''Class''' || '''Description'''\r
20 |- \r
21 | [../javadoc/org/simantics/databoard/binding/DataBinding.html|DataBinding]\r
22 | Base class for all data Bindings\r
23 |- \r
24 | [../javadoc/org/simantics/databoard/binding/RecordBinding.html|RecordBinding]\r
25 | Record \r
26 |- \r
27 | [../javadoc/org/simantics/databoard/binding/ArrayBinding.html|ArrayBinding]\r
28 | Array - an ordered sequence of elements of one value.\r
29 |- \r
30 | [../javadoc/org/simantics/databoard/binding/MapBinding.html|MapBinding]\r
31 | Map - an ''ordered'' map of keys to values. \r
32 |- \r
33 | [../javadoc/org/simantics/databoard/binding/UnionBinding.html|UnionBinding]\r
34 | Union\r
35 |- \r
36 | [../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]\r
37 | Primitive and numeric Bindings\r
38 |- \r
39 | [../javadoc/org/simantics/databoard/binding/StringBinding.html|StringBinding]\r
40 | String \r
41 |- \r
42 | [../javadoc/org/simantics/databoard/binding/OptionalBinding.html|OptionalBinding]\r
43 | Optional value\r
44 |- \r
45 | [../javadoc/org/simantics/databoard/binding/VariantBinding.html|VariantBinding]\r
46 | Variant value\r
47 |}\r
48 \r
49 \r
50 Binding can be acquired or created using one of the following methods:\r
51 * Constructor \r
52 * Constant\r
53 * Reflection-Read from a Class \r
54 * Created using [../javadoc/org/simantics/databoard/bindingscheme/BindingScheme.html|BindingScheme]\r
55 <pre class="code">\r
56     Binding binding = new DoubleBinding( doubleType );\r
57     Binding binding = new RecordBinding() { ... };\r
58     Binding binding = Bindings.DOUBLE;\r
59     Binding binding = Binding.getBinding( Double.class );\r
60     Binding binding = Binding.getBinding( Datatypes.DOUBLE );\r
61 </pre>\r
62 \r
63 ==Reflection==\r
64 '''Data Type and Binding can be read automatically from a Class by utility.'''\r
65 <pre class="code">\r
66     Datatype type = Datatypes.getDatatype( Foo.class );\r
67     Binding binding = Bindings.getBinding( Foo.class );\r
68 </pre>\r
69 \r
70 Bindings for generics classes can be created by passing arguments.\r
71 <pre class="code">\r
72     Binding e = Bindings.getBinding(List.class, String.class);\r
73     List<String> list = (List<String>) e.createRandom(5);\r
74 \r
75     Binding binding = Bindings.getBinding( Map.class, Integer.class, Integer.class );\r
76     Map<Integer, Integer> value = (Map<Integer, Integer>) binding.createDefault();\r
77 </pre>\r
78 \r
79 Even cascading generics...\r
80 <pre class="code">\r
81     Binding e = Bindings.getBinding(List.class, List.class, String.class);\r
82     List<List<String>> listList = (List<List<String>>) e.createRandom(5);\r
83 </pre>\r
84 \r
85 '''Classes are RecordTypes'''\r
86 <pre class="code">\r
87     class Foo {\r
88         public int x, y, z;\r
89     }\r
90 </pre>\r
91 Is a binding to the following Datatype\r
92 <pre class="code">\r
93     type Foo = { x : Integer, y : Integer, z : Integer }\r
94 </pre>\r
95 \r
96 '''There are three types of classes supported, and therefore three ways how objects are constructed.'''\r
97 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. \r
98 \r
99 ''Record-like classes:''\r
100 <pre class="code">\r
101     class Foo {\r
102         public String name;\r
103         public Object value;\r
104     }\r
105 </pre>\r
106 \r
107 ''Immutable classes:''\r
108 <pre class="code">\r
109     class Foo {\r
110         private String name;\r
111         private Object value;\r
112         \r
113         public Foo(String name, Object value) {\r
114             this.name = name;\r
115             this.value = value;\r
116         }\r
117         \r
118         public String getName() {\r
119             return name;\r
120         }\r
121         \r
122         public Object getValue() {\r
123             return value;\r
124         }\r
125         \r
126     }\r
127 </pre>\r
128 \r
129 ''Bean-like classes:''\r
130 <pre class="code">\r
131     class Foo {\r
132         private String name;\r
133         private Object value;\r
134         \r
135         public void setName(String name) {\r
136             this.name = name;\r
137         }\r
138         \r
139         public void setValue(Object value) {\r
140             this.value = value;\r
141         }\r
142         \r
143         public String getName() {\r
144             return name;\r
145         }\r
146         \r
147         public Object getValue() {\r
148             return value;\r
149         }\r
150         \r
151     }\r
152 </pre<\r
153 \r
154 '''Static and transient fields are omited:'''\r
155 <pre class="code">\r
156     static final long serialVersionUID = -3387516993124229943L;\r
157     transient int hashCode;\r
158 </pre>\r
159 \r
160 '''Enumerations are Union Types'''\r
161 <pre class="code">\r
162     enum Cars { Ferrari, Porche, Lamborghini, Jaguar }\r
163 </pre>    \r
164 is interpreted as union type\r
165     type Cars = | Ferrari | Porche | Lamborghini | Jaguar\r
166 \r
167 If you cannot modify the class, you have to create binding for it by subclassing base binding classes, eg. RecordBinding.\r
168 \r
169 '''Other exceptions:'''\r
170 *<code>java.lang.Object</code> is <tt>Variant</tt>.\r
171 *<code>java.lang.Set<T></code> is <tt>Map(T, {})</tt>.\r
172 *<code>java.lang.TreeSet<T></code> is <tt>Map(T, {})</tt>.\r
173 *<code>java.lang.HashSet<T></code> is <tt>Map(T, {})</tt>. (Note HashSet binding has very low performance.)\r
174 *<code>java.lang.Map<K, V></code> is <tt>Map(K, V)</tt>.\r
175 *<code>java.lang.TreeMap<K, V></code> is <tt>Map(K, V)</tt>.\r
176 *<code>java.lang.HashMap<K, V></code> is <tt>Map(K, V)</tt>. (Note HashMap binding has very low performance.)\r
177 *<code>java.lang.List<T></code> is <tt>Array(T)</tt>.\r
178 *<code>java.lang.ArrayList<T></code> is <tt>Array(T)</tt>.\r
179 *<code>java.lang.LinkedList<T></code> is <tt>Array(T)</tt>.\r
180 *<code>void</code> is <tt>{}</tt>.\r
181 *The stacktrace of <code>Exception.class</code> is omited.\r
182 \r
183 ===Annotations===\r
184 Java Classes / Fields can be annotated with the following annotations ('''[../javadoc/org/simantics/databoard/annotations/|org.simantics.databoard.annotations]]''').\r
185 \r
186 \r
187 '''UnionTypes are abstract classes or interfaces with <code>@Union</code> annotation.'''\r
188 <pre class="code">\r
189     @Union({A.class, B.class}) interface Union1 {               \r
190     }\r
191     \r
192     class A implements Union1 {\r
193         public int value;\r
194     }\r
195     \r
196     class B implements Union1 {\r
197         public String name;\r
198     }\r
199 </pre>\r
200 \r
201 '''<code>@Referable</code> denotes that the class has recursion and is a referable record.'''\r
202 <pre class="code">\r
203     public @Referable class Node {\r
204         public Node[] children;\r
205     }\r
206 </pre>\r
207 \r
208 '''Fields that can have <tt>null</tt> value have <code>@Optional</code> annotation.'''\r
209 <pre class="code">\r
210     @Optional String name;\r
211 </pre>\r
212 \r
213 '''String valid values are set with <code>@Pattern</code> as regular expression. ([http://en.wikipedia.org/wiki/Regular_expression])'''\r
214 <pre class="code">\r
215     String @Pattern("(19|20)\\d\\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])") date;\r
216     \r
217     type Date = String( Pattern = "(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])" )\r
218 </pre>\r
219 \r
220 '''String content type is set with a <code>@MIMEType</code>. ([http://en.wikipedia.org/wiki/Mime_type MIME Type])'''\r
221 <pre class="code">\r
222     @MIMEType("text/xml") String document;\r
223 </pre>\r
224 \r
225 '''Array size restricted with @Length.'''\r
226 <pre class="code">\r
227     @Length("[0..10]") int[] array;\r
228     @Length({"[320]", "[240]"}) int[][] image;\r
229 </pre>\r
230 \r
231 '''Valid numeric range is set with @Range.'''\r
232 <pre class="code">\r
233     @Range("[0..100]") double alpha;\r
234     @Range("[0..]" double length;\r
235 </pre>\r
236 \r
237 '''<tt>Range</tt> and <tt>Length</tt> notation:'''\r
238 *Exact Value "0"\r
239 *Exclude all "()"\r
240 *Unlimited "[..]"\r
241 *Inclusive range "[0..100]"\r
242 *Exclusive range "(0..100)"\r
243 *Inclusive lower bound and exclusive upper bound "[0..100)"\r
244 \r
245 \r
246 '''Engineering unit type is given with @Unit.'''\r
247 <pre class="code">\r
248     @Unit("km/h") double maxVelocity;\r
249 </pre>\r
250 \r
251 '''The serializer generated with reflection can be overriden with @SpecializedSerializer'''\r
252 <pre class="code">\r
253     @SpecializedSerializer(MySerializer.class) \r
254     public class MyRecord {\r
255         ...\r
256     }\r
257 </pre>\r
258 \r
259 == Mapping Scheme ==\r
260 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.\r
261 \r
262 <code>DefaultBindingScheme</code> is a scheme that converts any datatype to a binding. It prefers java.lang.X primitives.\r
263 The Class mapping for each type is listed below.\r
264 {| style="background-color: #f9f9f9; border: 1px solid #aaaaaa; "\r
265 |- style="background-color: #e9e9e9;\r
266 | '''Type''' || '''Class'''\r
267 |- \r
268 | <code>BooleanType</code> || <code>Boolean.class</code>\r
269 |- \r
270 | <code>ByteType</code> || <code>Byte.class</code>\r
271 |- \r
272 | <code>FloatType</code> || <code>Float.class</code>\r
273 |- \r
274 | <code>DoubleType</code> || <code>eDouble.class</code>\r
275 |- \r
276 | <code>IntegerType</code> || <code>Integer.class</code>\r
277 |- \r
278 | <code>LongType</code> || <code>Long.class</code>\r
279 |- \r
280 | <code>StringType</code> || <code>String.class</code>\r
281 |- \r
282 | <code>UnionType</code> || <code>TaggedObject.class</code>\r
283 |- \r
284 | <code>OptionType</code> || <code>ValueContainer.class</code>\r
285 |- \r
286 | <code>RecordType</code> || <code>Object[].class</code>\r
287 |- \r
288 | <code>ArrayType</code> || <code>ArrayList.class</code>\r
289 |- \r
290 | <code>Array(Byte)</code> || <code>byte[].class</code>\r
291 |- \r
292 | <code>MapType</code> || <code>TreeMap.class</code>\r
293 |- \r
294 | <code>VariantType</code> || <code>Variant.class</code>\r
295 |}\r
296 \r
297 <code>MutableBindingScheme</code> is a scheme that provides a fully implementing mutable binding for all data types. \r
298 The Class mapping for each type is listed below.\r
299 \r
300 {| style="background-color: #f9f9f9; border: 1px solid #aaaaaa; "\r
301 |- style="background-color: #e9e9e9; " |\r
302 | '''Type''' || '''Class'''\r
303 |- \r
304 | <code>BooleanType</code> || <code>MutableBoolean.class</code>\r
305 |- \r
306 | <code>ByteType</code> || <code>MutableByte.class</code>\r
307 |- \r
308 | <code>FloatType</code> || <code>MutableFloat.class</code>\r
309 |- \r
310 | <code>DoubleType</code> || <code>MutableDouble.class</code>\r
311 |- \r
312 | <code>IntegerType</code> || <code>MutableInt.class</code>\r
313 |- \r
314 | <code>LongType</code> || <code>MutableLong.class</code>\r
315 |- \r
316 | <code>StringType</code> || <code>MutableString.class</code>\r
317 |- \r
318 | <code>UnionType</code> || <code>TaggedObject.class</code>\r
319 |- \r
320 | <code>OptionType</code> || <code>ValueContainer.class</code>\r
321 |- \r
322 | <code>RecordType</code> || <code>Object[].class</code>\r
323 |- \r
324 | <code>ArrayType</code> || <code>ArrayList.class</code>\r
325 |- \r
326 | <code>MapType</code> || <code>TreeMap.class</code>\r
327 |- \r
328 | <code>VariantType</code> || <code>Variant.class</code>\r
329 |}\r
330 \r
331 \r
332 ===Serialization===\r
333 [../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].\r
334 <pre class="code">\r
335     Binding binding = Bindings.DOUBLE;\r
336     Serializer serializer = Bindings.getSerializer( binding );\r
337     byte[] data = serializer.serialize( new Double( 100.0 ) );\r
338     \r
339     Double value = (Double) serializer.deserialize( data );\r
340 </pre>\r
341 \r
342 Files can be partially accessed using BinaryAccessor, see [accessor|Accessors]. This is useful when handling larger than memory files.\r
343 \r
344 ===Validation===\r
345 '''Value''' can be ''well-formed'' or ''valid''. \r
346 The domain of valid values are defined with restrictions in data types, and <code>@Length</code>, <code>@Range</code>, <code>@Pattern</code> and <code>@MIMEType</code> Annotations in Classes\r
347 \r
348 Validation mechanism in Binding asserts that the instance is a valid value of the respective Data Type.\r
349 <pre class="code">\r
350     try {\r
351         Binding.assertInstaceIsValid( object );\r
352     } catch( BindingException e ) {\r
353         // In-valid object\r
354     }\r
355 </pre>\r
356 \r
357 ===Other Notes===\r
358 *<tt>Binding</tt> is a <tt>Comparator</tt>, all data values are comparable, the order is defined in [[Databoard_Specification#Comparison|Specification]].\r
359 *<tt>Binding#createDefault()</tt> creates a valid instance of the Datatype.\r
360 *<tt>Binding#createRandom(int)</tt> creates a valid instance with random values. Useful for unit tests.\r
361 *<tt>Binding#clone(Object)</tt> creates a new instance with same content.\r
362 *<tt>Binding#readFrom(Object, Binding, Binding)</tt> copies contents from another object of same type.\r
363 \r
364 ===Parsing & Printing===\r
365 \r
366 Data values are printed and parsed of the [[Databoard_Specification|Text notation]] with the following <code>Binding</code> methods:\r
367 <pre class="code">\r
368     String text = binding.printValue( value, true );\r
369     \r
370     Object value = binding.parseValue( text );\r
371 </pre>\r
372 And also to value definitions <tt>''name : type = value''</tt>\r
373 \r
374 <pre class="code">\r
375     StringBuilder sb = new StringBuilder();\r
376     DataValueRepository repo = new DataValueRepository();\r
377     repo.put( "temp", binding, value );\r
378     binding.printValue( value, sb, repo, true );\r
379     String text = sb.toString();\r
380     \r
381     Object value = binding.parseValueDefinition( text );\r
382 </pre>