]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.history/src/org/simantics/history/util/subscription/SamplingFormat.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.history / src / org / simantics / history / util / subscription / SamplingFormat.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
3  * Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.history.util.subscription;\r
13 \r
14 import java.util.Arrays;\r
15 import java.util.Comparator;\r
16 \r
17 import org.simantics.databoard.Bindings;\r
18 import org.simantics.databoard.Datatypes;\r
19 import org.simantics.databoard.adapter.AdaptException;\r
20 import org.simantics.databoard.type.ArrayType;\r
21 import org.simantics.databoard.type.Component;\r
22 import org.simantics.databoard.type.Datatype;\r
23 import org.simantics.databoard.type.NumberType;\r
24 import org.simantics.databoard.type.RecordType;\r
25 import org.simantics.databoard.util.Bean;\r
26 import org.simantics.databoard.util.Limit;\r
27 import org.simantics.databoard.util.Range;\r
28 \r
29 /**\r
30  * This is an utility class for SubscriptionItem.\r
31  * \r
32  * The Simantics Charts samples history data in a specified way. \r
33  * One data source item is recorded into multiple history item, each identified\r
34  * with a named SamplingFormat. This class describes a named sampling format.\r
35  * \r
36  * @author toni.kalajainen@semantum.fi\r
37  */\r
38 public class SamplingFormat extends Bean {\r
39         \r
40         public static final SamplingFormat[] EMPTY = new SamplingFormat[0];\r
41         \r
42         public final static Comparator<Bean> INTERVAL_COMPARATOR = new Comparator<Bean>() {\r
43                 @Override\r
44                 public int compare(Bean o1, Bean o2) {\r
45                         double i1 = (Double) o1.getFieldUnchecked("interval");\r
46                         double i2 = (Double) o2.getFieldUnchecked("interval");\r
47                         boolean nan1 = Double.isNaN( i1 );\r
48                         boolean nan2 = Double.isNaN( i2 );\r
49                         \r
50                         if ( nan1 && nan2 ) return 0;\r
51                         if ( nan1 && !nan2) return -1;\r
52                         if ( !nan1 && nan2) return 1;\r
53                         return i1 == i2 ? 0 : ( i1 < i2 ? -1 : 1 );\r
54                 }\r
55         };\r
56         \r
57         public final static Comparator<SamplingFormat> DEADBAND_COMPARATOR = new Comparator<SamplingFormat>() {\r
58                 @Override\r
59                 public int compare(SamplingFormat o1, SamplingFormat o2) {\r
60                         boolean nan1 = Double.isNaN( o1.deadband );\r
61                         boolean nan2 = Double.isNaN( o2.deadband );\r
62                         \r
63                         if ( nan1 && nan2 ) return 0;\r
64                         if ( nan1 && !nan2) return -1;\r
65                         if ( !nan1 && nan2) return 1;\r
66                         return o1.deadband == o2.deadband ? 0 : ( o1.deadband < o2.deadband ? -1 : 1 );\r
67                 }\r
68         };\r
69 \r
70         /** Identifier, this value is used for separating the time series files */\r
71         public String formatId;\r
72         \r
73         /** \r
74          * Describes the format of the packed sample. The sample must be a record.\r
75          * The record must have any combination of the following named fields.\r
76          * The field types must one of: byte, integer, long, float, double.\r
77          * \r
78          * time, endTime, value - are mandatory fields.\r
79          * \r
80          *  time      -  Region start time, the time of the 1st included sample\r
81          *  endTime   -  Region end time, the time of the last included sample\r
82          *  \r
83          *  value     -  First value in the region\r
84          *  lastValue -  Last value in the region\r
85          *  avg       -  Average value of all included samples\r
86          *  median    -  Median value of all samples in the region\r
87          *  min       -  Lowest value in the region\r
88          *  max       -  Highest value in the region\r
89          *  \r
90          *  quality   -  0 = Good, -1 = No value\r
91          *  count     -  The number of included samples in the region\r
92          */\r
93         public Datatype format;\r
94 \r
95         /** Interval sets the minimum time for a packed sample */\r
96         public double interval = Double.NaN;\r
97 \r
98         /** Deadband determines the minimum value change for a packed sample when collecting data */\r
99         public double deadband = Double.NaN;\r
100         \r
101         public SamplingFormat()\r
102         {               \r
103         }\r
104         \r
105         public SamplingFormat(String id, RecordType sampleType, double interval, double deadband)\r
106         {\r
107                 this.formatId = id;\r
108                 this.format = sampleType;\r
109                 this.interval = interval;\r
110                 this.deadband = deadband;\r
111         }\r
112         \r
113         // Sampling format templates\r
114         public static SamplingFormat simple, allfields, vector;\r
115         \r
116         public RecordType record() { return (RecordType) format; }\r
117 \r
118         static {\r
119                 simple = new SamplingFormat();\r
120                 simple.formatId = "Simple";\r
121                 RecordType format = (RecordType) (simple.format = new RecordType());            \r
122                 format.addComponent("time", Datatypes.DOUBLE);\r
123                 format.addComponent("endTime", Datatypes.DOUBLE);\r
124                 format.addComponent("value", Datatypes.DOUBLE);\r
125                 format.addComponent("quality", Datatypes.BYTE);\r
126                 simple.interval = Double.NaN;\r
127                 simple.deadband = Double.NaN;\r
128                 \r
129                 allfields = new SamplingFormat();\r
130                 allfields.formatId = "Allfields";\r
131                 allfields.format = new RecordType();\r
132                 format = (RecordType) (allfields.format = new RecordType());            \r
133                 format.addComponent("time", Datatypes.DOUBLE);\r
134                 format.addComponent("endTime", Datatypes.DOUBLE);\r
135                 \r
136                 format.addComponent("value", Datatypes.DOUBLE);\r
137                 format.addComponent("lastValue", Datatypes.DOUBLE);             \r
138                 format.addComponent("min", Datatypes.DOUBLE);\r
139                 format.addComponent("max", Datatypes.DOUBLE);\r
140                 format.addComponent("avg", Datatypes.DOUBLE);\r
141                 format.addComponent("median", Datatypes.DOUBLE);\r
142                 \r
143                 format.addComponent("quality", Datatypes.BYTE);\r
144                 format.addComponent("count", Datatypes.INTEGER);\r
145                 allfields.interval = Double.NaN;\r
146                 allfields.deadband = Double.NaN;                \r
147                 \r
148                 vector = new SamplingFormat();\r
149                 vector.formatId = "Vector";\r
150                 vector.format = new RecordType();\r
151                 format = (RecordType) (vector.format = new RecordType());               \r
152                 format.addComponent("time", Datatypes.FLOAT);\r
153                 format.addComponent("endTime", Datatypes.FLOAT);\r
154                 format.addComponent("value", new ArrayType( Datatypes.DOUBLE, Range.between(Limit.inclusive(3), Limit.inclusive(3)) ));\r
155                 format.addComponent("count", Datatypes.INTEGER);\r
156                 vector.interval = Double.NaN;\r
157                 vector.deadband = Double.NaN;\r
158                 \r
159         }\r
160                 \r
161         @Override\r
162         public boolean equals(Object obj) {\r
163                 if ( obj == null ) return false;\r
164                 if ( obj == this ) return true;\r
165                 if ( obj instanceof SamplingFormat == false ) return false;\r
166                 SamplingFormat other = (SamplingFormat) obj;            \r
167 //              if ( !doubleEquals(interval, other.interval) || !doubleEquals(deadband, other.deadband) ) return false;\r
168 //              return RecordTypeBinding.equals( other.sampleType, sampleType );\r
169                 return formatId.equals(other.formatId);\r
170         }\r
171         \r
172         @Override\r
173         public String toString() {\r
174                 return "id="+formatId+", "+format +", interval="+interval+", deadband="+deadband;\r
175         }\r
176         \r
177         @Override\r
178         public SamplingFormat clone() {\r
179                 try {\r
180                         SamplingFormat result = new SamplingFormat();\r
181                         result.formatId = formatId;\r
182                         result.interval = interval;\r
183                         result.deadband = deadband;\r
184                         result.format = (Datatype) Bindings.getBindingUnchecked( Datatype.class ).clone( format );\r
185                         return result;\r
186                 } catch (AdaptException e) {\r
187                         throw new RuntimeException( e );\r
188                 }\r
189         }\r
190 \r
191         public SamplingFormat clone(double interval, double deadband) {\r
192                 try {\r
193                         SamplingFormat result = new SamplingFormat();\r
194                         result.formatId = formatId;\r
195                         result.interval = interval;\r
196                         result.deadband = deadband;\r
197                         result.format = (Datatype) Bindings.getBindingUnchecked( Datatype.class ).clone( format );\r
198                         return result;\r
199                 } catch (AdaptException e) {\r
200                         throw new RuntimeException( e );\r
201                 }\r
202         }\r
203         \r
204         public SamplingFormat cloneTo(String id, double interval, double deadband) {\r
205                 try {\r
206                         SamplingFormat result = new SamplingFormat();\r
207                         result.formatId = id;\r
208                         result.interval = interval;\r
209                         result.deadband = deadband;\r
210                         result.format = (Datatype) Bindings.getBindingUnchecked( Datatype.class ).clone( format );\r
211                         return result;\r
212                 } catch (AdaptException e) {\r
213                         throw new RuntimeException( e );\r
214                 }\r
215         }\r
216         \r
217         public SamplingFormat setUnit(String unit) {\r
218                 for ( int i = 0; i<format.getComponentCount(); i++ ) {\r
219                         Component c = ((RecordType)format).getComponent(i);\r
220                         if ( c.name.equals( "value" ) || \r
221                                         c.name.equals( "min" ) || \r
222                                         c.name.equals( "max" ) || \r
223                                         c.name.equals( "avg" ) ||\r
224                                         c.name.equals( "median" )\r
225                                         ) {\r
226                                 if ( c.type instanceof NumberType ) {\r
227                                         NumberType nt = (NumberType) c.type;\r
228                                         nt.setUnit( unit );\r
229                                 }\r
230                         }\r
231                 }\r
232                 return this;\r
233         }\r
234         \r
235         public static void sortByInterval( SamplingFormat[] formats ) {\r
236                 Arrays.sort(formats, INTERVAL_COMPARATOR);\r
237         }\r
238         \r
239         public static void sortByDeadband( SamplingFormat[] formats ) {\r
240                 Arrays.sort(formats, DEADBAND_COMPARATOR);\r
241         }\r
242         \r
243 }\r