]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.history/src/org/simantics/history/util/subscription/SamplingFormat.java
Added another sampling method to HistorySampler
[simantics/platform.git] / bundles / org.simantics.history / src / org / simantics / history / util / subscription / SamplingFormat.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.subscription;
13
14 import java.util.Arrays;
15 import java.util.Comparator;
16
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;
28
29 /**
30  * This is an utility class for SubscriptionItem.
31  * 
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.
35  * 
36  * @author toni.kalajainen@semantum.fi
37  */
38 public class SamplingFormat extends Bean {
39         
40         public static final SamplingFormat[] EMPTY = new SamplingFormat[0];
41
42         public static int compareSamplingInterval(double i1, double i2) {
43                 boolean nan1 = Double.isNaN( i1 );
44                 boolean nan2 = Double.isNaN( i2 );
45
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 );
50         }
51
52         public final static Comparator<Bean> INTERVAL_COMPARATOR = new Comparator<Bean>() {
53                 @Override
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);
58                 }
59         };
60         
61         public final static Comparator<SamplingFormat> DEADBAND_COMPARATOR = new Comparator<SamplingFormat>() {
62                 @Override
63                 public int compare(SamplingFormat o1, SamplingFormat o2) {
64                         boolean nan1 = Double.isNaN( o1.deadband );
65                         boolean nan2 = Double.isNaN( o2.deadband );
66                         
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 );
71                 }
72         };
73
74         /** Identifier, this value is used for separating the time series files */
75         public String formatId;
76         
77         /** 
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.
81          * 
82          * time, endTime, value - are mandatory fields.
83          * 
84          *  time      -  Region start time, the time of the 1st included sample
85          *  endTime   -  Region end time, the time of the last included sample
86          *  
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
93          *  
94          *  quality   -  0 = Good, -1 = No value
95          *  count     -  The number of included samples in the region
96          */
97         public Datatype format;
98
99         /** Interval sets the minimum time for a packed sample */
100         public double interval = Double.NaN;
101
102         /** Deadband determines the minimum value change for a packed sample when collecting data */
103         public double deadband = Double.NaN;
104         
105         public SamplingFormat()
106         {               
107         }
108         
109         public SamplingFormat(String id, RecordType sampleType, double interval, double deadband)
110         {
111                 this.formatId = id;
112                 this.format = sampleType;
113                 this.interval = interval;
114                 this.deadband = deadband;
115         }
116         
117         // Sampling format templates
118         public static SamplingFormat simple, allfields, vector;
119         
120         public RecordType record() { return (RecordType) format; }
121
122         static {
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;
132                 
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);
139                 
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);
146                 
147                 format.addComponent("quality", Datatypes.BYTE);
148                 format.addComponent("count", Datatypes.INTEGER);
149                 allfields.interval = Double.NaN;
150                 allfields.deadband = Double.NaN;                
151                 
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;
162                 
163         }
164                 
165         @Override
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);
174         }
175         
176         @Override
177         public String toString() {
178                 return "id="+formatId+", "+format +", interval="+interval+", deadband="+deadband;
179         }
180         
181         @Override
182         public SamplingFormat clone() {
183                 try {
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 );
189                         return result;
190                 } catch (AdaptException e) {
191                         throw new RuntimeException( e );
192                 }
193         }
194
195         public SamplingFormat clone(double interval, double deadband) {
196                 try {
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 );
202                         return result;
203                 } catch (AdaptException e) {
204                         throw new RuntimeException( e );
205                 }
206         }
207         
208         public SamplingFormat cloneTo(String id, double interval, double deadband) {
209                 try {
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 );
215                         return result;
216                 } catch (AdaptException e) {
217                         throw new RuntimeException( e );
218                 }
219         }
220         
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" )
229                                         ) {
230                                 if ( c.type instanceof NumberType ) {
231                                         NumberType nt = (NumberType) c.type;
232                                         nt.setUnit( unit );
233                                 }
234                         }
235                 }
236                 return this;
237         }
238         
239         public static void sortByInterval( SamplingFormat[] formats ) {
240                 Arrays.sort(formats, INTERVAL_COMPARATOR);
241         }
242         
243         public static void sortByDeadband( SamplingFormat[] formats ) {
244                 Arrays.sort(formats, DEADBAND_COMPARATOR);
245         }
246         
247 }