1 /*******************************************************************************
2 * Copyright (c) 2007, 2012 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.lang.reflect.Constructor;
16 import java.lang.reflect.InvocationTargetException;
17 import java.util.Collections;
18 import java.util.Comparator;
19 import java.util.HashMap;
22 import org.simantics.databoard.adapter.AdaptException;
23 import org.simantics.databoard.adapter.Adapter;
24 import org.simantics.databoard.adapter.AdapterConstructionException;
25 import org.simantics.databoard.adapter.AdapterFactory;
26 import org.simantics.databoard.adapter.RuntimeAdaptException;
27 import org.simantics.databoard.adapter.RuntimeAdapterConstructionException;
28 import org.simantics.databoard.annotations.ArgumentImpl;
29 import org.simantics.databoard.annotations.Arguments;
30 import org.simantics.databoard.binding.Binding;
31 import org.simantics.databoard.binding.VariantBinding;
32 import org.simantics.databoard.binding.classfactory.ImmutableClassesFactory;
33 import org.simantics.databoard.binding.classfactory.TypeClassFactory;
34 import org.simantics.databoard.binding.classfactory.TypeClassSubFactory;
35 import org.simantics.databoard.binding.error.BindingConstructionException;
36 import org.simantics.databoard.binding.error.BindingException;
37 import org.simantics.databoard.binding.error.RuntimeBindingConstructionException;
38 import org.simantics.databoard.binding.factory.BindingRepository;
39 import org.simantics.databoard.binding.factory.DefaultBindingFactory;
40 import org.simantics.databoard.binding.factory.JavaUtilBindingsProvider;
41 import org.simantics.databoard.binding.factory.MutableBindingFactory;
42 import org.simantics.databoard.binding.factory.TroveBindingsProvider;
43 import org.simantics.databoard.binding.factory.TypeBindingFactory;
44 import org.simantics.databoard.binding.impl.BeanBinding;
45 import org.simantics.databoard.binding.impl.ObjectVariantBinding;
46 import org.simantics.databoard.binding.impl.StringVariantBinding;
47 import org.simantics.databoard.binding.mutable.ImmutableVariantBinding;
48 import org.simantics.databoard.binding.mutable.MutableVariant;
49 import org.simantics.databoard.binding.mutable.Variant;
50 import org.simantics.databoard.binding.reflection.BindingProvider;
51 import org.simantics.databoard.binding.reflection.BindingRequest;
52 import org.simantics.databoard.binding.reflection.ClassBindingFactory;
53 import org.simantics.databoard.binding.reflection.VoidBinding;
54 import org.simantics.databoard.serialization.DefaultConcurrentSerializerFactory;
55 import org.simantics.databoard.serialization.RuntimeSerializerConstructionException;
56 import org.simantics.databoard.serialization.Serializer;
57 import org.simantics.databoard.serialization.SerializerConstructionException;
58 import org.simantics.databoard.serialization.SerializerScheme;
59 import org.simantics.databoard.type.Datatype;
60 import org.simantics.databoard.util.Bean;
61 import org.simantics.databoard.util.DataValueUtil;
63 public class Databoard {
67 /** Repository of mutable bindings */
68 public final Map<Datatype, Binding> mutableBindingRepository = Collections.synchronizedMap( new HashMap<Datatype, Binding>() );
70 /** Repository of default bindings */
71 public final Map<Datatype, Binding> defaultBindingRepository = Collections.synchronizedMap( new HashMap<Datatype, Binding>() );
73 /** Repository of class Bindings */
74 public final BindingRepository bindingRepository = new BindingRepository();
76 /** Repository of serializers */
77 public final Map<Binding, Serializer> serializerRepository = Collections.synchronizedMap( new HashMap<Binding, Serializer>() );
82 /** Mutable Bindings Factory */
83 public final TypeBindingFactory mutableBindingFactory = new MutableBindingFactory( mutableBindingRepository );
85 /** Default Bindings Factory */
86 public final TypeBindingFactory defaultBindingFactory = new DefaultBindingFactory( defaultBindingRepository );
88 /** Reflection based Binding Factory, create binding to class */
89 public final ClassBindingFactory classBindingFactory = new ClassBindingFactory( bindingRepository, defaultBindingFactory );
91 /** Serializer Factory */
92 //public final SerializerFactory serializationFactory = new DefaultSerializerFactory( serializerRepository );
93 public final SerializerScheme serializationFactory = new DefaultConcurrentSerializerFactory();
95 /** Adapter Factory */
96 public final AdapterFactory adapterFactory = new AdapterFactory();
99 public final TypeClassFactory typeClassFactory = new TypeClassFactory();
102 public final VariantBinding VARIANT; // Variant
103 public final VariantBinding OBJECT; // java.lang.Object ( as variant )
104 public final VariantBinding STR_VARIANT; // java.lang.String ( as variant )
105 public final Binding BEAN; // Bean ( as variant )
108 classBindingFactory.addFactory( new TroveBindingsProvider() );
109 classBindingFactory.addFactory( new JavaUtilBindingsProvider() );
111 addDefaultBinding( Datatypes.STRING, Bindings.STRING );
112 addDefaultBinding( Datatypes.INTEGER, Bindings.INTEGER );
113 addDefaultBinding( Datatypes.BOOLEAN, Bindings.BOOLEAN );
114 addDefaultBinding( Datatypes.BYTE, Bindings.BYTE );
115 addDefaultBinding( Datatypes.LONG, Bindings.LONG );
116 addDefaultBinding( Datatypes.DOUBLE, Bindings.DOUBLE );
117 addDefaultBinding( Datatypes.FLOAT, Bindings.FLOAT );
118 addDefaultBinding( Datatypes.VOID, Bindings.VOID );
119 addDefaultBinding( Datatypes.BOOLEAN_ARRAY, Bindings.BOOLEAN_ARRAY );
120 addDefaultBinding( Datatypes.BYTE_ARRAY, Bindings.BYTE_ARRAY );
121 addDefaultBinding( Datatypes.INTEGER_ARRAY, Bindings.INT_ARRAY );
122 addDefaultBinding( Datatypes.LONG_ARRAY, Bindings.LONG_ARRAY );
123 addDefaultBinding( Datatypes.FLOAT_ARRAY, Bindings.FLOAT_ARRAY );
124 addDefaultBinding( Datatypes.DOUBLE_ARRAY, Bindings.DOUBLE_ARRAY );
125 addDefaultBinding( Datatypes.STRING_ARRAY, Bindings.STRING_ARRAY );
127 VARIANT = new ImmutableVariantBinding( classBindingFactory, adapterFactory );
128 OBJECT = new ObjectVariantBinding( classBindingFactory, adapterFactory );
129 BEAN = new BeanBinding( classBindingFactory, typeClassFactory, adapterFactory );
130 STR_VARIANT = new StringVariantBinding( serializationFactory, VARIANT );
132 // Add sub-factory that creates binding for Bean
133 classBindingFactory.addFactory( new DataboardBindings() );
135 // Add class factory that constructs basic types
136 typeClassFactory.addFactory( new ImmutableClassesFactory() );
138 // Bindings.databoard cannot initialize itself
139 if (Bindings.databoard != null) {
145 // Add run-time class factory, if objectweb.asm-library is available.
148 Class.forName("org.objectweb.asm.ClassWriter");
149 Class<?> y = Class.forName("org.simantics.databoard.binding.classfactory.AsmTypeClassFactory");
150 Constructor<?> c = y.getConstructor( TypeClassFactory.class );
151 TypeClassSubFactory f = (TypeClassSubFactory) c.newInstance(typeClassFactory);
152 typeClassFactory.addFactory( f );
154 BindingRequest br = new BindingRequest( Datatype.class );
155 Binding datatypeBinding = getBinding( br );
156 typeClassFactory.getRepository().put(datatypeBinding.type(), br);
157 bindingRepository.put(br, datatypeBinding);
158 } catch (ClassNotFoundException e) {
159 } catch (InstantiationException e) {
160 } catch (IllegalAccessException e) {
161 } catch (IllegalArgumentException e) {
162 } catch (InvocationTargetException e) {
163 } catch (SecurityException e) {
164 } catch (NoSuchMethodException e) {
165 } catch (BindingConstructionException e) {
170 public void clear() {
171 mutableBindingRepository.clear();
172 defaultBindingRepository.clear();
173 bindingRepository.clear();
174 serializerRepository.clear();
178 * Get or create a binding that is completely mutable java class.
180 * DataType | Class of the bound instance
181 * ===================|==================
182 * UnionType | GenericBinding.TaggedObject.class
183 * OptionType | ValueContainer.class
184 * RecordType | Object[].class
185 * BooleanType | MutableBoolean.class
186 * DoubleType | MutableDouble.class
187 * FloatType | MutableFloat.class
188 * ByteType | MutableByte.class
189 * IntegerType | MutableInt.class
190 * LongType | MutableLong.class
191 * StringType | ValueContainer.class
192 * ArrayType | ArrayList.class
193 * MapType | TreeMap.class
194 * VariantType | MutableVariant.class
196 * Note, requesting a binding with this convenience method stores the
197 * binding and the type with strong reference, thus preventing garbage
198 * collection. To allow garbage collection, please use another instance of
199 * GenericBindingFactory and binding repository (Map<Datatype, Binding>). <p>
201 * @param type the type to create binding to
202 * @return binding binding to a mutable class
204 @SuppressWarnings("unchecked")
205 public <T extends Binding> T getMutableBinding(Datatype type) {
207 Binding binding = mutableBindingRepository.get(type);
208 if (binding!=null) return (T) binding;
209 synchronized(mutableBindingRepository) {
210 return (T) mutableBindingFactory.getBinding(type);
212 } catch (BindingConstructionException e) {
213 // Unexpected - if error is thrown there is fault in GenericBindingScheme
214 throw new RuntimeBindingConstructionException(e);
219 * Get or create a binding based on default java classes, such as
220 * Integer.class, or byte[].class. The result is often binding for an
221 * immutable classs. These bindings are more efficient than mutable bindings (above).
223 * DataType | Class of the bound instance
224 * ===================|==================
225 * BooleanType | Boolean.class
226 * ByteType | Byte.class
227 * FloatType | Float.class
228 * DoubleType | Double.class
229 * IntegerType | Int.class
230 * LongType | Long.class
231 * StringType | String.class
232 * UnionType | TaggedObject.class
233 * OptionType | ValueContainer.class
234 * RecordType | Object[].class
235 * MapType | TreeMap.class
236 * VariantType | Variant.class
237 * ArrayType(Boolean) | boolean[].class
238 * ArrayType(Byte) | byte[].class
239 * ArrayType(Integer) | int[].class
240 * ArrayType(Long) | long[].class
241 * ArrayType(Float) | float[].class
242 * ArrayType(Double) | double[].class
243 * ArrayType(Byte) | byte[].class
244 * ArrayType( T ) | Object[].class
246 * Note, requesting a binding with this convenience method stores the
247 * binding and the type with strong reference, thus preventing garbage
248 * collection. To allow garbage collection, please use another instance of
249 * DefaultBindingFactory and binding repository (Map<Datatype, Binding>). <p>
251 * @param type the type to create binding to
252 * @return binding binding to a mutable class
254 @SuppressWarnings("unchecked")
255 public <T extends Binding> T getBinding(Datatype type) {
257 Binding binding = defaultBindingRepository.get(type);
258 if (binding!=null) return (T) binding;
259 synchronized(defaultBindingRepository) {
260 return (T) defaultBindingFactory.getBinding(type);
262 } catch (BindingConstructionException e) {
263 // Unexpected - if error is thrown there is fault in DefaultBindingScheme
264 throw new RuntimeBindingConstructionException(e);
269 * Get a binding to a Java Class. Details can be added by placing annotations
270 * to the java classes. See more in package org.simantics.databoard.annotations.
273 * Whether the result is a completely mutable or not depends on the
274 * requested class. For instance, fields such as Boolean, Integer, Long
275 * are not mutable, instead MutableBoolean, MutableInteger and MutableLong are.
276 * The length of Object[] is not mutable, but length of List<Object> is. <p>
278 * Note, requesting a binding with this convenience method stores the
279 * binding and the class with strong reference, thus preventing garbage
280 * collection. To allow garbage collection, please use another instance of
281 * BindingFactory and binding repository (Map<BindingRequest, Binding>). <p>
283 * @see ClassBindingFactory
286 * @throws BindingConstructionException
288 @SuppressWarnings("unchecked")
289 public <T extends Binding> T getBinding(Class<?> clazz)
290 throws BindingConstructionException
292 Binding binding = bindingRepository.get( clazz );
293 if (binding != null) {
297 BindingRequest request = new BindingRequest( clazz );
298 synchronized(classBindingFactory) {
299 binding = classBindingFactory.construct(request);
304 @SuppressWarnings("unchecked")
305 public <T extends Binding> T getBinding(BindingRequest request)
306 throws BindingConstructionException
308 synchronized(classBindingFactory) {
309 return (T) classBindingFactory.construct(request);
314 * Get a binding for a Java Class. Use this method to acquire class
315 * parameters for a generics class. <p>
319 * Binding binding = getBinding(Map.class, String.class, Integer.class);
320 * Map<String, Integer> map = (Map<String, Integer>) binding.createDefault();
324 * Binding d = getBinding(List.class, Integer.class);
325 * List<Integer> list = (List<Integer>) d.createRandom(5);
329 * Binding d = getBinding(List.class, List.class, Integer.class);
330 * List<List<Integer>> list = (List<List<Integer>>) d.createRandom(5);
332 * @see ClassBindingFactory
335 * @throws BindingConstructionException
337 @SuppressWarnings("unchecked")
338 public <T extends Binding> T getBinding(Class<?> clazz, Class<?>...parameters)
339 throws BindingConstructionException
341 BindingRequest request = new BindingRequest( clazz, parameters );
342 synchronized(classBindingFactory) {
343 return (T) classBindingFactory.construct(request);
348 * Read binding and type from a class. DataType details and parameters
349 * are read as annotations placed in the class.
350 * (See org.simantics.databoard.annotations)
352 * As an exception, in the subclasses of {@link Throwable}, the fields of
353 * Throwable are omited.
355 * This method is used for well-known classes where the caller is 100% sure
356 * that a binding is construable without exception. <p>
360 * @throws RuntimeBindingConstructionException
362 @SuppressWarnings("unchecked")
363 public <T extends Binding> T getBindingUnchecked(Class<?> clazz)
364 throws RuntimeBindingConstructionException
367 return (T) getBinding(clazz);
368 } catch (BindingConstructionException e) {
369 throw new RuntimeBindingConstructionException(e);
374 * Get a binding for a Java Class. Use this method to acquire class
375 * parameters for a generics class. <p>
379 * Binding binding = getBinding(Map.class, String.class, Integer.class);
380 * Map<String, Integer> map = (Map<String, Integer>) binding.createDefault();
384 * Binding d = getBinding(List.class, Integer.class);
385 * List<Integer> list = (List<Integer>) d.createRandom(5);
389 * Binding d = getBinding(List.class, List.class, Integer.class);
390 * List<List<Integer>> list = (List<List<Integer>>) d.createRandom(5);
392 * @see ClassBindingFactory
395 * @throws BindingConstructionException
397 @SuppressWarnings("unchecked")
398 public <T extends Binding> T getBindingUnchecked(Class<?> clazz, Class<?>...parameters)
399 throws RuntimeBindingConstructionException
402 Arguments args = new ArgumentImpl(parameters);
403 BindingRequest request = new BindingRequest( clazz, args );
404 Binding binding = bindingRepository.get( request );
406 synchronized(classBindingFactory) {
407 binding = classBindingFactory.construct(request);
410 } catch (BindingConstructionException e) {
411 throw new RuntimeBindingConstructionException(e);
416 * Add a simple binding to reflection binding factory.
420 * @param parameters parameter classes
422 public void addBinding( Binding binding, Class<?> clazz, Class<?>...parameters )
424 ArgumentImpl args = new ArgumentImpl( parameters );
425 BindingRequest request = new BindingRequest( clazz, args );
426 bindingRepository.put( request, binding );
430 * Add binding factory for compositive bindings
434 public void addBindingFactory( BindingProvider factory )
436 classBindingFactory.addFactory( factory );
440 * Creates a bean class
444 public BindingRequest getBeanBindingRequest( Datatype type ) throws RuntimeBindingConstructionException {
446 return typeClassFactory.getClass(type);
447 } catch (BindingConstructionException e) {
448 throw new RuntimeBindingConstructionException(e);
453 * Creates a bean class
457 public Class<?> getBeanClass( Datatype type ) throws BindingConstructionException {
458 BindingRequest br = typeClassFactory.getClass(type);
459 return br.getClazz();
463 * Create binding from datatype that instantiates java classes.
464 * RecordTypes are Beans, UnionTypes are Classes with @Union annotation,
470 public Binding getBeanBinding( Datatype type ) throws RuntimeBindingConstructionException {
472 BindingRequest br = typeClassFactory.getClass(type);
473 return getBinding( br );
474 } catch (BindingConstructionException e) {
475 throw new RuntimeBindingConstructionException(e);
480 * Get serializer that follows Databoard serialization spec.
484 * @throws SerializerConstructionException
486 public Serializer getSerializer(Binding binding) throws SerializerConstructionException {
487 return serializationFactory.getSerializer(binding);
491 * Get serializer that follows Databoard serialization spec.
495 * @throws RuntimeSerializerConstructionException
497 public Serializer getSerializerUnchecked(Binding binding) throws RuntimeSerializerConstructionException {
498 return serializationFactory.getSerializerUnchecked(binding);
502 * Get serializer that follows Databoard serialization spec.
506 * @throws SerializerConstructionException
508 public Serializer getSerializer(Class<?> clazz) throws SerializerConstructionException {
510 Binding binding = getBinding(clazz);
511 return serializationFactory.getSerializer(binding);
512 } catch (BindingConstructionException e) {
513 throw new SerializerConstructionException( e );
518 * Get serializer that follows Databoard serialization spec.
521 * @return serializer serializer
522 * @throws RuntimeSerializerConstructionException
524 public Serializer getSerializerUnchecked(Class<?> clazz) throws RuntimeSerializerConstructionException {
526 Binding binding = getBinding(clazz);
527 return serializationFactory.getSerializerUnchecked(binding);
528 } catch (BindingConstructionException e) {
529 throw new RuntimeSerializerConstructionException( new SerializerConstructionException(e) );
533 * Create an adapter that adapts two bindings of the same
536 * @param domain binding of the source instance
537 * @param range binding of the result instance
538 * @return result adapter
539 * @throws AdapterConstructionException
541 public Adapter getAdapter(Binding domain, Binding range)
542 throws AdapterConstructionException
544 return adapterFactory.getAdapter(domain, range, false, false);
548 * Create an adapter that adapts between two bindings of the same
551 * @param domain binding of the source instance
552 * @param range binding of the result instance
553 * @return result adapter
554 * @throws AdapterConstructionException
556 public Adapter getAdapterUnchecked(Binding domain, Binding range)
557 throws RuntimeAdapterConstructionException
560 return adapterFactory.getAdapter(domain, range, false, false);
561 } catch (AdapterConstructionException e) {
562 throw new RuntimeAdapterConstructionException(e);
567 * Create a type adapter that adapts instances from one Datatype to
568 * another. Type Adapter does the following conversions:
570 * o Number Types, e.g. long -> double
571 * o Unit Types, e.g. mph -> km/h
572 * o Record Types, for each field of the range, there must be equal in domain
573 * o Union Types, for each tag type of the domain, there must be equal in range
575 * {@link AdaptException} is thrown at runtime, if number conversion is not
576 * posible, e.g. converting value 500 from Integer to Byte.
577 * Note, there is also a possibility of precision loss, in many conversions
578 * e.g. from double to int.
580 * @param domain binding of the source instance
581 * @param range binding of the result instance
583 * @throws AdapterConstructionException
585 public Adapter getTypeAdapter(Binding domain, Binding range)
586 throws AdapterConstructionException
588 return adapterFactory.getAdapter(domain, range, true, false);
592 * Create a type adapter that adapts instances from one DataType to
593 * another. Type Adapter does the following conversions:
595 * o Number Types, e.g. long -> double
596 * o Unit Types, e.g. mph -> km/h
597 * o Record Types, for each field of the range, there must be equal in domain
598 * o Union Types, for each tag type of the domain, there must be equal in range
600 * {@link AdaptException} is thrown at runtime, if number values are
601 * not compatible, e.g. converting value 500 from Long to Byte.
602 * Note, there is also a possibility of precision loss, e.g. when
603 * converting from double to int.
605 * @param domain binding of the source instance
606 * @param range binding of the result instance
607 * @return result adapter
608 * @throws AdapterConstructionException
610 public Adapter getTypeAdapterUnchecked(Binding domain, Binding range)
613 return adapterFactory.getAdapter(domain, range, true, false);
614 } catch (AdapterConstructionException e) {
615 throw new RuntimeAdapterConstructionException(e);
620 * Adapt a value of one type to another.
625 * @return adapted value
626 * @throws AdapterConstructionException
627 * @throws AdaptException
629 public Object adapt(Object value, Binding domain, Binding range)
630 throws AdaptException
636 return adapterFactory.getAdapter(domain, range, true, false).adapt(value);
637 } catch (AdapterConstructionException e) {
638 throw new AdaptException(e);
643 * Adapt a value of one type to another. Exceptions are run-time. Use this
644 * if it safe to assume the conversion will be successful.
649 * @return adapted value
650 * @throws AdapterConstructionException
651 * @throws AdaptException
653 public Object adaptUnchecked(Object value, Binding domain, Binding range)
654 throws RuntimeAdapterConstructionException, RuntimeAdaptException
660 return adapterFactory.getAdapter(domain, range, true, false).adaptUnchecked(value);
661 } catch (RuntimeAdapterConstructionException e) {
662 throw new RuntimeAdaptException(new AdaptException(e.getCause()));
663 } catch (AdapterConstructionException e) {
664 throw new RuntimeAdaptException(new AdaptException(e));
669 * Adapt and clone a value instance to another type. Immutable
670 * bindings may return the argument as is, others return a cloned copy.
675 * @return adapted value
676 * @throws AdapterConstructionException
677 * @throws AdaptException
679 public Object clone(Object value, Binding domain, Binding range)
680 throws AdaptException
684 if (domain.isImmutable()) {
687 return domain.clone(value);
690 return adapterFactory.getAdapter(domain, range, true, true).adapt(value);
691 } catch (AdapterConstructionException e) {
692 throw new AdaptException(e);
698 * Clone a value of one binding to another. Bindings that handle immutable values
699 * may return the same instance, others will guarantee a complete copy.
701 * This method throws only runtime exceptions. Use this if it is safe to assume
702 * that the conversion will be successful.
707 * @return adapted value
708 * @throws AdapterConstructionException
709 * @throws AdaptException
711 public Object cloneUnchecked(Object value, Binding domain, Binding range)
712 throws RuntimeAdapterConstructionException, RuntimeAdaptException
715 return adapterFactory.getAdapter(domain, range, true, true).adapt(value);
716 } catch (AdaptException e) {
717 throw new RuntimeAdaptException(e);
718 } catch (RuntimeAdapterConstructionException e) {
719 throw new RuntimeAdaptException(new AdaptException(e.getCause()));
720 } catch (AdapterConstructionException e) {
721 throw new RuntimeAdaptException(new AdaptException(e));
726 * Compares two data values for order. Returns a negative integer,
727 * zero, or a positive integer if, the first argument precedes/lesser than
728 * the second, is equal to, or successor/greater than the second.<p>
730 * DataTypes of b1 and b2 are not equal, then data types are compared. <p>
732 * The comparison function is defined at
733 * http://dev.simantics.org/index.php/Org.simantics.datatype_Manual#CompareTo_and_Equals <p>
735 * Note, comparing 2 different number types will not result a value comparison.
736 * Instead values have the following type precedence ByteType, IntegerType, LongType,
737 * FloatType, and the highest DoubleType. <p>
739 * @param b1 Binding of o1
740 * @param o1 the first object to be compared.
741 * @param b2 Binding of o2
742 * @param o2 the second object to be compared.
743 * @return a negative integer, zero, or a positive integer as the
744 * first argument is less than, equal to, or greater than the
746 * @throws BindingException if object cannot be handled by a binding
748 public int compare(Binding b1, Object o1, Binding b2, Object o2)
749 throws BindingException
751 return DataValueUtil.compare(b1, o1, b2, o2);
755 * Compare two data values for equality. <p>
757 * Note, comparing 2 different number types will not result a value comparison.
758 * Instead values have the following type precedence ByteType, IntegerType, LongType,
759 * FloatType, and the highest DoubleType. <p>
765 * @return true if equal
766 * @throws BindingException
768 public boolean equals(Binding b1, Object o1, Binding b2, Object o2)
769 throws BindingException
771 return DataValueUtil.equals(b1, o1, b2, o2);
774 public Comparator<Object> createComparator(final Binding b1, final Binding b2)
776 return DataValueUtil.createComparator(b1, b2);
780 * Print the content of an object as a structure.
781 * Utility function for debug purposes.
786 public String toString(Object o) {
788 Binding b = getBinding( o.getClass() );
789 return b.printValueDefinition(o, true);
790 } catch (BindingConstructionException e) {
791 return "<error "+e.getClass().getName()+" "+e.getMessage()+">";
792 } catch (IOException e) {
793 return "<error "+e.getClass().getName()+" "+e.getMessage()+">";
794 } catch (BindingException e) {
795 return "<error "+e.getClass().getName()+" "+e.getMessage()+">";
799 class DataboardBindings implements BindingProvider {
801 public Binding provideBinding(ClassBindingFactory mainFactory, BindingRequest request) throws BindingConstructionException {
803 if (request.getClazz().equals( Object.class )) return OBJECT;
804 if (request.getClazz().equals( Void.class ) || request.getClazz().equals(void.class) ) return VoidBinding.VOID_BINDING;
805 if (request.getClazz().equals( Variant.class) ) return Bindings.VARIANT;
806 if (request.getClazz().equals( MutableVariant.class) ) return Bindings.MUTABLE_VARIANT;
807 if (request.getClazz().equals( Bean.class ) ) return BEAN;
813 private void addDefaultBinding(Datatype datatype, Binding binding ) {
814 defaultBindingRepository.put(datatype, binding);