]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src-isv/old/old_manual.mediawiki
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.databoard / src-isv / old / old_manual.mediawiki
1 center>'''Databoard 0.6.1 Developer Manual'''</center>\r
2 \r
3 =Datatype=\r
4 In Databoard all values have a type representation, [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/type/Datatype.java|Datatype.java]]. \r
5 It is the base abstract class for all concrete type classes (See table below). \r
6 There is a facade class utility ([[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/Datatypes.java|Datatypes]]) that provides functions to most of the Datatype library's features.\r
7 \r
8 '''[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/type|org.simantics.databoard.type]]'''.\r
9 {| style="background-color: #e9e9e9; border: 1px solid #aaaaaa; "\r
10 | '''Class'''\r
11 | '''Description'''\r
12 |- style="background-color: #f9f9f9; " |\r
13 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/type/Datatype.java|Datatype]]\r
14 | Base class for all data types\r
15 |- style="background-color: #f9f9f9; " |\r
16 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/type/RecordType.java|RecordType]]\r
17 | Record \r
18 |- style="background-color: #f9f9f9; " |\r
19 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/type/ArrayType.java|ArrayType]]\r
20 | Array - an ordered sequence of elements of one type.\r
21 |- style="background-color: #f9f9f9; " |\r
22 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/type/MapType.java|MapType]]\r
23 | Map - an ordered map of keys to values. \r
24 |- style="background-color: #f9f9f9; " |\r
25 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/type/UnionType.java|UnionType]]\r
26 | Union\r
27 |- style="background-color: #f9f9f9; " |\r
28 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/type/BooleanType.java|BooleanType]],[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/type/IntType.java|IntType]],[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/type/LongType.java|LongType]],[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/type/FloatType.java|FloatType]],[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/type/DoubleType.java|DoubleType]]\r
29 | Primitive and numeric types\r
30 |- style="background-color: #f9f9f9; " |\r
31 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/type/StringType.java|StringType]]\r
32 | String \r
33 |- style="background-color: #f9f9f9; " |\r
34 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/type/OptionalType.java|OptionalType]]\r
35 | Optional value\r
36 |- style="background-color: #f9f9f9; " |\r
37 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/type/VariantType.java|VariantType]]\r
38 | Variant value\r
39 |}\r
40 \r
41 \r
42 Datatype can be acquired or created using one of the following methods:\r
43 * Construct new\r
44 * Constant \r
45 * [[#Reflection|Reflection]]-Read from a Class\r
46 * Read from string of [[Databoard_Specification|the text notation]].\r
47     Datatype type = new DoubleType();\r
48     Datatype type = Datatypes.DOUBLE;\r
49     Datatype type = Datatypes.getDatatype( Double.class );\r
50     \r
51     Datatypes.addDefinition("type Node = { id : String; children : Node[] }");\r
52     Datatype type = Datatypes.getDatatype("Node");\r
53 \r
54 \r
55 ==Parsing==\r
56 Datatypes are parsed using <code>Datatypes.DatatypeRepository</code>. \r
57     Datatypes.addDefinition("type Node = { id : String; children : Node[] }");\r
58     Datatype type = Datatypes.getDatatype("Node");\r
59 \r
60 Types are printed to types and definitions with \r
61     String type = type.toString();\r
62     \r
63     DatatypeRepository repo = new DatatypeRepository();\r
64     repo.add("temp1", type);\r
65     String typeDef = repo.toString();\r
66 \r
67 ==Structure Example==\r
68 A node is a recursive type. With databoard typesystem it could be stated as\r
69   type Node = {\r
70          id : String;\r
71          displayNames : LocalizedTexts;\r
72          children : Node[];\r
73          value : Optional(Variant);\r
74        }\r
75 \r
76 [[Image:NodeType.png|Type presented as tree]]\r
77 \r
78 \r
79 A couple of instances with Databoard value notation:\r
80   root : Node = {\r
81            id = \93PI_01\94\r
82            displayNames = map{ \93en\94 = \93Instrument \93 }\r
83            children = \r
84             [ \r
85               {id=\94Child\94\r
86                displayNames = map{ \93en\94 = \93Child\94} },\r
87                value = 5 : Integer\r
88               }\r
89             ]\r
90            value = \93<root>\94 : String\r
91          }\r
92 \r
93 [[Image:NodeInstance.png|Node values preseted as tree]]\r
94 \r
95 =Binding=\r
96 There is a [[Databoard_Specification#Datatypes|type system]], and when developing with java, platform neutral data values can be read from and written to objects. This is the role of a binding, a map from a Java Class to a Datatype. \r
97 \r
98 For instance, take a java.lang.Double. Its instance is the container (<code>private final double value;</code>) of the data and its Binding (DoubleBinding) is the access (<code>.valueOf()</code>, <code>.getDouble()</code>) to the data. \r
99     Java Object + Binding = Databoard Value\r
100 \r
101 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
102     Binding binding = Binding.getBinding( Double.class );\r
103 \r
104 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
105     Binding binding = new RecordBinding() { ... };\r
106 \r
107 \r
108 '''[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/binding|org.simantics.databoard.binding]]'''.\r
109 {| style="background-color: #e9e9e9; border: 1px solid #aaaaaa; "\r
110 | '''Class'''\r
111 | '''Description'''\r
112 |- style="background-color: #f9f9f9; " |\r
113 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/binding/DataBinding.java|DataBinding]]\r
114 | Base class for all data Bindings\r
115 |- style="background-color: #f9f9f9; " |\r
116 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/binding/RecordBinding.java|RecordBinding]]\r
117 | Record \r
118 |- style="background-color: #f9f9f9; " |\r
119 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/binding/ArrayBinding.java|ArrayBinding]]\r
120 | Array - an ordered sequence of elements of one value.\r
121 |- style="background-color: #f9f9f9; " |\r
122 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/binding/MapBinding.java|MapBinding]]\r
123 | Map - an ''ordered'' map of keys to values. \r
124 |- style="background-color: #f9f9f9; " |\r
125 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/binding/UnionBinding.java|UnionBinding]]\r
126 | Union\r
127 |- style="background-color: #f9f9f9; " |\r
128 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/binding/BooleanBinding.java|BooleanBinding]],[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/binding/IntBinding.java|IntBinding]],[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/binding/LongBinding.java|LongBinding]],[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/binding/FloatBinding.java|FloatBinding]],[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/binding/DoubleBinding.java|DoubleBinding]]\r
129 | Primitive and numeric Bindings\r
130 |- style="background-color: #f9f9f9; " |\r
131 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/binding/StringBinding.java|StringBinding]]\r
132 | String \r
133 |- style="background-color: #f9f9f9; " |\r
134 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/binding/OptionalBinding.java|OptionalBinding]]\r
135 | Optional value\r
136 |- style="background-color: #f9f9f9; " |\r
137 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/binding/VariantBinding.java|VariantBinding]]\r
138 | Variant value\r
139 |}\r
140 \r
141 \r
142 Binding can be acquired or created using one of the following methods:\r
143 * Constructor \r
144 * Constant\r
145 * Reflection-Read from a Class \r
146 * Created using [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/bindingscheme/BindingScheme.java|BindingScheme]]\r
147     Binding binding = new DoubleBinding( doubleType );\r
148     Binding binding = new RecordBinding() { ... };\r
149     Binding binding = Bindings.DOUBLE;\r
150     Binding binding = Binding.getBinding( Double.class );\r
151     Binding binding = Binding.getBinding( Datatypes.DOUBLE );\r
152 \r
153 ==Reflection==\r
154 '''Data Type and Binding can be read automatically from a Class by utility.'''\r
155     Datatype type = Datatypes.getDatatype( Foo.class );\r
156     Binding binding = Bindings.getBinding( Foo.class );\r
157 \r
158 Bindings for generics classes can be created by passing arguments.\r
159     Binding e = Bindings.getBinding(List.class, String.class);\r
160     List<String> list = (List<String>) e.createRandom(5);\r
161 \r
162     Binding binding = Bindings.getBinding( Map.class, Integer.class, Integer.class );\r
163     Map<Integer, Integer> value = (Map<Integer, Integer>) binding.createDefault();\r
164 \r
165 Even cascading generics...\r
166     Binding e = Bindings.getBinding(List.class, List.class, String.class);\r
167     List<List<String>> listList = (List<List<String>>) e.createRandom(5);\r
168 \r
169 \r
170 '''Classes are RecordTypes'''\r
171     class Foo {\r
172         public int x, y, z;\r
173     }\r
174 Is a binding to the following Datatype\r
175     type Foo = { x : Integer, y : Integer, z : Integer }\r
176 \r
177 '''There are three types of classes supported, and therefore three ways how objects are constructed.'''\r
178 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
179 \r
180 ''Record-like classes:''\r
181     class Foo {\r
182         public String name;\r
183         public Object value;\r
184     }\r
185 \r
186 ''Immutable classes:''\r
187     class Foo {\r
188         private String name;\r
189         private Object value;\r
190         \r
191         public Foo(String name, Object value) {\r
192             this.name = name;\r
193             this.value = value;\r
194         }\r
195         \r
196         public String getName() {\r
197             return name;\r
198         }\r
199         \r
200         public Object getValue() {\r
201             return value;\r
202         }\r
203         \r
204     }\r
205 \r
206 ''Bean-like classes:''\r
207     class Foo {\r
208         private String name;\r
209         private Object value;\r
210         \r
211         public void setName(String name) {\r
212             this.name = name;\r
213         }\r
214         \r
215         public void setValue(Object value) {\r
216             this.value = value;\r
217         }\r
218         \r
219         public String getName() {\r
220             return name;\r
221         }\r
222         \r
223         public Object getValue() {\r
224             return value;\r
225         }\r
226         \r
227     }\r
228 \r
229 '''Static and transient fields are omited:'''\r
230     static final long serialVersionUID = -3387516993124229943L;\r
231     transient int hashCode;\r
232 \r
233 '''Enumerations are Union Types'''\r
234     enum Cars { Ferrari, Porche, Lamborghini, Jaguar }    \r
235 is interpreted as union type\r
236     type Cars = | Ferrari | Porche | Lamborghini | Jaguar\r
237 \r
238 If you cannot modify the class, you have to create binding for it by subclassing base binding classes, eg. RecordBinding.\r
239 \r
240 '''Other exceptions:'''\r
241 *<code>java.lang.Object</code> is <tt>Variant</tt>.\r
242 *<code>java.lang.Set<T></code> is <tt>Map(T, {})</tt>.\r
243 *<code>java.lang.TreeSet<T></code> is <tt>Map(T, {})</tt>.\r
244 *<code>java.lang.HashSet<T></code> is <tt>Map(T, {})</tt>. (Note HashSet binding has very low performance.)\r
245 *<code>java.lang.Map<K, V></code> is <tt>Map(K, V)</tt>.\r
246 *<code>java.lang.TreeMap<K, V></code> is <tt>Map(K, V)</tt>.\r
247 *<code>java.lang.HashMap<K, V></code> is <tt>Map(K, V)</tt>. (Note HashMap binding has very low performance.)\r
248 *<code>java.lang.List<T></code> is <tt>Array(T)</tt>.\r
249 *<code>java.lang.ArrayList<T></code> is <tt>Array(T)</tt>.\r
250 *<code>java.lang.LinkedList<T></code> is <tt>Array(T)</tt>.\r
251 *<code>void</code> is <tt>{}</tt>.\r
252 *The stacktrace of <code>Exception.class</code> is omited.\r
253 \r
254 ===Annotations===\r
255 Java Classes / Fields can be annotated with the following annotations ('''[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/annotations/|org.simantics.databoard.annotations]]''').\r
256 \r
257 \r
258 '''UnionTypes are abstract classes or interfaces with <code>@Union</code> annotation.'''\r
259     @Union({A.class, B.class}) interface Union1 {               \r
260     }\r
261     \r
262     class A implements Union1 {\r
263         public int value;\r
264     }\r
265     \r
266     class B implements Union1 {\r
267         public String name;\r
268     }\r
269 \r
270 \r
271 '''<code>@Referable</code> denotes that the class has recursion and is a referable record.'''\r
272     public @Referable class Node {\r
273         public Node[] children;\r
274     }\r
275 \r
276 \r
277 '''Fields that can have <tt>null</tt> value have <code>@Optional</code> annotation.'''\r
278     @Optional String name;\r
279 \r
280 \r
281 '''String valid values are set with <code>@Pattern</code> as regular expression. ([http://en.wikipedia.org/wiki/Regular_expression])'''\r
282     String @Pattern("(19|20)\\d\\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])") date;\r
283     \r
284     type Date = String( Pattern = "(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])" )\r
285 \r
286 \r
287 '''String content type is set with a <code>@MIMEType</code>. ([http://en.wikipedia.org/wiki/Mime_type MIME Type])'''\r
288     @MIMEType("text/xml") String document;\r
289 \r
290 \r
291 '''Array size restricted with @Length.'''\r
292     @Length("[0..10]") int[] array;\r
293     @Length({"[320]", "[240]"}) int[][] image;\r
294 \r
295 \r
296 '''Valid numeric range is set with @Range.'''\r
297     @Range("[0..100]") double alpha;\r
298     @Range("[0..]" double length;\r
299 \r
300 \r
301 '''<tt>Range</tt> and <tt>Length</tt> notation:'''\r
302 *Exact Value "0"\r
303 *Exclude all "()"\r
304 *Unlimited "[..]"\r
305 *Inclusive range "[0..100]"\r
306 *Exclusive range "(0..100)"\r
307 *Inclusive lower bound and exclusive upper bound "[0..100)"\r
308 \r
309 \r
310 '''Engineering unit type is given with @Unit.'''\r
311     @Unit("km/h") double maxVelocity;\r
312 \r
313 '''The serializer generated with reflection can be overriden with @SpecializedSerializer'''\r
314     @SpecializedSerializer(MySerializer.class) \r
315     public class MyRecord {\r
316         ...\r
317     }\r
318 \r
319 == Mapping Scheme ==\r
320 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
321 \r
322 <code>DefaultBindingScheme</code> is a scheme that converts any datatype to a binding. It prefers java.lang.X primitives.\r
323 The Class mapping for each type is listed below.\r
324 {| style="background-color: #e9e9e9; border: 1px solid #aaaaaa; "\r
325 | '''Type'''\r
326 | '''Class'''\r
327 |- style="background-color: #f9f9f9; " |\r
328 | <code>BooleanType</code>\r
329 | <code>Boolean.class</code>\r
330 |- style="background-color: #f9f9f9; " |\r
331 | <code>ByteType</code>\r
332 | <code>Byte.class</code>\r
333 |- style="background-color: #f9f9f9; " |\r
334 | <code>FloatType</code>\r
335 | <code>Float.class</code>\r
336 |- style="background-color: #f9f9f9; " |\r
337 | <code>DoubleType</code>\r
338 | <code>eDouble.class</code>\r
339 |- style="background-color: #f9f9f9; " |\r
340 | <code>IntegerType</code>\r
341 | <code>Integer.class</code>\r
342 |- style="background-color: #f9f9f9; " |\r
343 | <code>LongType</code>\r
344 | <code>Long.class</code>\r
345 |- style="background-color: #f9f9f9; " |\r
346 | <code>StringType</code>\r
347 | <code>String.class</code>\r
348 |- style="background-color: #f9f9f9; " |\r
349 | <code>UnionType</code>\r
350 | <code>TaggedObject.class</code>\r
351 |- style="background-color: #f9f9f9; " |\r
352 | <code>OptionType</code>\r
353 | <code>ValueContainer.class</code>\r
354 |- style="background-color: #f9f9f9; " |\r
355 | <code>RecordType</code>\r
356 | <code>Object[].class</code>\r
357 |- style="background-color: #f9f9f9; " |\r
358 | <code>ArrayType</code>\r
359 | <code>ArrayList.class</code>\r
360 |- style="background-color: #f9f9f9; " |\r
361 | <code>Array(Byte)</code>\r
362 | <code>byte[].class</code>\r
363 |- style="background-color: #f9f9f9; " |\r
364 | <code>MapType</code>\r
365 | <code>TreeMap.class</code>\r
366 |- style="background-color: #f9f9f9; " |\r
367 | <code>VariantType</code>\r
368 | <code>Variant.class</code>\r
369 |}\r
370 \r
371 <code>MutableBindingScheme</code> is a scheme that provides a fully implementing mutable binding for all data types. \r
372 The Class mapping for each type is listed below.\r
373 \r
374 {| style="background-color: #e9e9e9; border: 1px solid #aaaaaa; "\r
375 | '''Type'''\r
376 | '''Class'''\r
377 |- style="background-color: #f9f9f9; " |\r
378 | <code>BooleanType</code>\r
379 | <code>MutableBoolean.class</code>\r
380 |- style="background-color: #f9f9f9; " |\r
381 | <code>ByteType</code>\r
382 | <code>MutableByte.class</code>\r
383 |- style="background-color: #f9f9f9; " |\r
384 | <code>FloatType</code>\r
385 | <code>MutableFloat.class</code>\r
386 |- style="background-color: #f9f9f9; " |\r
387 | <code>DoubleType</code>\r
388 | <code>MutableDouble.class</code>\r
389 |- style="background-color: #f9f9f9; " |\r
390 | <code>IntegerType</code>\r
391 | <code>MutableInt.class</code>\r
392 |- style="background-color: #f9f9f9; " |\r
393 | <code>LongType</code>\r
394 | <code>MutableLong.class</code>\r
395 |- style="background-color: #f9f9f9; " |\r
396 | <code>StringType</code>\r
397 | <code>MutableString.class</code>\r
398 |- style="background-color: #f9f9f9; " |\r
399 | <code>UnionType</code>\r
400 | <code>TaggedObject.class</code>\r
401 |- style="background-color: #f9f9f9; " |\r
402 | <code>OptionType</code>\r
403 | <code>ValueContainer.class</code>\r
404 |- style="background-color: #f9f9f9; " |\r
405 | <code>RecordType</code>\r
406 | <code>Object[].class</code>\r
407 |- style="background-color: #f9f9f9; " |\r
408 | <code>ArrayType</code>\r
409 | <code>ArrayList.class</code>\r
410 |- style="background-color: #f9f9f9; " |\r
411 | <code>MapType</code>\r
412 | <code>TreeMap.class</code>\r
413 |- style="background-color: #f9f9f9; " |\r
414 | <code>VariantType</code>\r
415 | <code>Variant.class</code>\r
416 |}\r
417 \r
418 \r
419 ===Serialization===\r
420 [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/serialization/binary/Serializer.java|Serializer.java]] 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
421 \r
422     Binding binding = Bindings.DOUBLE;\r
423     Serializer serializer = Bindings.getSerializer( binding );\r
424     byte[] data = serializer.serialize( new Double( 100.0 ) );\r
425     \r
426     Double value = (Double) serializer.deserialize( data );\r
427 \r
428 Files can be partially accessed using BinaryAccessor, see [[#Accessors|Accessors]]. This is useful when handling larger than memory files.\r
429 \r
430 ===Validation===\r
431 '''Value''' can be ''well-formed'' or ''valid''. \r
432 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
433 \r
434 Validation mechanism in Binding asserts that the instance is a valid value of the respective Data Type.\r
435     try {\r
436         Binding.assertInstaceIsValid( object );\r
437     } catch( BindingException e ) {\r
438         // In-valid object\r
439     }\r
440 \r
441 ===Other Notes===\r
442 *<tt>Binding</tt> is a <tt>Comparator</tt>, all data values are comparable, the order is defined in [[Databoard_Specification#Comparison|Specification]].\r
443 *<tt>Binding#createDefault()</tt> creates a valid instance of the Datatype.\r
444 *<tt>Binding#createRandom(int)</tt> creates a valid instance with random values. Useful for unit tests.\r
445 *<tt>Binding#clone(Object)</tt> creates a new instance with same content.\r
446 *<tt>Binding#readFrom(Object, Binding, Binding)</tt> copies contents from another object of same type.\r
447 \r
448 ===Parsing & Printing===\r
449 \r
450 Data values are printed and parsed of the [[Databoard_Specification|Text notation]] with the following <code>Binding</code> methods:\r
451 \r
452     String text = binding.printValue( value, true );\r
453     \r
454     Object value = binding.parseValue( text );\r
455 \r
456 And also to value definitions <tt>''name : type = value''</tt>\r
457     StringBuilder sb = new StringBuilder();\r
458     DataValueRepository repo = new DataValueRepository();\r
459     repo.put( "temp", binding, value );\r
460     binding.printValue( value, sb, repo, true );\r
461     String text = sb.toString();\r
462     \r
463     Object value = binding.parseValueDefinition( text );\r
464 \r
465 =Adapter=\r
466 There can be different Java Class Bindings for a single data type. For example, <code>Double</code> type can be have bindings <code>DoubleJavaBinding</code> and <code>MutableDoubleBinding</code> to two respective classes <code>java.lang.Double</code> and <code>MutableDouble</code>. Instance of one binding can be adapted to instance of another with an <code>[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/adapter/Adapter.java|Adapter]]</code>.\r
467 \r
468 Adapter can be created automatically or implemented self.\r
469     Adapter adapter = new Adapter() { ... };\r
470     Adapter adapter = Bindings.getAdapter( domainBinding, rangeBinding );\r
471 \r
472 Example:\r
473     Adapter adapter = Bindings.getAdapter(Bindings.MUTABLE_DOUBLE, Bindings.DOUBLE);\r
474     java.lang.Double double = adapter.adapt( new MutableDouble(5.0) );\r
475 \r
476 There is also convenience.\r
477     java.lang.Double double = Bindings.adapt( new MutableDouble(5.0), Bindings.MUTABLE_DOUBLE, Bindings.DOUBLE );\r
478 \r
479 The argument given to <code>Adapter#adapt(Object)</code> may be re-used in the result unless the adapter is a cloning adapter which guarantees a clone. Note, even wih cloning adapters immutable classes, (eg java.lang.Integer) are never cloned.\r
480     Adapter cloner = Bindings.adapterCache.getAdapter(domain, range, false, true);\r
481     cloner.adapt( ... );\r
482 \r
483     Rectangle2D rect2 = Bindings.clone( rect1, rectBinding, rectBinding );\r
484 \r
485 ===Type Conversion===\r
486 In some cases different types may be are type-conversion compatible. An instance of one type is convertible to instance of another.\r
487 \r
488 '''Engineering Units of same quantity are convertible.'''\r
489     class CarSI {\r
490         String modelName;               \r
491         @Unit("km/h") double maxVelocity;               \r
492         @Unit("kg") double mass;                \r
493         @Unit("cm") double length; \r
494         @Unit("kW") double power;\r
495     }\r
496     \r
497     class CarIm {\r
498         String modelName;               \r
499         @Unit("mph") float maxVelocity;         \r
500         @Unit("lbs") float mass;                \r
501         @Unit("ft") float length; \r
502         @Unit("hp(M)") float power;\r
503     }\r
504     \r
505     Adapter si2imAdapter = Bindings.getTypeAdapter(\r
506         Bindings.getBinding(CarSI.class), \r
507         Bindings.getBinding(CarIm.class) );\r
508     \r
509     CarIm americanCarInfo = si2imAdapter.adapt( europeanCarInfo );\r
510 \r
511 \r
512 '''Primitive Types.''' Note, primitive adapter throws an exception at runtime if values are not adaptable.\r
513     Adapter adapter = getTypeAdapter( integerBinding, doubleBinding );\r
514     Double double = adapter.adapt( new Integer( 5 ) );\r
515 \r
516 \r
517 '''Records are matched by field names.'''\r
518     class Foo {\r
519         int x, y, z;\r
520     }\r
521     class Bar {\r
522         int z, y, x;\r
523     }\r
524     Adapter adapter = getTypeAdapter( fooBinding, barBinding );\r
525     \r
526 \r
527 '''Subtype to supertype:''' Note, this conversion cannot be not symmetric, supertypes cannot be converted to subtypes.\r
528     class Node {\r
529         String id;\r
530     }\r
531     class ValueNode extends Node {\r
532         Object value;\r
533     }\r
534     Adapter adapter = getTypeAdapter( valueNodeBinding, nodeBinding );\r
535 \r
536 '''Non-existing fields to Optional fields''' \r
537     class Node {\r
538         String id;\r
539     }\r
540     class NominalNode {\r
541         String id;\r
542         @Optional String name;\r
543     }\r
544     Adapter adapter = getTypeAdapter( nodeBinding, nominalNodeBinding );\r
545     \r
546 \r
547 '''Enumerations'''\r
548     enum Cars { Audio, BMW, Mercedes, Honda, Mazda, Toyota, Ford, Mitsubishi, Nissan, GM }\r
549     enum JapaneseCars { Honda, Mazda, Toyota, Nissan, Mitsubishi }\r
550     \r
551     Binding carsBinding = Bindings.getBinding( Cars.class );\r
552     Binding japaneseCarsBinding = Bindings.getBinding( JapaneseCars.class );\r
553     Adapter adapter = Bindings.adapterCache.getAdapter(japaneseCarsBinding, carsBinding, true, false);\r
554 \r
555 =Accessors=\r
556 Say, you have several gigabytes of data in a file. The whole object doesn't need to be serialized at once. You can read and write the value partially using [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/accessor/|Accessor]] interface. The actual container can be a file, memory byte[]/ByteBuffer or a Java Object. The content is structured as tree using Databoard's type system. All but referable records are supported (=no recursion in accessors). \r
557 \r
558 '''[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/accessor|org.simantics.databoard.accessor]] interfaces'''.\r
559 {| style="background-color: #e9e9e9; border: 1px solid #aaaaaa; "\r
560 | '''Class'''\r
561 | '''Description'''\r
562 |- style="background-color: #f9f9f9; " |\r
563 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/accessor/Accessor.java|Accessor]]\r
564 | Base class for all data Accessors\r
565 |- style="background-color: #f9f9f9; " |\r
566 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/accessor/RecordAccessor.java|RecordAccessor]]\r
567 | Record \r
568 |- style="background-color: #f9f9f9; " |\r
569 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/accessor/ArrayAccessor.java|ArrayAccessor]]\r
570 | Array - an ordered sequence of elements of one value.\r
571 |- style="background-color: #f9f9f9; " |\r
572 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/accessor/MapAccessor.java|MapAccessor]]\r
573 | Map - an ''ordered'' map of keys to values. \r
574 |- style="background-color: #f9f9f9; " |\r
575 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/accessor/UnionAccessor.java|UnionAccessor]]\r
576 | Union\r
577 |- style="background-color: #f9f9f9; " |\r
578 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/accessor/BooleanAccessor.java|BooleanAccessor]],[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/accessor/IntAccessor.java|IntAccessor]],[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/accessor/LongAccessor.java|LongAccessor]],[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/accessor/FloatAccessor.java|FloatAccessor]],[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/accessor/DoubleAccessor.java|DoubleAccessor]]\r
579 | Primitive and numeric Accessors\r
580 |- style="background-color: #f9f9f9; " |\r
581 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/accessor/StringAccessor.java|StringAccessor]]\r
582 | String \r
583 |- style="background-color: #f9f9f9; " |\r
584 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/accessor/OptionalAccessor.java|OptionalAccessor]]\r
585 | Optional value\r
586 |- style="background-color: #f9f9f9; " |\r
587 | [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/accessor/VariantAccessor.java|VariantAccessor]]\r
588 | Variant value\r
589 |}\r
590 \r
591 [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/Accessors.java|Accessors]] and [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/Files.java|Files]] are facade classes that contains utilities for instantiating and handling Accessors.\r
592 \r
593 <code>[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/accessor/binary/|Binary Accessor]]</code> is an access to a value in binary format (<tt>byte[]</tt> or <tt>ByteBuffer</tt>).\r
594 \r
595 '''Example:''' Binary accessor\r
596 <div style="background-color:#fffff7; border: 1px dashed #cccccc; padding: 2ex; margin-left:2em; margin-right:2em; margin-top: 1em; margin-bottom:1em;"><syntaxhighlight lang="java">\r
597 Datatype type = Datatypes.getDatatype( Rectangle2D.Double.class );\r
598 Binding binding = Bindings.getBinding( Rectangle2D.Double.class );\r
599 Serializer s = Binding.getSerializer( binding );\r
600 \r
601 // Serialize rectangle\r
602 Rectangle2D rect = new Rectangle2D.Double(0,0, 10, 10);\r
603 byte[] data = s.serialize(rect);\r
604 \r
605 // Open accessor to byte data and modify first field in the byte data\r
606 RecordAccessor ra = Accessors.getAccessor(data, type);\r
607 ra.setFieldValue(0, Bindings.DOUBLE, 5.0);\r
608 \r
609 // Deserialize values from the byte data back to the rectangle object\r
610 s.deserialize(data, rect);\r
611 System.out.println(rect.getX());\r
612 </syntaxhighlight></div>\r
613 \r
614 '''Example:''' File accessor, create\r
615 <div style="background-color:#fffff7; border: 1px dashed #cccccc; padding: 2ex; margin-left:2em; margin-right:2em; margin-top: 1em; margin-bottom:1em;"><syntaxhighlight lang="java">\r
616 RecordType type = Datatypes.getDatatype( Rectangle2D.Double.class );\r
617 // Create a new file and initialize it with rectangle type, and open file accessor\r
618 FileRecordAccessor fa = Accessors.createFile( file, type );\r
619 \r
620 // Write the first field (x)\r
621 fa.setFieldValue(0, Bindings.DOUBLE, 5.0);\r
622 fa.close();\r
623 </syntaxhighlight></div>\r
624 \r
625 '''Example:''' File accessor, open\r
626 <div style="background-color:#fffff7; border: 1px dashed #cccccc; padding: 2ex; margin-left:2em; margin-right:2em; margin-top: 1em; margin-bottom:1em;"><syntaxhighlight lang="java">\r
627 // Open an accessor to an existing binary file\r
628 FileVariantAccessor fa = Accessors.openAccessor(file);\r
629 RecordAccessor ra = fa.getContentAccessor();\r
630 \r
631 // Read the first field (x)\r
632 Double x = (Double) ra.getFieldValue(0, Bindings.DOUBLE);\r
633 fa.close();\r
634 </syntaxhighlight></div>\r
635 \r
636 '''Example:''' Java Accessor\r
637 <div style="background-color:#fffff7; border: 1px dashed #cccccc; padding: 2ex; margin-left:2em; margin-right:2em; margin-top: 1em; margin-bottom:1em;"><syntaxhighlight lang="java">\r
638 Binding binding = Bindings.getBinding(Rectangle2D.Double.class);\r
639 Rectangle2D rect = new Rectangle2D.Double(0,0, 10, 10);\r
640 \r
641 // Open accessor to rectangle\r
642 RecordAccessor ra = Accessors.getAccessor(binding, rect);\r
643 \r
644 // Set rectangle's first field (x) to 5.0\r
645 ra.setFieldValue(0, Bindings.DOUBLE, 5.0);\r
646 System.out.println( rect.getX() );\r
647 </syntaxhighlight></div>\r
648 \r
649 \r
650 ==Accessor Reference==\r
651 Accessors can be opened to a sub-nodes with AccessorReference or by calling getAccessor. AccessorReference is a string of instances, either accessor type specific of LabelReferences. \r
652     ChildReference ref = ChildReference.compile(\r
653       new NameReference("node"),\r
654       new ComponentReference()\r
655     );\r
656     Accessor child = accessor.getComponent( ref );\r
657 \r
658     ChildReference ref = ChildReference.compile(\r
659        new LabelReference("node"),\r
660        new LabelReference("v")\r
661     );\r
662     Accessor child = accessor.getComponent( ref );\r
663 \r
664     ChildReference ref = ChildReference.create("n-node/v");\r
665     Accessor child = accessor.getComponent( ref );\r
666 \r
667     ChildReference ref = ChildReference.create("node/v");\r
668     Accessor child = accessor.getComponent( ref );\r
669 \r
670     VariantAccessor va = recordAccessor.getFieldAccessor("node");\r
671     Accessor child = va.getValueAccessor();\r
672 \r
673 ==Listening mechanism==\r
674 Accessor offers a monitoring mechanism for the data model. \r
675 There is an <code>[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/accessor/interestset/InterestSet.java|InterestSet]]</code> that is a description of a sub-tree that is to be monitored of the data model.\r
676 <code>[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/accessor/event/Event.java|Events]]</code> are objects that spawned on changes to the data model. Each event object is annotated with [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/accessor/reference/|reference path]] that is in relation to the node where the listener was placed.\r
677 \r
678 Accessor Listeners use [[EventThread Pattern]] pattern.\r
679 \r
680 =Utilities=\r
681 \r
682 *[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/Datatypes.java|Datatypes]] is a facade class that has functions for handling Datatypes.\r
683 *[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/Bindings.java|Bindings]] is a facade class that has functions for handling Bindings.\r
684 *[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/Accessors.java|Accessors]] is a facade class that has functions for handling Accessors.\r
685 *[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/Files.java|Files]] has Read, Write and accessor functions.\r
686 *[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/Units.java|Units]] is a facade class that has functions for handling Engineering Units.\r
687 *[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/Methods.java|Methods]] has Methods, Interfaces and RPC utility functions.\r
688 \r
689 *[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/util/binary/RandomAccessBinary.java|RandomAccessBinary]] is a interface for byte handling operations. In addition to basic primitive reading & writing, there are methods for grow, shrink, insert and remove. \r
690 **[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/util/binary/BinaryFile.java|BinaryFile]] and [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/util/binary/BinaryMemory.java|BinaryMemory]] are corresponding file and memory implementations. \r
691 **[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/util/binary/Blob.java|Blob]] is an implementation that represents a sub-region of a RandomAccessBinary. \r
692 \r
693 ==Interface Types==\r
694 There are interfaces, method types and method type definitions. \r
695 Interface type describes a software interface. It is a collection of methods type definitions. \r
696 Method type is an unnamed function with the following properties : Response Type, Request Type and ErrorType; where Response Type is any Data Type, Request Type is a Record and Error Type is an Union.\r
697 Method type definition is nominal method description.\r
698 \r
699 The respective Java classes are:\r
700 *[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/method/Interface.java|Interface.java]] \r
701 *[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/method/MethodTypeDefinition.java|MethodTypeDefinition.java]]\r
702 *[[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/method/MethodType.java|MethodType.java]]\r
703 \r
704 In java InterfaceType description can be created with one of the following methods:\r
705 * Implementing InterfaceType\r
706 * Reading an Java Interface Class using reflection\r
707     Interface it = new Interface( ... methodDefinitions );\r
708     Interface it = getInterface( MyInterface.class );\r
709 \r
710 [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/method/MethodInterface.java|MethodInterface.java]] is a binding of an\r
711 Java Instance and an Interface Type. It decouples the method invocation from the object.\r
712 \r
713 MethodInterface can be created with the following methods:\r
714 * Implementation\r
715 * Reflection\r
716     MethodInterface mi   = new MethodInterface() {...}\r
717     MethodInterface mi   = Datatypes.bindInterface( MyInterface.class, myObject );\r
718 \r
719 Utilities <code>Datatypes.createProxy()</code> and <code>Datatypes.bindInterface()</code> adapt between MethodInterface and Java Instance.\r
720     MethodInterface mi   = Datatypes.bindInterface( MyInterface.class, myObject );\r
721     MyInterface myObject = Datatypes.createProxy( MyInterface.class, mi );\r
722 \r
723 ==Remote Procedure Call==\r
724 Utilities [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/method/Server.java|Server.java]] and [[svn:foundation/databoard/trunk/org.simantics.databoard/src/org/simantics/databoard/method/Client.java|Client.java]] put MethodInterface over TCP Socket. \r
725     Server myServer      = new Server(8192, mi);\r
726     MethodInterface mi   = new Client("localhost", 8192);\r
727 \r
728 MethodInterface with Server and Client together forms a Remote Procedure Call (RPC) mechanism.\r
729     public interface MyInterface { String helloWorld(String msg); }\r
730     \r
731     [Server]\r
732     MethodInterface mi   = Methods.bindInterface( MyInterface.class, myObject );\r
733     Server myServer      = new Server(8192, mi);\r
734     \r
735     [Client]\r
736     MethodInterface mi   = new Client("localhost", 8192);\r
737     MyInterface myObject = Methods.createProxy( MyInterface.class, mi );\r
738 \r
739 [[Category: Data management & Experiment Control]]\r