]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/binding/mutable/MutableVariant.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / binding / mutable / MutableVariant.java
1 /*******************************************************************************
2  *  Copyright (c) 2010 Association for Decentralized Information Management in
3  *  Industry THTH ry.
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
8  *
9  *  Contributors:
10  *      VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.databoard.binding.mutable;
13
14 import java.io.IOException;
15 import java.io.InputStream;
16 import java.io.InvalidObjectException;
17 import java.io.ObjectStreamException;
18 import java.io.Serializable;
19
20 import org.simantics.databoard.Accessors;
21 import org.simantics.databoard.Bindings;
22 import org.simantics.databoard.accessor.error.AccessorConstructionException;
23 import org.simantics.databoard.accessor.error.AccessorException;
24 import org.simantics.databoard.accessor.java.JavaObject;
25 import org.simantics.databoard.accessor.reference.ChildReference;
26 import org.simantics.databoard.adapter.AdaptException;
27 import org.simantics.databoard.binding.Binding;
28 import org.simantics.databoard.binding.error.BindingException;
29 import org.simantics.databoard.binding.reflection.VoidBinding;
30 import org.simantics.databoard.type.Datatype;
31
32 /**
33  * MutableVariant is a container to a data value of any type. 
34  * The value and type can be changed. 
35  *
36  * MutableVariant is hash-equals-comparable, even variants of bindings (and types). 
37  * The hash function and comparison rules are defined in the manual.   
38  *
39  * @see MutableVariantBinding is binding for Variant-class
40  * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
41  */
42 public class MutableVariant extends Variant implements Serializable, Cloneable {
43         
44         private static final long serialVersionUID = 1L;
45         
46         public static MutableVariant ofInstance(Object instance) {
47                 Binding binding = Bindings.getBindingUnchecked( instance.getClass() );
48                 return new MutableVariant(binding, instance);
49         }
50         
51         /**
52          * Constract a variant with a default value of empty record {}
53          */
54         public MutableVariant() {
55                 binding = VoidBinding.VOID_BINDING;
56                 value = null;
57         }
58         
59         public MutableVariant(Variant v) {
60 //              assert(isValid(binding, value));
61                 this.binding = v.getBinding();
62                 this.value = v.getValue();
63         }       
64         
65         public MutableVariant(Binding binding, Object value) {
66 //              assert(isValid(binding, value));
67                 this.binding = binding;
68                 this.value = value;
69         }
70         
71         /**
72          * Set value and binding from a variant. This method takes the references, 
73          * and does not clone the value.
74          * 
75          * @param v source variant
76          */
77         public void setValue(Variant v) {
78                 this.binding = v.getBinding();
79                 this.value = v.getValue();
80         }
81         
82         public void setValue(Binding binding, Object newValue) {
83 //              assert(isValid(binding, newValue));
84                 this.binding = binding;
85                 this.value = newValue;
86         }
87         
88         public void readFrom(Binding binding, Object newValue) throws BindingException {
89                 if (binding.isImmutable()) {
90                         this.binding = binding;
91                         this.value = newValue;
92                         return;
93                 }
94                                 
95                 if (this.binding == binding) {
96                         binding.readFrom(binding, newValue, this.value);
97                 } else {
98                         try {
99                                 this.value = binding.clone( newValue );
100                                 this.binding = binding;
101                         } catch (AdaptException e) {
102                                 throw new BindingException( e );
103                         }
104                 }
105         }
106
107         public MutableVariant clone() {
108                 if (binding.isImmutable()) return new MutableVariant(binding, value);
109                 Object newValue = Bindings.cloneUnchecked(value, binding, binding);
110                 return new MutableVariant(binding, newValue);
111         }
112         
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);
117         }
118         
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;
125                 this.value = value;
126         }
127         
128         @SuppressWarnings("unused")
129         private void readObjectNoData() throws ObjectStreamException {
130                 throw new InvalidObjectException("Don't know how to instantiate "+type()+" with no data");              
131         }
132         
133         public MutableVariant getComponent(ChildReference ref) throws AccessorConstructionException {
134                 if ( ref == null ) return this;
135                 JavaObject jo = (JavaObject) Accessors.getAccessor(this, ref);
136                 return new MutableVariant( jo.getBinding(), jo.getObject() );
137         }
138         
139         public void setComponent(ChildReference ref, Binding binding, Object value) throws AccessorException, AccessorConstructionException {
140         if ( ref == null ) {
141             setValue( binding, value );
142         }
143         else {
144             JavaObject jo = (JavaObject) Accessors.getAccessor(this, ref);
145             jo.setValue( ref, binding, value );
146         }
147         }
148 }