KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mckoi > database > AbstractAggregateFunction


1 /**
2  * com.mckoi.database.AbstractAggregateFunction 06 Aug 2000
3  *
4  * Mckoi SQL Database ( http://www.mckoi.com/database )
5  * Copyright (C) 2000, 2001, 2002 Diehl and Associates, Inc.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * Version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License Version 2 for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * Version 2 along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  *
20  * Change Log:
21  *
22  *
23  */

24
25 package com.mckoi.database;
26
27 /**
28  * Provides convenience methods for handling aggregate functions (functions
29  * that are evaluated over a grouping set). Note that this class handles the
30  * most common form of aggregate functions. These are aggregates with no more
31  * or no less than one parameter, and that return NULL if the group set has a
32  * length of 0. If an aggregate function doesn't fit this design, then the
33  * developer must roll their own AbstractFunction to handle it.
34  * <p>
35  * This object handles full expressions being passed as parameters to the
36  * aggregate function. The expression is evaluated for each set in the
37  * group. Therefore the aggregate function, avg(length(description)) will
38  * find the average length of the description column. sum(price * quantity)
39  * will find the sum of the price * quantity of each set in the group.
40  *
41  * @author Tobias Downer
42  */

43
44 public abstract class AbstractAggregateFunction extends AbstractFunction {
45
46   /**
47    * Constructs an aggregate function.
48    */

49   public AbstractAggregateFunction(String JavaDoc name, Expression[] params) {
50     super(name, params);
51     setAggregate(true);
52
53     // Aggregates must have only one argument
54
if (parameterCount() != 1) {
55       throw new RuntimeException JavaDoc("'" + name +
56                                  "' function must have one argument.");
57     }
58
59   }
60
61   // ---------- Abstract ----------
62

63   /**
64    * Evaluates the aggregate function for the given values and returns the
65    * result. If this aggregate was 'sum' then this method would sum the two
66    * values. If this aggregate was 'avg' then this method would also sum the
67    * two values and the 'postEvalAggregate' would divide by the number
68    * processed.
69    * <p>
70    * NOTE: This first time this method is called on a set, 'val1' is 'null' and
71    * 'val2' contains the first value in the set.
72    */

73   public abstract TObject evalAggregate(GroupResolver group,
74                                         QueryContext context,
75                                         TObject val1, TObject val2);
76
77   /**
78    * Called just before the value is returned to the parent. This does any
79    * final processing on the result before it is returned. If this aggregate
80    * was 'avg' then we'd divide by the size of the group.
81    */

82   public TObject postEvalAggregate(GroupResolver group,
83                                    QueryContext context,
84                                    TObject result) {
85     // By default, do nothing....
86
return result;
87   }
88
89
90
91   // ---------- Implemented from AbstractFunction ----------
92

93   public final TObject evaluate(GroupResolver group,
94                                 VariableResolver resolver,
95                                 QueryContext context) {
96     if (group == null) {
97       throw new RuntimeException JavaDoc("'" + getName() +
98                              "' can only be used as an aggregate function.");
99     }
100
101     TObject result = null;
102     // All aggregates functions return 'null' if group size is 0
103
int size = group.size();
104     if (size == 0) {
105       // Return a NULL of the return type
106
return new TObject(returnTType(resolver, context), null);
107     }
108
109     TObject val;
110     Variable v = getParameter(0).getVariable();
111     // If the aggregate parameter is a simple variable, then use optimal
112
// routine,
113
if (v != null) {
114       for (int i = 0; i < size; ++i) {
115         val = group.resolve(v, i);
116         result = evalAggregate(group, context, result, val);
117       }
118     }
119     else {
120       // Otherwise we must resolve the expression for each entry in group,
121
// This allows for expressions such as 'sum(quantity * price)' to
122
// work for a group.
123
Expression exp = getParameter(0);
124       for (int i = 0; i < size; ++i) {
125         val = exp.evaluate(null, group.getVariableResolver(i), context);
126         result = evalAggregate(group, context, result, val);
127       }
128     }
129
130     // Post method.
131
result = postEvalAggregate(group, context, result);
132
133     return result;
134   }
135
136 }
137
Popular Tags