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.subscription;
14 import java.util.Arrays;
15 import java.util.Comparator;
17 import org.simantics.databoard.Bindings;
18 import org.simantics.databoard.Datatypes;
19 import org.simantics.databoard.adapter.AdaptException;
20 import org.simantics.databoard.type.ArrayType;
21 import org.simantics.databoard.type.Component;
22 import org.simantics.databoard.type.Datatype;
23 import org.simantics.databoard.type.NumberType;
24 import org.simantics.databoard.type.RecordType;
25 import org.simantics.databoard.util.Bean;
26 import org.simantics.databoard.util.Limit;
27 import org.simantics.databoard.util.Range;
30 * This is an utility class for SubscriptionItem.
32 * The Simantics Charts samples history data in a specified way.
33 * One data source item is recorded into multiple history item, each identified
34 * with a named SamplingFormat. This class describes a named sampling format.
36 * @author toni.kalajainen@semantum.fi
38 public class SamplingFormat extends Bean {
40 public static final SamplingFormat[] EMPTY = new SamplingFormat[0];
42 public static int compareSamplingInterval(double i1, double i2) {
43 boolean nan1 = Double.isNaN( i1 );
44 boolean nan2 = Double.isNaN( i2 );
46 if ( nan1 && nan2 ) return 0;
47 if ( nan1 && !nan2) return -1;
48 if ( !nan1 && nan2) return 1;
49 return i1 == i2 ? 0 : ( i1 < i2 ? -1 : 1 );
52 public final static Comparator<Bean> INTERVAL_COMPARATOR = new Comparator<Bean>() {
54 public int compare(Bean o1, Bean o2) {
55 double i1 = (Double) o1.getFieldUnchecked("interval");
56 double i2 = (Double) o2.getFieldUnchecked("interval");
57 return compareSamplingInterval(i1, i2);
61 public final static Comparator<SamplingFormat> DEADBAND_COMPARATOR = new Comparator<SamplingFormat>() {
63 public int compare(SamplingFormat o1, SamplingFormat o2) {
64 boolean nan1 = Double.isNaN( o1.deadband );
65 boolean nan2 = Double.isNaN( o2.deadband );
67 if ( nan1 && nan2 ) return 0;
68 if ( nan1 && !nan2) return -1;
69 if ( !nan1 && nan2) return 1;
70 return o1.deadband == o2.deadband ? 0 : ( o1.deadband < o2.deadband ? -1 : 1 );
74 /** Identifier, this value is used for separating the time series files */
75 public String formatId;
78 * Describes the format of the packed sample. The sample must be a record.
79 * The record must have any combination of the following named fields.
80 * The field types must one of: byte, integer, long, float, double.
82 * time, endTime, value - are mandatory fields.
84 * time - Region start time, the time of the 1st included sample
85 * endTime - Region end time, the time of the last included sample
87 * value - First value in the region
88 * lastValue - Last value in the region
89 * avg - Average value of all included samples
90 * median - Median value of all samples in the region
91 * min - Lowest value in the region
92 * max - Highest value in the region
94 * quality - 0 = Good, -1 = No value
95 * count - The number of included samples in the region
97 public Datatype format;
99 /** Interval sets the minimum time for a packed sample */
100 public double interval = Double.NaN;
102 /** Deadband determines the minimum value change for a packed sample when collecting data */
103 public double deadband = Double.NaN;
105 public SamplingFormat()
109 public SamplingFormat(String id, RecordType sampleType, double interval, double deadband)
112 this.format = sampleType;
113 this.interval = interval;
114 this.deadband = deadband;
117 // Sampling format templates
118 public static SamplingFormat simple, allfields, vector;
120 public RecordType record() { return (RecordType) format; }
123 simple = new SamplingFormat();
124 simple.formatId = "Simple";
125 RecordType format = (RecordType) (simple.format = new RecordType());
126 format.addComponent("time", Datatypes.DOUBLE);
127 format.addComponent("endTime", Datatypes.DOUBLE);
128 format.addComponent("value", Datatypes.DOUBLE);
129 format.addComponent("quality", Datatypes.BYTE);
130 simple.interval = Double.NaN;
131 simple.deadband = Double.NaN;
133 allfields = new SamplingFormat();
134 allfields.formatId = "Allfields";
135 allfields.format = new RecordType();
136 format = (RecordType) (allfields.format = new RecordType());
137 format.addComponent("time", Datatypes.DOUBLE);
138 format.addComponent("endTime", Datatypes.DOUBLE);
140 format.addComponent("value", Datatypes.DOUBLE);
141 format.addComponent("lastValue", Datatypes.DOUBLE);
142 format.addComponent("min", Datatypes.DOUBLE);
143 format.addComponent("max", Datatypes.DOUBLE);
144 format.addComponent("avg", Datatypes.DOUBLE);
145 format.addComponent("median", Datatypes.DOUBLE);
147 format.addComponent("quality", Datatypes.BYTE);
148 format.addComponent("count", Datatypes.INTEGER);
149 allfields.interval = Double.NaN;
150 allfields.deadband = Double.NaN;
152 vector = new SamplingFormat();
153 vector.formatId = "Vector";
154 vector.format = new RecordType();
155 format = (RecordType) (vector.format = new RecordType());
156 format.addComponent("time", Datatypes.FLOAT);
157 format.addComponent("endTime", Datatypes.FLOAT);
158 format.addComponent("value", new ArrayType( Datatypes.DOUBLE, Range.between(Limit.inclusive(3), Limit.inclusive(3)) ));
159 format.addComponent("count", Datatypes.INTEGER);
160 vector.interval = Double.NaN;
161 vector.deadband = Double.NaN;
166 public boolean equals(Object obj) {
167 if ( obj == null ) return false;
168 if ( obj == this ) return true;
169 if ( obj instanceof SamplingFormat == false ) return false;
170 SamplingFormat other = (SamplingFormat) obj;
171 // if ( !doubleEquals(interval, other.interval) || !doubleEquals(deadband, other.deadband) ) return false;
172 // return RecordTypeBinding.equals( other.sampleType, sampleType );
173 return formatId.equals(other.formatId);
177 public String toString() {
178 return "id="+formatId+", "+format +", interval="+interval+", deadband="+deadband;
182 public SamplingFormat clone() {
184 SamplingFormat result = new SamplingFormat();
185 result.formatId = formatId;
186 result.interval = interval;
187 result.deadband = deadband;
188 result.format = (Datatype) Bindings.getBindingUnchecked( Datatype.class ).clone( format );
190 } catch (AdaptException e) {
191 throw new RuntimeException( e );
195 public SamplingFormat clone(double interval, double deadband) {
197 SamplingFormat result = new SamplingFormat();
198 result.formatId = formatId;
199 result.interval = interval;
200 result.deadband = deadband;
201 result.format = (Datatype) Bindings.getBindingUnchecked( Datatype.class ).clone( format );
203 } catch (AdaptException e) {
204 throw new RuntimeException( e );
208 public SamplingFormat cloneTo(String id, double interval, double deadband) {
210 SamplingFormat result = new SamplingFormat();
211 result.formatId = id;
212 result.interval = interval;
213 result.deadband = deadband;
214 result.format = (Datatype) Bindings.getBindingUnchecked( Datatype.class ).clone( format );
216 } catch (AdaptException e) {
217 throw new RuntimeException( e );
221 public SamplingFormat setUnit(String unit) {
222 for ( int i = 0; i<format.getComponentCount(); i++ ) {
223 Component c = ((RecordType)format).getComponent(i);
224 if ( c.name.equals( "value" ) ||
225 c.name.equals( "min" ) ||
226 c.name.equals( "max" ) ||
227 c.name.equals( "avg" ) ||
228 c.name.equals( "median" )
230 if ( c.type instanceof NumberType ) {
231 NumberType nt = (NumberType) c.type;
239 public static void sortByInterval( SamplingFormat[] formats ) {
240 Arrays.sort(formats, INTERVAL_COMPARATOR);
243 public static void sortByDeadband( SamplingFormat[] formats ) {
244 Arrays.sort(formats, DEADBAND_COMPARATOR);