Source Code Cross Referenced for Expression.java in  » Database-DBMS » mckoi » com » mckoi » database » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database DBMS » mckoi » com.mckoi.database 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * com.mckoi.database.Expression  11 Jul 2000
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:        import java.util.Date;
026:        import java.util.List;
027:        import java.util.ArrayList;
028:        import java.io.StringReader;
029:        import java.io.IOException;
030:        import java.io.ObjectInputStream;
031:        import java.io.ObjectOutputStream;
032:        import com.mckoi.database.sql.SQL;
033:        import com.mckoi.util.BigNumber;
034:
035:        /**
036:         * An expression that can be evaluated in a statement.  This is used as a more
037:         * complete and flexible version of 'Condition' as well as representing column
038:         * and aggregate functions.
039:         * <p>
040:         * This class can represent constant expressions (expressions that have no
041:         * variable input), as well as variable expressions.  Optimizations may be
042:         * possible when evaluating constant expressions.
043:         * <p>
044:         * Some examples of constant expressions;<p><pre>
045:         *   ( 9 + 3 ) * 90
046:         *   ( ? * 9 ) / 1
047:         *   lower("CaPS MUMma")
048:         *   40 & 0x0FF != 39
049:         * </pre>
050:         * Some examples of variable expressions;<p><pre>
051:         *   upper(Part.description)
052:         *   Part.id >= 50
053:         *   VendorMakesPart.part_id == Part.id
054:         *   Part.value_of <= Part.cost_of / 4
055:         * </pre>
056:         * <p>
057:         * <strong>NOTE:</strong> the expression is stored in postfix orientation.  eg.
058:         *   "8 + 9 * 3" becomes "8,9,3,*,+"
059:         * <p>
060:         * <strong>NOTE:</strong> This class is <b>NOT</b> thread safe.  Do not use an
061:         *   expression instance between threads.
062:         *
063:         * @author Tobias Downer
064:         */
065:
066:        public final class Expression implements  java.io.Serializable,
067:                Cloneable {
068:
069:            /**
070:             * Serialization UID.
071:             */
072:            static final long serialVersionUID = 6981261114471924028L;
073:
074:            /**
075:             * The list of elements followed by operators in our expression.  The
076:             * expression elements may be of any type represented by the database
077:             * (see 'addElement' method for the accepted objects).  The expression
078:             * operators may be '+', '-', '*', '*', '/', '=', '>=', '<>', etc (as an
079:             * Operator object (see the Operator class for details)).
080:             * <p>
081:             * This list is stored in postfix order.
082:             */
083:            private ArrayList elements = new ArrayList();
084:
085:            /**
086:             * The evaluation stack for when the expression is evaluated.
087:             */
088:            private transient ArrayList eval_stack;
089:
090:            /**
091:             * The expression as a plain human readable string.  This is in a form that
092:             * can be readily parsed to an Expression object.
093:             */
094:            private StringBuffer text;
095:
096:            /**
097:             * Constructs a new Expression.
098:             */
099:            public Expression() {
100:                text = new StringBuffer();
101:            }
102:
103:            /**
104:             * Constructs a new Expression with a single object element.
105:             */
106:            public Expression(Object ob) {
107:                this ();
108:                addElement(ob);
109:            }
110:
111:            /**
112:             * Constructs a copy of the given Expression.
113:             */
114:            public Expression(Expression exp) {
115:                concat(exp);
116:                text = new StringBuffer(new String(exp.text));
117:            }
118:
119:            /**
120:             * Constructs a new Expression from the concatination of expression1 and
121:             * expression2 and the operator for them.
122:             */
123:            public Expression(Expression exp1, Operator op, Expression exp2) {
124:                // Remember, this is in postfix notation.
125:                elements.addAll(exp1.elements);
126:                elements.addAll(exp2.elements);
127:                elements.add(op);
128:            }
129:
130:            /**
131:             * Returns the StringBuffer that we can use to append plain text
132:             * representation as we are parsing the expression.
133:             */
134:            public StringBuffer text() {
135:                return text;
136:            }
137:
138:            /**
139:             * Copies the text from the given expression.
140:             */
141:            public void copyTextFrom(Expression e) {
142:                this .text = new StringBuffer(new String(e.text()));
143:            }
144:
145:            /**
146:             * Static method that parses the given string which contains an expression
147:             * into an Expression object.  For example, this will parse strings such
148:             * as '(a + 9) * 2 = b' or 'upper(concat('12', '56', id))'.
149:             * <p>
150:             * Care should be taken to not use this method inside an inner loop because
151:             * it creates a lot of objects.
152:             */
153:            public static Expression parse(String expression) {
154:                synchronized (expression_parser) {
155:                    try {
156:                        expression_parser.ReInit(new StringReader(expression));
157:                        expression_parser.reset();
158:                        Expression exp = expression_parser.parseExpression();
159:
160:                        exp.text().setLength(0);
161:                        exp.text().append(expression);
162:                        return exp;
163:                    } catch (com.mckoi.database.sql.ParseException e) {
164:                        throw new RuntimeException(e.getMessage());
165:                    }
166:                }
167:            }
168:
169:            /**
170:             * A static expression parser.  To use this we must first synchronize over
171:             * the object.
172:             */
173:            private final static SQL expression_parser = new SQL(
174:                    new StringReader(""));
175:
176:            /**
177:             * Generates a simple expression from two objects and an operator.
178:             */
179:            public static Expression simple(Object ob1, Operator op, Object ob2) {
180:                Expression exp = new Expression(ob1);
181:                exp.addElement(ob2);
182:                exp.addElement(op);
183:                return exp;
184:            }
185:
186:            /**
187:             * Adds a new element into the expression.  String, BigNumber, Boolean and
188:             * Variable are the types of elements allowed.
189:             * <p>
190:             * Must be added in postfix order.
191:             */
192:            public void addElement(Object ob) {
193:                if (ob == null) {
194:                    elements.add(TObject.nullVal());
195:                } else if (ob instanceof  TObject
196:                        || ob instanceof  ParameterSubstitution
197:                        || ob instanceof  CorrelatedVariable
198:                        || ob instanceof  Variable || ob instanceof  FunctionDef
199:                        || ob instanceof  Operator
200:                        || ob instanceof  StatementTreeObject) {
201:                    elements.add(ob);
202:                } else {
203:                    throw new Error(
204:                            "Unknown element type added to expression: "
205:                                    + ob.getClass());
206:                }
207:            }
208:
209:            /**
210:             * Merges an expression with this expression.  For example, given the
211:             * expression 'ab', if the expression 'abc+-' was added the expression would
212:             * become 'ababc+-'.
213:             * <p>
214:             * This method is useful when copying parts of other expressions when forming
215:             * an expression.
216:             * <p>
217:             * This always returns this expression.  This does not change 'text()'.
218:             */
219:            public Expression concat(Expression expr) {
220:                elements.addAll(expr.elements);
221:                return this ;
222:            }
223:
224:            /**
225:             * Adds a new operator into the expression.  Operators are represented as
226:             * an Operator (eg. ">", "+", "<<", "!=" )
227:             * <p>
228:             * Must be added in postfix order.
229:             */
230:            public void addOperator(Operator op) {
231:                elements.add(op);
232:            }
233:
234:            /**
235:             * Returns the number of elements and operators that are in this postfix
236:             * list.
237:             */
238:            public int size() {
239:                return elements.size();
240:            }
241:
242:            /**
243:             * Returns the element at the given position in the postfix list.  Note, this
244:             * can return Operator's.
245:             */
246:            public Object elementAt(int n) {
247:                return elements.get(n);
248:            }
249:
250:            /**
251:             * Returns the element at the end of the postfix list (the last element).
252:             */
253:            public Object last() {
254:                return elements.get(size() - 1);
255:            }
256:
257:            /**
258:             * Sets the element at the given position in the postfix list.  This should
259:             * be called after the expression has been setup to alter variable alias
260:             * names, etc.
261:             */
262:            public void setElementAt(int n, Object ob) {
263:                elements.set(n, ob);
264:            }
265:
266:            /**
267:             * Pushes an element onto the evaluation stack.
268:             */
269:            private final void push(Object ob) {
270:                eval_stack.add(ob);
271:            }
272:
273:            /**
274:             * Pops an element from the evaluation stack.
275:             */
276:            private final Object pop() {
277:                return eval_stack.remove(eval_stack.size() - 1);
278:            }
279:
280:            /**
281:             * Returns a complete List of Variable objects in this expression not
282:             * including correlated variables.
283:             */
284:            public List allVariables() {
285:                ArrayList vars = new ArrayList();
286:                for (int i = 0; i < elements.size(); ++i) {
287:                    Object ob = elements.get(i);
288:                    if (ob instanceof  Variable) {
289:                        vars.add(ob);
290:                    } else if (ob instanceof  FunctionDef) {
291:                        Expression[] params = ((FunctionDef) ob)
292:                                .getParameters();
293:                        for (int n = 0; n < params.length; ++n) {
294:                            vars.addAll(params[n].allVariables());
295:                        }
296:                    } else if (ob instanceof  TObject) {
297:                        TObject tob = (TObject) ob;
298:                        if (tob.getTType() instanceof  TArrayType) {
299:                            Expression[] exp_list = (Expression[]) tob
300:                                    .getObject();
301:                            for (int n = 0; n < exp_list.length; ++n) {
302:                                vars.addAll(exp_list[n].allVariables());
303:                            }
304:                        }
305:                    }
306:                }
307:                return vars;
308:            }
309:
310:            /**
311:             * Returns a complete list of all element objects that are in this expression
312:             * and in the parameters of the functions of this expression.
313:             */
314:            public List allElements() {
315:                ArrayList elems = new ArrayList();
316:                for (int i = 0; i < elements.size(); ++i) {
317:                    Object ob = elements.get(i);
318:                    if (ob instanceof  Operator) {
319:                    } else if (ob instanceof  FunctionDef) {
320:                        Expression[] params = ((FunctionDef) ob)
321:                                .getParameters();
322:                        for (int n = 0; n < params.length; ++n) {
323:                            elems.addAll(params[n].allElements());
324:                        }
325:                    } else if (ob instanceof  TObject) {
326:                        TObject tob = (TObject) ob;
327:                        if (tob.getTType() instanceof  TArrayType) {
328:                            Expression[] exp_list = (Expression[]) tob
329:                                    .getObject();
330:                            for (int n = 0; n < exp_list.length; ++n) {
331:                                elems.addAll(exp_list[n].allElements());
332:                            }
333:                        } else {
334:                            elems.add(ob);
335:                        }
336:                    } else {
337:                        elems.add(ob);
338:                    }
339:                }
340:                return elems;
341:            }
342:
343:            /**
344:             * A general prepare that cascades through the expression and its parents and
345:             * substitutes an elements that the preparer wants to substitute.
346:             * <p>
347:             * NOTE: This will not cascade through to the parameters of Function objects
348:             *   however it will cascade through FunctionDef parameters.  For this
349:             *   reason you MUST call 'prepareFunctions' after this method.
350:             */
351:            public void prepare(ExpressionPreparer preparer)
352:                    throws DatabaseException {
353:                for (int n = 0; n < elements.size(); ++n) {
354:                    Object ob = elements.get(n);
355:
356:                    // If the preparer will prepare this type of object then set the
357:                    // entry with the prepared object.
358:                    if (preparer.canPrepare(ob)) {
359:                        elements.set(n, preparer.prepare(ob));
360:                    }
361:
362:                    Expression[] exp_list = null;
363:                    if (ob instanceof  FunctionDef) {
364:                        FunctionDef func = (FunctionDef) ob;
365:                        exp_list = func.getParameters();
366:                    } else if (ob instanceof  TObject) {
367:                        TObject tob = (TObject) ob;
368:                        if (tob.getTType() instanceof  TArrayType) {
369:                            exp_list = (Expression[]) tob.getObject();
370:                        }
371:                    } else if (ob instanceof  StatementTreeObject) {
372:                        StatementTreeObject stree = (StatementTreeObject) ob;
373:                        stree.prepareExpressions(preparer);
374:                    }
375:
376:                    if (exp_list != null) {
377:                        for (int p = 0; p < exp_list.length; ++p) {
378:                            exp_list[p].prepare(preparer);
379:                        }
380:                    }
381:
382:                }
383:            }
384:
385:            /**
386:             * Returns true if the expression doesn't include any variables or non
387:             * constant functions (is constant).  Note that a correlated variable is
388:             * considered a constant.
389:             */
390:            public boolean isConstant() {
391:                for (int n = 0; n < elements.size(); ++n) {
392:                    Object ob = elements.get(n);
393:                    if (ob instanceof  TObject) {
394:                        TObject tob = (TObject) ob;
395:                        TType ttype = tob.getTType();
396:                        // If this is a query plan, return false
397:                        if (ttype instanceof  TQueryPlanType) {
398:                            return false;
399:                        }
400:                        // If this is an array, check the array for constants
401:                        else if (ttype instanceof  TArrayType) {
402:                            Expression[] exp_list = (Expression[]) tob
403:                                    .getObject();
404:                            for (int p = 0; p < exp_list.length; ++p) {
405:                                if (!exp_list[p].isConstant()) {
406:                                    return false;
407:                                }
408:                            }
409:                        }
410:                    } else if (ob instanceof  Variable) {
411:                        return false;
412:                    } else if (ob instanceof  FunctionDef) {
413:                        Expression[] params = ((FunctionDef) ob)
414:                                .getParameters();
415:                        for (int p = 0; p < params.length; ++p) {
416:                            if (!params[p].isConstant()) {
417:                                return false;
418:                            }
419:                        }
420:                    }
421:                }
422:                return true;
423:            }
424:
425:            /**
426:             * Returns true if the expression has a subquery (eg 'in ( select ... )')
427:             * somewhere in it (this cascades through function parameters also).
428:             */
429:            public boolean hasSubQuery() {
430:                List list = allElements();
431:                int len = list.size();
432:                for (int n = 0; n < len; ++n) {
433:                    Object ob = list.get(n);
434:                    if (ob instanceof  TObject) {
435:                        TObject tob = (TObject) ob;
436:                        if (tob.getTType() instanceof  TQueryPlanType) {
437:                            return true;
438:                        }
439:                    }
440:                }
441:                return false;
442:            }
443:
444:            /**
445:             * Returns true if the expression contains a NOT operator somewhere in it.
446:             */
447:            public boolean containsNotOperator() {
448:                for (int n = 0; n < elements.size(); ++n) {
449:                    Object ob = elements.get(n);
450:                    if (ob instanceof  Operator) {
451:                        if (((Operator) ob).isNot()) {
452:                            return true;
453:                        }
454:                    }
455:                }
456:                return false;
457:            }
458:
459:            /**
460:             * Discovers all the correlated variables in this expression.  If this
461:             * expression contains a sub-query plan, we ask the plan to find the list of
462:             * correlated variables.  The discovery process increments the 'level'
463:             * variable for each sub-plan.
464:             */
465:            public ArrayList discoverCorrelatedVariables(int level,
466:                    ArrayList list) {
467:                List elems = allElements();
468:                int sz = elems.size();
469:                // For each element
470:                for (int i = 0; i < sz; ++i) {
471:                    Object ob = elems.get(i);
472:                    if (ob instanceof  CorrelatedVariable) {
473:                        CorrelatedVariable v = (CorrelatedVariable) ob;
474:                        if (v.getQueryLevelOffset() == level) {
475:                            list.add(v);
476:                        }
477:                    } else if (ob instanceof  TObject) {
478:                        TObject tob = (TObject) ob;
479:                        if (tob.getTType() instanceof  TQueryPlanType) {
480:                            QueryPlanNode node = (QueryPlanNode) tob
481:                                    .getObject();
482:                            list = node.discoverCorrelatedVariables(level + 1,
483:                                    list);
484:                        }
485:                    }
486:                }
487:                return list;
488:            }
489:
490:            /**
491:             * Discovers all the tables in the sub-queries of this expression.  This is
492:             * used for determining all the tables that a query plan touches.
493:             */
494:            public ArrayList discoverTableNames(ArrayList list) {
495:                List elems = allElements();
496:                int sz = elems.size();
497:                // For each element
498:                for (int i = 0; i < sz; ++i) {
499:                    Object ob = elems.get(i);
500:                    if (ob instanceof  TObject) {
501:                        TObject tob = (TObject) ob;
502:                        if (tob.getTType() instanceof  TQueryPlanType) {
503:                            QueryPlanNode node = (QueryPlanNode) tob
504:                                    .getObject();
505:                            list = node.discoverTableNames(list);
506:                        }
507:                    }
508:                }
509:                return list;
510:            }
511:
512:            /**
513:             * Returns the QueryPlanNode object in this expression if it evaluates to a
514:             * single QueryPlanNode, otherwise returns null.
515:             */
516:            public QueryPlanNode getQueryPlanNode() {
517:                Object ob = elementAt(0);
518:                if (size() == 1 && ob instanceof  TObject) {
519:                    TObject tob = (TObject) ob;
520:                    if (tob.getTType() instanceof  TQueryPlanType) {
521:                        return (QueryPlanNode) tob.getObject();
522:                    }
523:                }
524:                return null;
525:            }
526:
527:            /**
528:             * Returns the Variable if this expression evaluates to a single variable,
529:             * otherwise returns null.  A correlated variable will not be returned.
530:             */
531:            public Variable getVariable() {
532:                Object ob = elementAt(0);
533:                if (size() == 1 && ob instanceof  Variable) {
534:                    return (Variable) ob;
535:                }
536:                return null;
537:            }
538:
539:            /**
540:             * Returns an array of two Expression objects that represent the left hand
541:             * and right and side of the last operator in the post fix notation.
542:             * For example, (a + b) - (c + d) will return { (a + b), (c + d) }.  Or
543:             * more a more useful example is;<p><pre>
544:             *   id + 3 > part_id - 2 will return ( id + 3, part_id - 2 }
545:             * </pre>
546:             */
547:            public Expression[] split() {
548:                if (size() <= 1) {
549:                    throw new Error(
550:                            "Can only split expressions with more than 1 element.");
551:                }
552:
553:                int midpoint = -1;
554:                int stack_size = 0;
555:                for (int n = 0; n < size() - 1; ++n) {
556:                    Object ob = elementAt(n);
557:                    if (ob instanceof  Operator) {
558:                        --stack_size;
559:                    } else {
560:                        ++stack_size;
561:                    }
562:
563:                    if (stack_size == 1) {
564:                        midpoint = n;
565:                    }
566:                }
567:
568:                if (midpoint == -1) {
569:                    throw new Error("postfix format error: Midpoint not found.");
570:                }
571:
572:                Expression lhs = new Expression();
573:                for (int n = 0; n <= midpoint; ++n) {
574:                    lhs.addElement(elementAt(n));
575:                }
576:
577:                Expression rhs = new Expression();
578:                for (int n = midpoint + 1; n < size() - 1; ++n) {
579:                    rhs.addElement(elementAt(n));
580:                }
581:
582:                return new Expression[] { lhs, rhs };
583:            }
584:
585:            /**
586:             * Returns the end Expression of this expression.  For example, an expression
587:             * of 'ab' has an end expression of 'b'.  The expression 'abc+=' has an end
588:             * expression of 'abc+='.
589:             * <p>
590:             * This is a useful method to call in the middle of an Expression object
591:             * being formed.  It allows for the last complete expression to be
592:             * returned.
593:             * <p>
594:             * If this is called when an expression is completely formed it will always
595:             * return the complete expression.
596:             */
597:            public Expression getEndExpression() {
598:
599:                int stack_size = 1;
600:                int end = size() - 1;
601:                for (int n = end; n > 0; --n) {
602:                    Object ob = elementAt(n);
603:                    if (ob instanceof  Operator) {
604:                        ++stack_size;
605:                    } else {
606:                        --stack_size;
607:                    }
608:
609:                    if (stack_size == 0) {
610:                        // Now, n .. end represents the new expression.
611:                        Expression new_exp = new Expression();
612:                        for (int i = n; i <= end; ++i) {
613:                            new_exp.addElement(elementAt(i));
614:                        }
615:                        return new_exp;
616:                    }
617:                }
618:
619:                return new Expression(this );
620:            }
621:
622:            /**
623:             * Breaks this expression into a list of sub-expressions that are split
624:             * by the given operator.  For example, given the expression;
625:             * <p><pre>
626:             *   (a = b AND b = c AND (a = 2 OR c = 1))
627:             * </pre><p>
628:             * Calling this method with logical_op = "and" will return a list of the
629:             * three expressions.
630:             * <p>
631:             * This is a common function used to split up an expressions into logical
632:             * components for processing.
633:             */
634:            public ArrayList breakByOperator(ArrayList list,
635:                    final String logical_op) {
636:                // The last operator must be 'and'
637:                Object ob = last();
638:                if (ob instanceof  Operator) {
639:                    Operator op = (Operator) ob;
640:                    if (op.is(logical_op)) {
641:                        // Last operator is 'and' so split and recurse.
642:                        Expression[] exps = split();
643:                        list = exps[0].breakByOperator(list, logical_op);
644:                        list = exps[1].breakByOperator(list, logical_op);
645:                        return list;
646:                    }
647:                }
648:                // If no last expression that matches then add this expression to the
649:                // list.
650:                list.add(this );
651:                return list;
652:            }
653:
654:            /**
655:             * Evaluates this expression and returns an Object that represents the
656:             * result of the evaluation.  The passed VariableResolver object is used
657:             * to resolve the variable name to a value.  The GroupResolver object is
658:             * used if there are any aggregate functions in the evaluation - this can be
659:             * null if evaluating an expression without grouping aggregates.  The query
660:             * context object contains contextual information about the environment of
661:             * the query.
662:             * <p>
663:             * NOTE: This method is gonna be called a lot, so we need it to be optimal.
664:             * <p>
665:             * NOTE: This method is <b>not</b> thread safe!  The reason it's not safe
666:             *   is because of the evaluation stack.
667:             */
668:            public TObject evaluate(GroupResolver group,
669:                    VariableResolver resolver, QueryContext context) {
670:                // Optimization - trivial case of 'a' or 'ab*' postfix are tested for
671:                //   here.
672:                int element_count = elements.size();
673:                if (element_count == 1) {
674:                    return (TObject) elementToObject(0, group, resolver,
675:                            context);
676:                } else if (element_count == 3) {
677:                    TObject o1 = (TObject) elementToObject(0, group, resolver,
678:                            context);
679:                    TObject o2 = (TObject) elementToObject(1, group, resolver,
680:                            context);
681:                    Operator op = (Operator) elements.get(2);
682:                    return op.eval(o1, o2, group, resolver, context);
683:                }
684:
685:                if (eval_stack == null) {
686:                    eval_stack = new ArrayList();
687:                }
688:
689:                for (int n = 0; n < element_count; ++n) {
690:                    Object val = elementToObject(n, group, resolver, context);
691:                    if (val instanceof  Operator) {
692:                        // Pop the last two values off the stack, evaluate them and push
693:                        // the new value back on.
694:                        Operator op = (Operator) val;
695:
696:                        TObject v2 = (TObject) pop();
697:                        TObject v1 = (TObject) pop();
698:
699:                        push(op.eval(v1, v2, group, resolver, context));
700:                    } else {
701:                        push(val);
702:                    }
703:                }
704:                // We should end with a single value on the stack.
705:                return (TObject) pop();
706:            }
707:
708:            /**
709:             * Evaluation without a grouping table.
710:             */
711:            public TObject evaluate(VariableResolver resolver,
712:                    QueryContext context) {
713:                return evaluate(null, resolver, context);
714:            }
715:
716:            /**
717:             * Returns the element at the given position in the expression list.  If
718:             * the element is a variable then it is resolved on the VariableResolver.
719:             * If the element is a function then it is evaluated and the result is
720:             * returned.
721:             */
722:            private Object elementToObject(int n, GroupResolver group,
723:                    VariableResolver resolver, QueryContext context) {
724:                Object ob = elements.get(n);
725:                if (ob instanceof  TObject || ob instanceof  Operator) {
726:                    return ob;
727:                } else if (ob instanceof  Variable) {
728:                    return resolver.resolve((Variable) ob);
729:                } else if (ob instanceof  CorrelatedVariable) {
730:                    return ((CorrelatedVariable) ob).getEvalResult();
731:                } else if (ob instanceof  FunctionDef) {
732:                    Function fun = ((FunctionDef) ob).getFunction(context);
733:                    return fun.evaluate(group, resolver, context);
734:                } else {
735:                    if (ob == null) {
736:                        throw new NullPointerException(
737:                                "Null element in expression");
738:                    }
739:                    throw new Error("Unknown element type: " + ob.getClass());
740:                }
741:            }
742:
743:            /**
744:             * Cascades through the expression and if any aggregate functions are found
745:             * returns true, otherwise returns false.
746:             */
747:            public boolean hasAggregateFunction(QueryContext context) {
748:                for (int n = 0; n < elements.size(); ++n) {
749:                    Object ob = elements.get(n);
750:                    if (ob instanceof  FunctionDef) {
751:                        if (((FunctionDef) ob).isAggregate(context)) {
752:                            return true;
753:                        }
754:                    } else if (ob instanceof  TObject) {
755:                        TObject tob = (TObject) ob;
756:                        if (tob.getTType() instanceof  TArrayType) {
757:                            Expression[] list = (Expression[]) tob.getObject();
758:                            for (int i = 0; i < list.length; ++i) {
759:                                if (list[i].hasAggregateFunction(context)) {
760:                                    return true;
761:                                }
762:                            }
763:                        }
764:                    }
765:                }
766:                return false;
767:            }
768:
769:            /**
770:             * Determines the type of object this expression evaluates to.  We determine
771:             * this by looking at the last element of the expression.  If the last
772:             * element is a TType object, it returns the type.  If the last element is a
773:             * Function, Operator or Variable then it returns the type that these
774:             * objects have set as their result type.
775:             */
776:            public TType returnTType(VariableResolver resolver,
777:                    QueryContext context) {
778:                Object ob = elements.get(elements.size() - 1);
779:                if (ob instanceof  FunctionDef) {
780:                    Function fun = ((FunctionDef) ob).getFunction(context);
781:                    return fun.returnTType(resolver, context);
782:                } else if (ob instanceof  TObject) {
783:                    return ((TObject) ob).getTType();
784:                } else if (ob instanceof  Operator) {
785:                    Operator op = (Operator) ob;
786:                    return op.returnTType();
787:                } else if (ob instanceof  Variable) {
788:                    Variable variable = (Variable) ob;
789:                    return resolver.returnTType(variable);
790:                } else if (ob instanceof  CorrelatedVariable) {
791:                    CorrelatedVariable variable = (CorrelatedVariable) ob;
792:                    return variable.returnTType();
793:                } else {
794:                    throw new Error("Unable to determine type for expression.");
795:                }
796:            }
797:
798:            /**
799:             * Performs a deep clone of this object, calling 'clone' on any elements
800:             * that are mutable or shallow copying immutable members.
801:             */
802:            public Object clone() throws CloneNotSupportedException {
803:                // Shallow clone
804:                Expression v = (Expression) super .clone();
805:                v.eval_stack = null;
806:                //    v.text = new StringBuffer(new String(text));
807:                int size = elements.size();
808:                ArrayList cloned_elements = new ArrayList(size);
809:                v.elements = cloned_elements;
810:
811:                // Clone items in the elements list
812:                for (int i = 0; i < size; ++i) {
813:                    Object element = elements.get(i);
814:
815:                    if (element instanceof  TObject) {
816:                        // TObject is immutable except for TArrayType and TQueryPlanType
817:                        TObject tob = (TObject) element;
818:                        TType ttype = tob.getTType();
819:                        // For a query plan
820:                        if (ttype instanceof  TQueryPlanType) {
821:                            QueryPlanNode node = (QueryPlanNode) tob
822:                                    .getObject();
823:                            node = (QueryPlanNode) node.clone();
824:                            element = new TObject(ttype, node);
825:                        }
826:                        // For an array
827:                        else if (ttype instanceof  TArrayType) {
828:                            Expression[] arr = (Expression[]) tob.getObject();
829:                            arr = (Expression[]) arr.clone();
830:                            for (int n = 0; n < arr.length; ++n) {
831:                                arr[n] = (Expression) arr[n].clone();
832:                            }
833:                            element = new TObject(ttype, arr);
834:                        }
835:                    } else if (element instanceof  Operator
836:                            || element instanceof  ParameterSubstitution) {
837:                        // immutable so we do not need to clone these
838:                    } else if (element instanceof  CorrelatedVariable) {
839:                        element = ((CorrelatedVariable) element).clone();
840:                    } else if (element instanceof  Variable) {
841:                        element = ((Variable) element).clone();
842:                    } else if (element instanceof  FunctionDef) {
843:                        element = ((FunctionDef) element).clone();
844:                    } else if (element instanceof  StatementTreeObject) {
845:                        element = ((StatementTreeObject) element).clone();
846:                    } else {
847:                        throw new CloneNotSupportedException(element.getClass()
848:                                .toString());
849:                    }
850:                    cloned_elements.add(element);
851:                }
852:
853:                return v;
854:            }
855:
856:            /**
857:             * Returns a string representation of this object for diagnostic
858:             * purposes.
859:             */
860:            public String toString() {
861:                StringBuffer buf = new StringBuffer();
862:                buf.append("[ Expression ");
863:                if (text() != null) {
864:                    buf.append("[");
865:                    buf.append(text().toString());
866:                    buf.append("]");
867:                }
868:                buf.append(": ");
869:                for (int n = 0; n < elements.size(); ++n) {
870:                    buf.append(elements.get(n));
871:                    if (n < elements.size() - 1) {
872:                        buf.append(",");
873:                    }
874:                }
875:                buf.append(" ]");
876:                return new String(buf);
877:            }
878:
879:            // ---------- Serialization methods ----------
880:
881:            /**
882:             * Writes the state of this object to the object stream.  This method is
883:             * implemented because GCJ doesn't like it if you implement readObject
884:             * without writeObject.
885:             */
886:            private void writeObject(ObjectOutputStream out) throws IOException {
887:                out.defaultWriteObject();
888:            }
889:
890:            /**
891:             * Reads the state of this object from the object stream.
892:             */
893:            private void readObject(ObjectInputStream in) throws IOException,
894:                    ClassNotFoundException {
895:                in.defaultReadObject();
896:
897:                // This converts old types to the new TObject type system introduced
898:                // in version 0.94.
899:                int sz = elements.size();
900:                for (int i = 0; i < sz; ++i) {
901:                    Object ob = elements.get(i);
902:                    TObject conv_object = null;
903:                    if (ob == null
904:                            || ob instanceof  com.mckoi.database.global.NullObject) {
905:                        conv_object = TObject.nullVal();
906:                    } else if (ob instanceof  String) {
907:                        conv_object = TObject.stringVal((String) ob);
908:                    } else if (ob instanceof  java.math.BigDecimal) {
909:                        conv_object = TObject.bigNumberVal(BigNumber
910:                                .fromBigDecimal((java.math.BigDecimal) ob));
911:                    } else if (ob instanceof  java.util.Date) {
912:                        conv_object = TObject.dateVal((java.util.Date) ob);
913:                    } else if (ob instanceof  Boolean) {
914:                        conv_object = TObject.booleanVal(((Boolean) ob)
915:                                .booleanValue());
916:                    }
917:                    if (conv_object != null) {
918:                        elements.set(i, conv_object);
919:                    }
920:                }
921:            }
922:
923:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.