1 /*******************************************************************************
\r
2 * Copyright (c) 2010 Association for Decentralized Information Management in
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.databoard.binding.mutable;
14 import java.io.IOException;
\r
15 import java.io.InputStream;
\r
16 import java.io.InvalidObjectException;
\r
17 import java.io.ObjectStreamException;
\r
18 import java.io.Serializable;
\r
20 import org.simantics.databoard.Accessors;
\r
21 import org.simantics.databoard.Bindings;
\r
22 import org.simantics.databoard.accessor.error.AccessorConstructionException;
\r
23 import org.simantics.databoard.accessor.error.AccessorException;
\r
24 import org.simantics.databoard.accessor.java.JavaObject;
\r
25 import org.simantics.databoard.accessor.reference.ChildReference;
\r
26 import org.simantics.databoard.adapter.AdaptException;
\r
27 import org.simantics.databoard.binding.Binding;
\r
28 import org.simantics.databoard.binding.error.BindingException;
\r
29 import org.simantics.databoard.binding.reflection.VoidBinding;
\r
30 import org.simantics.databoard.type.Datatype;
\r
33 * MutableVariant is a container to a data value of any type.
34 * The value and type can be changed.
36 * MutableVariant is hash-equals-comparable, even variants of bindings (and types).
37 * The hash function and comparison rules are defined in the manual.
39 * @see MutableVariantBinding is binding for Variant-class
40 * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
42 public class MutableVariant extends Variant implements Serializable, Cloneable {
44 private static final long serialVersionUID = 1L;
46 public static MutableVariant ofInstance(Object instance) {
\r
47 Binding binding = Bindings.getBindingUnchecked( instance.getClass() );
\r
48 return new MutableVariant(binding, instance);
\r
52 * Constract a variant with a default value of empty record {}
\r
54 public MutableVariant() {
\r
55 binding = VoidBinding.VOID_BINDING;
\r
59 public MutableVariant(Variant v) {
\r
60 // assert(isValid(binding, value));
\r
61 this.binding = v.getBinding();
\r
62 this.value = v.getValue();
\r
65 public MutableVariant(Binding binding, Object value) {
66 // assert(isValid(binding, value));
67 this.binding = binding;
72 * Set value and binding from a variant. This method takes the references,
\r
73 * and does not clone the value.
\r
75 * @param v source variant
\r
77 public void setValue(Variant v) {
\r
78 this.binding = v.getBinding();
\r
79 this.value = v.getValue();
\r
82 public void setValue(Binding binding, Object newValue) {
83 // assert(isValid(binding, newValue));
84 this.binding = binding;
85 this.value = newValue;
88 public void readFrom(Binding binding, Object newValue) throws BindingException {
\r
89 if (binding.isImmutable()) {
\r
90 this.binding = binding;
\r
91 this.value = newValue;
\r
95 if (this.binding == binding) {
\r
96 binding.readFrom(binding, newValue, this.value);
\r
99 this.value = binding.clone( newValue );
\r
100 this.binding = binding;
\r
101 } catch (AdaptException e) {
\r
102 throw new BindingException( e );
\r
107 public MutableVariant clone() {
\r
108 if (binding.isImmutable()) return new MutableVariant(binding, value);
\r
109 Object newValue = Bindings.cloneUnchecked(value, binding, binding);
\r
110 return new MutableVariant(binding, newValue);
\r
113 private void writeObject(java.io.ObjectOutputStream out) throws IOException {
114 Binding dataTypeBinding = Bindings.getBindingUnchecked( Datatype.class );
115 Bindings.getSerializerUnchecked( dataTypeBinding ).serialize(type());
116 Bindings.getSerializerUnchecked( binding ).serialize(value, out);
119 private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
120 Binding dataTypeBinding = Bindings.getBindingUnchecked( Datatype.class );
121 Datatype type = (Datatype) Bindings.getSerializerUnchecked( dataTypeBinding ).deserialize((InputStream)in);
122 Binding binding = Bindings.getMutableBinding(type);
123 Object value = Bindings.getSerializerUnchecked( binding ).deserialize((InputStream)in);
124 this.binding = binding;
128 @SuppressWarnings("unused")
129 private void readObjectNoData() throws ObjectStreamException {
130 throw new InvalidObjectException("Don't know how to instantiate "+type()+" with no data");
133 public MutableVariant getComponent(ChildReference ref) throws AccessorConstructionException {
\r
134 if ( ref == null ) return this;
\r
135 JavaObject jo = (JavaObject) Accessors.getAccessor(this, ref);
\r
136 return new MutableVariant( jo.getBinding(), jo.getObject() );
\r
139 public void setComponent(ChildReference ref, Binding binding, Object value) throws AccessorException, AccessorConstructionException {
\r
140 if ( ref == null ) {
\r
141 setValue( binding, value );
\r
144 JavaObject jo = (JavaObject) Accessors.getAccessor(this, ref);
\r
145 jo.setValue( ref, binding, value );
\r