001    package org.LiveGraph.dataCache;
002    
003    import java.util.Iterator;
004    
005    import com.softnetConsult.utils.collections.ReadOnlyIterator;
006    
007    
008    /**
009     * Repsesents a data series inside the cache; stores all series specific information
010     * and provides convenience methods for accessing that information. A data series
011     * usually cossesponds to a data column inside a data file. 
012     * 
013     * <p>
014     *   <strong>LiveGraph</strong>
015     *   (<a href="http://www.live-graph.org" target="_blank">http://www.live-graph.org</a>).
016     * </p> 
017     * <p>Copyright (c) 2007 by G. Paperin.</p>
018     * <p>File: DataSeries.java</p>
019     * <p style="font-size:smaller;">Redistribution and use in source and binary forms, with or
020     *    without modification, are permitted provided that the following terms and conditions are met:
021     * </p>
022     * <p style="font-size:smaller;">1. Redistributions of source code must retain the above
023     *    acknowledgement of the LiveGraph project and its web-site, the above copyright notice,
024     *    this list of conditions and the following disclaimer.<br />
025     *    2. Redistributions in binary form must reproduce the above acknowledgement of the
026     *    LiveGraph project and its web-site, the above copyright notice, this list of conditions
027     *    and the following disclaimer in the documentation and/or other materials provided with
028     *    the distribution.<br />
029     *    3. All advertising materials mentioning features or use of this software or any derived
030     *    software must display the following acknowledgement:<br />
031     *    <em>This product includes software developed by the LiveGraph project and its
032     *    contributors.<br />(http://www.live-graph.org)</em><br />
033     *    4. All advertising materials distributed in form of HTML pages or any other technology
034     *    permitting active hyper-links that mention features or use of this software or any
035     *    derived software must display the acknowledgment specified in condition 3 of this
036     *    agreement, and in addition, include a visible and working hyper-link to the LiveGraph
037     *    homepage (http://www.live-graph.org).
038     * </p>
039     * <p style="font-size:smaller;">THIS SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY
040     *    OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
041     *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT SHALL
042     *    THE AUTHORS, CONTRIBUTORS OR COPYRIGHT  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
043     *    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING  FROM, OUT OF OR
044     *    IN CONNECTION WITH THE SOFTWARE OR THE USE OR  OTHER DEALINGS IN THE SOFTWARE.
045     * </p>
046     * 
047     * @author Greg Paperin (<a href="http://www.paperin.org" target="_blank">http://www.paperin.org</a>)
048     * @version {@value org.LiveGraph.LiveGraph#version}
049     */
050    public class DataSeries {
051    
052    /**
053     * Serien name/label.
054     */
055    private String label = null;
056    
057    /**
058     * The cache in which the data of this series is stored.
059     */
060    private DataCache adminCache = null;
061    
062    /**
063     * The (0 based) index of this series' data in the cache.
064     */
065    private int seriesIndexInCache = -1;
066    
067    /**
068     * Min data value in this series.
069     */
070    private double minValue = Double.NaN;
071    
072    /**
073     * Max data value in this series.
074     */
075    private double maxValue = Double.NaN;
076    
077    /**
078     * The constructor.
079     * 
080     * @param label Series label.
081     * @param adminCache The cache adminestering the data.
082     * @param seriesIndexInCache The index of this series in the cache.
083     */
084    /*package*/ DataSeries(String label, DataCache adminCache, int seriesIndexInCache) {
085            this.label = label;
086            this.adminCache = adminCache;
087            this.seriesIndexInCache = seriesIndexInCache;
088            resetExtremeValues();
089    }
090    
091    /**
092     * @return This series' name / label.
093     */
094    public String getLabel() {
095            return label;
096    }
097    
098    /**
099     * @return The cache holding the data of this series.
100     */
101    public DataCache getAdministratingCache() {
102            return adminCache;
103    }
104    
105    /**
106     * @return The series' data index in the cache. 
107     */
108    public int getSeriesIndexInCache() {
109            return seriesIndexInCache;
110    }
111    
112    /**
113     * @return Number of datasets the cache currently holds for this series.
114     */
115    public int countDataSets() {
116            return adminCache.countDataSets();
117    }
118    
119    /**
120     * @return A read-only iterator over the data values of this series currently held in cache.
121     */
122    public ReadOnlyIterator<Double> iterateDataValues() {
123            
124            return new DataValuesIterator(adminCache.iterateDataSets(), seriesIndexInCache);
125    }
126    
127    /**
128     * @param cacheIndex A cache index of a dataset.
129     * @return This series' dataset the held at the specified index in the cache.
130     */
131    public double getDataValue(int cacheIndex) {
132            return adminCache.getDataSet(cacheIndex).getValue(seriesIndexInCache);
133    }
134    
135    /**
136     * @param cacheIndex A cache index of a dataset.
137     * @return The index in the original file of the dataset at the specified cache index.
138     */
139    public int getDatasetFileIndex(int cacheIndex) {
140            return adminCache.getDataSet(cacheIndex).getDataFileIndex();
141    }
142    
143    /**
144     * @param dataFileIndex An data row index of the original data file. 
145     * @return The data value of this series' dataset which was located at the specified
146     * index in the original data file; if that dataset is not in the cache, this method
147     * returns {@link DataSet#returnValueForIllegalIndex}.doubleValue(). 
148     */
149    public double findDataValue(int dataFileIndex) {
150            
151            DataSet ds = adminCache.findDataSet(dataFileIndex);
152            
153            if (null == ds)
154                    return DataSet.returnValueForIllegalIndex.doubleValue();
155            
156            return ds.getValue(seriesIndexInCache);
157    }
158    
159    /**
160     * @param val Makes sure that min and max value caches of this series include the
161     * specified value.
162     */
163    /*package*/ void includeExtremeValue(double val) {
164            
165            if (Double.isNaN(val) || Double.isInfinite(val))
166                    return;
167            
168            if (val < minValue || Double.isNaN(minValue) )
169                    minValue = val;
170            
171            if (val > maxValue || Double.isNaN(maxValue))
172                    maxValue = val;
173    }
174    
175    /**
176     * @return The smallest data value of this series or {@code Double.NaN} if this series
177     * is empty.  
178     */
179    public double getMinValue() {
180            return minValue;
181    }
182    
183    /**
184     * @return The largest data value of this series or {@code Double.NaN} if this series
185     * is empty.  
186     */
187    public double getMaxValue() {
188            return maxValue;
189    }
190    
191    /**
192     * Resets the min and max value caches for this series.
193     */
194    /*package*/ void resetExtremeValues() {
195            minValue = Double.NaN;
196            maxValue = Double.NaN;
197    }
198    
199    /**
200     * A read-only iterator over the data values of a series.
201     */
202    private class DataValuesIterator extends ReadOnlyIterator<Double> {
203    
204            private Iterator<DataSet> iterator = null;
205            private int seriesIndexInCache = -1;
206            
207            public DataValuesIterator(Iterator<DataSet> iter, int seriesIndexInCache) {
208                    super(null);
209                    this.iterator = iter;
210                    this.seriesIndexInCache = seriesIndexInCache;
211            }
212            
213            @Override
214            public boolean hasNext() {
215                    return iterator.hasNext();
216            }
217            
218            @Override
219            public Double next() {
220                    return iterator.next().getValue(seriesIndexInCache);
221            }
222            
223            @Override
224            public void remove() {
225                    throw new UnsupportedOperationException("Cannot use this iterator to remove items.");       
226            }
227    
228    } // class DataSeriesLabelIterator
229    
230    } // class DataSeries