1 /*******************************************************************************
2 * Copyright (c) 2010 Association for Decentralized Information Management in
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.databoard;
14 import java.io.IOException;
15 import java.util.Comparator;
18 import org.simantics.databoard.adapter.AdaptException;
19 import org.simantics.databoard.adapter.Adapter;
20 import org.simantics.databoard.adapter.AdapterConstructionException;
21 import org.simantics.databoard.adapter.AdapterFactory;
22 import org.simantics.databoard.adapter.RuntimeAdaptException;
23 import org.simantics.databoard.adapter.RuntimeAdapterConstructionException;
24 import org.simantics.databoard.annotations.ArgumentImpl;
25 import org.simantics.databoard.annotations.Arguments;
26 import org.simantics.databoard.binding.ArrayBinding;
27 import org.simantics.databoard.binding.Binding;
28 import org.simantics.databoard.binding.BooleanBinding;
29 import org.simantics.databoard.binding.ByteBinding;
30 import org.simantics.databoard.binding.DoubleBinding;
31 import org.simantics.databoard.binding.FloatBinding;
32 import org.simantics.databoard.binding.IntegerBinding;
33 import org.simantics.databoard.binding.LongBinding;
34 import org.simantics.databoard.binding.StringBinding;
35 import org.simantics.databoard.binding.VariantBinding;
36 import org.simantics.databoard.binding.classfactory.TypeClassFactory;
37 import org.simantics.databoard.binding.error.BindingConstructionException;
38 import org.simantics.databoard.binding.error.BindingException;
39 import org.simantics.databoard.binding.error.RuntimeBindingConstructionException;
40 import org.simantics.databoard.binding.factory.BindingRepository;
41 import org.simantics.databoard.binding.factory.TypeBindingFactory;
42 import org.simantics.databoard.binding.impl.BooleanArrayBinding;
43 import org.simantics.databoard.binding.impl.BooleanBindingDefault;
44 import org.simantics.databoard.binding.impl.ByteArrayBinding;
45 import org.simantics.databoard.binding.impl.ByteBindingDefault;
46 import org.simantics.databoard.binding.impl.DoubleArrayBinding;
47 import org.simantics.databoard.binding.impl.DoubleBindingDefault;
48 import org.simantics.databoard.binding.impl.FloatArrayBinding;
49 import org.simantics.databoard.binding.impl.FloatBindingDefault;
50 import org.simantics.databoard.binding.impl.IntArrayBinding;
51 import org.simantics.databoard.binding.impl.IntegerBindingDefault;
52 import org.simantics.databoard.binding.impl.LongArrayBinding;
53 import org.simantics.databoard.binding.impl.LongBindingDefault;
54 import org.simantics.databoard.binding.impl.StringArrayBinding;
55 import org.simantics.databoard.binding.impl.StringBindingDefault;
56 import org.simantics.databoard.binding.impl.UnsignedByteBinding;
57 import org.simantics.databoard.binding.impl.UnsignedIntegerBinding;
58 import org.simantics.databoard.binding.impl.UnsignedLongBinding;
59 import org.simantics.databoard.binding.mutable.MutableBooleanBinding;
60 import org.simantics.databoard.binding.mutable.MutableByteBinding;
61 import org.simantics.databoard.binding.mutable.MutableDoubleBinding;
62 import org.simantics.databoard.binding.mutable.MutableFloatBinding;
63 import org.simantics.databoard.binding.mutable.MutableIntegerBinding;
64 import org.simantics.databoard.binding.mutable.MutableLongBinding;
65 import org.simantics.databoard.binding.mutable.MutableStringBinding;
66 import org.simantics.databoard.binding.mutable.MutableVariantBinding;
67 import org.simantics.databoard.binding.reflection.BindingProvider;
68 import org.simantics.databoard.binding.reflection.BindingRequest;
69 import org.simantics.databoard.binding.reflection.ClassBindingFactory;
70 import org.simantics.databoard.binding.reflection.VoidBinding;
71 import org.simantics.databoard.serialization.RuntimeSerializerConstructionException;
72 import org.simantics.databoard.serialization.Serializer;
73 import org.simantics.databoard.serialization.SerializerConstructionException;
74 import org.simantics.databoard.serialization.SerializerFactory;
75 import org.simantics.databoard.type.ArrayType;
76 import org.simantics.databoard.type.Datatype;
77 import org.simantics.databoard.util.DataValueUtil;
80 * This ia a facade class for the binding services.
82 * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
84 public class Bindings {
86 public static final Databoard databoard;
90 /** Repository of mutable bindings */
91 public static final Map<Datatype, Binding> mutableBindingRepository;
93 /** Repository of default bindings */
94 public static final Map<Datatype, Binding> defaultBindingRepository;
96 /** Repository of class Bindings */
97 public static final BindingRepository bindingRepository;
99 /** Repository of serializers */
100 public static final Map<Binding, Serializer> serializerRepository;
105 /** Mutable Bindings Factory */
106 public static final TypeBindingFactory mutableBindingFactory;
108 /** Default Bindings Factory */
109 public static final TypeBindingFactory defaultBindingFactory;
111 /** Reflection based Binding Factory, create binding to class */
112 public static final ClassBindingFactory classBindingFactory;
114 /** Serializer Factory */
115 public static final SerializerFactory serializationFactory;
117 /** Adapter Factory */
118 public static final AdapterFactory adapterFactory;
121 public static final TypeClassFactory typeClassFactory;
124 // Bindings to various primitives
125 public static final StringBinding STRING; // java.lang.String
126 public static final IntegerBinding INTEGER; // java.lang.Integer
127 public static final BooleanBinding BOOLEAN; // java.lang.Boolean
128 public static final ByteBinding BYTE; // java.lang.Byte
129 public static final LongBinding LONG; // java.lang.Long
130 public static final DoubleBinding DOUBLE; // java.lang.Double
131 public static final FloatBinding FLOAT; // java.lang.Float
132 public static final VariantBinding VARIANT; // Variant
133 public static final VariantBinding OBJECT; // java.lang.Object ( as variant )
134 public static final VariantBinding STR_VARIANT; // java.lang.String ( as variant )
136 public static final Binding VOID; // void ( as {} )
137 public static final Binding BEAN; // Bean ( as variant )
138 public static final Binding DATATYPE; // org.simantics.databoard.type.Datatype
140 public static final ArrayBinding BOOLEAN_ARRAY; // boolean[]
141 public static final ArrayBinding BYTE_ARRAY; // byte[]
142 public static final ArrayBinding INT_ARRAY; // int[]
143 public static final ArrayBinding LONG_ARRAY; // long[]
144 public static final ArrayBinding FLOAT_ARRAY; // float[]
145 public static final ArrayBinding DOUBLE_ARRAY; // double[]
146 public static final ArrayBinding STRING_ARRAY; // String[]
148 public static final StringBinding MUTABLE_STRING; // MutableString
149 public static final IntegerBinding MUTABLE_INTEGER; // MutableInteger
150 public static final BooleanBinding MUTABLE_BOOLEAN; // MutableBoolean
151 public static final ByteBinding MUTABLE_BYTE; // MutableByte
152 public static final LongBinding MUTABLE_LONG; // MutableLong
153 public static final FloatBinding MUTABLE_FLOAT; // MutableFloat
154 public static final DoubleBinding MUTABLE_DOUBLE; // MutableDouble
155 public static final VariantBinding MUTABLE_VARIANT; // MutableVariant
157 public static final IntegerBinding UNSIGNED_INTEGER; // UnsignedInteger.Immutable
158 public static final ByteBinding UNSIGNED_BYTE; // UnsignedByte.Immutable
159 public static final LongBinding UNSIGNED_LONG; // UnsignedLong.Immutable
161 public static final IntegerBinding MUTABLE_UNSIGNED_INTEGER; // UnsignedInteger.Mutable
162 public static final ByteBinding MUTABLE_UNSIGNED_BYTE; // UnsignedByte.Mutable
163 public static final LongBinding MUTABLE_UNSIGNED_LONG; // UnsignedLong.Mutable
166 * Get or create a binding that is completely mutable java class.
168 * DataType | Class of the bound instance
169 * ===================|==================
170 * UnionType | GenericBinding.TaggedObject.class
171 * OptionType | ValueContainer.class
172 * RecordType | Object[].class
173 * BooleanType | MutableBoolean.class
174 * DoubleType | MutableDouble.class
175 * FloatType | MutableFloat.class
176 * ByteType | MutableByte.class
177 * IntegerType | MutableInt.class
178 * LongType | MutableLong.class
179 * StringType | ValueContainer.class
180 * ArrayType | ArrayList.class
181 * MapType | TreeMap.class
182 * VariantType | MutableVariant.class
184 * Note, requesting a binding with this convenience method stores the
185 * binding and the type with strong reference, thus preventing garbage
186 * collection. To allow garbage collection, please use another instance of
187 * GenericBindingFactory and binding repository (Map<Datatype, Binding>). <p>
189 * @param type the type to create binding to
190 * @return binding binding to a mutable class
192 @SuppressWarnings("unchecked")
193 public static <T extends Binding> T getMutableBinding(Datatype type) {
195 Binding binding = mutableBindingRepository.get(type);
196 if (binding!=null) return (T) binding;
197 synchronized(mutableBindingRepository) {
198 return (T) mutableBindingFactory.getBinding(type);
200 } catch (BindingConstructionException e) {
201 // Unexpected - if error is thrown there is fault in GenericBindingScheme
202 throw new RuntimeBindingConstructionException(e);
207 * Get or create a binding based on default java classes, such as
208 * Integer.class, or byte[].class. The result is often binding for an
209 * immutable classs. These bindings are more efficient than mutable bindings (above).
211 * DataType | Class of the bound instance
212 * ===================|==================
213 * BooleanType | Boolean.class
214 * ByteType | Byte.class
215 * FloatType | Float.class
216 * DoubleType | Double.class
217 * IntegerType | Int.class
218 * LongType | Long.class
219 * StringType | String.class
220 * UnionType | TaggedObject.class
221 * OptionType | ValueContainer.class
222 * RecordType | Object[].class
223 * MapType | TreeMap.class
224 * VariantType | Variant.class
225 * ArrayType(Boolean) | boolean[].class
226 * ArrayType(Byte) | byte[].class
227 * ArrayType(Integer) | int[].class
228 * ArrayType(Long) | long[].class
229 * ArrayType(Float) | float[].class
230 * ArrayType(Double) | double[].class
231 * ArrayType(Byte) | byte[].class
232 * ArrayType( T ) | Object[].class
234 * Note, requesting a binding with this convenience method stores the
235 * binding and the type with strong reference, thus preventing garbage
236 * collection. To allow garbage collection, please use another instance of
237 * DefaultBindingFactory and binding repository (Map<Datatype, Binding>). <p>
239 * @param type the type to create binding to
240 * @return binding binding to a mutable class
242 @SuppressWarnings("unchecked")
243 public static <T extends Binding> T getBinding(Datatype type) {
245 Binding binding = defaultBindingRepository.get(type);
246 if (binding!=null) return (T) binding;
247 synchronized(defaultBindingRepository) {
248 return (T) defaultBindingFactory.getBinding(type);
250 } catch (BindingConstructionException e) {
251 // Unexpected - if error is thrown there is fault in DefaultBindingScheme
252 throw new RuntimeBindingConstructionException(e);
257 * Get a binding to a Java Class. Details can be added by placing annotations
258 * to the java classes. See more in package org.simantics.databoard.annotations.
261 * Whether the result is a completely mutable or not depends on the
262 * requested class. For instance, fields such as Boolean, Integer, Long
263 * are not mutable, instead MutableBoolean, MutableInteger and MutableLong are.
264 * The length of Object[] is not mutable, but length of List<Object> is. <p>
266 * Note, requesting a binding with this convenience method stores the
267 * binding and the class with strong reference, thus preventing garbage
268 * collection. To allow garbage collection, please use another instance of
269 * BindingFactory and binding repository (Map<BindingRequest, Binding>). <p>
271 * Is asm library is available, the binding is bytecode generated. Then read
272 * and write operations are direct get/set calls or direct field read/writes.
273 * There is no reflection used. <p>
275 * @see ClassBindingFactory
278 * @throws BindingConstructionException
280 @SuppressWarnings("unchecked")
281 public static <T extends Binding> T getBinding(Class<?> clazz)
282 throws BindingConstructionException
284 Binding binding = bindingRepository.get( clazz );
285 if (binding != null) {
289 BindingRequest request = new BindingRequest( clazz );
290 synchronized(classBindingFactory) {
291 binding = classBindingFactory.construct(request);
296 @SuppressWarnings("unchecked")
297 public static <T extends Binding> T getBinding(BindingRequest request)
298 throws BindingConstructionException
300 synchronized(classBindingFactory) {
301 return (T) classBindingFactory.construct(request);
306 * Get a binding for a Java Class. Use this method to acquire class
307 * parameters for a generics class. <p>
311 * Binding binding = Bindings.getBinding(Map.class, String.class, Integer.class);
312 * Map<String, Integer> map = (Map<String, Integer>) binding.createDefault();
316 * Binding d = Bindings.getBinding(List.class, Integer.class);
317 * List<Integer> list = (List<Integer>) d.createRandom(5);
321 * Binding d = Bindings.getBinding(List.class, List.class, Integer.class);
322 * List<List<Integer>> list = (List<List<Integer>>) d.createRandom(5);
324 * @see ClassBindingFactory
327 * @throws BindingConstructionException
329 @SuppressWarnings("unchecked")
330 public static <T extends Binding> T getBinding(Class<?> clazz, Class<?>...parameters)
331 throws BindingConstructionException
333 BindingRequest request = new BindingRequest( clazz, parameters );
334 synchronized(classBindingFactory) {
335 return (T) classBindingFactory.construct(request);
340 * Try to get a binding for the actual class of a Java object.
341 * @param obj A Java object
342 * @return A binding for the class of the object
343 * @throws BindingConstructionException if no binding can be constructed
345 public static <T extends Binding> T getInstanceBinding(Object obj)
346 throws BindingConstructionException
348 return getBinding(obj.getClass());
352 * Read binding and type from a class. DataType details and parameters
353 * are read as annotations placed in the class.
354 * (See org.simantics.databoard.annotations)
356 * As an exception, in the subclasses of {@link Throwable}, the fields of
357 * Throwable are omited.
359 * This method is used for well-known classes where the caller is 100% sure
360 * that a binding is construable without exception. <p>
364 * @throws RuntimeBindingConstructionException
366 @SuppressWarnings("unchecked")
367 public static <T extends Binding> T getBindingUnchecked(Class<?> clazz)
368 throws RuntimeBindingConstructionException
371 return (T) getBinding(clazz);
372 } catch (BindingConstructionException e) {
373 throw new RuntimeBindingConstructionException(e);
378 * Get a binding for a Java Class. Use this method to acquire class
379 * parameters for a generics class. <p>
383 * Binding binding = Bindings.getBinding(Map.class, String.class, Integer.class);
384 * Map<String, Integer> map = (Map<String, Integer>) binding.createDefault();
388 * Binding d = Bindings.getBinding(List.class, Integer.class);
389 * List<Integer> list = (List<Integer>) d.createRandom(5);
393 * Binding d = Bindings.getBinding(List.class, List.class, Integer.class);
394 * List<List<Integer>> list = (List<List<Integer>>) d.createRandom(5);
396 * @see ClassBindingFactory
399 * @throws BindingConstructionException
401 @SuppressWarnings("unchecked")
402 public static <T extends Binding> T getBindingUnchecked(Class<?> clazz, Class<?>...parameters)
403 throws RuntimeBindingConstructionException
406 Arguments args = new ArgumentImpl(parameters);
407 BindingRequest request = new BindingRequest( clazz, args );
408 Binding binding = bindingRepository.get( request );
410 synchronized(classBindingFactory) {
411 binding = classBindingFactory.construct(request);
414 } catch (BindingConstructionException e) {
415 throw new RuntimeBindingConstructionException(e);
420 * Add a simple binding to reflection binding factory.
424 * @param parameters parameter classes
426 public static void addBinding( Binding binding, Class<?> clazz, Class<?>...parameters )
428 ArgumentImpl args = new ArgumentImpl( parameters );
429 BindingRequest request = new BindingRequest( clazz, args );
430 bindingRepository.put( request, binding );
434 * Add binding factory for compositive bindings
438 public static void addBindingFactory( BindingProvider factory )
440 classBindingFactory.addFactory( factory );
444 * Creates a bean class
448 public static BindingRequest getBeanBindingRequest( Datatype type ) throws RuntimeBindingConstructionException {
450 return typeClassFactory.getClass(type);
451 } catch (BindingConstructionException e) {
452 throw new RuntimeBindingConstructionException(e);
457 * Creates a bean class
461 public static Class<?> getBeanClass( Datatype type ) throws BindingConstructionException {
462 BindingRequest br = typeClassFactory.getClass(type);
463 return br.getClazz();
467 * Create binding from datatype that instantiates java classes.
468 * RecordTypes are Beans, UnionTypes are Classes with @Union annotation,
474 public static Binding getBeanBinding( Datatype type ) throws RuntimeBindingConstructionException {
476 BindingRequest br = typeClassFactory.getClass(type);
477 return getBinding( br );
478 } catch (BindingConstructionException e) {
479 throw new RuntimeBindingConstructionException(e);
484 * Get a default array binding for a given component type binding.
485 * Returns a primitive array type binding for primitive types and an
486 * ObjectArrayBinding for others.
488 * @param componentBinding A binding for a component type
489 * @return A binding for the array type
491 public static Binding getArrayBinding(Binding componentBinding) {
492 return getBinding(new ArrayType(componentBinding.type()));
496 * Get serializer that follows Databoard serialization spec.
500 * @throws SerializerConstructionException
502 public static Serializer getSerializer(Binding binding) throws SerializerConstructionException {
503 return serializationFactory.construct(binding);
507 * Get serializer that follows Databoard serialization spec.
511 * @throws RuntimeSerializerConstructionException
513 public static Serializer getSerializerUnchecked(Binding binding) throws RuntimeSerializerConstructionException {
515 return serializationFactory.construct(binding);
516 } catch (SerializerConstructionException e) {
517 throw new RuntimeSerializerConstructionException(e);
522 * Get serializer that follows Databoard serialization spec.
526 * @throws SerializerConstructionException
528 public static Serializer getSerializer(Class<?> clazz) throws SerializerConstructionException {
530 Binding binding = getBinding(clazz);
531 return serializationFactory.construct(binding);
532 } catch (BindingConstructionException e) {
533 throw new SerializerConstructionException( e );
538 * Get serializer that follows Databoard serialization spec.
541 * @return serializer serializer
542 * @throws RuntimeSerializerConstructionException
544 public static Serializer getSerializerUnchecked(Class<?> clazz) throws RuntimeSerializerConstructionException {
546 Binding binding = getBinding(clazz);
547 return serializationFactory.construct(binding);
548 } catch (SerializerConstructionException e) {
549 throw new RuntimeSerializerConstructionException(e);
550 } catch (BindingConstructionException e) {
551 throw new RuntimeSerializerConstructionException( new SerializerConstructionException(e) );
555 * Create an adapter that adapts two bindings of the same
558 * @param domain binding of the source instance
559 * @param range binding of the result instance
560 * @return result adapter
561 * @throws AdapterConstructionException
563 public static Adapter getAdapter(Binding domain, Binding range)
564 throws AdapterConstructionException
566 return adapterFactory.getAdapter(domain, range, false, false);
570 * Create an adapter that adapts between two bindings of the same
573 * @param domain binding of the source instance
574 * @param range binding of the result instance
575 * @return result adapter
576 * @throws AdapterConstructionException
578 public static Adapter getAdapterUnchecked(Binding domain, Binding range)
579 throws RuntimeAdapterConstructionException
582 return adapterFactory.getAdapter(domain, range, false, false);
583 } catch (AdapterConstructionException e) {
584 throw new RuntimeAdapterConstructionException(e);
589 * Create a type adapter that adapts instances from one Datatype to
590 * another. Type Adapter does the following conversions:
592 * o Number Types, e.g. long -> double
593 * o Unit Types, e.g. mph -> km/h
594 * o Record Types, for each field of the range, there must be equal in domain
595 * o Union Types, for each tag type of the domain, there must be equal in range
597 * {@link AdaptException} is thrown at runtime, if number conversion is not
598 * posible, e.g. converting value 500 from Integer to Byte.
599 * Note, there is also a possibility of precision loss, in many conversions
600 * e.g. from double to int.
602 * @param domain binding of the source instance
603 * @param range binding of the result instance
605 * @throws AdapterConstructionException
607 public static Adapter getTypeAdapter(Binding domain, Binding range)
608 throws AdapterConstructionException
610 return adapterFactory.getAdapter(domain, range, true, false);
614 * Create a type adapter that adapts instances from one DataType to
615 * another. Type Adapter does the following conversions:
617 * o Number Types, e.g. long -> double
618 * o Unit Types, e.g. mph -> km/h
619 * o Record Types, for each field of the range, there must be equal in domain
620 * o Union Types, for each tag type of the domain, there must be equal in range
622 * {@link AdaptException} is thrown at runtime, if number values are
623 * not compatible, e.g. converting value 500 from Long to Byte.
624 * Note, there is also a possibility of precision loss, e.g. when
625 * converting from double to int.
627 * @param domain binding of the source instance
628 * @param range binding of the result instance
629 * @return result adapter
630 * @throws AdapterConstructionException
632 public static Adapter getTypeAdapterUnchecked(Binding domain, Binding range)
635 return adapterFactory.getAdapter(domain, range, true, false);
636 } catch (AdapterConstructionException e) {
637 throw new RuntimeAdapterConstructionException(e);
642 * Adapt a value of one type to another.
647 * @return adapted value
648 * @throws AdapterConstructionException
649 * @throws AdaptException
651 public static Object adapt(Object value, Binding domain, Binding range)
652 throws AdaptException
655 if (domain.equals(range)) {
658 else if (range instanceof VariantBinding) {
659 if (domain instanceof VariantBinding) {
660 // Copy variant contents directly
661 Binding contentBinding = ((VariantBinding)domain).getContentBinding( value );
662 Object content = ((VariantBinding)domain).getContent( value );
663 return ((VariantBinding)range).create( contentBinding, content );
666 // Default to just wrapping the value (avoid adapter construction to save memory)
667 return ((VariantBinding)range).create(domain, value);
670 else if (domain instanceof VariantBinding) {
671 return adapt(((VariantBinding)domain).getContent( value ), ((VariantBinding)domain).getContentBinding( value ), range );
674 return adapterFactory.getAdapter(domain, range, true, false).adapt(value);
676 } catch (AdapterConstructionException | BindingException e) {
677 throw new AdaptException(e);
682 * Adapt a value of one type to another. Exceptions are run-time. Use this
683 * if it safe to assume the conversion will be successful.
688 * @return adapted value
689 * @throws AdapterConstructionException
690 * @throws AdaptException
692 public static Object adaptUnchecked(Object value, Binding domain, Binding range)
693 throws RuntimeAdapterConstructionException, RuntimeAdaptException
699 if (range instanceof VariantBinding && !(domain instanceof VariantBinding)) {
700 // Default to just wrapping the value (avoid adapter construction to save memory)
701 return ((VariantBinding)range).create(domain, value);
703 return adapterFactory.getAdapter(domain, range, true, false).adaptUnchecked(value);
704 } catch (RuntimeAdapterConstructionException e) {
705 throw new RuntimeAdaptException(new AdaptException(e.getCause()));
706 } catch (AdapterConstructionException e) {
707 throw new RuntimeAdaptException(new AdaptException(e));
708 } catch (BindingException e) {
709 throw new RuntimeAdaptException(new AdaptException(e));
714 * Adapt and clone a value instance to another type. Immutable
715 * bindings may return the argument as is, others return a cloned copy.
720 * @return adapted value
721 * @throws AdapterConstructionException
722 * @throws AdaptException
724 public static Object clone(Object value, Binding domain, Binding range)
725 throws AdaptException
729 if (domain.isImmutable()) {
732 return domain.clone(value);
735 return adapterFactory.getAdapter(domain, range, true, true).adapt(value);
736 } catch (AdapterConstructionException e) {
737 throw new AdaptException(e);
743 * Clone a value of one binding to another. Bindings that handle immutable values
744 * may return the same instance, others will guarantee a complete copy.
746 * This method throws only runtime exceptions. Use this if it is safe to assume
747 * that the conversion will be successful.
752 * @return adapted value
753 * @throws AdapterConstructionException
754 * @throws AdaptException
756 public static Object cloneUnchecked(Object value, Binding domain, Binding range)
757 throws RuntimeAdapterConstructionException, RuntimeAdaptException
760 return adapterFactory.getAdapter(domain, range, true, true).adapt(value);
761 } catch (AdaptException e) {
762 throw new RuntimeAdaptException(e);
763 } catch (RuntimeAdapterConstructionException e) {
764 throw new RuntimeAdaptException(new AdaptException(e.getCause()));
765 } catch (AdapterConstructionException e) {
766 throw new RuntimeAdaptException(new AdaptException(e));
771 * Compares two data values for order. Returns a negative integer,
772 * zero, or a positive integer if, the first argument precedes/lesser than
773 * the second, is equal to, or successor/greater than the second.<p>
775 * DataTypes of b1 and b2 are not equal, then data types are compared. <p>
777 * The comparison function is defined at
778 * http://dev.simantics.org/index.php/Org.simantics.datatype_Manual#CompareTo_and_Equals <p>
780 * Note, comparing 2 different number types will not result a value comparison.
781 * Instead values have the following type precedence ByteType, IntegerType, LongType,
782 * FloatType, and the highest DoubleType. <p>
784 * @param b1 Binding of o1
785 * @param o1 the first object to be compared.
786 * @param b2 Binding of o2
787 * @param o2 the second object to be compared.
788 * @return a negative integer, zero, or a positive integer as the
789 * first argument is less than, equal to, or greater than the
791 * @throws BindingException if object cannot be handled by a binding
793 public static int compare(Binding b1, Object o1, Binding b2, Object o2)
794 throws BindingException
796 return DataValueUtil.compare(b1, o1, b2, o2);
800 * Compare two data values for equality. <p>
802 * Note, comparing 2 different number types will not result a value comparison.
803 * Instead values have the following type precedence ByteType, IntegerType, LongType,
804 * FloatType, and the highest DoubleType. <p>
810 * @return true if equal
811 * @throws BindingException
813 public static boolean equals(Binding b1, Object o1, Binding b2, Object o2)
814 throws BindingException
816 return DataValueUtil.equals(b1, o1, b2, o2);
819 public static Comparator<Object> createComparator(final Binding b1, final Binding b2)
821 return DataValueUtil.createComparator(b1, b2);
825 * Print the content of an object as a structure.
826 * Utility function for debug purposes.
831 public static String toString(Object o) {
833 Binding b = Bindings.getBinding( o.getClass() );
834 return b.printValueDefinition(o, true);
835 } catch (BindingConstructionException e) {
836 return "<error "+e.getClass().getName()+" "+e.getMessage()+">";
837 } catch (IOException e) {
838 return "<error "+e.getClass().getName()+" "+e.getMessage()+">";
839 } catch (BindingException e) {
840 return "<error "+e.getClass().getName()+" "+e.getMessage()+">";
845 STRING = new StringBindingDefault( Datatypes.STRING );
846 INTEGER = new IntegerBindingDefault( Datatypes.INTEGER );
847 BOOLEAN = new BooleanBindingDefault( Datatypes.BOOLEAN );
848 BYTE = new ByteBindingDefault( Datatypes.BYTE );
849 LONG = new LongBindingDefault( Datatypes.LONG );
850 DOUBLE = new DoubleBindingDefault( Datatypes.DOUBLE );
851 FLOAT = new FloatBindingDefault( Datatypes.FLOAT );
852 VOID = VoidBinding.VOID_BINDING;
853 BOOLEAN_ARRAY = new BooleanArrayBinding( Datatypes.BOOLEAN_ARRAY, BOOLEAN );
854 BYTE_ARRAY = new ByteArrayBinding( Datatypes.BYTE_ARRAY, BYTE );
855 INT_ARRAY = new IntArrayBinding( Datatypes.INTEGER_ARRAY, INTEGER );
856 LONG_ARRAY = new LongArrayBinding( Datatypes.LONG_ARRAY, LONG );
857 FLOAT_ARRAY = new FloatArrayBinding( Datatypes.FLOAT_ARRAY, FLOAT );
858 DOUBLE_ARRAY = new DoubleArrayBinding( Datatypes.DOUBLE_ARRAY, DOUBLE );
859 STRING_ARRAY = new StringArrayBinding( Datatypes.STRING_ARRAY, STRING );
860 UNSIGNED_INTEGER = new UnsignedIntegerBinding.Immutable( Datatypes.INTEGER );
861 UNSIGNED_BYTE = new UnsignedByteBinding.Immutable( Datatypes.BYTE );
862 UNSIGNED_LONG = new UnsignedLongBinding.Immutable( Datatypes.LONG );
863 MUTABLE_STRING = new MutableStringBinding( Datatypes.STRING );
864 MUTABLE_INTEGER = new MutableIntegerBinding( Datatypes.INTEGER );
865 MUTABLE_BOOLEAN = new MutableBooleanBinding( Datatypes.BOOLEAN );
866 MUTABLE_BYTE = new MutableByteBinding( Datatypes.BYTE );
867 MUTABLE_LONG = new MutableLongBinding( Datatypes.LONG );
868 MUTABLE_FLOAT = new MutableFloatBinding( Datatypes.FLOAT );
869 MUTABLE_DOUBLE = new MutableDoubleBinding( Datatypes.DOUBLE );
870 MUTABLE_UNSIGNED_INTEGER = new UnsignedIntegerBinding.Mutable( Datatypes.INTEGER );
871 MUTABLE_UNSIGNED_BYTE = new UnsignedByteBinding.Mutable( Datatypes.BYTE );
872 MUTABLE_UNSIGNED_LONG = new UnsignedLongBinding.Mutable( Datatypes.LONG );
874 databoard = new Databoard();
876 mutableBindingRepository = databoard.mutableBindingRepository;
877 defaultBindingRepository = databoard.defaultBindingRepository;
878 bindingRepository = databoard.bindingRepository;
879 serializerRepository = databoard.serializerRepository;
880 mutableBindingFactory = databoard.mutableBindingFactory;
881 defaultBindingFactory = databoard.defaultBindingFactory;
882 classBindingFactory = databoard.classBindingFactory;
883 serializationFactory = databoard.serializationFactory;
884 adapterFactory = databoard.adapterFactory;
885 typeClassFactory = databoard.typeClassFactory;
887 BEAN = databoard.BEAN;
888 VARIANT = databoard.VARIANT;
889 MUTABLE_VARIANT = new MutableVariantBinding( classBindingFactory, adapterFactory );
890 STR_VARIANT = databoard.STR_VARIANT;
891 OBJECT = databoard.OBJECT;
893 databoard.initialize();
895 DATATYPE = getBindingUnchecked(Datatype.class);