]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/accessor/binary/BinaryString.java
Fixing several binding-related bugs
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / accessor / binary / BinaryString.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.accessor.binary;
13
14 import java.io.IOException;
15
16 import org.simantics.databoard.Bindings;
17 import org.simantics.databoard.accessor.Accessor;
18 import org.simantics.databoard.accessor.StringAccessor;
19 import org.simantics.databoard.accessor.error.AccessorConstructionException;
20 import org.simantics.databoard.accessor.error.AccessorException;
21 import org.simantics.databoard.accessor.error.ReferenceException;
22 import org.simantics.databoard.accessor.event.Event;
23 import org.simantics.databoard.accessor.event.ValueAssigned;
24 import org.simantics.databoard.accessor.file.FileStringAccessor;
25 import org.simantics.databoard.accessor.impl.AccessorParams;
26 import org.simantics.databoard.accessor.impl.ListenerEntry;
27 import org.simantics.databoard.accessor.interestset.StringInterestSet;
28 import org.simantics.databoard.accessor.reference.ChildReference;
29 import org.simantics.databoard.binding.Binding;
30 import org.simantics.databoard.binding.StringBinding;
31 import org.simantics.databoard.binding.error.BindingException;
32 import org.simantics.databoard.type.StringType;
33 import org.simantics.databoard.util.binary.Blob;
34 import org.simantics.databoard.util.binary.Endian;
35 import org.simantics.databoard.util.binary.UTF8;
36
37 public class BinaryString extends BinaryObject implements StringAccessor, FileStringAccessor {
38
39         public BinaryString(BinaryObject parent, Blob blob, StringType type, AccessorParams params) 
40         throws AccessorConstructionException {
41                 super(parent, blob, type, params);
42         }
43
44         @Override
45         public StringType type() {
46                 return (StringType) type;
47         }
48
49         @Override
50         Event applyLocal(Event e, boolean makeRollback) throws AccessorException {
51                 Event rollback = makeRollback ? new ValueAssigned( Bindings.STRING, getValue() ) : null;                
52                 if (e instanceof ValueAssigned) {
53                         ValueAssigned va = (ValueAssigned) e;
54                         if (va.newValue == null) throw new AccessorException("String value expected, got null");                        
55                         setValueNoflush(va.newValue.getBinding(), va.newValue.getValue());
56                         return rollback;
57                 } else {
58                         throw new AccessorException("Cannot apply "+e.getClass().getName()+" to String");
59                 }
60         }
61
62         @SuppressWarnings("unchecked")
63         @Override
64         public <T extends Accessor> T getComponent(ChildReference reference)
65                         throws AccessorConstructionException {
66                 if (reference==null) return (T) this;           
67                 throw new ReferenceException(reference.getClass()+" is not a subreference of StringType");      
68         }
69         
70         @Override
71         public Object getValue(Binding binding) throws AccessorException {
72                 try {
73                         StringBinding bb = (StringBinding) binding; 
74                         String v = getValue();
75                         return bb.create(v);
76                 } catch(BindingException e) {           
77                         throw new AccessorException(e);
78                 }
79         }
80 // MODIFIED UTF-8       
81         @Override
82         public String getValue() throws AccessorException {
83                 assert b.isOpen();
84                 readLock();
85                 try {
86                         b.position(0L);         
87                         
88                         int utflen = Endian.readDynamicUInt32(b);
89                         return UTF8.readModifiedUTF(b, utflen);
90                 } catch (IOException e) {
91                         throw new AccessorException(e);
92                 } finally {
93                         readUnlock();
94                 }
95         }
96         
97         public void setValueNoflush(String string) throws AccessorException {
98                 assert b.isOpen();
99                 writeLock();
100                 try {
101                         // Write
102                         b.position(0);
103                         int strlen = UTF8.getModifiedUTF8EncodingByteLength(string);
104                         int lenlen = Endian.getDynamicUInt32Length(strlen);
105                         b.setLength(strlen+lenlen);
106                         Endian.writeDynamicUInt32(b, strlen);
107                         UTF8.writeModifiedUTF(b, string);
108                         
109                         // Notify
110                         ListenerEntry le = listeners;
111                         while (le!=null) {
112                                 StringInterestSet is = le.getInterestSet();
113                                 if (is.inNotifications()) {                                     
114                                         Event e = new ValueAssigned( Bindings.STRING, is.inValues() ? string : null );
115                                         emitEvent(le, e);
116                                 }
117                                 le = le.next;
118                         }
119                         
120                 } catch (IOException e) {
121                         throw new AccessorException(e);
122                 } finally {
123                         writeUnlock();
124                 }
125         }
126         
127 /* REAL UTF-8
128         @Override
129         public String getValue() throws AccessorException {
130                 readLock();
131                 try {
132                         b.position(0L);
133                         int length = UTF8StringSerializer.getLength(b); 
134                         byte[] bytes = new byte[length];
135                         b.readFully(bytes);
136                         return new String(bytes, UTF8StringSerializer.UTF8);
137                 } catch (IOException e) {
138                         throw new AccessorException(e);
139                 } finally {
140                         readUnlock();
141                 }
142         }
143         
144         public void setValueNoflush(String string) throws AccessorException {
145                 writeLock();
146                 try {
147                         // Write
148                         int stringByteLength = UTF8StringSerializer.getUTF8EncodingByteLength( string ); 
149                         int lengthLength = UTF8StringSerializer.getSizeOfPutLength( stringByteLength );
150                         int len = stringByteLength + lengthLength; 
151                         
152                         b.position(0);
153                         b.setLength(len);
154                         byte[] bytes = string.getBytes( UTF8StringSerializer.UTF8 );
155                         UTF8StringSerializer.putLength(b, bytes.length);
156                         b.put(bytes);                   
157                         
158                         // Notify
159                         ListenerEntry le = listeners;
160                         while (le!=null) {
161                                 StringInterestSet is = le.getInterestSet();
162                                 if (is.inNotifications()) {                                     
163                                         Event e = new ValueAssigned( Bindings.STRING, is.inValues() ? string : null );
164                                         emitEvent(le, e);
165                                 }
166                                 le = le.next;
167                         }
168                         
169                 } catch (IOException e) {
170                         throw new AccessorException(e);
171                 } finally {
172                         writeUnlock();
173                 }
174         }
175 */      
176         @Override
177         public void setValue(String string) throws AccessorException {
178                 assert b.isOpen();
179                 writeLock();
180                 try {
181                         setValueNoflush(string);
182                         b.flush();
183                 } catch (IOException e) {
184                         throw new AccessorException(e);
185                 } finally {
186                         writeUnlock();
187                 }
188         }
189         
190         @Override
191         public void setValueNoflush(Binding binding, Object newValue)
192                         throws AccessorException {
193                 try {
194                         String nv = ((StringBinding)binding).getValue(newValue);
195                         setValueNoflush(nv);
196                 } catch (BindingException e) {
197                         throw new AccessorException(e);
198                 }
199         }
200         
201 }
202