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 * Semantum Oy - gitlab #313
12 *******************************************************************************/
13 package org.simantics.databoard;
15 import java.io.IOException;
16 import java.util.Comparator;
19 import org.simantics.databoard.adapter.AdaptException;
20 import org.simantics.databoard.adapter.Adapter;
21 import org.simantics.databoard.adapter.AdapterConstructionException;
22 import org.simantics.databoard.adapter.AdapterFactory;
23 import org.simantics.databoard.adapter.RuntimeAdaptException;
24 import org.simantics.databoard.adapter.RuntimeAdapterConstructionException;
25 import org.simantics.databoard.annotations.ArgumentImpl;
26 import org.simantics.databoard.annotations.Arguments;
27 import org.simantics.databoard.binding.ArrayBinding;
28 import org.simantics.databoard.binding.Binding;
29 import org.simantics.databoard.binding.BooleanBinding;
30 import org.simantics.databoard.binding.ByteBinding;
31 import org.simantics.databoard.binding.DoubleBinding;
32 import org.simantics.databoard.binding.FloatBinding;
33 import org.simantics.databoard.binding.IntegerBinding;
34 import org.simantics.databoard.binding.LongBinding;
35 import org.simantics.databoard.binding.StringBinding;
36 import org.simantics.databoard.binding.VariantBinding;
37 import org.simantics.databoard.binding.classfactory.TypeClassFactory;
38 import org.simantics.databoard.binding.error.BindingConstructionException;
39 import org.simantics.databoard.binding.error.BindingException;
40 import org.simantics.databoard.binding.error.RuntimeBindingConstructionException;
41 import org.simantics.databoard.binding.factory.BindingRepository;
42 import org.simantics.databoard.binding.factory.TypeBindingFactory;
43 import org.simantics.databoard.binding.impl.BooleanArrayBinding;
44 import org.simantics.databoard.binding.impl.BooleanBindingDefault;
45 import org.simantics.databoard.binding.impl.ByteArrayBinding;
46 import org.simantics.databoard.binding.impl.ByteBindingDefault;
47 import org.simantics.databoard.binding.impl.DoubleArrayBinding;
48 import org.simantics.databoard.binding.impl.DoubleBindingDefault;
49 import org.simantics.databoard.binding.impl.FloatArrayBinding;
50 import org.simantics.databoard.binding.impl.FloatBindingDefault;
51 import org.simantics.databoard.binding.impl.IntArrayBinding;
52 import org.simantics.databoard.binding.impl.IntegerBindingDefault;
53 import org.simantics.databoard.binding.impl.LongArrayBinding;
54 import org.simantics.databoard.binding.impl.LongBindingDefault;
55 import org.simantics.databoard.binding.impl.StringArrayBinding;
56 import org.simantics.databoard.binding.impl.StringBindingDefault;
57 import org.simantics.databoard.binding.impl.UnsignedByteBinding;
58 import org.simantics.databoard.binding.impl.UnsignedIntegerBinding;
59 import org.simantics.databoard.binding.impl.UnsignedLongBinding;
60 import org.simantics.databoard.binding.mutable.MutableBooleanBinding;
61 import org.simantics.databoard.binding.mutable.MutableByteBinding;
62 import org.simantics.databoard.binding.mutable.MutableDoubleBinding;
63 import org.simantics.databoard.binding.mutable.MutableFloatBinding;
64 import org.simantics.databoard.binding.mutable.MutableIntegerBinding;
65 import org.simantics.databoard.binding.mutable.MutableLongBinding;
66 import org.simantics.databoard.binding.mutable.MutableStringBinding;
67 import org.simantics.databoard.binding.mutable.MutableVariantBinding;
68 import org.simantics.databoard.binding.reflection.BindingProvider;
69 import org.simantics.databoard.binding.reflection.BindingRequest;
70 import org.simantics.databoard.binding.reflection.ClassBindingFactory;
71 import org.simantics.databoard.binding.reflection.VoidBinding;
72 import org.simantics.databoard.serialization.RuntimeSerializerConstructionException;
73 import org.simantics.databoard.serialization.Serializer;
74 import org.simantics.databoard.serialization.SerializerConstructionException;
75 import org.simantics.databoard.serialization.SerializerScheme;
76 import org.simantics.databoard.type.ArrayType;
77 import org.simantics.databoard.type.Datatype;
78 import org.simantics.databoard.util.DataValueUtil;
81 * This ia a facade class for the binding services.
83 * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
85 public class Bindings {
87 public static final Databoard databoard;
91 /** Repository of mutable bindings */
92 public static final Map<Datatype, Binding> mutableBindingRepository;
94 /** Repository of default bindings */
95 public static final Map<Datatype, Binding> defaultBindingRepository;
97 /** Repository of class Bindings */
98 public static final BindingRepository bindingRepository;
100 /** Repository of serializers */
101 public static final Map<Binding, Serializer> serializerRepository;
106 /** Mutable Bindings Factory */
107 public static final TypeBindingFactory mutableBindingFactory;
109 /** Default Bindings Factory */
110 public static final TypeBindingFactory defaultBindingFactory;
112 /** Reflection based Binding Factory, create binding to class */
113 public static final ClassBindingFactory classBindingFactory;
115 /** Serializer Factory */
116 public static final SerializerScheme serializationFactory;
118 /** Adapter Factory */
119 public static final AdapterFactory adapterFactory;
122 public static final TypeClassFactory typeClassFactory;
125 // Bindings to various primitives
126 public static final StringBinding STRING; // java.lang.String
127 public static final IntegerBinding INTEGER; // java.lang.Integer
128 public static final BooleanBinding BOOLEAN; // java.lang.Boolean
129 public static final ByteBinding BYTE; // java.lang.Byte
130 public static final LongBinding LONG; // java.lang.Long
131 public static final DoubleBinding DOUBLE; // java.lang.Double
132 public static final FloatBinding FLOAT; // java.lang.Float
133 public static final VariantBinding VARIANT; // Variant
134 public static final VariantBinding OBJECT; // java.lang.Object ( as variant )
135 public static final VariantBinding STR_VARIANT; // java.lang.String ( as variant )
137 public static final Binding VOID; // void ( as {} )
138 public static final Binding BEAN; // Bean ( as variant )
139 public static final Binding DATATYPE; // org.simantics.databoard.type.Datatype
141 public static final ArrayBinding BOOLEAN_ARRAY; // boolean[]
142 public static final ArrayBinding BYTE_ARRAY; // byte[]
143 public static final ArrayBinding INT_ARRAY; // int[]
144 public static final ArrayBinding LONG_ARRAY; // long[]
145 public static final ArrayBinding FLOAT_ARRAY; // float[]
146 public static final ArrayBinding DOUBLE_ARRAY; // double[]
147 public static final ArrayBinding STRING_ARRAY; // String[]
149 public static final StringBinding MUTABLE_STRING; // MutableString
150 public static final IntegerBinding MUTABLE_INTEGER; // MutableInteger
151 public static final BooleanBinding MUTABLE_BOOLEAN; // MutableBoolean
152 public static final ByteBinding MUTABLE_BYTE; // MutableByte
153 public static final LongBinding MUTABLE_LONG; // MutableLong
154 public static final FloatBinding MUTABLE_FLOAT; // MutableFloat
155 public static final DoubleBinding MUTABLE_DOUBLE; // MutableDouble
156 public static final VariantBinding MUTABLE_VARIANT; // MutableVariant
158 public static final IntegerBinding UNSIGNED_INTEGER; // UnsignedInteger.Immutable
159 public static final ByteBinding UNSIGNED_BYTE; // UnsignedByte.Immutable
160 public static final LongBinding UNSIGNED_LONG; // UnsignedLong.Immutable
162 public static final IntegerBinding MUTABLE_UNSIGNED_INTEGER; // UnsignedInteger.Mutable
163 public static final ByteBinding MUTABLE_UNSIGNED_BYTE; // UnsignedByte.Mutable
164 public static final LongBinding MUTABLE_UNSIGNED_LONG; // UnsignedLong.Mutable
167 * Get or create a binding that is completely mutable java class.
169 * DataType | Class of the bound instance
170 * ===================|==================
171 * UnionType | GenericBinding.TaggedObject.class
172 * OptionType | ValueContainer.class
173 * RecordType | Object[].class
174 * BooleanType | MutableBoolean.class
175 * DoubleType | MutableDouble.class
176 * FloatType | MutableFloat.class
177 * ByteType | MutableByte.class
178 * IntegerType | MutableInt.class
179 * LongType | MutableLong.class
180 * StringType | ValueContainer.class
181 * ArrayType | ArrayList.class
182 * MapType | TreeMap.class
183 * VariantType | MutableVariant.class
185 * Note, requesting a binding with this convenience method stores the
186 * binding and the type with strong reference, thus preventing garbage
187 * collection. To allow garbage collection, please use another instance of
188 * GenericBindingFactory and binding repository (Map<Datatype, Binding>). <p>
190 * @param type the type to create binding to
191 * @return binding binding to a mutable class
193 @SuppressWarnings("unchecked")
194 public static <T extends Binding> T getMutableBinding(Datatype type) {
196 Binding binding = mutableBindingRepository.get(type);
197 if (binding!=null) return (T) binding;
198 synchronized(mutableBindingRepository) {
199 return (T) mutableBindingFactory.getBinding(type);
201 } catch (BindingConstructionException e) {
202 // Unexpected - if error is thrown there is fault in GenericBindingScheme
203 throw new RuntimeBindingConstructionException(e);
208 * Get or create a binding based on default java classes, such as
209 * Integer.class, or byte[].class. The result is often binding for an
210 * immutable classs. These bindings are more efficient than mutable bindings (above).
212 * DataType | Class of the bound instance
213 * ===================|==================
214 * BooleanType | Boolean.class
215 * ByteType | Byte.class
216 * FloatType | Float.class
217 * DoubleType | Double.class
218 * IntegerType | Int.class
219 * LongType | Long.class
220 * StringType | String.class
221 * UnionType | TaggedObject.class
222 * OptionType | ValueContainer.class
223 * RecordType | Object[].class
224 * MapType | TreeMap.class
225 * VariantType | Variant.class
226 * ArrayType(Boolean) | boolean[].class
227 * ArrayType(Byte) | byte[].class
228 * ArrayType(Integer) | int[].class
229 * ArrayType(Long) | long[].class
230 * ArrayType(Float) | float[].class
231 * ArrayType(Double) | double[].class
232 * ArrayType(Byte) | byte[].class
233 * ArrayType( T ) | Object[].class
235 * Note, requesting a binding with this convenience method stores the
236 * binding and the type with strong reference, thus preventing garbage
237 * collection. To allow garbage collection, please use another instance of
238 * DefaultBindingFactory and binding repository (Map<Datatype, Binding>). <p>
240 * @param type the type to create binding to
241 * @return binding binding to a mutable class
243 @SuppressWarnings("unchecked")
244 public static <T extends Binding> T getBinding(Datatype type) {
246 Binding binding = defaultBindingRepository.get(type);
247 if (binding!=null) return (T) binding;
248 synchronized(defaultBindingRepository) {
249 return (T) defaultBindingFactory.getBinding(type);
251 } catch (BindingConstructionException e) {
252 // Unexpected - if error is thrown there is fault in DefaultBindingScheme
253 throw new RuntimeBindingConstructionException(e);
258 * Get a binding to a Java Class. Details can be added by placing annotations
259 * to the java classes. See more in package org.simantics.databoard.annotations.
262 * Whether the result is a completely mutable or not depends on the
263 * requested class. For instance, fields such as Boolean, Integer, Long
264 * are not mutable, instead MutableBoolean, MutableInteger and MutableLong are.
265 * The length of Object[] is not mutable, but length of List<Object> is. <p>
267 * Note, requesting a binding with this convenience method stores the
268 * binding and the class with strong reference, thus preventing garbage
269 * collection. To allow garbage collection, please use another instance of
270 * BindingFactory and binding repository (Map<BindingRequest, Binding>). <p>
272 * Is asm library is available, the binding is bytecode generated. Then read
273 * and write operations are direct get/set calls or direct field read/writes.
274 * There is no reflection used. <p>
276 * @see ClassBindingFactory
279 * @throws BindingConstructionException
281 @SuppressWarnings("unchecked")
282 public static <T extends Binding> T getBinding(Class<?> clazz)
283 throws BindingConstructionException
285 Binding binding = bindingRepository.get( clazz );
286 if (binding != null) {
290 BindingRequest request = new BindingRequest( clazz );
291 synchronized(classBindingFactory) {
292 binding = classBindingFactory.construct(request);
297 @SuppressWarnings("unchecked")
298 public static <T extends Binding> T getBinding(BindingRequest request)
299 throws BindingConstructionException
301 synchronized(classBindingFactory) {
302 return (T) classBindingFactory.construct(request);
307 * Get a binding for a Java Class. Use this method to acquire class
308 * parameters for a generics class. <p>
312 * Binding binding = Bindings.getBinding(Map.class, String.class, Integer.class);
313 * Map<String, Integer> map = (Map<String, Integer>) binding.createDefault();
317 * Binding d = Bindings.getBinding(List.class, Integer.class);
318 * List<Integer> list = (List<Integer>) d.createRandom(5);
322 * Binding d = Bindings.getBinding(List.class, List.class, Integer.class);
323 * List<List<Integer>> list = (List<List<Integer>>) d.createRandom(5);
325 * @see ClassBindingFactory
328 * @throws BindingConstructionException
330 @SuppressWarnings("unchecked")
331 public static <T extends Binding> T getBinding(Class<?> clazz, Class<?>...parameters)
332 throws BindingConstructionException
334 BindingRequest request = new BindingRequest( clazz, parameters );
335 synchronized(classBindingFactory) {
336 return (T) classBindingFactory.construct(request);
341 * Try to get a binding for the actual class of a Java object.
342 * @param obj A Java object
343 * @return A binding for the class of the object
344 * @throws BindingConstructionException if no binding can be constructed
346 public static <T extends Binding> T getInstanceBinding(Object obj)
347 throws BindingConstructionException
349 return getBinding(obj.getClass());
353 * Read binding and type from a class. DataType details and parameters
354 * are read as annotations placed in the class.
355 * (See org.simantics.databoard.annotations)
357 * As an exception, in the subclasses of {@link Throwable}, the fields of
358 * Throwable are omited.
360 * This method is used for well-known classes where the caller is 100% sure
361 * that a binding is construable without exception. <p>
365 * @throws RuntimeBindingConstructionException
367 @SuppressWarnings("unchecked")
368 public static <T extends Binding> T getBindingUnchecked(Class<?> clazz)
369 throws RuntimeBindingConstructionException
372 return (T) getBinding(clazz);
373 } catch (BindingConstructionException e) {
374 throw new RuntimeBindingConstructionException(e);
379 * Get a binding for a Java Class. Use this method to acquire class
380 * parameters for a generics class. <p>
384 * Binding binding = Bindings.getBinding(Map.class, String.class, Integer.class);
385 * Map<String, Integer> map = (Map<String, Integer>) binding.createDefault();
389 * Binding d = Bindings.getBinding(List.class, Integer.class);
390 * List<Integer> list = (List<Integer>) d.createRandom(5);
394 * Binding d = Bindings.getBinding(List.class, List.class, Integer.class);
395 * List<List<Integer>> list = (List<List<Integer>>) d.createRandom(5);
397 * @see ClassBindingFactory
400 * @throws BindingConstructionException
402 @SuppressWarnings("unchecked")
403 public static <T extends Binding> T getBindingUnchecked(Class<?> clazz, Class<?>...parameters)
404 throws RuntimeBindingConstructionException
407 Arguments args = new ArgumentImpl(parameters);
408 BindingRequest request = new BindingRequest( clazz, args );
409 Binding binding = bindingRepository.get( request );
411 synchronized(classBindingFactory) {
412 binding = classBindingFactory.construct(request);
415 } catch (BindingConstructionException e) {
416 throw new RuntimeBindingConstructionException(e);
421 * Add a simple binding to reflection binding factory.
425 * @param parameters parameter classes
427 public static void addBinding( Binding binding, Class<?> clazz, Class<?>...parameters )
429 ArgumentImpl args = new ArgumentImpl( parameters );
430 BindingRequest request = new BindingRequest( clazz, args );
431 bindingRepository.put( request, binding );
435 * Add binding factory for compositive bindings
439 public static void addBindingFactory( BindingProvider factory )
441 classBindingFactory.addFactory( factory );
445 * Creates a bean class
449 public static BindingRequest getBeanBindingRequest( Datatype type ) throws RuntimeBindingConstructionException {
451 return typeClassFactory.getClass(type);
452 } catch (BindingConstructionException e) {
453 throw new RuntimeBindingConstructionException(e);
458 * Creates a bean class
462 public static Class<?> getBeanClass( Datatype type ) throws BindingConstructionException {
463 BindingRequest br = typeClassFactory.getClass(type);
464 return br.getClazz();
468 * Create binding from datatype that instantiates java classes.
469 * RecordTypes are Beans, UnionTypes are Classes with @Union annotation,
475 public static Binding getBeanBinding( Datatype type ) throws RuntimeBindingConstructionException {
477 BindingRequest br = typeClassFactory.getClass(type);
478 return getBinding( br );
479 } catch (BindingConstructionException e) {
480 throw new RuntimeBindingConstructionException(e);
485 * Get a default array binding for a given component type binding.
486 * Returns a primitive array type binding for primitive types and an
487 * ObjectArrayBinding for others.
489 * @param componentBinding A binding for a component type
490 * @return A binding for the array type
492 public static Binding getArrayBinding(Binding componentBinding) {
493 return getBinding(new ArrayType(componentBinding.type()));
497 * Get serializer that follows Databoard serialization spec.
501 * @throws SerializerConstructionException
503 public static Serializer getSerializer(Binding binding) throws SerializerConstructionException {
504 return serializationFactory.getSerializer(binding);
508 * Get serializer that follows Databoard serialization spec.
512 * @throws RuntimeSerializerConstructionException
514 public static Serializer getSerializerUnchecked(Binding binding) throws RuntimeSerializerConstructionException {
515 return serializationFactory.getSerializerUnchecked(binding);
519 * Get serializer that follows Databoard serialization spec.
523 * @throws SerializerConstructionException
525 public static Serializer getSerializer(Class<?> clazz) throws SerializerConstructionException {
527 Binding binding = getBinding(clazz);
528 return serializationFactory.getSerializer(binding);
529 } catch (BindingConstructionException e) {
530 throw new SerializerConstructionException( e );
535 * Get serializer that follows Databoard serialization spec.
538 * @return serializer serializer
539 * @throws RuntimeSerializerConstructionException
541 public static Serializer getSerializerUnchecked(Class<?> clazz) throws RuntimeSerializerConstructionException {
543 Binding binding = getBinding(clazz);
544 return serializationFactory.getSerializerUnchecked(binding);
545 } catch (BindingConstructionException e) {
546 throw new RuntimeSerializerConstructionException( new SerializerConstructionException(e) );
550 * Create an adapter that adapts two bindings of the same
553 * @param domain binding of the source instance
554 * @param range binding of the result instance
555 * @return result adapter
556 * @throws AdapterConstructionException
558 public static Adapter getAdapter(Binding domain, Binding range)
559 throws AdapterConstructionException
561 return adapterFactory.getAdapter(domain, range, false, false);
565 * Create an adapter that adapts between two bindings of the same
568 * @param domain binding of the source instance
569 * @param range binding of the result instance
570 * @return result adapter
571 * @throws AdapterConstructionException
573 public static Adapter getAdapterUnchecked(Binding domain, Binding range)
574 throws RuntimeAdapterConstructionException
577 return adapterFactory.getAdapter(domain, range, false, false);
578 } catch (AdapterConstructionException e) {
579 throw new RuntimeAdapterConstructionException(e);
584 * Create a type adapter that adapts instances from one Datatype to
585 * another. Type Adapter does the following conversions:
587 * o Number Types, e.g. long -> double
588 * o Unit Types, e.g. mph -> km/h
589 * o Record Types, for each field of the range, there must be equal in domain
590 * o Union Types, for each tag type of the domain, there must be equal in range
592 * {@link AdaptException} is thrown at runtime, if number conversion is not
593 * posible, e.g. converting value 500 from Integer to Byte.
594 * Note, there is also a possibility of precision loss, in many conversions
595 * e.g. from double to int.
597 * @param domain binding of the source instance
598 * @param range binding of the result instance
600 * @throws AdapterConstructionException
602 public static Adapter getTypeAdapter(Binding domain, Binding range)
603 throws AdapterConstructionException
605 return adapterFactory.getAdapter(domain, range, true, false);
609 * Create a type adapter that adapts instances from one DataType to
610 * another. Type Adapter does the following conversions:
612 * o Number Types, e.g. long -> double
613 * o Unit Types, e.g. mph -> km/h
614 * o Record Types, for each field of the range, there must be equal in domain
615 * o Union Types, for each tag type of the domain, there must be equal in range
617 * {@link AdaptException} is thrown at runtime, if number values are
618 * not compatible, e.g. converting value 500 from Long to Byte.
619 * Note, there is also a possibility of precision loss, e.g. when
620 * converting from double to int.
622 * @param domain binding of the source instance
623 * @param range binding of the result instance
624 * @return result adapter
625 * @throws AdapterConstructionException
627 public static Adapter getTypeAdapterUnchecked(Binding domain, Binding range)
630 return adapterFactory.getAdapter(domain, range, true, false);
631 } catch (AdapterConstructionException e) {
632 throw new RuntimeAdapterConstructionException(e);
637 * Adapt a value of one type to another.
642 * @return adapted value
643 * @throws AdapterConstructionException
644 * @throws AdaptException
646 public static Object adapt(Object value, Binding domain, Binding range)
647 throws AdaptException
650 if (domain.equals(range)) {
653 else if (range instanceof VariantBinding) {
654 if (domain instanceof VariantBinding) {
655 // Copy variant contents directly
656 Binding contentBinding = ((VariantBinding)domain).getContentBinding( value );
657 Object content = ((VariantBinding)domain).getContent( value );
658 return ((VariantBinding)range).create( contentBinding, content );
661 // Default to just wrapping the value (avoid adapter construction to save memory)
662 return ((VariantBinding)range).create(domain, value);
665 else if (domain instanceof VariantBinding) {
666 return adapt(((VariantBinding)domain).getContent( value ), ((VariantBinding)domain).getContentBinding( value ), range );
669 return adapterFactory.getAdapter(domain, range, true, false).adapt(value);
671 } catch (AdapterConstructionException | BindingException e) {
672 throw new AdaptException(e);
677 * Adapt a value of one type to another. Exceptions are run-time. Use this
678 * if it safe to assume the conversion will be successful.
683 * @return adapted value
684 * @throws AdapterConstructionException
685 * @throws AdaptException
687 public static Object adaptUnchecked(Object value, Binding domain, Binding range)
688 throws RuntimeAdapterConstructionException, RuntimeAdaptException
694 if (range instanceof VariantBinding && !(domain instanceof VariantBinding)) {
695 // Default to just wrapping the value (avoid adapter construction to save memory)
696 return ((VariantBinding)range).create(domain, value);
698 return adapterFactory.getAdapter(domain, range, true, false).adaptUnchecked(value);
699 } catch (RuntimeAdapterConstructionException e) {
700 throw new RuntimeAdaptException(new AdaptException(e.getCause()));
701 } catch (AdapterConstructionException e) {
702 throw new RuntimeAdaptException(new AdaptException(e));
703 } catch (BindingException e) {
704 throw new RuntimeAdaptException(new AdaptException(e));
709 * Adapt and clone a value instance to another type. Immutable
710 * bindings may return the argument as is, others return a cloned copy.
715 * @return adapted value
716 * @throws AdapterConstructionException
717 * @throws AdaptException
719 public static Object clone(Object value, Binding domain, Binding range)
720 throws AdaptException
724 if (domain.isImmutable()) {
727 return domain.clone(value);
730 return adapterFactory.getAdapter(domain, range, true, true).adapt(value);
731 } catch (AdapterConstructionException e) {
732 throw new AdaptException(e);
738 * Clone a value of one binding to another. Bindings that handle immutable values
739 * may return the same instance, others will guarantee a complete copy.
741 * This method throws only runtime exceptions. Use this if it is safe to assume
742 * that the conversion will be successful.
747 * @return adapted value
748 * @throws AdapterConstructionException
749 * @throws AdaptException
751 public static Object cloneUnchecked(Object value, Binding domain, Binding range)
752 throws RuntimeAdapterConstructionException, RuntimeAdaptException
755 return adapterFactory.getAdapter(domain, range, true, true).adapt(value);
756 } catch (AdaptException e) {
757 throw new RuntimeAdaptException(e);
758 } catch (RuntimeAdapterConstructionException e) {
759 throw new RuntimeAdaptException(new AdaptException(e.getCause()));
760 } catch (AdapterConstructionException e) {
761 throw new RuntimeAdaptException(new AdaptException(e));
766 * Compares two data values for order. Returns a negative integer,
767 * zero, or a positive integer if, the first argument precedes/lesser than
768 * the second, is equal to, or successor/greater than the second.<p>
770 * DataTypes of b1 and b2 are not equal, then data types are compared. <p>
772 * The comparison function is defined at
773 * http://dev.simantics.org/index.php/Org.simantics.datatype_Manual#CompareTo_and_Equals <p>
775 * Note, comparing 2 different number types will not result a value comparison.
776 * Instead values have the following type precedence ByteType, IntegerType, LongType,
777 * FloatType, and the highest DoubleType. <p>
779 * @param b1 Binding of o1
780 * @param o1 the first object to be compared.
781 * @param b2 Binding of o2
782 * @param o2 the second object to be compared.
783 * @return a negative integer, zero, or a positive integer as the
784 * first argument is less than, equal to, or greater than the
786 * @throws BindingException if object cannot be handled by a binding
788 public static int compare(Binding b1, Object o1, Binding b2, Object o2)
789 throws BindingException
791 return DataValueUtil.compare(b1, o1, b2, o2);
795 * Compare two data values for equality. <p>
797 * Note, comparing 2 different number types will not result a value comparison.
798 * Instead values have the following type precedence ByteType, IntegerType, LongType,
799 * FloatType, and the highest DoubleType. <p>
805 * @return true if equal
806 * @throws BindingException
808 public static boolean equals(Binding b1, Object o1, Binding b2, Object o2)
809 throws BindingException
811 return DataValueUtil.equals(b1, o1, b2, o2);
814 public static Comparator<Object> createComparator(final Binding b1, final Binding b2)
816 return DataValueUtil.createComparator(b1, b2);
820 * Print the content of an object as a structure.
821 * Utility function for debug purposes.
826 public static String toString(Object o) {
828 Binding b = Bindings.getBinding( o.getClass() );
829 return b.printValueDefinition(o, true);
830 } catch (BindingConstructionException e) {
831 return "<error "+e.getClass().getName()+" "+e.getMessage()+">";
832 } catch (IOException e) {
833 return "<error "+e.getClass().getName()+" "+e.getMessage()+">";
834 } catch (BindingException e) {
835 return "<error "+e.getClass().getName()+" "+e.getMessage()+">";
840 STRING = new StringBindingDefault( Datatypes.STRING );
841 INTEGER = new IntegerBindingDefault( Datatypes.INTEGER );
842 BOOLEAN = new BooleanBindingDefault( Datatypes.BOOLEAN );
843 BYTE = new ByteBindingDefault( Datatypes.BYTE );
844 LONG = new LongBindingDefault( Datatypes.LONG );
845 DOUBLE = new DoubleBindingDefault( Datatypes.DOUBLE );
846 FLOAT = new FloatBindingDefault( Datatypes.FLOAT );
847 VOID = VoidBinding.VOID_BINDING;
848 BOOLEAN_ARRAY = new BooleanArrayBinding( Datatypes.BOOLEAN_ARRAY, BOOLEAN );
849 BYTE_ARRAY = new ByteArrayBinding( Datatypes.BYTE_ARRAY, BYTE );
850 INT_ARRAY = new IntArrayBinding( Datatypes.INTEGER_ARRAY, INTEGER );
851 LONG_ARRAY = new LongArrayBinding( Datatypes.LONG_ARRAY, LONG );
852 FLOAT_ARRAY = new FloatArrayBinding( Datatypes.FLOAT_ARRAY, FLOAT );
853 DOUBLE_ARRAY = new DoubleArrayBinding( Datatypes.DOUBLE_ARRAY, DOUBLE );
854 STRING_ARRAY = new StringArrayBinding( Datatypes.STRING_ARRAY, STRING );
855 UNSIGNED_INTEGER = new UnsignedIntegerBinding.Immutable( Datatypes.INTEGER );
856 UNSIGNED_BYTE = new UnsignedByteBinding.Immutable( Datatypes.BYTE );
857 UNSIGNED_LONG = new UnsignedLongBinding.Immutable( Datatypes.LONG );
858 MUTABLE_STRING = new MutableStringBinding( Datatypes.STRING );
859 MUTABLE_INTEGER = new MutableIntegerBinding( Datatypes.INTEGER );
860 MUTABLE_BOOLEAN = new MutableBooleanBinding( Datatypes.BOOLEAN );
861 MUTABLE_BYTE = new MutableByteBinding( Datatypes.BYTE );
862 MUTABLE_LONG = new MutableLongBinding( Datatypes.LONG );
863 MUTABLE_FLOAT = new MutableFloatBinding( Datatypes.FLOAT );
864 MUTABLE_DOUBLE = new MutableDoubleBinding( Datatypes.DOUBLE );
865 MUTABLE_UNSIGNED_INTEGER = new UnsignedIntegerBinding.Mutable( Datatypes.INTEGER );
866 MUTABLE_UNSIGNED_BYTE = new UnsignedByteBinding.Mutable( Datatypes.BYTE );
867 MUTABLE_UNSIGNED_LONG = new UnsignedLongBinding.Mutable( Datatypes.LONG );
869 databoard = new Databoard();
871 mutableBindingRepository = databoard.mutableBindingRepository;
872 defaultBindingRepository = databoard.defaultBindingRepository;
873 bindingRepository = databoard.bindingRepository;
874 serializerRepository = databoard.serializerRepository;
875 mutableBindingFactory = databoard.mutableBindingFactory;
876 defaultBindingFactory = databoard.defaultBindingFactory;
877 classBindingFactory = databoard.classBindingFactory;
878 serializationFactory = databoard.serializationFactory;
879 adapterFactory = databoard.adapterFactory;
880 typeClassFactory = databoard.typeClassFactory;
882 BEAN = databoard.BEAN;
883 VARIANT = databoard.VARIANT;
884 MUTABLE_VARIANT = new MutableVariantBinding( classBindingFactory, adapterFactory );
885 STR_VARIANT = databoard.STR_VARIANT;
886 OBJECT = databoard.OBJECT;
888 databoard.initialize();
890 DATATYPE = getBindingUnchecked(Datatype.class);
892 * {@link Datatype} class has annotations but it can be considered a "class
893 * request" as it is a fundamental building block of Databoard and it has a
894 * fixed structure. Therefore {@link BindingRepository#classMap} is allowed
895 * to contain a cached Datatype.class -> Binding mapping.
897 bindingRepository.registerClassMapping(Datatype.class, DATATYPE);