]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.history/src/org/simantics/history/util/ValueBand.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.history / src / org / simantics / history / util / ValueBand.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2011 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.history.util;
13
14 import org.simantics.databoard.Bindings;
15 import org.simantics.databoard.adapter.AdaptException;
16 import org.simantics.databoard.adapter.Adapter;
17 import org.simantics.databoard.adapter.AdapterConstructionException;
18 import org.simantics.databoard.binding.Binding;
19 import org.simantics.databoard.binding.BooleanBinding;
20 import org.simantics.databoard.binding.ByteBinding;
21 import org.simantics.databoard.binding.DoubleBinding;
22 import org.simantics.databoard.binding.FloatBinding;
23 import org.simantics.databoard.binding.NumberBinding;
24 import org.simantics.databoard.binding.RecordBinding;
25 import org.simantics.databoard.binding.error.BindingException;
26 import org.simantics.databoard.binding.error.RuntimeBindingException;
27 import org.simantics.databoard.type.RecordType;
28 import org.simantics.history.HistoryException;
29
30 /**
31  * Value band is an utility class intended for reading and writing to samples.
32  * There are many different formats of samples, their fields, order and datatypes vary.
33  *
34  * @author toni.kalajainen
35  */
36 public class ValueBand {
37         
38         public static final Byte QUALITY_GOOD = Byte.valueOf( (byte) 0 ); 
39         public static final Byte QUALITY_NOVALUE = Byte.valueOf( (byte) -1 ); 
40         
41         protected RecordBinding binding;
42         protected RecordType type;
43         protected Object sample;
44         
45         /** Field value cloners */
46         FieldAdapter timeField, endTimeField, valueField, lastValueField, avgField, medianField, minField, maxField, countField, qualityField;
47         /** Default value*/
48         Object defaultValue;
49         
50         public ValueBand(Binding sampleBinding)
51         {
52                 if ( sampleBinding instanceof RecordBinding == false ) {
53                         throw new IllegalArgumentException();
54                 }
55                 
56                 this.binding = (RecordBinding) sampleBinding;           
57                 type = this.binding.type();
58                 
59                 timeField = new FieldAdapter("time");
60                 endTimeField = new FieldAdapter("endTime");
61                 valueField = new FieldAdapter("value");
62                 lastValueField = new FieldAdapter("lastValue");
63                 avgField = new FieldAdapter("avg");
64                 medianField = new FieldAdapter("median");
65                 minField = new FieldAdapter("min");
66                 maxField = new FieldAdapter("max");
67                 countField = new FieldAdapter("count");
68                 qualityField = new FieldAdapter("quality");
69                                 
70                 try {
71                         defaultValue = binding.createDefault();
72                 } catch (BindingException e) {
73                         throw new RuntimeBindingException( e );
74                 }
75         }
76         
77         public ValueBand(Binding sampleBinding, Object sample)
78         {
79                 this( sampleBinding );
80                 this.sample = sample;
81         }
82         
83         
84         public void reset()
85         {
86                 try {
87                         binding.readFrom(binding, defaultValue, sample);
88                 } catch (BindingException e) {
89                         throw new RuntimeBindingException( e );
90                 }
91         }
92         
93         public Binding getBinding()
94         {
95                 return binding;
96         }
97
98         /**
99          * Get the internal sample instance
100          * 
101          * @return the internal sample instance
102          */
103         public Object getSample() {
104                 return sample;
105         }
106
107         /**
108          * Change the internal sample instance
109          * 
110          * @param sample
111          */
112         public void setSample(Object sample) {
113                 this.sample = sample;
114         }
115
116         /**
117          * Write to the internal sample instance 
118          * 
119          * @param sample
120          */
121         public void writeSample(Object sample) {
122                 try {
123                         binding.readFrom(binding, sample, this.sample);
124                 } catch (BindingException e) {
125                         throw new RuntimeBindingException(e);
126                 }
127         }
128         
129         /**
130          * Write to the internal sample instance 
131          * 
132          * @param binding
133          * @param sample
134          */
135         public void writeSample(Binding binding, Object sample) {
136                 try {
137                         binding.readFrom(binding, sample, this.sample);
138                 } catch (BindingException e) {
139                         throw new RuntimeBindingException(e);
140                 }
141         }
142                 
143         
144         /// Time ///
145         public boolean hasTime() {
146                 return timeField.isEnabled();
147         }
148         
149         public Binding getTimeBinding() {
150                 return timeField.binding;
151         }
152         
153         public Object getTime() throws HistoryException {
154                 return timeField.getValue();
155         }
156
157         public Object getTime(Binding b) throws HistoryException {
158                 return timeField.getValue(b);
159         }
160         
161         public double getTimeDouble() throws HistoryException {
162                 return timeField.getDoubleValue();
163         }
164         
165         public void setTime(Object v) throws HistoryException {
166                 timeField.setValue(v);
167         }
168         
169         public void setTime(Binding binding, Object v) throws HistoryException
170         {
171                 timeField.setValue(binding, v);
172         }
173
174         /// EndTime ///
175         public boolean hasEndTime() {
176                 return endTimeField.isEnabled();
177         }
178         
179         public Binding getEndTimeBinding() {
180                 return endTimeField.binding;
181         }
182         
183         public Object getEndTime() throws HistoryException {
184                 return endTimeField.getValue();
185         }
186
187         public Object getEndTime(Binding b) throws HistoryException {
188                 return endTimeField.getValue(b);
189         }
190         
191         public double getEndTimeDouble() throws HistoryException {
192                 return endTimeField.getDoubleValue();
193         }
194         
195         
196         public void setEndTime(Object v) throws HistoryException {
197                 endTimeField.setValue(v);
198         }
199
200         public void setEndTime(Binding binding, Object v) throws HistoryException
201         {
202                 endTimeField.setValue(binding, v);
203         }
204         
205         /// Value ///
206         public boolean hasValue() {
207                 return valueField.isEnabled();
208         }
209         
210         public Binding getValueBinding() {
211                 return valueField.binding;
212         }
213         
214         public Object getValue() throws HistoryException {
215                 return valueField.getValue();
216         }
217
218         public Object getValue(Binding b) throws HistoryException {
219                 return valueField.getValue(b);
220         }
221
222         public double getValueDouble() throws HistoryException {
223                 return valueField.getDoubleValue();
224         }
225         
226         public Object getPossibleValue() throws HistoryException {
227                 if ( isNullValue() ) return null;
228                 return valueField.getValue();
229         }
230
231         public Object getPossibleValue(Binding b) throws HistoryException {
232                 if ( isNullValue() ) return null;
233                 return valueField.getValue(b);
234         }
235
236         public Double getPossibleValueDouble() throws HistoryException {
237                 if ( isNullValue() ) return null;
238                 return valueField.getDoubleValue();
239         }
240         
241         
242         public boolean getValueBoolean() throws HistoryException {
243                 return valueField.getBooleanValue();
244         }
245         
246         public void setValue(Object v) throws HistoryException {
247                 valueField.setValue(v);
248         }
249
250         public void setValue(Binding binding, Object v) throws HistoryException
251         {
252                 valueField.setValue(binding, v);
253         }
254         
255         /// LastValue ///
256         public boolean hasLastValue() {
257                 return lastValueField.isEnabled();
258         }
259         
260         public Binding getLastValueBinding() {
261                 return lastValueField.binding;
262         }
263         
264         public Object getLastValue() throws HistoryException {
265                 return lastValueField.getValue();
266         }
267
268         public Object getLastValue(Binding b) throws HistoryException {
269                 return lastValueField.getValue(b);
270         }
271
272         public void setLastValue(Object v) throws HistoryException {
273                 lastValueField.setValue(v);
274         }
275         
276         public void setLastValue(Binding binding, Object v) throws HistoryException {
277                 lastValueField.setValue(binding, v);
278         }
279         
280         /// Avg ///
281         public boolean hasAvg() {
282                 return avgField.isEnabled();
283         }
284         
285         public Binding getAvgBinding() {
286                 return avgField.binding;
287         }
288         
289         public Object getAvg() throws HistoryException {
290                 return avgField.getValue();
291         }
292
293         public Object getAvg(Binding b) throws HistoryException {
294                 return avgField.getValue(b);
295         }
296         
297         public double getAvgDouble() throws HistoryException {
298                 return avgField.getDoubleValue();
299         }       
300         
301         public void setAvg(Object v) throws HistoryException {
302                 avgField.setValue(v);
303         }
304
305         public void setAvg(Binding binding, Object v) throws HistoryException
306         {
307                 avgField.setValue(binding, v);
308         }
309         
310         /// Median ///
311         public boolean hasMedian() {
312                 return medianField.isEnabled();
313         }
314         
315         public Binding getMedianBinding() {
316                 return medianField.binding;
317         }
318         
319         public Object getMedian() throws HistoryException {
320                 return medianField.getValue();
321         }
322
323         public Object getMedian(Binding b) throws HistoryException {
324                 return medianField.getValue(b);
325         }
326         
327         public double getMedianDouble() throws HistoryException {
328                 return medianField.getDoubleValue();
329         }
330         
331         public void setMedian(Object v) throws HistoryException {
332                 medianField.setValue(v);
333         }
334
335         public void setMedian(Binding binding, Object v) throws HistoryException
336         {
337                 medianField.setValue(binding, v);
338         }
339         
340         /// Min ///
341         public boolean hasMin() {
342                 return minField.isEnabled();
343         }
344         
345         public Binding getMinBinding() {
346                 return minField.binding;
347         }
348         
349         public Object getMin() throws HistoryException {
350                 return minField.getValue();
351         }
352
353         public Object getMin(Binding b) throws HistoryException {
354                 return minField.getValue(b);
355         }
356         
357         public double getMinDouble() throws HistoryException {
358                 return minField.getDoubleValue();
359         }
360         
361         public void setMin(Object v) throws HistoryException {
362                 minField.setValue(v);
363         }       
364
365         public void setMin(Binding binding, Object v) throws HistoryException
366         {
367                 minField.setValue(binding, v);
368         }
369         
370         /// Max ///
371         public boolean hasMax() {
372                 return maxField.isEnabled();
373         }
374         
375         public Binding getMaxBinding() {
376                 return maxField.binding;
377         }
378         
379         public Object getMax() throws HistoryException {
380                 return maxField.getValue();
381         }
382
383         public Object getMax(Binding b) throws HistoryException {
384                 return maxField.getValue(b);
385         }
386         
387         public double getMaxDouble() throws HistoryException {
388                 return maxField.getDoubleValue();
389         }
390         
391         public void setMax(Object v) throws HistoryException {
392                 maxField.setValue(v);
393         }       
394         
395         public void setMax(Binding binding, Object v) throws HistoryException
396         {
397                 maxField.setValue(binding, v);
398         }
399         
400         
401         /// Count ///
402         public boolean hasCount() {
403                 return countField.isEnabled();
404         }
405         
406         public NumberBinding getCountBinding() {
407                 return (NumberBinding) countField.binding;
408         }
409         
410         public int getCount() throws HistoryException {
411                 Integer i = (Integer) countField.getValue( Bindings.INTEGER );
412                 return i == null ? 0 : i;
413         }
414
415         public Object getCount(Binding b) throws HistoryException {
416                 return countField.getValue(b);
417         }
418         
419         public void setCount(int v) throws HistoryException {
420                 countField.setValue(Bindings.INTEGER, v);
421         }       
422
423         /// Quality ///
424         public boolean hasQuality() {
425                 return qualityField.isEnabled();
426         }
427         
428         public Binding getQualityBinding() {
429                 return qualityField.binding;
430         }
431         
432         public Object getQuality() throws HistoryException {
433                 return qualityField.getValue();
434         }
435
436         public Object getQuality(Binding b) throws HistoryException {
437                 return qualityField.getValue(b);
438         }
439         
440         public void setQuality(Object v) throws HistoryException {
441                 qualityField.setValue(v);
442         }       
443
444         public void setQuality(Binding binding, Object v) throws HistoryException
445         {
446                 qualityField.setValue(binding, v);
447         }
448         
449         
450         /**
451          * Value band is a region of one or more samples.
452          * This method returns true, if value band is expressed with a single sample.
453          * 
454          * If value band is expressed with two samples, there is start and end
455          * sample. The format is typicaly simple (time, value).  
456          * 
457          * @return true if it can represent more than one sample
458          */
459         public boolean isRanged()
460         {
461                 return endTimeField.isEnabled();
462         }
463         
464         public boolean isValidValue() throws HistoryException {
465                 return !isNanSample() && !isNullValue();
466         }
467
468         /**
469          * Return true, if this sample 
470          * 
471          * @return true if the value is Not-a-number
472          */
473         public boolean isNanSample() {
474                 try {
475                         if (valueField.binding instanceof DoubleBinding) {
476                                 DoubleBinding db = (DoubleBinding) valueField.binding;
477                                 double d = db.getValue_( binding.getComponent(sample, valueField.index) );
478                                 return Double.isNaN( d );
479                         }
480                         if (valueField.binding instanceof FloatBinding) {
481                                 FloatBinding db = (FloatBinding) valueField.binding;
482                                 float d = db.getValue_( binding.getComponent(sample, valueField.index) );
483                                 return Float.isNaN( d );
484                         }
485                         return false;
486                 } catch (BindingException e) {
487                         return false;
488                 }
489         }
490         
491         /**
492          * Returns true, if this sample format supports a way to express 
493          * discontinuation regions. 
494          * 
495          * @return true if can support discontinuation
496          */
497         public boolean supportsNullValue() {
498                 return qualityField.isEnabled();
499         }
500         
501         /**
502          * Marks this sample as discontinuation sample
503          * @throws HistoryException 
504          */
505         public void setValueNull() throws HistoryException {
506                 qualityField.setValue(Bindings.BYTE, QUALITY_NOVALUE);
507         }
508         
509         /**
510          * Returns true, if the sample is discontinuation sample
511          * 
512          * @return true, if the sample is discontinuation sample
513          * @throws HistoryException 
514          */
515         public boolean isNullValue() throws HistoryException {
516                 Byte b = (Byte) qualityField.getValue(Bindings.BYTE);
517                 return b == null ? false : b.equals( QUALITY_NOVALUE );
518         }
519         
520         public boolean isNumericValue() {
521                 return valueField.isNumeric();
522         }
523         
524         @Override
525         public String toString() {
526                 try {
527                         return binding.toString(sample);
528                 } catch (BindingException e) {
529                         return e.toString();
530                 }
531         }
532         
533         class FieldAdapter {
534                 /** Binding of the field, with possible optionalbinding stripped */
535                 Binding binding;
536                 
537                 /// Adapter1 is cached adapter for setValue  
538                 Binding adapter1binding;
539                 Adapter adapter1;
540                 
541                 /// Adapter2 is cached adapter for getValue
542                 Binding adapter2binding;
543                 Adapter adapter2;
544                 
545                 /** Field index in sample record */
546                 int index;
547                 
548                 /** Field name */
549                 String fieldName;
550                 
551                 public FieldAdapter(String fieldName) {
552                         this.fieldName = fieldName;
553                         index = ValueBand.this.binding.type().getComponentIndex2( fieldName );
554                         if (index<0) return;
555                         
556                         this.binding = ValueBand.this.binding.getComponentBinding(index);
557                 }
558                 
559                 public boolean getBooleanValue() throws HistoryException {
560                         if (sample == null || index==-1) return false;
561                         try {
562                                 Object value = ValueBand.this.binding.getComponent(sample, index);
563                                 if (binding instanceof BooleanBinding) {
564                                         return ValueBand.this.binding.getBoolean(sample, index);
565 //                                      BooleanBinding bb = (BooleanBinding) binding;
566 //                                      return bb.getValue_( value );
567                                 }
568                                 if (binding instanceof ByteBinding) {
569                                         ByteBinding nb = (ByteBinding) binding;
570                                         return nb.getValue_( value ) != 0;
571                                 }
572                                 if (binding instanceof DoubleBinding) {
573                                         DoubleBinding nb = (DoubleBinding) binding;
574                                         return nb.getValue_( value ) != 0.;
575                                 }
576                                 if (binding instanceof NumberBinding) {
577                                         NumberBinding nb = (NumberBinding) binding;
578                                         return nb.getValue( value ).doubleValue() != 0.;
579                                 }
580                                 return false;
581                         } catch (BindingException e) {
582                                 throw new HistoryException( e );
583                         }                       
584                 }
585
586                 public double getDoubleValue() throws HistoryException {
587                         if (sample == null || index==-1) return Double.NaN;
588                         try {
589                                 // Read field from record
590                                 if (binding != Bindings.DOUBLE) {
591                                         Object result = ValueBand.this.binding.getComponent(sample, index);
592                                         result = Bindings.adapt(result, binding, Bindings.DOUBLE);
593                                         return (Double) result;
594                                 } else {
595                                         return ValueBand.this.binding.getDouble(sample, index);
596                                 }
597                         } catch (BindingException e) {
598                                 throw new HistoryException( e );
599                         } catch (AdaptException e) {
600                                 throw new HistoryException( e );
601                         }                       
602                 }
603
604                 public boolean isEnabled() {
605                         return index>=0;
606                 }
607                 
608                 /**
609                  * Get the value
610                  *  
611                  * @return value or null, if value is not available
612                  * @throws HistoryException
613                  */
614                 public Object getValue() throws HistoryException {
615                         if (sample == null || index==-1) return null;
616                         try {
617                                 // Read field from record
618                                 Object result = ValueBand.this.binding.getComponent(sample, index);
619
620                                 return result;
621                         } catch (BindingException e) {
622                                 throw new HistoryException( e );
623                         }
624                 }
625
626                 /**
627                  * Get the value
628                  * @param binding
629                  * @return value in given binding or null, if value is not available
630                  * @throws HistoryException
631                  */
632                 public Object getValue(Binding binding) throws HistoryException {
633                         if (sample == null || index==-1) return null;
634                         try {
635                                 // Read field from record
636                                 Object result = ValueBand.this.binding.getComponent(sample, index);
637                                 
638                                 // Adapt value
639                                 if ( binding != this.binding ) {
640                                         if ( binding != adapter2binding ) {
641                                                 adapter2 = Bindings.adapterFactory.getAdapter(this.binding, binding, true, false);
642                                                 adapter2binding = binding;
643                                         }
644                                         result = adapter2.adapt( result );
645                                 }
646
647                                 return result;
648                         } catch (BindingException e) {
649                                 throw new HistoryException( e );
650                         } catch (AdaptException e) {
651                                 throw new HistoryException( e );
652                         } catch (AdapterConstructionException e) {
653                                 throw new HistoryException( e );
654                         }
655                 }
656                 
657                 public void setValue(Object object) throws HistoryException {
658                         if (sample == null || index==-1) return;
659                         setValue(binding, object);
660                 }               
661                                         
662                 public void setValue(Binding binding, Object object) throws HistoryException {
663                         if (sample == null || index==-1) return;
664                         
665                         try {
666                                 // Adapt value                  
667                                 if (this.binding != binding) {                                  
668                                         // Create new adapter
669                                         if (binding != adapter1binding) {
670                                                 adapter1 = Bindings.adapterFactory.getAdapter(binding, this.binding, true, !binding.isImmutable());     
671                                                 adapter1binding = binding;
672                                         }
673                                         
674                                         // Adapt
675                                         object = adapter1.adapt(object);        
676                                 }
677                         
678                                 // Write value
679                                 ValueBand.this.binding.setComponent(sample, index, object);
680                                 
681                         } catch (AdaptException e) {
682                                 throw new HistoryException( e ); 
683                         } catch (BindingException e) {
684                                 throw new HistoryException( e ); 
685                         } catch (AdapterConstructionException e) {
686                                 throw new HistoryException( e ); 
687                         }
688                 }               
689         
690                 public boolean isNumeric() {
691                         return binding instanceof NumberBinding;
692                 }       
693         
694         }
695         
696 }