1 /*******************************************************************************
2 * Copyright (c) 2007, 2011 Association for Decentralized Information Management in
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
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.history.util;
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;
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.
34 * @author toni.kalajainen
36 public class ValueBand {
38 public static final Byte QUALITY_GOOD = Byte.valueOf( (byte) 0 );
39 public static final Byte QUALITY_NOVALUE = Byte.valueOf( (byte) -1 );
41 protected RecordBinding binding;
42 protected RecordType type;
43 protected Object sample;
45 /** Field value cloners */
46 FieldAdapter timeField, endTimeField, valueField, lastValueField, avgField, medianField, minField, maxField, countField, qualityField;
50 public ValueBand(Binding sampleBinding)
52 if ( sampleBinding instanceof RecordBinding == false ) {
53 throw new IllegalArgumentException();
56 this.binding = (RecordBinding) sampleBinding;
57 type = this.binding.type();
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");
71 defaultValue = binding.createDefault();
72 } catch (BindingException e) {
73 throw new RuntimeBindingException( e );
77 public ValueBand(Binding sampleBinding, Object sample)
79 this( sampleBinding );
87 binding.readFrom(binding, defaultValue, sample);
88 } catch (BindingException e) {
89 throw new RuntimeBindingException( e );
93 public Binding getBinding()
99 * Get the internal sample instance
101 * @return the internal sample instance
103 public Object getSample() {
108 * Change the internal sample instance
112 public void setSample(Object sample) {
113 this.sample = sample;
117 * Write to the internal sample instance
121 public void writeSample(Object sample) {
123 binding.readFrom(binding, sample, this.sample);
124 } catch (BindingException e) {
125 throw new RuntimeBindingException(e);
130 * Write to the internal sample instance
135 public void writeSample(Binding binding, Object sample) {
137 binding.readFrom(binding, sample, this.sample);
138 } catch (BindingException e) {
139 throw new RuntimeBindingException(e);
145 public boolean hasTime() {
146 return timeField.isEnabled();
149 public Binding getTimeBinding() {
150 return timeField.binding;
153 public Object getTime() throws HistoryException {
154 return timeField.getValue();
157 public Object getTime(Binding b) throws HistoryException {
158 return timeField.getValue(b);
161 public double getTimeDouble() throws HistoryException {
162 return timeField.getDoubleValue();
165 public void setTime(Object v) throws HistoryException {
166 timeField.setValue(v);
169 public void setTime(Binding binding, Object v) throws HistoryException
171 timeField.setValue(binding, v);
175 public boolean hasEndTime() {
176 return endTimeField.isEnabled();
179 public Binding getEndTimeBinding() {
180 return endTimeField.binding;
183 public Object getEndTime() throws HistoryException {
184 return endTimeField.getValue();
187 public Object getEndTime(Binding b) throws HistoryException {
188 return endTimeField.getValue(b);
191 public double getEndTimeDouble() throws HistoryException {
192 return endTimeField.getDoubleValue();
196 public void setEndTime(Object v) throws HistoryException {
197 endTimeField.setValue(v);
200 public void setEndTime(Binding binding, Object v) throws HistoryException
202 endTimeField.setValue(binding, v);
206 public boolean hasValue() {
207 return valueField.isEnabled();
210 public Binding getValueBinding() {
211 return valueField.binding;
214 public Object getValue() throws HistoryException {
215 return valueField.getValue();
218 public Object getValue(Binding b) throws HistoryException {
219 return valueField.getValue(b);
222 public double getValueDouble() throws HistoryException {
223 return valueField.getDoubleValue();
226 public Object getPossibleValue() throws HistoryException {
227 if ( isNullValue() ) return null;
228 return valueField.getValue();
231 public Object getPossibleValue(Binding b) throws HistoryException {
232 if ( isNullValue() ) return null;
233 return valueField.getValue(b);
236 public Double getPossibleValueDouble() throws HistoryException {
237 if ( isNullValue() ) return null;
238 return valueField.getDoubleValue();
242 public boolean getValueBoolean() throws HistoryException {
243 return valueField.getBooleanValue();
246 public void setValue(Object v) throws HistoryException {
247 valueField.setValue(v);
250 public void setValue(Binding binding, Object v) throws HistoryException
252 valueField.setValue(binding, v);
256 public boolean hasLastValue() {
257 return lastValueField.isEnabled();
260 public Binding getLastValueBinding() {
261 return lastValueField.binding;
264 public Object getLastValue() throws HistoryException {
265 return lastValueField.getValue();
268 public Object getLastValue(Binding b) throws HistoryException {
269 return lastValueField.getValue(b);
272 public void setLastValue(Object v) throws HistoryException {
273 lastValueField.setValue(v);
276 public void setLastValue(Binding binding, Object v) throws HistoryException {
277 lastValueField.setValue(binding, v);
281 public boolean hasAvg() {
282 return avgField.isEnabled();
285 public Binding getAvgBinding() {
286 return avgField.binding;
289 public Object getAvg() throws HistoryException {
290 return avgField.getValue();
293 public Object getAvg(Binding b) throws HistoryException {
294 return avgField.getValue(b);
297 public double getAvgDouble() throws HistoryException {
298 return avgField.getDoubleValue();
301 public void setAvg(Object v) throws HistoryException {
302 avgField.setValue(v);
305 public void setAvg(Binding binding, Object v) throws HistoryException
307 avgField.setValue(binding, v);
311 public boolean hasMedian() {
312 return medianField.isEnabled();
315 public Binding getMedianBinding() {
316 return medianField.binding;
319 public Object getMedian() throws HistoryException {
320 return medianField.getValue();
323 public Object getMedian(Binding b) throws HistoryException {
324 return medianField.getValue(b);
327 public double getMedianDouble() throws HistoryException {
328 return medianField.getDoubleValue();
331 public void setMedian(Object v) throws HistoryException {
332 medianField.setValue(v);
335 public void setMedian(Binding binding, Object v) throws HistoryException
337 medianField.setValue(binding, v);
341 public boolean hasMin() {
342 return minField.isEnabled();
345 public Binding getMinBinding() {
346 return minField.binding;
349 public Object getMin() throws HistoryException {
350 return minField.getValue();
353 public Object getMin(Binding b) throws HistoryException {
354 return minField.getValue(b);
357 public double getMinDouble() throws HistoryException {
358 return minField.getDoubleValue();
361 public void setMin(Object v) throws HistoryException {
362 minField.setValue(v);
365 public void setMin(Binding binding, Object v) throws HistoryException
367 minField.setValue(binding, v);
371 public boolean hasMax() {
372 return maxField.isEnabled();
375 public Binding getMaxBinding() {
376 return maxField.binding;
379 public Object getMax() throws HistoryException {
380 return maxField.getValue();
383 public Object getMax(Binding b) throws HistoryException {
384 return maxField.getValue(b);
387 public double getMaxDouble() throws HistoryException {
388 return maxField.getDoubleValue();
391 public void setMax(Object v) throws HistoryException {
392 maxField.setValue(v);
395 public void setMax(Binding binding, Object v) throws HistoryException
397 maxField.setValue(binding, v);
402 public boolean hasCount() {
403 return countField.isEnabled();
406 public NumberBinding getCountBinding() {
407 return (NumberBinding) countField.binding;
410 public int getCount() throws HistoryException {
411 Integer i = (Integer) countField.getValue( Bindings.INTEGER );
412 return i == null ? 0 : i;
415 public Object getCount(Binding b) throws HistoryException {
416 return countField.getValue(b);
419 public void setCount(int v) throws HistoryException {
420 countField.setValue(Bindings.INTEGER, v);
424 public boolean hasQuality() {
425 return qualityField.isEnabled();
428 public Binding getQualityBinding() {
429 return qualityField.binding;
432 public Object getQuality() throws HistoryException {
433 return qualityField.getValue();
436 public Object getQuality(Binding b) throws HistoryException {
437 return qualityField.getValue(b);
440 public void setQuality(Object v) throws HistoryException {
441 qualityField.setValue(v);
444 public void setQuality(Binding binding, Object v) throws HistoryException
446 qualityField.setValue(binding, v);
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.
454 * If value band is expressed with two samples, there is start and end
455 * sample. The format is typicaly simple (time, value).
457 * @return true if it can represent more than one sample
459 public boolean isRanged()
461 return endTimeField.isEnabled();
464 public boolean isValidValue() throws HistoryException {
465 return !isNanSample() && !isNullValue();
469 * Return true, if this sample
471 * @return true if the value is Not-a-number
473 public boolean isNanSample() {
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 );
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 );
486 } catch (BindingException e) {
492 * Returns true, if this sample format supports a way to express
493 * discontinuation regions.
495 * @return true if can support discontinuation
497 public boolean supportsNullValue() {
498 return qualityField.isEnabled();
502 * Marks this sample as discontinuation sample
503 * @throws HistoryException
505 public void setValueNull() throws HistoryException {
506 qualityField.setValue(Bindings.BYTE, QUALITY_NOVALUE);
510 * Returns true, if the sample is discontinuation sample
512 * @return true, if the sample is discontinuation sample
513 * @throws HistoryException
515 public boolean isNullValue() throws HistoryException {
516 Byte b = (Byte) qualityField.getValue(Bindings.BYTE);
517 return b == null ? false : b.equals( QUALITY_NOVALUE );
520 public boolean isNumericValue() {
521 return valueField.isNumeric();
525 public String toString() {
527 return binding.toString(sample);
528 } catch (BindingException e) {
534 /** Binding of the field, with possible optionalbinding stripped */
537 /// Adapter1 is cached adapter for setValue
538 Binding adapter1binding;
541 /// Adapter2 is cached adapter for getValue
542 Binding adapter2binding;
545 /** Field index in sample record */
551 public FieldAdapter(String fieldName) {
552 this.fieldName = fieldName;
553 index = ValueBand.this.binding.type().getComponentIndex2( fieldName );
556 this.binding = ValueBand.this.binding.getComponentBinding(index);
559 public boolean getBooleanValue() throws HistoryException {
560 if (sample == null || index==-1) return false;
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 );
568 if (binding instanceof ByteBinding) {
569 ByteBinding nb = (ByteBinding) binding;
570 return nb.getValue_( value ) != 0;
572 if (binding instanceof DoubleBinding) {
573 DoubleBinding nb = (DoubleBinding) binding;
574 return nb.getValue_( value ) != 0.;
576 if (binding instanceof NumberBinding) {
577 NumberBinding nb = (NumberBinding) binding;
578 return nb.getValue( value ).doubleValue() != 0.;
581 } catch (BindingException e) {
582 throw new HistoryException( e );
586 public double getDoubleValue() throws HistoryException {
587 if (sample == null || index==-1) return Double.NaN;
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;
595 return ValueBand.this.binding.getDouble(sample, index);
597 } catch (BindingException e) {
598 throw new HistoryException( e );
599 } catch (AdaptException e) {
600 throw new HistoryException( e );
604 public boolean isEnabled() {
611 * @return value or null, if value is not available
612 * @throws HistoryException
614 public Object getValue() throws HistoryException {
615 if (sample == null || index==-1) return null;
617 // Read field from record
618 Object result = ValueBand.this.binding.getComponent(sample, index);
621 } catch (BindingException e) {
622 throw new HistoryException( e );
629 * @return value in given binding or null, if value is not available
630 * @throws HistoryException
632 public Object getValue(Binding binding) throws HistoryException {
633 if (sample == null || index==-1) return null;
635 // Read field from record
636 Object result = ValueBand.this.binding.getComponent(sample, index);
639 if ( binding != this.binding ) {
640 if ( binding != adapter2binding ) {
641 adapter2 = Bindings.adapterFactory.getAdapter(this.binding, binding, true, false);
642 adapter2binding = binding;
644 result = adapter2.adapt( 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 );
657 public void setValue(Object object) throws HistoryException {
658 if (sample == null || index==-1) return;
659 setValue(binding, object);
662 public void setValue(Binding binding, Object object) throws HistoryException {
663 if (sample == null || index==-1) return;
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;
675 object = adapter1.adapt(object);
679 ValueBand.this.binding.setComponent(sample, index, object);
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 );
690 public boolean isNumeric() {
691 return binding instanceof NumberBinding;