1   /*
2    * Copyright 2003-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.commons.math.stat.descriptive;
17  
18  import java.io.Serializable;
19  import java.util.ArrayList;
20  import java.util.List;
21  
22  import org.apache.commons.math.MathException;
23  import org.apache.commons.math.stat.descriptive.UnivariateStatistic;
24  import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
25  import org.apache.commons.math.util.DefaultTransformer;
26  import org.apache.commons.math.util.NumberTransformer;
27  
28  /**
29   * @version $Revision: 348519 $ $Date: 2005-11-23 12:12:18 -0700 (Wed, 23 Nov 2005) $
30   */
31  public class ListUnivariateImpl extends DescriptiveStatistics implements Serializable {
32  
33      /** Serializable version identifier */
34      private static final long serialVersionUID = -8837442489133392138L;
35      
36      /**
37       * Holds a reference to a list - GENERICs are going to make
38       * out lives easier here as we could only accept List<Number>
39       */
40      protected List list;
41  
42      /** Number Transformer maps Objects to Number for us. */
43      protected NumberTransformer transformer;
44      
45      /** hold the window size **/
46      protected int windowSize = DescriptiveStatistics.INFINITE_WINDOW;
47  
48      /**
49       * No argument Constructor
50       */
51      public ListUnivariateImpl(){
52          this(new ArrayList());
53      }
54      
55      /**
56       * Construct a ListUnivariate with a specific List.
57       * @param list The list that will back this DescriptiveStatistics
58       */
59      public ListUnivariateImpl(List list) {
60          this(list, new DefaultTransformer());
61      }
62      
63      /**
64       * Construct a ListUnivariate with a specific List.
65       * @param list The list that will back this DescriptiveStatistics
66       * @param transformer the number transformer used to convert the list items.
67       */
68      public ListUnivariateImpl(List list, NumberTransformer transformer) {
69          super();
70          this.list = list;
71          this.transformer = transformer;
72      }
73  
74      /**
75       * @see org.apache.commons.math.stat.descriptive.DescriptiveStatistics#getValues()
76       */
77      public double[] getValues() {
78  
79          int length = list.size();
80  
81          // If the window size is not INFINITE_WINDOW AND
82          // the current list is larger that the window size, we need to
83          // take into account only the last n elements of the list
84          // as definied by windowSize
85  
86          if (windowSize != DescriptiveStatistics.INFINITE_WINDOW &&
87              windowSize < list.size())
88          {
89              length = list.size() - Math.max(0, list.size() - windowSize);
90          }
91  
92          // Create an array to hold all values
93          double[] copiedArray = new double[length];
94  
95          for (int i = 0; i < copiedArray.length; i++) {
96              copiedArray[i] = getElement(i);
97          }
98          return copiedArray;
99      }
100 
101     /**
102      * @see org.apache.commons.math.stat.descriptive.DescriptiveStatistics#getElement(int)
103      */
104     public double getElement(int index) {
105 
106         double value = Double.NaN;
107 
108         int calcIndex = index;
109 
110         if (windowSize != DescriptiveStatistics.INFINITE_WINDOW &&
111             windowSize < list.size())
112         {
113             calcIndex = (list.size() - windowSize) + index;
114         }
115 
116         
117         try {
118             value = transformer.transform(list.get(calcIndex));
119         } catch (MathException e) {
120             e.printStackTrace();
121         }
122         
123         return value;
124     }
125 
126     /**
127      * @see org.apache.commons.math.stat.descriptive.DescriptiveStatistics#getN()
128      */
129     public long getN() {
130         int n = 0;
131 
132         if (windowSize != DescriptiveStatistics.INFINITE_WINDOW) {
133             if (list.size() > windowSize) {
134                 n = windowSize;
135             } else {
136                 n = list.size();
137             }
138         } else {
139             n = list.size();
140         }
141         return n;
142     }
143 
144     /**
145      * @see org.apache.commons.math.stat.descriptive.DescriptiveStatistics#addValue(double)
146      */
147     public void addValue(double v) {
148         list.add(new Double(v));
149     }
150     
151     /**
152      * Adds an object to this list. 
153      * @param o Object to add to the list
154      */
155     public void addObject(Object o) {
156         list.add(o);
157     }
158 
159     /**
160      * Clears all statistics.
161      * <p>
162      * <strong>N.B.: </strong> This method has the side effect of clearing the underlying list.
163      */
164     public void clear() {
165         list.clear();
166     }
167     
168     /**
169      * Apply the given statistic to this univariate collection.
170      * @param stat the statistic to apply
171      * @return the computed value of the statistic.
172      */
173     public double apply(UnivariateStatistic stat) {
174         double[] v = this.getValues();
175 
176         if (v != null) {
177             return stat.evaluate(v, 0, v.length);
178         }
179         return Double.NaN;
180     }
181     
182     /**
183      * Access the number transformer.
184      * @return the number transformer.
185      */
186     public NumberTransformer getTransformer() {
187         return transformer;
188     }
189 
190     /**
191      * Modify the number transformer.
192      * @param transformer the new number transformer.
193      */
194     public void setTransformer(NumberTransformer transformer) {
195         this.transformer = transformer;
196     }
197     
198     /**
199      * @see org.apache.commons.math.stat.descriptive.DescriptiveStatistics#setWindowSize(int)
200      */
201     public synchronized void setWindowSize(int windowSize) {
202         this.windowSize = windowSize;
203         //Discard elements from the front of the list if the windowSize is less than 
204         // the size of the list.
205         int extra = list.size() - windowSize;
206         for (int i = 0; i < extra; i++) {
207             list.remove(0);
208         }
209     }
210 
211     /**
212      * @see org.apache.commons.math.stat.descriptive.DescriptiveStatistics#getWindowSize
213      */
214     public int getWindowSize() {
215         return windowSize;
216     }
217 
218 }