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.DefaultSerializerFactory;
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.SerializerFactory;
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 );
94 /** Adapter Factory */
95 public final AdapterFactory adapterFactory = new AdapterFactory();
98 public final TypeClassFactory typeClassFactory = new TypeClassFactory();
101 public final VariantBinding VARIANT; // Variant
102 public final VariantBinding OBJECT; // java.lang.Object ( as variant )
103 public final VariantBinding STR_VARIANT; // java.lang.String ( as variant )
104 public final Binding BEAN; // Bean ( as variant )
107 classBindingFactory.addFactory( new TroveBindingsProvider() );
108 classBindingFactory.addFactory( new JavaUtilBindingsProvider() );
110 addDefaultBinding( Datatypes.STRING, Bindings.STRING );
111 addDefaultBinding( Datatypes.INTEGER, Bindings.INTEGER );
112 addDefaultBinding( Datatypes.BOOLEAN, Bindings.BOOLEAN );
113 addDefaultBinding( Datatypes.BYTE, Bindings.BYTE );
114 addDefaultBinding( Datatypes.LONG, Bindings.LONG );
115 addDefaultBinding( Datatypes.DOUBLE, Bindings.DOUBLE );
116 addDefaultBinding( Datatypes.FLOAT, Bindings.FLOAT );
117 addDefaultBinding( Datatypes.VOID, Bindings.VOID );
118 addDefaultBinding( Datatypes.BOOLEAN_ARRAY, Bindings.BOOLEAN_ARRAY );
119 addDefaultBinding( Datatypes.BYTE_ARRAY, Bindings.BYTE_ARRAY );
120 addDefaultBinding( Datatypes.INTEGER_ARRAY, Bindings.INT_ARRAY );
121 addDefaultBinding( Datatypes.LONG_ARRAY, Bindings.LONG_ARRAY );
122 addDefaultBinding( Datatypes.FLOAT_ARRAY, Bindings.FLOAT_ARRAY );
123 addDefaultBinding( Datatypes.DOUBLE_ARRAY, Bindings.DOUBLE_ARRAY );
124 addDefaultBinding( Datatypes.STRING_ARRAY, Bindings.STRING_ARRAY );
126 VARIANT = new ImmutableVariantBinding( classBindingFactory, adapterFactory );
127 OBJECT = new ObjectVariantBinding( classBindingFactory, adapterFactory );
128 BEAN = new BeanBinding( classBindingFactory, typeClassFactory, adapterFactory );
129 STR_VARIANT = new StringVariantBinding( serializationFactory, VARIANT );
131 // Add sub-factory that creates binding for Bean
132 classBindingFactory.addFactory( new DataboardBindings() );
134 // Add class factory that constructs basic types
135 typeClassFactory.addFactory( new ImmutableClassesFactory() );
137 // Bindings.databoard cannot initialize itself
138 if (Bindings.databoard != null) {
144 // Add run-time class factory, if objectweb.asm-library is available.
147 Class.forName("org.objectweb.asm.ClassWriter");
148 Class<?> y = Class.forName("org.simantics.databoard.binding.classfactory.AsmTypeClassFactory");
149 Constructor<?> c = y.getConstructor( TypeClassFactory.class );
150 TypeClassSubFactory f = (TypeClassSubFactory) c.newInstance(typeClassFactory);
151 typeClassFactory.addFactory( f );
153 BindingRequest br = new BindingRequest( Datatype.class );
154 Binding datatypeBinding = getBinding( br );
155 typeClassFactory.getRepository().put(datatypeBinding.type(), br);
156 } catch (ClassNotFoundException e) {
157 } catch (InstantiationException e) {
158 } catch (IllegalAccessException e) {
159 } catch (IllegalArgumentException e) {
160 } catch (InvocationTargetException e) {
161 } catch (SecurityException e) {
162 } catch (NoSuchMethodException e) {
163 } catch (BindingConstructionException e) {
168 public void clear() {
169 mutableBindingRepository.clear();
170 defaultBindingRepository.clear();
171 bindingRepository.clear();
172 serializerRepository.clear();
176 * Get or create a binding that is completely mutable java class.
178 * DataType | Class of the bound instance
179 * ===================|==================
180 * UnionType | GenericBinding.TaggedObject.class
181 * OptionType | ValueContainer.class
182 * RecordType | Object[].class
183 * BooleanType | MutableBoolean.class
184 * DoubleType | MutableDouble.class
185 * FloatType | MutableFloat.class
186 * ByteType | MutableByte.class
187 * IntegerType | MutableInt.class
188 * LongType | MutableLong.class
189 * StringType | ValueContainer.class
190 * ArrayType | ArrayList.class
191 * MapType | TreeMap.class
192 * VariantType | MutableVariant.class
194 * Note, requesting a binding with this convenience method stores the
195 * binding and the type with strong reference, thus preventing garbage
196 * collection. To allow garbage collection, please use another instance of
197 * GenericBindingFactory and binding repository (Map<Datatype, Binding>). <p>
199 * @param type the type to create binding to
200 * @return binding binding to a mutable class
202 @SuppressWarnings("unchecked")
203 public <T extends Binding> T getMutableBinding(Datatype type) {
205 Binding binding = mutableBindingRepository.get(type);
206 if (binding!=null) return (T) binding;
207 synchronized(mutableBindingRepository) {
208 return (T) mutableBindingFactory.getBinding(type);
210 } catch (BindingConstructionException e) {
211 // Unexpected - if error is thrown there is fault in GenericBindingScheme
212 throw new RuntimeBindingConstructionException(e);
217 * Get or create a binding based on default java classes, such as
218 * Integer.class, or byte[].class. The result is often binding for an
219 * immutable classs. These bindings are more efficient than mutable bindings (above).
221 * DataType | Class of the bound instance
222 * ===================|==================
223 * BooleanType | Boolean.class
224 * ByteType | Byte.class
225 * FloatType | Float.class
226 * DoubleType | Double.class
227 * IntegerType | Int.class
228 * LongType | Long.class
229 * StringType | String.class
230 * UnionType | TaggedObject.class
231 * OptionType | ValueContainer.class
232 * RecordType | Object[].class
233 * MapType | TreeMap.class
234 * VariantType | Variant.class
235 * ArrayType(Boolean) | boolean[].class
236 * ArrayType(Byte) | byte[].class
237 * ArrayType(Integer) | int[].class
238 * ArrayType(Long) | long[].class
239 * ArrayType(Float) | float[].class
240 * ArrayType(Double) | double[].class
241 * ArrayType(Byte) | byte[].class
242 * ArrayType( T ) | Object[].class
244 * Note, requesting a binding with this convenience method stores the
245 * binding and the type with strong reference, thus preventing garbage
246 * collection. To allow garbage collection, please use another instance of
247 * DefaultBindingFactory and binding repository (Map<Datatype, Binding>). <p>
249 * @param type the type to create binding to
250 * @return binding binding to a mutable class
252 @SuppressWarnings("unchecked")
253 public <T extends Binding> T getBinding(Datatype type) {
255 Binding binding = defaultBindingRepository.get(type);
256 if (binding!=null) return (T) binding;
257 synchronized(defaultBindingRepository) {
258 return (T) defaultBindingFactory.getBinding(type);
260 } catch (BindingConstructionException e) {
261 // Unexpected - if error is thrown there is fault in DefaultBindingScheme
262 throw new RuntimeBindingConstructionException(e);
267 * Get a binding to a Java Class. Details can be added by placing annotations
268 * to the java classes. See more in package org.simantics.databoard.annotations.
271 * Whether the result is a completely mutable or not depends on the
272 * requested class. For instance, fields such as Boolean, Integer, Long
273 * are not mutable, instead MutableBoolean, MutableInteger and MutableLong are.
274 * The length of Object[] is not mutable, but length of List<Object> is. <p>
276 * Note, requesting a binding with this convenience method stores the
277 * binding and the class with strong reference, thus preventing garbage
278 * collection. To allow garbage collection, please use another instance of
279 * BindingFactory and binding repository (Map<BindingRequest, Binding>). <p>
281 * @see ClassBindingFactory
284 * @throws BindingConstructionException
286 @SuppressWarnings("unchecked")
287 public <T extends Binding> T getBinding(Class<?> clazz)
288 throws BindingConstructionException
290 Binding binding = bindingRepository.get( clazz );
291 if (binding != null) {
295 BindingRequest request = new BindingRequest( clazz );
296 synchronized(classBindingFactory) {
297 binding = classBindingFactory.construct(request);
302 @SuppressWarnings("unchecked")
303 public <T extends Binding> T getBinding(BindingRequest request)
304 throws BindingConstructionException
306 synchronized(classBindingFactory) {
307 return (T) classBindingFactory.construct(request);
312 * Get a binding for a Java Class. Use this method to acquire class
313 * parameters for a generics class. <p>
317 * Binding binding = getBinding(Map.class, String.class, Integer.class);
318 * Map<String, Integer> map = (Map<String, Integer>) binding.createDefault();
322 * Binding d = getBinding(List.class, Integer.class);
323 * List<Integer> list = (List<Integer>) d.createRandom(5);
327 * Binding d = getBinding(List.class, List.class, Integer.class);
328 * List<List<Integer>> list = (List<List<Integer>>) d.createRandom(5);
330 * @see ClassBindingFactory
333 * @throws BindingConstructionException
335 @SuppressWarnings("unchecked")
336 public <T extends Binding> T getBinding(Class<?> clazz, Class<?>...parameters)
337 throws BindingConstructionException
339 BindingRequest request = new BindingRequest( clazz, parameters );
340 synchronized(classBindingFactory) {
341 return (T) classBindingFactory.construct(request);
346 * Read binding and type from a class. DataType details and parameters
347 * are read as annotations placed in the class.
348 * (See org.simantics.databoard.annotations)
350 * As an exception, in the subclasses of {@link Throwable}, the fields of
351 * Throwable are omited.
353 * This method is used for well-known classes where the caller is 100% sure
354 * that a binding is construable without exception. <p>
358 * @throws RuntimeBindingConstructionException
360 @SuppressWarnings("unchecked")
361 public <T extends Binding> T getBindingUnchecked(Class<?> clazz)
362 throws RuntimeBindingConstructionException
365 return (T) getBinding(clazz);
366 } catch (BindingConstructionException e) {
367 throw new RuntimeBindingConstructionException(e);
372 * Get a binding for a Java Class. Use this method to acquire class
373 * parameters for a generics class. <p>
377 * Binding binding = getBinding(Map.class, String.class, Integer.class);
378 * Map<String, Integer> map = (Map<String, Integer>) binding.createDefault();
382 * Binding d = getBinding(List.class, Integer.class);
383 * List<Integer> list = (List<Integer>) d.createRandom(5);
387 * Binding d = getBinding(List.class, List.class, Integer.class);
388 * List<List<Integer>> list = (List<List<Integer>>) d.createRandom(5);
390 * @see ClassBindingFactory
393 * @throws BindingConstructionException
395 @SuppressWarnings("unchecked")
396 public <T extends Binding> T getBindingUnchecked(Class<?> clazz, Class<?>...parameters)
397 throws RuntimeBindingConstructionException
400 Arguments args = new ArgumentImpl(parameters);
401 BindingRequest request = new BindingRequest( clazz, args );
402 Binding binding = bindingRepository.get( request );
404 synchronized(classBindingFactory) {
405 binding = classBindingFactory.construct(request);
408 } catch (BindingConstructionException e) {
409 throw new RuntimeBindingConstructionException(e);
414 * Add a simple binding to reflection binding factory.
418 * @param parameters parameter classes
420 public void addBinding( Binding binding, Class<?> clazz, Class<?>...parameters )
422 ArgumentImpl args = new ArgumentImpl( parameters );
423 BindingRequest request = new BindingRequest( clazz, args );
424 bindingRepository.put( request, binding );
428 * Add binding factory for compositive bindings
432 public void addBindingFactory( BindingProvider factory )
434 classBindingFactory.addFactory( factory );
438 * Creates a bean class
442 public BindingRequest getBeanBindingRequest( Datatype type ) throws RuntimeBindingConstructionException {
444 return typeClassFactory.getClass(type);
445 } catch (BindingConstructionException e) {
446 throw new RuntimeBindingConstructionException(e);
451 * Creates a bean class
455 public Class<?> getBeanClass( Datatype type ) throws BindingConstructionException {
456 BindingRequest br = typeClassFactory.getClass(type);
457 return br.getClazz();
461 * Create binding from datatype that instantiates java classes.
462 * RecordTypes are Beans, UnionTypes are Classes with @Union annotation,
468 public Binding getBeanBinding( Datatype type ) throws RuntimeBindingConstructionException {
470 BindingRequest br = typeClassFactory.getClass(type);
471 return getBinding( br );
472 } catch (BindingConstructionException e) {
473 throw new RuntimeBindingConstructionException(e);
478 * Get serializer that follows Databoard serialization spec.
482 * @throws SerializerConstructionException
484 public Serializer getSerializer(Binding binding) throws SerializerConstructionException {
485 return serializationFactory.construct(binding);
489 * Get serializer that follows Databoard serialization spec.
493 * @throws RuntimeSerializerConstructionException
495 public Serializer getSerializerUnchecked(Binding binding) throws RuntimeSerializerConstructionException {
497 return serializationFactory.construct(binding);
498 } catch (SerializerConstructionException e) {
499 throw new RuntimeSerializerConstructionException(e);
504 * Get serializer that follows Databoard serialization spec.
508 * @throws SerializerConstructionException
510 public Serializer getSerializer(Class<?> clazz) throws SerializerConstructionException {
512 Binding binding = getBinding(clazz);
513 return serializationFactory.construct(binding);
514 } catch (BindingConstructionException e) {
515 throw new SerializerConstructionException( e );
520 * Get serializer that follows Databoard serialization spec.
523 * @return serializer serializer
524 * @throws RuntimeSerializerConstructionException
526 public Serializer getSerializerUnchecked(Class<?> clazz) throws RuntimeSerializerConstructionException {
528 Binding binding = getBinding(clazz);
529 return serializationFactory.construct(binding);
530 } catch (SerializerConstructionException e) {
531 throw new RuntimeSerializerConstructionException(e);
532 } catch (BindingConstructionException e) {
533 throw new RuntimeSerializerConstructionException( new SerializerConstructionException(e) );
537 * Create an adapter that adapts two bindings of the same
540 * @param domain binding of the source instance
541 * @param range binding of the result instance
542 * @return result adapter
543 * @throws AdapterConstructionException
545 public Adapter getAdapter(Binding domain, Binding range)
546 throws AdapterConstructionException
548 return adapterFactory.getAdapter(domain, range, false, false);
552 * Create an adapter that adapts between two bindings of the same
555 * @param domain binding of the source instance
556 * @param range binding of the result instance
557 * @return result adapter
558 * @throws AdapterConstructionException
560 public Adapter getAdapterUnchecked(Binding domain, Binding range)
561 throws RuntimeAdapterConstructionException
564 return adapterFactory.getAdapter(domain, range, false, false);
565 } catch (AdapterConstructionException e) {
566 throw new RuntimeAdapterConstructionException(e);
571 * Create a type adapter that adapts instances from one Datatype to
572 * another. Type Adapter does the following conversions:
574 * o Number Types, e.g. long -> double
575 * o Unit Types, e.g. mph -> km/h
576 * o Record Types, for each field of the range, there must be equal in domain
577 * o Union Types, for each tag type of the domain, there must be equal in range
579 * {@link AdaptException} is thrown at runtime, if number conversion is not
580 * posible, e.g. converting value 500 from Integer to Byte.
581 * Note, there is also a possibility of precision loss, in many conversions
582 * e.g. from double to int.
584 * @param domain binding of the source instance
585 * @param range binding of the result instance
587 * @throws AdapterConstructionException
589 public Adapter getTypeAdapter(Binding domain, Binding range)
590 throws AdapterConstructionException
592 return adapterFactory.getAdapter(domain, range, true, false);
596 * Create a type adapter that adapts instances from one DataType to
597 * another. Type Adapter does the following conversions:
599 * o Number Types, e.g. long -> double
600 * o Unit Types, e.g. mph -> km/h
601 * o Record Types, for each field of the range, there must be equal in domain
602 * o Union Types, for each tag type of the domain, there must be equal in range
604 * {@link AdaptException} is thrown at runtime, if number values are
605 * not compatible, e.g. converting value 500 from Long to Byte.
606 * Note, there is also a possibility of precision loss, e.g. when
607 * converting from double to int.
609 * @param domain binding of the source instance
610 * @param range binding of the result instance
611 * @return result adapter
612 * @throws AdapterConstructionException
614 public Adapter getTypeAdapterUnchecked(Binding domain, Binding range)
617 return adapterFactory.getAdapter(domain, range, true, false);
618 } catch (AdapterConstructionException e) {
619 throw new RuntimeAdapterConstructionException(e);
624 * Adapt a value of one type to another.
629 * @return adapted value
630 * @throws AdapterConstructionException
631 * @throws AdaptException
633 public Object adapt(Object value, Binding domain, Binding range)
634 throws AdaptException
640 return adapterFactory.getAdapter(domain, range, true, false).adapt(value);
641 } catch (AdapterConstructionException e) {
642 throw new AdaptException(e);
647 * Adapt a value of one type to another. Exceptions are run-time. Use this
648 * if it safe to assume the conversion will be successful.
653 * @return adapted value
654 * @throws AdapterConstructionException
655 * @throws AdaptException
657 public Object adaptUnchecked(Object value, Binding domain, Binding range)
658 throws RuntimeAdapterConstructionException, RuntimeAdaptException
664 return adapterFactory.getAdapter(domain, range, true, false).adaptUnchecked(value);
665 } catch (RuntimeAdapterConstructionException e) {
666 throw new RuntimeAdaptException(new AdaptException(e.getCause()));
667 } catch (AdapterConstructionException e) {
668 throw new RuntimeAdaptException(new AdaptException(e));
673 * Adapt and clone a value instance to another type. Immutable
674 * bindings may return the argument as is, others return a cloned copy.
679 * @return adapted value
680 * @throws AdapterConstructionException
681 * @throws AdaptException
683 public Object clone(Object value, Binding domain, Binding range)
684 throws AdaptException
688 if (domain.isImmutable()) {
691 return domain.clone(value);
694 return adapterFactory.getAdapter(domain, range, true, true).adapt(value);
695 } catch (AdapterConstructionException e) {
696 throw new AdaptException(e);
702 * Clone a value of one binding to another. Bindings that handle immutable values
703 * may return the same instance, others will guarantee a complete copy.
705 * This method throws only runtime exceptions. Use this if it is safe to assume
706 * that the conversion will be successful.
711 * @return adapted value
712 * @throws AdapterConstructionException
713 * @throws AdaptException
715 public Object cloneUnchecked(Object value, Binding domain, Binding range)
716 throws RuntimeAdapterConstructionException, RuntimeAdaptException
719 return adapterFactory.getAdapter(domain, range, true, true).adapt(value);
720 } catch (AdaptException e) {
721 throw new RuntimeAdaptException(e);
722 } catch (RuntimeAdapterConstructionException e) {
723 throw new RuntimeAdaptException(new AdaptException(e.getCause()));
724 } catch (AdapterConstructionException e) {
725 throw new RuntimeAdaptException(new AdaptException(e));
730 * Compares two data values for order. Returns a negative integer,
731 * zero, or a positive integer if, the first argument precedes/lesser than
732 * the second, is equal to, or successor/greater than the second.<p>
734 * DataTypes of b1 and b2 are not equal, then data types are compared. <p>
736 * The comparison function is defined at
737 * http://dev.simantics.org/index.php/Org.simantics.datatype_Manual#CompareTo_and_Equals <p>
739 * Note, comparing 2 different number types will not result a value comparison.
740 * Instead values have the following type precedence ByteType, IntegerType, LongType,
741 * FloatType, and the highest DoubleType. <p>
743 * @param b1 Binding of o1
744 * @param o1 the first object to be compared.
745 * @param b2 Binding of o2
746 * @param o2 the second object to be compared.
747 * @return a negative integer, zero, or a positive integer as the
748 * first argument is less than, equal to, or greater than the
750 * @throws BindingException if object cannot be handled by a binding
752 public int compare(Binding b1, Object o1, Binding b2, Object o2)
753 throws BindingException
755 return DataValueUtil.compare(b1, o1, b2, o2);
759 * Compare two data values for equality. <p>
761 * Note, comparing 2 different number types will not result a value comparison.
762 * Instead values have the following type precedence ByteType, IntegerType, LongType,
763 * FloatType, and the highest DoubleType. <p>
769 * @return true if equal
770 * @throws BindingException
772 public boolean equals(Binding b1, Object o1, Binding b2, Object o2)
773 throws BindingException
775 return DataValueUtil.equals(b1, o1, b2, o2);
778 public Comparator<Object> createComparator(final Binding b1, final Binding b2)
780 return DataValueUtil.createComparator(b1, b2);
784 * Print the content of an object as a structure.
785 * Utility function for debug purposes.
790 public String toString(Object o) {
792 Binding b = getBinding( o.getClass() );
793 return b.printValueDefinition(o, true);
794 } catch (BindingConstructionException e) {
795 return "<error "+e.getClass().getName()+" "+e.getMessage()+">";
796 } catch (IOException e) {
797 return "<error "+e.getClass().getName()+" "+e.getMessage()+">";
798 } catch (BindingException e) {
799 return "<error "+e.getClass().getName()+" "+e.getMessage()+">";
803 class DataboardBindings implements BindingProvider {
805 public Binding provideBinding(ClassBindingFactory mainFactory, BindingRequest request) throws BindingConstructionException {
807 if (request.getClazz().equals( Object.class )) return OBJECT;
808 if (request.getClazz().equals( Void.class ) || request.getClazz().equals(void.class) ) return VoidBinding.VOID_BINDING;
809 if (request.getClazz().equals( Variant.class) ) return Bindings.VARIANT;
810 if (request.getClazz().equals( MutableVariant.class) ) return Bindings.MUTABLE_VARIANT;
811 if (request.getClazz().equals( Bean.class ) ) return BEAN;
817 private void addDefaultBinding(Datatype datatype, Binding binding ) {
818 defaultBindingRepository.put(datatype, binding);