001: /**
002: * com.mckoi.database.FunctionDef 07 Sep 2001
003: *
004: * Mckoi SQL Database ( http://www.mckoi.com/database )
005: * Copyright (C) 2000, 2001, 2002 Diehl and Associates, Inc.
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * Version 2 as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License Version 2 for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * Version 2 along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
019: *
020: * Change Log:
021: *
022: *
023: */package com.mckoi.database;
024:
025: /**
026: * A definition of a function including its name and parameters. A FunctionDef
027: * can easily be transformed into a Function object via a set of
028: * FunctionFactory instances.
029: * <p>
030: * NOTE: This object is NOT immutable or thread-safe. A FunctionDef should not
031: * be shared among different threads.
032: *
033: * @author Tobias Downer
034: */
035:
036: public final class FunctionDef implements java.io.Serializable,
037: Cloneable {
038:
039: static final long serialVersionUID = 3339781003247956829L;
040:
041: /**
042: * The name of the function.
043: */
044: private String name;
045:
046: /**
047: * The list of parameters for the function.
048: */
049: private Expression[] params;
050:
051: /**
052: * A cached Function object that was generated when this FunctionDef was
053: * looked up. Note that the Function object is transient.
054: */
055: private transient Function cached_function;
056:
057: /**
058: * Constructs the FunctionDef.
059: */
060: public FunctionDef(String name, Expression[] params) {
061: this .name = name;
062: this .params = params;
063: }
064:
065: /**
066: * The name of the function. For example, 'MIN' or 'CONCAT'.
067: */
068: public String getName() {
069: return name;
070: }
071:
072: /**
073: * The list of parameters that are passed to the function. For example,
074: * a concat function may have 7 parameters ('There', ' ', 'are', ' ', 10,
075: * ' ', 'bottles.')
076: */
077: public Expression[] getParameters() {
078: return params;
079: }
080:
081: /**
082: * Returns true if this function is an aggregate, or the parameters are
083: * aggregates. It requires a QueryContext object to lookup the function in
084: * the function factory database.
085: */
086: public boolean isAggregate(QueryContext context) {
087: FunctionLookup fun_lookup = context.getFunctionLookup();
088: boolean is_aggregate = fun_lookup.isAggregate(this );
089: if (is_aggregate) {
090: return true;
091: }
092: // Look at params
093: Expression[] params = getParameters();
094: for (int i = 0; i < params.length; ++i) {
095: is_aggregate = params[i].hasAggregateFunction(context);
096: if (is_aggregate) {
097: return true;
098: }
099: }
100: // No
101: return false;
102: }
103:
104: /**
105: * Returns a Function object from this FunctionDef. Note that two calls to
106: * this method will produce the same Function object, however the same
107: * Function object will not be produced over multiple instances of
108: * FunctionDef even when they represent the same thing.
109: */
110: public Function getFunction(QueryContext context) {
111: if (cached_function != null) {
112: return cached_function;
113: } else {
114: FunctionLookup lookup = context.getFunctionLookup();
115: cached_function = lookup.generateFunction(this );
116: if (cached_function == null) {
117: throw new StatementException("Function '" + getName()
118: + "' doesn't exist.");
119: }
120: return cached_function;
121: }
122: }
123:
124: /**
125: * Performs a deep clone of this object.
126: */
127: public Object clone() throws CloneNotSupportedException {
128: FunctionDef v = (FunctionDef) super .clone();
129: // Deep clone the parameters
130: Expression[] exps = (Expression[]) ((Expression[]) v.params)
131: .clone();
132: // Clone each element of the array
133: for (int n = 0; n < exps.length; ++n) {
134: exps[n] = (Expression) exps[n].clone();
135: }
136: v.params = exps;
137: v.cached_function = null;
138: return v;
139: }
140:
141: /**
142: * Human understandable string, used for the column title.
143: */
144: public String toString() {
145: StringBuffer buf = new StringBuffer();
146: buf.append(name);
147: buf.append('(');
148: for (int i = 0; i < params.length; ++i) {
149: buf.append(params[i].text().toString());
150: if (i < params.length - 1) {
151: buf.append(',');
152: }
153: }
154: buf.append(')');
155: return new String(buf);
156: }
157:
158: }
|