KickJava   Java API By Example, From Geeks To Geeks.

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


1 /**
2  * com.mckoi.database.FunctionFactory 12 Jul 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 import java.lang.reflect.Constructor JavaDoc;
28 import java.lang.reflect.InvocationTargetException JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.HashMap JavaDoc;
31 import java.util.Set JavaDoc;
32 import java.text.*;
33
34 /**
35  * A factory that generates Function objects given a function name and a
36  * set of expression's that represent parameters. A developer may create
37  * their own instance of this class and register the factory with the
38  * DatabaseSystem. When the SQL grammer comes across a function, it will
39  * try and resolve the function name against the registered function
40  * factories.
41  *
42  * @author Tobias Downer
43  */

44
45 public abstract class FunctionFactory implements FunctionLookup {
46
47   private static final Expression GLOB_EXPRESSION;
48
49   static {
50     GLOB_EXPRESSION = new Expression();
51     GLOB_EXPRESSION.addElement(TObject.stringVal("*"));
52     GLOB_EXPRESSION.text().append("*");
53   }
54
55   /**
56    * Represents a function argument * for glob's such as 'count(*)'
57    */

58   public static final Expression[] GLOB_LIST =
59                                      new Expression[] { GLOB_EXPRESSION };
60
61   /**
62    * The mapping of 'fun_name' to 'fun_class' for each function that's
63    * registered with this factory.
64    */

65   private HashMap JavaDoc fun_class_mapping;
66
67   /**
68    * Constructor arguments for the function.
69    */

70   private Class JavaDoc[] construct_proto;
71
72
73   /**
74    * Constructs the FunctionFactory.
75    */

76   public FunctionFactory() {
77     fun_class_mapping = new HashMap JavaDoc();
78     // The is the prototype for the constructor when creating a new function.
79
construct_proto = new Class JavaDoc[1];
80     Object JavaDoc exp_arr_ob =
81           java.lang.reflect.Array.newInstance(new Expression().getClass(), 0);
82     construct_proto[0] = exp_arr_ob.getClass();
83   }
84
85   /**
86    * Adds a new function to this factory. Takes a function name and a
87    * class that is the Function implementation. When the 'generateFunction'
88    * method is called, it looks up the class with the function name and
89    * returns a new instance of the function.
90    * <p>
91    * @param fun_name the name of the function (eg. 'sum', 'concat').
92    * @param fun_class the Function class that we instantiate for this function.
93    * @param fun_type that type of function (either FunctionInfo.STATIC,
94    * FunctionInfo.AGGREGATE, FunctionInfo.STATE_BASED).
95    */

96   protected void addFunction(String JavaDoc fun_name, Class JavaDoc fun_class, int fun_type) {
97     try {
98       String JavaDoc lf_name = fun_name.toLowerCase();
99       if (fun_class_mapping.get(lf_name) == null) {
100         FF_FunctionInfo ff_info = new FF_FunctionInfo(fun_name, fun_type,
101                                    fun_class.getConstructor(construct_proto));
102         fun_class_mapping.put(lf_name, ff_info);
103       }
104       else {
105         throw new Error JavaDoc("Function '" + fun_name +
106                         "' already defined in factory.");
107       }
108     }
109     catch (NoSuchMethodException JavaDoc e) {
110       throw new RuntimeException JavaDoc(e.getMessage());
111     }
112   }
113
114   /**
115    * Adds a new static function to this factory.
116    */

117   protected void addFunction(String JavaDoc fun_name, Class JavaDoc fun_class) {
118     addFunction(fun_name, fun_class, FunctionInfo.STATIC);
119   }
120
121   /**
122    * Removes a static function from this factory.
123    */

124   protected void removeFunction(String JavaDoc fun_name) {
125     String JavaDoc lf_name = fun_name.toLowerCase();
126     if (fun_class_mapping.get(lf_name) != null) {
127       fun_class_mapping.remove(fun_name.toLowerCase());
128     }
129     else {
130       throw new Error JavaDoc("Function '" + lf_name +
131                       "' is not defined in this factory.");
132     }
133   }
134
135   /**
136    * Returns true if the function name is defined in this factory.
137    */

138   protected boolean functionDefined(String JavaDoc fun_name) {
139     String JavaDoc lf_name = fun_name.toLowerCase();
140     return fun_class_mapping.get(lf_name) != null;
141   }
142
143   /**
144    * Initializes this FunctionFactory. This is an abstract method that
145    * needs to be implemented. (It doesn't need to do anything if a developer
146    * implements their own version of 'generateFunction').
147    */

148   public abstract void init();
149
150   /**
151    * Creates a Function object for the function with the given name with the
152    * given arguments. If this factory does not handle a function with the
153    * given name then it returns null.
154    */

155   public Function generateFunction(FunctionDef function_def) {
156                                   //String func_name, Expression[] params) {
157

158     String JavaDoc func_name = function_def.getName();
159     Expression[] params = function_def.getParameters();
160
161     // This will lookup the function name (case insensitive) and if a
162
// function class was registered, instantiates and returns it.
163

164     FF_FunctionInfo ff_info = (FF_FunctionInfo)
165                               fun_class_mapping.get(func_name.toLowerCase());
166     if (ff_info == null) {
167       // Function not handled by this factory so return null.
168
return null;
169     }
170     else {
171       Constructor JavaDoc fun_constructor = (Constructor JavaDoc) ff_info.getConstructor();
172       Object JavaDoc[] args = new Object JavaDoc[] { params };
173       try {
174         return (Function) fun_constructor.newInstance(args);
175       }
176       catch (InvocationTargetException JavaDoc e) {
177         throw new RuntimeException JavaDoc(e.getTargetException().getMessage());
178       }
179       catch (Exception JavaDoc e) {
180         throw new RuntimeException JavaDoc(e.getMessage());
181       }
182     }
183   }
184
185   /**
186    * Returns true if the function defined by FunctionDef is an aggregate
187    * function, or false otherwise.
188    */

189   public boolean isAggregate(FunctionDef function_def) {
190     FunctionInfo f_info = getFunctionInfo(function_def.getName());
191     if (f_info == null) {
192       // Function not handled by this factory so return false.
193
return false;
194     }
195     else {
196       return (f_info.getType() == FunctionInfo.AGGREGATE);
197     }
198   }
199   
200   /**
201    * Returns a FunctionInfo instance of the function with the given name that
202    * this FunctionFactory manages. If 'generateFunction' is reimplemented then
203    * this method should be rewritten also.
204    */

205   public FunctionInfo getFunctionInfo(String JavaDoc fun_name) {
206     FF_FunctionInfo ff_info = (FF_FunctionInfo)
207                               fun_class_mapping.get(fun_name.toLowerCase());
208     return ff_info;
209   }
210
211   /**
212    * Returns the list of all function names that this FunctionFactory manages.
213    * This is used to compile information about the function factories. If
214    * 'generateFunction' is reimplemented then this method should be rewritten
215    * also.
216    */

217   public FunctionInfo[] getAllFunctionInfo() {
218     Set JavaDoc keys = fun_class_mapping.keySet();
219     int list_size = keys.size();
220     FunctionInfo[] list = new FunctionInfo[list_size];
221     Iterator JavaDoc i = keys.iterator();
222     int n = 0;
223     while (i.hasNext()) {
224       String JavaDoc fun_name = (String JavaDoc) i.next();
225       list[n] = getFunctionInfo(fun_name);
226       ++n;
227     }
228     return list;
229   }
230
231   /**
232    * An implementation of FunctionInfo.
233    */

234   protected class FF_FunctionInfo implements FunctionInfo {
235
236     private String JavaDoc name;
237     private int type;
238     private Constructor JavaDoc constructor;
239
240     public FF_FunctionInfo(String JavaDoc name, int type, Constructor JavaDoc constructor) {
241       this.name = name;
242       this.type = type;
243       this.constructor = constructor;
244     }
245
246     public String JavaDoc getName() {
247       return name;
248     }
249
250     public int getType() {
251       return type;
252     }
253
254     public Constructor JavaDoc getConstructor() {
255       return constructor;
256     }
257
258     public String JavaDoc getFunctionFactoryName() {
259       return FunctionFactory.this.getClass().toString();
260     }
261
262   };
263
264 }
265
Popular Tags