]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/binding/mutable/MutableVariant.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / binding / mutable / MutableVariant.java
1 /*******************************************************************************\r
2  *  Copyright (c) 2010 Association for Decentralized Information Management in\r
3  *  Industry THTH ry.\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
8  *\r
9  *  Contributors:\r
10  *      VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.databoard.binding.mutable;
13
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
19 \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
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  *\r
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         \r
46         public static MutableVariant ofInstance(Object instance) {\r
47                 Binding binding = Bindings.getBindingUnchecked( instance.getClass() );\r
48                 return new MutableVariant(binding, instance);\r
49         }\r
50         \r
51         /**\r
52          * Constract a variant with a default value of empty record {}\r
53          */
54         public MutableVariant() {\r
55                 binding = VoidBinding.VOID_BINDING;\r
56                 value = null;\r
57         }\r
58         
59         public MutableVariant(Variant v) {\r
60 //              assert(isValid(binding, value));\r
61                 this.binding = v.getBinding();\r
62                 this.value = v.getValue();\r
63         }       \r
64         
65         public MutableVariant(Binding binding, Object value) {
66 //              assert(isValid(binding, value));
67                 this.binding = binding;
68                 this.value = value;
69         }
70         \r
71         /**\r
72          * Set value and binding from a variant. This method takes the references, \r
73          * and does not clone the value.\r
74          * \r
75          * @param v source variant\r
76          */
77         public void setValue(Variant v) {\r
78                 this.binding = v.getBinding();\r
79                 this.value = v.getValue();\r
80         }\r
81         
82         public void setValue(Binding binding, Object newValue) {
83 //              assert(isValid(binding, newValue));
84                 this.binding = binding;
85                 this.value = newValue;
86         }\r
87         \r
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
92                         return;\r
93                 }\r
94                                 \r
95                 if (this.binding == binding) {\r
96                         binding.readFrom(binding, newValue, this.value);\r
97                 } else {\r
98                         try {\r
99                                 this.value = binding.clone( newValue );\r
100                                 this.binding = binding;\r
101                         } catch (AdaptException e) {\r
102                                 throw new BindingException( e );\r
103                         }\r
104                 }\r
105         }
106 \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
111         }\r
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 {\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
137         }\r
138         \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
142         }\r
143         else {\r
144             JavaObject jo = (JavaObject) Accessors.getAccessor(this, ref);\r
145             jo.setValue( ref, binding, value );\r
146         }\r
147         }\r
148 }