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 bindingRepository.put(br, datatypeBinding);
157 } catch (ClassNotFoundException e) {
158 } catch (InstantiationException e) {
159 } catch (IllegalAccessException e) {
160 } catch (IllegalArgumentException e) {
161 } catch (InvocationTargetException e) {
162 } catch (SecurityException e) {
163 } catch (NoSuchMethodException e) {
164 } catch (BindingConstructionException e) {
169 public void clear() {
170 mutableBindingRepository.clear();
171 defaultBindingRepository.clear();
172 bindingRepository.clear();
173 serializerRepository.clear();
177 * Get or create a binding that is completely mutable java class.
179 * DataType | Class of the bound instance
180 * ===================|==================
181 * UnionType | GenericBinding.TaggedObject.class
182 * OptionType | ValueContainer.class
183 * RecordType | Object[].class
184 * BooleanType | MutableBoolean.class
185 * DoubleType | MutableDouble.class
186 * FloatType | MutableFloat.class
187 * ByteType | MutableByte.class
188 * IntegerType | MutableInt.class
189 * LongType | MutableLong.class
190 * StringType | ValueContainer.class
191 * ArrayType | ArrayList.class
192 * MapType | TreeMap.class
193 * VariantType | MutableVariant.class
195 * Note, requesting a binding with this convenience method stores the
196 * binding and the type with strong reference, thus preventing garbage
197 * collection. To allow garbage collection, please use another instance of
198 * GenericBindingFactory and binding repository (Map<Datatype, Binding>). <p>
200 * @param type the type to create binding to
201 * @return binding binding to a mutable class
203 @SuppressWarnings("unchecked")
204 public <T extends Binding> T getMutableBinding(Datatype type) {
206 Binding binding = mutableBindingRepository.get(type);
207 if (binding!=null) return (T) binding;
208 synchronized(mutableBindingRepository) {
209 return (T) mutableBindingFactory.getBinding(type);
211 } catch (BindingConstructionException e) {
212 // Unexpected - if error is thrown there is fault in GenericBindingScheme
213 throw new RuntimeBindingConstructionException(e);
218 * Get or create a binding based on default java classes, such as
219 * Integer.class, or byte[].class. The result is often binding for an
220 * immutable classs. These bindings are more efficient than mutable bindings (above).
222 * DataType | Class of the bound instance
223 * ===================|==================
224 * BooleanType | Boolean.class
225 * ByteType | Byte.class
226 * FloatType | Float.class
227 * DoubleType | Double.class
228 * IntegerType | Int.class
229 * LongType | Long.class
230 * StringType | String.class
231 * UnionType | TaggedObject.class
232 * OptionType | ValueContainer.class
233 * RecordType | Object[].class
234 * MapType | TreeMap.class
235 * VariantType | Variant.class
236 * ArrayType(Boolean) | boolean[].class
237 * ArrayType(Byte) | byte[].class
238 * ArrayType(Integer) | int[].class
239 * ArrayType(Long) | long[].class
240 * ArrayType(Float) | float[].class
241 * ArrayType(Double) | double[].class
242 * ArrayType(Byte) | byte[].class
243 * ArrayType( T ) | Object[].class
245 * Note, requesting a binding with this convenience method stores the
246 * binding and the type with strong reference, thus preventing garbage
247 * collection. To allow garbage collection, please use another instance of
248 * DefaultBindingFactory and binding repository (Map<Datatype, Binding>). <p>
250 * @param type the type to create binding to
251 * @return binding binding to a mutable class
253 @SuppressWarnings("unchecked")
254 public <T extends Binding> T getBinding(Datatype type) {
256 Binding binding = defaultBindingRepository.get(type);
257 if (binding!=null) return (T) binding;
258 synchronized(defaultBindingRepository) {
259 return (T) defaultBindingFactory.getBinding(type);
261 } catch (BindingConstructionException e) {
262 // Unexpected - if error is thrown there is fault in DefaultBindingScheme
263 throw new RuntimeBindingConstructionException(e);
268 * Get a binding to a Java Class. Details can be added by placing annotations
269 * to the java classes. See more in package org.simantics.databoard.annotations.
272 * Whether the result is a completely mutable or not depends on the
273 * requested class. For instance, fields such as Boolean, Integer, Long
274 * are not mutable, instead MutableBoolean, MutableInteger and MutableLong are.
275 * The length of Object[] is not mutable, but length of List<Object> is. <p>
277 * Note, requesting a binding with this convenience method stores the
278 * binding and the class with strong reference, thus preventing garbage
279 * collection. To allow garbage collection, please use another instance of
280 * BindingFactory and binding repository (Map<BindingRequest, Binding>). <p>
282 * @see ClassBindingFactory
285 * @throws BindingConstructionException
287 @SuppressWarnings("unchecked")
288 public <T extends Binding> T getBinding(Class<?> clazz)
289 throws BindingConstructionException
291 Binding binding = bindingRepository.get( clazz );
292 if (binding != null) {
296 BindingRequest request = new BindingRequest( clazz );
297 synchronized(classBindingFactory) {
298 binding = classBindingFactory.construct(request);
303 @SuppressWarnings("unchecked")
304 public <T extends Binding> T getBinding(BindingRequest request)
305 throws BindingConstructionException
307 synchronized(classBindingFactory) {
308 return (T) classBindingFactory.construct(request);
313 * Get a binding for a Java Class. Use this method to acquire class
314 * parameters for a generics class. <p>
318 * Binding binding = getBinding(Map.class, String.class, Integer.class);
319 * Map<String, Integer> map = (Map<String, Integer>) binding.createDefault();
323 * Binding d = getBinding(List.class, Integer.class);
324 * List<Integer> list = (List<Integer>) d.createRandom(5);
328 * Binding d = getBinding(List.class, List.class, Integer.class);
329 * List<List<Integer>> list = (List<List<Integer>>) d.createRandom(5);
331 * @see ClassBindingFactory
334 * @throws BindingConstructionException
336 @SuppressWarnings("unchecked")
337 public <T extends Binding> T getBinding(Class<?> clazz, Class<?>...parameters)
338 throws BindingConstructionException
340 BindingRequest request = new BindingRequest( clazz, parameters );
341 synchronized(classBindingFactory) {
342 return (T) classBindingFactory.construct(request);
347 * Read binding and type from a class. DataType details and parameters
348 * are read as annotations placed in the class.
349 * (See org.simantics.databoard.annotations)
351 * As an exception, in the subclasses of {@link Throwable}, the fields of
352 * Throwable are omited.
354 * This method is used for well-known classes where the caller is 100% sure
355 * that a binding is construable without exception. <p>
359 * @throws RuntimeBindingConstructionException
361 @SuppressWarnings("unchecked")
362 public <T extends Binding> T getBindingUnchecked(Class<?> clazz)
363 throws RuntimeBindingConstructionException
366 return (T) getBinding(clazz);
367 } catch (BindingConstructionException e) {
368 throw new RuntimeBindingConstructionException(e);
373 * Get a binding for a Java Class. Use this method to acquire class
374 * parameters for a generics class. <p>
378 * Binding binding = getBinding(Map.class, String.class, Integer.class);
379 * Map<String, Integer> map = (Map<String, Integer>) binding.createDefault();
383 * Binding d = getBinding(List.class, Integer.class);
384 * List<Integer> list = (List<Integer>) d.createRandom(5);
388 * Binding d = getBinding(List.class, List.class, Integer.class);
389 * List<List<Integer>> list = (List<List<Integer>>) d.createRandom(5);
391 * @see ClassBindingFactory
394 * @throws BindingConstructionException
396 @SuppressWarnings("unchecked")
397 public <T extends Binding> T getBindingUnchecked(Class<?> clazz, Class<?>...parameters)
398 throws RuntimeBindingConstructionException
401 Arguments args = new ArgumentImpl(parameters);
402 BindingRequest request = new BindingRequest( clazz, args );
403 Binding binding = bindingRepository.get( request );
405 synchronized(classBindingFactory) {
406 binding = classBindingFactory.construct(request);
409 } catch (BindingConstructionException e) {
410 throw new RuntimeBindingConstructionException(e);
415 * Add a simple binding to reflection binding factory.
419 * @param parameters parameter classes
421 public void addBinding( Binding binding, Class<?> clazz, Class<?>...parameters )
423 ArgumentImpl args = new ArgumentImpl( parameters );
424 BindingRequest request = new BindingRequest( clazz, args );
425 bindingRepository.put( request, binding );
429 * Add binding factory for compositive bindings
433 public void addBindingFactory( BindingProvider factory )
435 classBindingFactory.addFactory( factory );
439 * Creates a bean class
443 public BindingRequest getBeanBindingRequest( Datatype type ) throws RuntimeBindingConstructionException {
445 return typeClassFactory.getClass(type);
446 } catch (BindingConstructionException e) {
447 throw new RuntimeBindingConstructionException(e);
452 * Creates a bean class
456 public Class<?> getBeanClass( Datatype type ) throws BindingConstructionException {
457 BindingRequest br = typeClassFactory.getClass(type);
458 return br.getClazz();
462 * Create binding from datatype that instantiates java classes.
463 * RecordTypes are Beans, UnionTypes are Classes with @Union annotation,
469 public Binding getBeanBinding( Datatype type ) throws RuntimeBindingConstructionException {
471 BindingRequest br = typeClassFactory.getClass(type);
472 return getBinding( br );
473 } catch (BindingConstructionException e) {
474 throw new RuntimeBindingConstructionException(e);
479 * Get serializer that follows Databoard serialization spec.
483 * @throws SerializerConstructionException
485 public Serializer getSerializer(Binding binding) throws SerializerConstructionException {
486 return serializationFactory.construct(binding);
490 * Get serializer that follows Databoard serialization spec.
494 * @throws RuntimeSerializerConstructionException
496 public Serializer getSerializerUnchecked(Binding binding) throws RuntimeSerializerConstructionException {
498 return serializationFactory.construct(binding);
499 } catch (SerializerConstructionException e) {
500 throw new RuntimeSerializerConstructionException(e);
505 * Get serializer that follows Databoard serialization spec.
509 * @throws SerializerConstructionException
511 public Serializer getSerializer(Class<?> clazz) throws SerializerConstructionException {
513 Binding binding = getBinding(clazz);
514 return serializationFactory.construct(binding);
515 } catch (BindingConstructionException e) {
516 throw new SerializerConstructionException( e );
521 * Get serializer that follows Databoard serialization spec.
524 * @return serializer serializer
525 * @throws RuntimeSerializerConstructionException
527 public Serializer getSerializerUnchecked(Class<?> clazz) throws RuntimeSerializerConstructionException {
529 Binding binding = getBinding(clazz);
530 return serializationFactory.construct(binding);
531 } catch (SerializerConstructionException e) {
532 throw new RuntimeSerializerConstructionException(e);
533 } catch (BindingConstructionException e) {
534 throw new RuntimeSerializerConstructionException( new SerializerConstructionException(e) );
538 * Create an adapter that adapts two bindings of the same
541 * @param domain binding of the source instance
542 * @param range binding of the result instance
543 * @return result adapter
544 * @throws AdapterConstructionException
546 public Adapter getAdapter(Binding domain, Binding range)
547 throws AdapterConstructionException
549 return adapterFactory.getAdapter(domain, range, false, false);
553 * Create an adapter that adapts between two bindings of the same
556 * @param domain binding of the source instance
557 * @param range binding of the result instance
558 * @return result adapter
559 * @throws AdapterConstructionException
561 public Adapter getAdapterUnchecked(Binding domain, Binding range)
562 throws RuntimeAdapterConstructionException
565 return adapterFactory.getAdapter(domain, range, false, false);
566 } catch (AdapterConstructionException e) {
567 throw new RuntimeAdapterConstructionException(e);
572 * Create a type adapter that adapts instances from one Datatype to
573 * another. Type Adapter does the following conversions:
575 * o Number Types, e.g. long -> double
576 * o Unit Types, e.g. mph -> km/h
577 * o Record Types, for each field of the range, there must be equal in domain
578 * o Union Types, for each tag type of the domain, there must be equal in range
580 * {@link AdaptException} is thrown at runtime, if number conversion is not
581 * posible, e.g. converting value 500 from Integer to Byte.
582 * Note, there is also a possibility of precision loss, in many conversions
583 * e.g. from double to int.
585 * @param domain binding of the source instance
586 * @param range binding of the result instance
588 * @throws AdapterConstructionException
590 public Adapter getTypeAdapter(Binding domain, Binding range)
591 throws AdapterConstructionException
593 return adapterFactory.getAdapter(domain, range, true, false);
597 * Create a type adapter that adapts instances from one DataType to
598 * another. Type Adapter does the following conversions:
600 * o Number Types, e.g. long -> double
601 * o Unit Types, e.g. mph -> km/h
602 * o Record Types, for each field of the range, there must be equal in domain
603 * o Union Types, for each tag type of the domain, there must be equal in range
605 * {@link AdaptException} is thrown at runtime, if number values are
606 * not compatible, e.g. converting value 500 from Long to Byte.
607 * Note, there is also a possibility of precision loss, e.g. when
608 * converting from double to int.
610 * @param domain binding of the source instance
611 * @param range binding of the result instance
612 * @return result adapter
613 * @throws AdapterConstructionException
615 public Adapter getTypeAdapterUnchecked(Binding domain, Binding range)
618 return adapterFactory.getAdapter(domain, range, true, false);
619 } catch (AdapterConstructionException e) {
620 throw new RuntimeAdapterConstructionException(e);
625 * Adapt a value of one type to another.
630 * @return adapted value
631 * @throws AdapterConstructionException
632 * @throws AdaptException
634 public Object adapt(Object value, Binding domain, Binding range)
635 throws AdaptException
641 return adapterFactory.getAdapter(domain, range, true, false).adapt(value);
642 } catch (AdapterConstructionException e) {
643 throw new AdaptException(e);
648 * Adapt a value of one type to another. Exceptions are run-time. Use this
649 * if it safe to assume the conversion will be successful.
654 * @return adapted value
655 * @throws AdapterConstructionException
656 * @throws AdaptException
658 public Object adaptUnchecked(Object value, Binding domain, Binding range)
659 throws RuntimeAdapterConstructionException, RuntimeAdaptException
665 return adapterFactory.getAdapter(domain, range, true, false).adaptUnchecked(value);
666 } catch (RuntimeAdapterConstructionException e) {
667 throw new RuntimeAdaptException(new AdaptException(e.getCause()));
668 } catch (AdapterConstructionException e) {
669 throw new RuntimeAdaptException(new AdaptException(e));
674 * Adapt and clone a value instance to another type. Immutable
675 * bindings may return the argument as is, others return a cloned copy.
680 * @return adapted value
681 * @throws AdapterConstructionException
682 * @throws AdaptException
684 public Object clone(Object value, Binding domain, Binding range)
685 throws AdaptException
689 if (domain.isImmutable()) {
692 return domain.clone(value);
695 return adapterFactory.getAdapter(domain, range, true, true).adapt(value);
696 } catch (AdapterConstructionException e) {
697 throw new AdaptException(e);
703 * Clone a value of one binding to another. Bindings that handle immutable values
704 * may return the same instance, others will guarantee a complete copy.
706 * This method throws only runtime exceptions. Use this if it is safe to assume
707 * that the conversion will be successful.
712 * @return adapted value
713 * @throws AdapterConstructionException
714 * @throws AdaptException
716 public Object cloneUnchecked(Object value, Binding domain, Binding range)
717 throws RuntimeAdapterConstructionException, RuntimeAdaptException
720 return adapterFactory.getAdapter(domain, range, true, true).adapt(value);
721 } catch (AdaptException e) {
722 throw new RuntimeAdaptException(e);
723 } catch (RuntimeAdapterConstructionException e) {
724 throw new RuntimeAdaptException(new AdaptException(e.getCause()));
725 } catch (AdapterConstructionException e) {
726 throw new RuntimeAdaptException(new AdaptException(e));
731 * Compares two data values for order. Returns a negative integer,
732 * zero, or a positive integer if, the first argument precedes/lesser than
733 * the second, is equal to, or successor/greater than the second.<p>
735 * DataTypes of b1 and b2 are not equal, then data types are compared. <p>
737 * The comparison function is defined at
738 * http://dev.simantics.org/index.php/Org.simantics.datatype_Manual#CompareTo_and_Equals <p>
740 * Note, comparing 2 different number types will not result a value comparison.
741 * Instead values have the following type precedence ByteType, IntegerType, LongType,
742 * FloatType, and the highest DoubleType. <p>
744 * @param b1 Binding of o1
745 * @param o1 the first object to be compared.
746 * @param b2 Binding of o2
747 * @param o2 the second object to be compared.
748 * @return a negative integer, zero, or a positive integer as the
749 * first argument is less than, equal to, or greater than the
751 * @throws BindingException if object cannot be handled by a binding
753 public int compare(Binding b1, Object o1, Binding b2, Object o2)
754 throws BindingException
756 return DataValueUtil.compare(b1, o1, b2, o2);
760 * Compare two data values for equality. <p>
762 * Note, comparing 2 different number types will not result a value comparison.
763 * Instead values have the following type precedence ByteType, IntegerType, LongType,
764 * FloatType, and the highest DoubleType. <p>
770 * @return true if equal
771 * @throws BindingException
773 public boolean equals(Binding b1, Object o1, Binding b2, Object o2)
774 throws BindingException
776 return DataValueUtil.equals(b1, o1, b2, o2);
779 public Comparator<Object> createComparator(final Binding b1, final Binding b2)
781 return DataValueUtil.createComparator(b1, b2);
785 * Print the content of an object as a structure.
786 * Utility function for debug purposes.
791 public String toString(Object o) {
793 Binding b = getBinding( o.getClass() );
794 return b.printValueDefinition(o, true);
795 } catch (BindingConstructionException e) {
796 return "<error "+e.getClass().getName()+" "+e.getMessage()+">";
797 } catch (IOException e) {
798 return "<error "+e.getClass().getName()+" "+e.getMessage()+">";
799 } catch (BindingException e) {
800 return "<error "+e.getClass().getName()+" "+e.getMessage()+">";
804 class DataboardBindings implements BindingProvider {
806 public Binding provideBinding(ClassBindingFactory mainFactory, BindingRequest request) throws BindingConstructionException {
808 if (request.getClazz().equals( Object.class )) return OBJECT;
809 if (request.getClazz().equals( Void.class ) || request.getClazz().equals(void.class) ) return VoidBinding.VOID_BINDING;
810 if (request.getClazz().equals( Variant.class) ) return Bindings.VARIANT;
811 if (request.getClazz().equals( MutableVariant.class) ) return Bindings.MUTABLE_VARIANT;
812 if (request.getClazz().equals( Bean.class ) ) return BEAN;
818 private void addDefaultBinding(Datatype datatype, Binding binding ) {
819 defaultBindingRepository.put(datatype, binding);