1:
31: package ;
32:
33: import ;
34: import ;
35: import ;
36: import ;
37: import ;
38: import ;
39: import ;
40: import ;
41: import ;
42: import ;
43:
44:
61: public class FormulaFunction extends AbstractLValue
62: {
63: private static class FormulaParameterCallback implements ParameterCallback
64: {
65: private TypeValuePair[] backend;
66: private FormulaFunction function;
67:
68: public FormulaParameterCallback(final FormulaFunction function)
69: {
70: this.function = function;
71: this.backend = new TypeValuePair[function.parameters.length];
72: }
73:
74: private TypeValuePair get(int pos) throws EvaluationException
75: {
76: final LValue parameter = function.parameters[pos];
77: final Type paramType = function.metaData.getParameterType(pos);
78: if (parameter != null)
79: {
80: final TypeValuePair result = parameter.evaluate();
81:
82: final TypeRegistry typeRegistry = function.getContext().getTypeRegistry();
83: final TypeValuePair converted = typeRegistry.convertTo(paramType, result);
84: if (converted == null)
85: {
86: Log.debug("Failed to evaluate parameter " + pos + " on function " + function);
87: throw new EvaluationException(LibFormulaErrorValue.ERROR_INVALID_AUTO_ARGUMENT_VALUE);
88: }
89: return converted;
90: }
91: else
92: {
93: return new TypeValuePair(paramType, function.metaData.getDefaultValue(pos));
94: }
95: }
96:
97: public LValue getRaw(int position)
98: {
99: return function.parameters[position];
100: }
101:
102: public Object getValue(int position) throws EvaluationException
103: {
104: final TypeValuePair retval = backend[position];
105: if (retval != null)
106: {
107: return retval.getValue();
108: }
109:
110: final TypeValuePair pair = get(position);
111: backend[position] = pair;
112: return pair.getValue();
113: }
114:
115: public Type getType(int position) throws EvaluationException
116: {
117: final TypeValuePair retval = backend[position];
118: if (retval != null)
119: {
120: return retval.getType();
121: }
122:
123: final TypeValuePair pair = get(position);
124: backend[position] = pair;
125: return pair.getType();
126: }
127:
128: public int getParameterCount()
129: {
130: return backend.length;
131: }
132: }
133:
134: private String functionName;
135: private LValue[] parameters;
136: private Function function;
137: private FunctionDescription metaData;
138:
139: public FormulaFunction(final String functionName, final LValue[] parameters)
140: {
141: this.functionName = functionName;
142: this.parameters = parameters;
143: }
144:
145: public void initialize(final FormulaContext context) throws EvaluationException
146: {
147: super.initialize(context);
148: final FunctionRegistry registry = context.getFunctionRegistry();
149: function = registry.createFunction(functionName);
150: metaData = registry.getMetaData(functionName);
151:
152: for (int i = 0; i < parameters.length; i++)
153: {
154: parameters[i].initialize(context);
155: }
156: }
157:
158:
165: public String getFunctionName()
166: {
167: return functionName;
168: }
169:
170:
177: public Function getFunction()
178: {
179: return function;
180: }
181:
182:
189: public FunctionDescription getMetaData()
190: {
191: return metaData;
192: }
193:
194: public Object clone() throws CloneNotSupportedException
195: {
196: final FormulaFunction fn = (FormulaFunction) super.clone();
197: fn.parameters = (LValue[]) parameters.clone();
198: for (int i = 0; i < parameters.length; i++)
199: {
200: final LValue parameter = parameters[i];
201: fn.parameters[i] = (LValue) parameter.clone();
202: }
203: return fn;
204: }
205:
206: public TypeValuePair evaluate() throws EvaluationException
207: {
208:
209: final FormulaContext context = getContext();
210:
211: if (function == null)
212: {
213: throw new EvaluationException(LibFormulaErrorValue.ERROR_INVALID_FUNCTION_VALUE);
214: }
215: try
216: {
217: return function.evaluate(context, new FormulaParameterCallback(this));
218: }
219: catch(EvaluationException e)
220: {
221: throw e;
222: }
223: catch(Exception e)
224: {
225: throw new EvaluationException(LibFormulaErrorValue.ERROR_UNEXPECTED_VALUE);
226: }
227: }
228:
229:
234: public LValue[] getChildValues()
235: {
236: return (LValue[]) parameters.clone();
237: }
238:
239:
240: public String toString()
241: {
242: StringBuffer b = new StringBuffer();
243: b.append(functionName);
244: b.append("(");
245: for (int i = 0; i < parameters.length; i++)
246: {
247: if (i > 0)
248: {
249: b.append(";");
250: }
251: LValue parameter = parameters[i];
252: b.append(parameter);
253: }
254: b.append(")");
255: return b.toString();
256: }
257:
258:
264: public boolean isConstant()
265: {
266: if (metaData.isVolatile())
267: {
268: return false;
269: }
270: for (int i = 0; i < parameters.length; i++)
271: {
272: LValue value = parameters[i];
273: if (value.isConstant() == false)
274: {
275: return false;
276: }
277: }
278: return true;
279: }
280:
281:
282: }