1:
31: package ;
32:
33: import ;
34:
35: import ;
36: import ;
37: import ;
38:
39:
46: public class Term extends AbstractLValue
47: {
48: private LValue optimizedHeadValue;
49: private LValue headValue;
50: private ArrayList operators;
51: private ArrayList operands;
52: private InfixOperator[] operatorArray;
53: private LValue[] operandsArray;
54: private boolean initialized;
55: private static final LValue[] EMPTY_L_VALUE = new LValue[0];
56: private static final InfixOperator[] EMPTY_OPERATOR = new InfixOperator[0];
57:
58: public Term(final LValue headValue)
59: {
60: if (headValue == null)
61: {
62: throw new NullPointerException();
63: }
64:
65: this.headValue = headValue;
66: }
67:
68: public TypeValuePair evaluate() throws EvaluationException
69: {
70: TypeValuePair result = optimizedHeadValue.evaluate();
71: for (int i = 0; i < operandsArray.length; i++)
72: {
73: final LValue value = operandsArray[i];
74: final InfixOperator op = operatorArray[i];
75: result = op.evaluate(getContext(), result, value.evaluate());
76: }
77: return result;
78: }
79:
80: public void add(final InfixOperator operator, final LValue operand)
81: {
82: if (operator == null)
83: {
84: throw new NullPointerException();
85: }
86: if (operand == null)
87: {
88: throw new NullPointerException();
89: }
90:
91: if (operands == null || operators == null)
92: {
93: this.operands = new ArrayList();
94: this.operators = new ArrayList();
95: }
96:
97: operands.add(operand);
98: operators.add(operator);
99: initialized = false;
100: }
101:
102: public void initialize(final FormulaContext context) throws EvaluationException
103: {
104: super.initialize(context);
105: if (operands == null || operators == null)
106: {
107: this.optimizedHeadValue = headValue;
108: this.optimizedHeadValue.initialize(context);
109: this.operandsArray = EMPTY_L_VALUE;
110: this.operatorArray = EMPTY_OPERATOR;
111: return;
112: }
113:
114: if (initialized)
115: {
116: optimizedHeadValue.initialize(context);
117: for (int i = 0; i < operandsArray.length; i++)
118: {
119: final LValue lValue = operandsArray[i];
120: lValue.initialize(context);
121: }
122: return;
123: }
124:
125: optimize(context);
126: }
127:
128: private void optimize(final FormulaContext context) throws EvaluationException
129: {
130: final ArrayList operators = (ArrayList) this.operators.clone();
131: final ArrayList operands = (ArrayList) this.operands.clone();
132: this.optimizedHeadValue = headValue;
133:
134: while (true)
135: {
136:
137:
138: final InfixOperator op = (InfixOperator) operators.get(0);
139: int level = op.getLevel();
140: boolean moreThanOne = false;
141: for (int i = 1; i < operators.size(); i++)
142: {
143: final InfixOperator operator = (InfixOperator) operators.get(i);
144: final int opLevel = operator.getLevel();
145: if (opLevel != level)
146: {
147: moreThanOne = true;
148: level = Math.min(opLevel, level);
149: }
150: }
151:
152: if (moreThanOne == false)
153: {
154:
155: break;
156: }
157:
158:
159: Term subTerm = null;
160: for (int i = 0; i < operators.size(); i++)
161: {
162: final InfixOperator operator = (InfixOperator) operators.get(i);
163: if (operator.getLevel() != level)
164: {
165: subTerm = null;
166: continue;
167: }
168:
169: if (subTerm == null)
170: {
171: if (i == 0)
172: {
173: subTerm = new Term(optimizedHeadValue);
174: optimizedHeadValue = subTerm;
175: }
176: else
177: {
178: final LValue lval = (LValue) operands.get(i - 1);
179: subTerm = new Term(lval);
180: operands.set(i - 1, subTerm);
181: }
182: }
183:
184:
185: final LValue operand = (LValue) operands.get(i);
186: subTerm.add(operator, operand);
187: operands.remove(i);
188: operators.remove(i);
189:
190:
191: i -= 1;
192: }
193: }
194:
195: this.operatorArray = (InfixOperator[])
196: operators.toArray(new InfixOperator[operators.size()]);
197: this.operandsArray = (LValue[])
198: operands.toArray(new LValue[operands.size()]);
199: this.optimizedHeadValue.initialize(context);
200: for (int i = 0; i < operandsArray.length; i++)
201: {
202: final LValue value = operandsArray[i];
203: value.initialize(context);
204: }
205:
206: }
207:
208:
213: public LValue[] getChildValues()
214: {
215: final LValue[] values = new LValue[operandsArray.length + 1];
216: values[0] = headValue;
217: System.arraycopy(operandsArray, 0, values, 1, operandsArray.length);
218: return values;
219: }
220:
221:
222: public String toString()
223: {
224: final StringBuffer b = new StringBuffer();
225:
226: b.append("(");
227: b.append(headValue);
228: if (operands != null && operators != null)
229: {
230: for (int i = 0; i < operands.size(); i++)
231: {
232: final InfixOperator op = (InfixOperator) operators.get(i);
233: final LValue value = (LValue) operands.get(i);
234: b.append(op);
235: b.append(value);
236: }
237: }
238: b.append(")");
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254: return b.toString();
255: }
256:
257:
263: public boolean isConstant()
264: {
265: if (headValue.isConstant() == false)
266: {
267: return false;
268: }
269:
270: for (int i = 0; i < operands.size(); i++)
271: {
272: final LValue value = (LValue) operands.get(i);
273: if (value.isConstant() == false)
274: {
275: return false;
276: }
277: }
278: return true;
279: }
280:
281: public Object clone() throws CloneNotSupportedException
282: {
283: final Term o = (Term) super.clone();
284: if (operands != null)
285: {
286: o.operands = (ArrayList) operands.clone();
287: }
288: if (operators != null)
289: {
290: o.operators = (ArrayList) operators.clone();
291: }
292: o.headValue = (LValue) headValue.clone();
293: o.optimizedHeadValue = null;
294: o.operandsArray = null;
295: o.operatorArray = null;
296: o.initialized = false;
297: return o;
298: }
299:
300: public InfixOperator[] getOperands ()
301: {
302: return (InfixOperator[]) operands.toArray(new InfixOperator[operands.size()]);
303: }
304:
305: public LValue[] getOperators ()
306: {
307: return (LValue[]) operators.toArray(new LValue[operators.size()]);
308: }
309:
310: public LValue getHeadValue()
311: {
312: return headValue;
313: }
314:
315:
322: public LValue getOptimizedHeadValue()
323: {
324: return optimizedHeadValue;
325: }
326:
327:
332: public InfixOperator[] getOptimizedOperators()
333: {
334: return operatorArray;
335: }
336:
337:
342: public LValue[] getOptimizedOperands()
343: {
344: return operandsArray;
345: }
346: }