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