Source Code Cross Referenced for QLParser.java in  » EJB-Server-resin-3.1.5 » resin » com » caucho » ejb » ql » 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 » EJB Server resin 3.1.5 » resin » com.caucho.ejb.ql 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
0003:         *
0004:         * This file is part of Resin(R) Open Source
0005:         *
0006:         * Each copy or derived work must preserve the copyright notice and this
0007:         * notice unmodified.
0008:         *
0009:         * Resin Open Source is free software; you can redistribute it and/or modify
0010:         * it under the terms of the GNU General Public License as published by
0011:         * the Free Software Foundation; either version 2 of the License, or
0012:         * (at your option) any later version.
0013:         *
0014:         * Resin Open Source is distributed in the hope that it will be useful,
0015:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
0017:         * of NON-INFRINGEMENT.  See the GNU General Public License for more
0018:         * details.
0019:         *
0020:         * You should have received a copy of the GNU General Public License
0021:         * along with Resin Open Source; if not, write to the
0022:         *
0023:         *   Free Software Foundation, Inc.
0024:         *   59 Temple Place, Suite 330
0025:         *   Boston, MA 02111-1307  USA
0026:         *
0027:         * @author Scott Ferguson
0028:         */
0029:
0030:        package com.caucho.ejb.ql;
0031:
0032:        import com.caucho.ejb.cfg21.EjbEntityBean;
0033:        import com.caucho.config.ConfigException;
0034:        import com.caucho.config.LineConfigException;
0035:        import com.caucho.ejb.cfg.*;
0036:        import com.caucho.util.CharBuffer;
0037:        import com.caucho.util.IntMap;
0038:        import com.caucho.util.L10N;
0039:        import com.caucho.util.Log;
0040:
0041:        import javax.ejb.EJBLocalObject;
0042:        import javax.ejb.EntityBean;
0043:        import javax.ejb.FinderException;
0044:        import java.util.ArrayList;
0045:        import java.util.HashMap;
0046:        import java.util.logging.Logger;
0047:
0048:        /**
0049:         * Contains the parser for EJB-QL queries and stores the parsed expressions.
0050:         *
0051:         * <p>The expression tree is rooted at Expr.
0052:         */
0053:        public class QLParser extends Query {
0054:            static final Logger log = Log.open(QLParser.class);
0055:            static final L10N L = new L10N(QLParser.class);
0056:
0057:            final static int IDENTIFIER = 128;
0058:            final static int INTEGER = IDENTIFIER + 1;
0059:            final static int LONG = INTEGER + 1;
0060:            final static int DOUBLE = LONG + 1;
0061:            final static int STRING = DOUBLE + 1;
0062:            final static int TRUE = STRING + 1;
0063:            final static int FALSE = TRUE + 1;
0064:            final static int UNKNOWN = FALSE + 1;
0065:            final static int MEMBER = UNKNOWN + 1;
0066:            final static int OF = MEMBER + 1;
0067:            final static int EMPTY = OF + 1;
0068:            final static int NULL = EMPTY + 1;
0069:
0070:            final static int FROM = NULL + 1;
0071:            final static int IN = FROM + 1;
0072:            final static int SELECT = IN + 1;
0073:            final static int DISTINCT = SELECT + 1;
0074:            final static int WHERE = SELECT + 1;
0075:            final static int AS = WHERE + 1;
0076:            final static int ORDER = AS + 1;
0077:            final static int BY = ORDER + 1;
0078:            final static int ASC = BY + 1;
0079:            final static int DESC = ASC + 1;
0080:            final static int LIMIT = DESC + 1;
0081:            final static int OFFSET = LIMIT + 1;
0082:
0083:            final static int BETWEEN = OFFSET + 1;
0084:            final static int LIKE = BETWEEN + 1;
0085:            final static int ESCAPE = LIKE + 1;
0086:            final static int IS = ESCAPE + 1;
0087:
0088:            final static int EQ = IS + 1;
0089:            final static int NE = EQ + 1;
0090:            final static int LT = NE + 1;
0091:            final static int LE = LT + 1;
0092:            final static int GT = LE + 1;
0093:            final static int GE = GT + 1;
0094:
0095:            final static int AND = GE + 1;
0096:            final static int OR = AND + 1;
0097:            final static int NOT = OR + 1;
0098:
0099:            final static int EXTERNAL_DOT = NOT + 1;
0100:
0101:            final static int ARG = EXTERNAL_DOT + 1;
0102:            final static int THIS = ARG + 1;
0103:
0104:            private static IntMap _reserved;
0105:
0106:            private String _location;
0107:
0108:            // The owning bean
0109:            private EjbEntityBean _bean;
0110:
0111:            // The target bean
0112:            private EjbEntityBean _target;
0113:
0114:            // the functions
0115:            private ArrayList<FunctionSignature> _functions;
0116:
0117:            // Method name to generate
0118:            private String _methodName;
0119:            // Return class
0120:            private Class _returnType;
0121:            // Return ejb
0122:            private String _returnEJB;
0123:            // EJB-QL
0124:            private String _query;
0125:
0126:            // list of the identifier
0127:            private ArrayList<FromItem> _fromList;
0128:            // list of the identifiers
0129:            private ArrayList<PathExpr> _fromIds = new ArrayList<PathExpr>();
0130:
0131:            // list of the relation links
0132:            //private ArrayList<LinkItem> _linkList;
0133:            // select expression
0134:            private Expr _selectExpr;
0135:            // is distinct (set)
0136:            private boolean _isDistinct;
0137:
0138:            // from table
0139:            private String _fromTable;
0140:            // from identifier
0141:            private String _fromId;
0142:            // this expression
0143:            private IdExpr _this Expr;
0144:            // where expression
0145:            private Expr _whereExpr;
0146:            // arguments
0147:            private ArrayList<Expr> _argList;
0148:            // order by expression
0149:            private ArrayList<Expr> _orderExprList;
0150:            // order by ascending/descending
0151:            private ArrayList<Boolean> _orderAscendingList;
0152:            // order by limit max
0153:            private Expr _limitMax;
0154:            // order by limit offset
0155:            private Expr _limitOffset;
0156:
0157:            private AndExpr _andExpr;
0158:            private boolean _isWhere;
0159:
0160:            private HashMap<String, PathExpr> _idMap;
0161:            private HashMap<Expr, Expr> _pathMap;
0162:
0163:            // parse index
0164:            private int _parseIndex;
0165:            // current token
0166:            private int _token;
0167:            // temp for parsing
0168:            private String lexeme;
0169:
0170:            private int _unique;
0171:
0172:            private String _booleanTrue = "1";
0173:            private String _booleanFalse = "0";
0174:
0175:            private boolean _addArgToQuery = true;
0176:
0177:            private boolean _queryLoadsBean = true;
0178:
0179:            private int _maxArg;
0180:
0181:            private QLParser(EjbEntityBean bean) {
0182:                _bean = bean;
0183:
0184:                // _functions = FunExpr.getStandardFunctions();
0185:                _functions = bean.getConfig().getFunctions();
0186:            }
0187:
0188:            /**
0189:             * Creates a new select method.
0190:             *
0191:             * @param bean the owning persistent bean
0192:             * @param methodName the method name to implement
0193:             * @param method the method signature
0194:             */
0195:            public QLParser(EjbEntityBean bean, String methodName,
0196:                    ApiMethod method, Class returnType) throws ConfigException {
0197:                this (bean);
0198:
0199:                setMethod(method);
0200:
0201:                _methodName = methodName;
0202:                _returnType = returnType;
0203:
0204:                Class[] exn = method.getExceptionTypes();
0205:                for (int i = 0; i < exn.length; i++)
0206:                    if (FinderException.class.isAssignableFrom(exn[i]))
0207:                        return;
0208:
0209:                throw new ConfigException(L.l(
0210:                        "{0}: '{1}' must throw javax.ejb.FinderException.",
0211:                        method.getDeclaringClass().getName(),
0212:                        getFullMethodName(method)));
0213:            }
0214:
0215:            public static void parseOrderBy(EjbEntityBean bean, String orderBy,
0216:                    ArrayList<String> orderList,
0217:                    ArrayList<Boolean> orderAscendingList)
0218:                    throws ConfigException {
0219:                QLParser query = new QLParser(bean);
0220:
0221:                query.parseOrderBy(orderBy, orderList, orderAscendingList);
0222:            }
0223:
0224:            /**
0225:             * Sets the location.
0226:             */
0227:            public void setLocation(String location) {
0228:                _location = location;
0229:            }
0230:
0231:            /**
0232:             * Returns the owning bean
0233:             */
0234:            public EjbEntityBean getPersistentBean() {
0235:                return _bean;
0236:            }
0237:
0238:            /**
0239:             * Gets a persistent bean by its type.
0240:             */
0241:            public EjbEntityBean getBeanByName(String ejbName) {
0242:                // return _bean.getManager().getBeanInfoByName(ejbName);
0243:                throw new UnsupportedOperationException();
0244:            }
0245:
0246:            /**
0247:             * Gets a persistent bean by its type.
0248:             */
0249:            public EjbEntityBean getBeanByType(Class type) {
0250:                //return _bean.getManager().getBeanInfoByRemote(type);
0251:                throw new UnsupportedOperationException();
0252:            }
0253:
0254:            /**
0255:             * Returns the name of the select method.
0256:             */
0257:            public String getName() {
0258:                return _methodName;
0259:            }
0260:
0261:            /**
0262:             * Returns the function map.
0263:             */
0264:            public ArrayList<FunctionSignature> getFunctions() {
0265:                return _functions;
0266:            }
0267:
0268:            /**
0269:             * Sets the function map.
0270:             */
0271:            public void setFunctions(ArrayList<FunctionSignature> functions) {
0272:                _functions = functions;
0273:            }
0274:
0275:            /**
0276:             * Sets the boolean true.
0277:             */
0278:            public void setBooleanTrue(String literal) {
0279:                _booleanTrue = literal;
0280:            }
0281:
0282:            /**
0283:             * Sets the boolean false.
0284:             */
0285:            public void setBooleanFalse(String literal) {
0286:                _booleanFalse = literal;
0287:            }
0288:
0289:            /**
0290:             * Returns the return type of the select method.
0291:             */
0292:            public Class getReturnType() {
0293:                return _returnType;
0294:            }
0295:
0296:            /**
0297:             * Returns the return type of the select method.
0298:             */
0299:            public String getReturnEJB() {
0300:                return _selectExpr.getReturnEJB();
0301:            }
0302:
0303:            /**
0304:             * Sets the return type of the select method
0305:             */
0306:            void setReturnType(Class returnType) {
0307:                _returnType = returnType;
0308:            }
0309:
0310:            /**
0311:             * Returns the EJB-QL string
0312:             */
0313:            public String getQuery() {
0314:                return _query;
0315:            }
0316:
0317:            /**
0318:             * Gets the select expression
0319:             */
0320:            public Expr getSelectExpr() {
0321:                return _selectExpr;
0322:            }
0323:
0324:            public boolean isDistinct() {
0325:                return _isDistinct;
0326:            }
0327:
0328:            public boolean getQueryLoadsBean() {
0329:                return _queryLoadsBean;
0330:            }
0331:
0332:            public void setQueryLoadsBean(boolean loadBean) {
0333:                _queryLoadsBean = loadBean;
0334:            }
0335:
0336:            /**
0337:             * Gets the this expression.
0338:             */
0339:            IdExpr getThisExpr() {
0340:                return _this Expr;
0341:            }
0342:
0343:            /**
0344:             * Gets the where expression.
0345:             */
0346:            Expr getWhereExpr() {
0347:                return _whereExpr;
0348:            }
0349:
0350:            /**
0351:             * Gets the order by expression.
0352:             */
0353:            ArrayList<Expr> getOrderExprList() {
0354:                return _orderExprList;
0355:            }
0356:
0357:            /**
0358:             * Returns true if the order is ascending.
0359:             */
0360:            ArrayList<Boolean> getAscendingList() {
0361:                return _orderAscendingList;
0362:            }
0363:
0364:            /**
0365:             * Returns any limit max expression
0366:             */
0367:            Expr getLimitMax() {
0368:                return _limitMax;
0369:            }
0370:
0371:            /**
0372:             * Returns any limit offset expression
0373:             */
0374:            Expr getLimitOffset() {
0375:                return _limitOffset;
0376:            }
0377:
0378:            /**
0379:             * Gets the from table
0380:             */
0381:            ArrayList<FromItem> getFromList() {
0382:                return _fromList;
0383:            }
0384:
0385:            void addFromItem(String id, String table) {
0386:                _fromList.add(new FromItem(id, table));
0387:            }
0388:
0389:            public int getUnique() {
0390:                return _unique++;
0391:            }
0392:
0393:            /**
0394:             * Adds a relation expression
0395:             */
0396:            /*
0397:            public void addLink(String tableA, String columnA,
0398:                                String tableB, String columnB,
0399:            	      boolean isCommon)
0400:            {
0401:              if (isCommon)
0402:                addCommonLink(tableA, columnA, tableB, columnB);
0403:              else
0404:                addLink(tableA, columnA, tableB, columnB);
0405:            }
0406:             */
0407:
0408:            /**
0409:             * Adds a relation expression
0410:             */
0411:            /*
0412:            public void addLink(String tableA, String columnA,
0413:                                String tableB, String columnB)
0414:            {
0415:              if (_andExpr != null) {
0416:                LinkExpr expr = new LinkExpr(tableA, columnA, tableB, columnB);
0417:
0418:                _andExpr.add(expr);
0419:
0420:                return;
0421:              }
0422:
0423:              addCommonLink(tableA, columnA, tableB, columnB);
0424:            }
0425:             */
0426:
0427:            /**
0428:             * Adds a relation expression
0429:             */
0430:            /*
0431:            public void addCommonLink(String tableA, String columnA,
0432:            		    String tableB, String columnB)
0433:            {
0434:              if (_linkList == null)
0435:                _linkList = new ArrayList<LinkItem>();
0436:
0437:              LinkItem item = new LinkItem(tableA, columnA, tableB, columnB);
0438:
0439:              if (! _linkList.contains(item))
0440:                _linkList.add(item);
0441:            }
0442:             */
0443:
0444:            /**
0445:             * Returns the auxiliary relation expressions
0446:             */
0447:            /*
0448:            ArrayList<LinkItem> getRelations()
0449:            {
0450:              return _linkList;
0451:            }
0452:             */
0453:
0454:            /**
0455:             * Adds a select method argument
0456:             */
0457:            public void addArg(Expr expr) {
0458:                _argList.add(expr);
0459:            }
0460:
0461:            /**
0462:             * Gets the select method arguments in SQL order.
0463:             */
0464:            ArrayList<Expr> getArgList() {
0465:                return _argList;
0466:            }
0467:
0468:            /**
0469:             * Parses the select method's query.
0470:             *
0471:             * @param query the source query string.
0472:             */
0473:            public void parseOrderBy(String orderBy,
0474:                    ArrayList<String> orderList,
0475:                    ArrayList<Boolean> orderAscendingList)
0476:                    throws ConfigException {
0477:                _query = orderBy;
0478:
0479:                _parseIndex = 0;
0480:                _unique = 0;
0481:                _token = -1;
0482:
0483:                int token = -1;
0484:
0485:                do {
0486:                    token = scanToken();
0487:
0488:                    if (token == IDENTIFIER)
0489:                        orderList.add(lexeme.toString());
0490:                    else
0491:                        throw error(L.l("unexpected token '{0}' in order-by",
0492:                                tokenName(token)));
0493:
0494:                    token = scanToken();
0495:                    if (token == DESC) {
0496:                        token = scanToken();
0497:                        orderAscendingList.add(Boolean.FALSE);
0498:                    } else if (token == ASC) {
0499:                        token = scanToken();
0500:                        orderAscendingList.add(Boolean.TRUE);
0501:                    } else
0502:                        orderAscendingList.add(Boolean.TRUE);
0503:                } while (token == ',');
0504:
0505:                if (token >= 0)
0506:                    throw error(L.l("extra token {0} at end of order-by",
0507:                            tokenName(peekToken())));
0508:            }
0509:
0510:            /**
0511:             * Parses the select method's query.
0512:             *
0513:             * @param query the source query string.
0514:             */
0515:            public EjbQuery parseQuery(String query) throws ConfigException {
0516:                int token;
0517:
0518:                _query = query;
0519:                _fromList = new ArrayList<FromItem>();
0520:                _pathMap = new HashMap<Expr, Expr>();
0521:                _idMap = new HashMap<String, PathExpr>();
0522:                _argList = new ArrayList<Expr>();
0523:                //_linkList = new ArrayList<LinkItem>();
0524:
0525:                _parseIndex = 0;
0526:                _unique = 0;
0527:                _token = -1;
0528:
0529:                setConfig(_bean.getConfig());
0530:
0531:                // First pass parses the from
0532:                for (; (token = peekToken()) >= 0 && token != FROM; token = scanToken()) {
0533:                }
0534:
0535:                if (token != FROM)
0536:                    throw error(L.l("expected FROM at {0}", tokenName(token)));
0537:
0538:                scanToken();
0539:
0540:                parseFrom();
0541:
0542:                token = peekToken();
0543:                if (token >= 0 && token != WHERE && token != ORDER)
0544:                    throw error(L.l("expected WHERE or ORDER at {0}",
0545:                            tokenName(token)));
0546:
0547:                _parseIndex = 0;
0548:                _token = -1;
0549:                token = scanToken();
0550:
0551:                if (token != SELECT)
0552:                    throw error(L.l("expected SELECT at {0}", tokenName(token)));
0553:
0554:                if (peekToken() == DISTINCT) {
0555:                    scanToken();
0556:                    _isDistinct = true;
0557:                }
0558:
0559:                _selectExpr = parseExpr();
0560:
0561:                /*
0562:                if (_selectExpr instanceof CollectionExpr) {
0563:                  CollectionExpr expr = (CollectionExpr) _selectExpr;
0564:                  
0565:                  _selectExpr = new CollectionIdExpr(this, "foo", expr);
0566:                }
0567:                 */
0568:
0569:                if (_selectExpr instanceof  PathExpr)
0570:                    ((PathExpr) _selectExpr).setUsesField();
0571:
0572:                /*
0573:                if (! (selectExpr instanceof PathExpr) &&
0574:                    ! (selectExpr instanceof FieldExpr))
0575:                  throw error(L.l("'{0}' is an illegal SELECT expression.  Only path expressions are allowed in SELECT.", selectExpr));
0576:                 */
0577:
0578:                token = peekToken();
0579:                if (token != FROM)
0580:                    throw error(L.l("expected FROM at {0}", tokenName(token)));
0581:
0582:                // skip over the from since it's been parsed
0583:                for (; (token = peekToken()) >= 0 && token != WHERE
0584:                        && token != ORDER; token = scanToken()) {
0585:                }
0586:
0587:                _addArgToQuery = true;
0588:
0589:                if ((token = scanToken()) == WHERE) {
0590:                    _isWhere = true;
0591:                    _whereExpr = parseExpr();
0592:                    _isWhere = false;
0593:                    token = scanToken();
0594:                }
0595:
0596:                if (_whereExpr != null && !_whereExpr.isBoolean())
0597:                    throw error(L.l(
0598:                            "WHERE must be a boolean expression at {0}",
0599:                            _whereExpr));
0600:
0601:                _addArgToQuery = false;
0602:
0603:                int oldMaxArg = _maxArg;
0604:                if (token == ORDER) {
0605:                    if (peekToken() == BY)
0606:                        scanToken();
0607:                    if (_orderExprList == null)
0608:                        _orderExprList = new ArrayList<Expr>();
0609:
0610:                    if (_orderAscendingList == null)
0611:                        _orderAscendingList = new ArrayList<Boolean>();
0612:
0613:                    do {
0614:                        _orderExprList.add(parseExpr());
0615:
0616:                        token = peekToken();
0617:                        if (token == DESC) {
0618:                            token = scanToken();
0619:                            _orderAscendingList.add(Boolean.FALSE);
0620:                        } else if (token == ASC) {
0621:                            token = scanToken();
0622:                            _orderAscendingList.add(Boolean.TRUE);
0623:                        } else
0624:                            _orderAscendingList.add(Boolean.TRUE);
0625:                    } while ((token = scanToken()) == ',');
0626:                }
0627:
0628:                if (token == OFFSET) {
0629:                    _limitOffset = parseExpr();
0630:                    token = scanToken();
0631:
0632:                    if (!_limitOffset.getJavaType().getName().equals("int"))
0633:                        throw error(L.l(
0634:                                "OFFSET '{0}' must be an integer expression",
0635:                                _limitMax));
0636:                }
0637:
0638:                if (token == LIMIT) {
0639:                    _limitMax = parseExpr();
0640:                    token = scanToken();
0641:
0642:                    if (!_limitMax.getJavaType().getName().equals("int"))
0643:                        throw error(L.l(
0644:                                "LIMIT '{0}' must be an integer expression",
0645:                                _limitMax));
0646:                }
0647:
0648:                if (token >= 0)
0649:                    throw error(L.l("extra token {0} at end of query",
0650:                            tokenName(peekToken())));
0651:                _maxArg = oldMaxArg;
0652:
0653:                EjbSelectQuery ejbQuery = new EjbSelectQuery(_query);
0654:
0655:                ejbQuery.setDistinct(_isDistinct);
0656:                ejbQuery.setFromList(_fromIds);
0657:                ejbQuery.setSelectExpr(_selectExpr);
0658:                ejbQuery.setWhereExpr(_whereExpr);
0659:
0660:                ejbQuery.setMaxArg(_maxArg);
0661:                ejbQuery.setThisExpr(_this Expr);
0662:
0663:                ejbQuery.setOrderBy(_orderExprList, _orderAscendingList);
0664:
0665:                ejbQuery.setOffset(_limitOffset);
0666:                ejbQuery.setLimit(_limitMax);
0667:
0668:                return ejbQuery;
0669:            }
0670:
0671:            /**
0672:             * Parses the FROM block.  parseFrom's effect is to populate the
0673:             * core identifiers.
0674:             *
0675:             * <pre>
0676:             * from-list ::= from-list ',' from-item
0677:             *           ::= from-item
0678:             *
0679:             * from-item ::= IDENTIFIER AS? IDENTIFIER
0680:             *           ::= IN(collection-path) AS? IDENTIFIER
0681:             * </pre>
0682:             */
0683:            private void parseFrom() throws ConfigException {
0684:                boolean moreTables = true;
0685:
0686:                while (moreTables) {
0687:                    int token = scanToken();
0688:
0689:                    if (token == IN) {
0690:                        if (scanToken() != '(')
0691:                            throw error(L
0692:                                    .l(
0693:                                            "expected '(' at {0} while parsing IN(<collection-path>).",
0694:                                            tokenName(token)));
0695:
0696:                        parseFromCollection();
0697:                    } else if (token == IDENTIFIER) {
0698:                        String id = lexeme;
0699:                        if (peekToken() == AS)
0700:                            scanToken();
0701:
0702:                        parseFromTable(id);
0703:                    } else
0704:                        throw error(L
0705:                                .l(
0706:                                        "expected identifier at {0} while parsing FROM",
0707:                                        tokenName(token)));
0708:
0709:                    if (peekToken() == ',') {
0710:                        scanToken();
0711:                        moreTables = true;
0712:                    } else
0713:                        moreTables = false;
0714:                }
0715:            }
0716:
0717:            /**
0718:             * Parses a single-valued table identifier.
0719:             */
0720:            private void parseFromTable(String table) throws ConfigException {
0721:                int token = scanToken();
0722:
0723:                if (token != IDENTIFIER) {
0724:                    throw error(L
0725:                            .l(
0726:                                    "expected identifier at {0} while parsing FROM {1} [AS] var",
0727:                                    tokenName(token), table));
0728:                }
0729:
0730:                String name = lexeme;
0731:
0732:                EjbConfig ejbConfig = _bean.getConfig();
0733:
0734:                EjbEntityBean entity = ejbConfig.findEntityBySchema(table);
0735:
0736:                if (entity == null)
0737:                    throw error(L
0738:                            .l(
0739:                                    "'{0}' is an unknown entity-bean schema in 'FROM {0} AS {1}'",
0740:                                    table, name));
0741:
0742:                // _bean.addBeanDepend(info.getEJBName());
0743:
0744:                IdExpr id = new IdExpr(this , name, entity);
0745:
0746:                addIdentifier(name, id);
0747:                addFromItem(name, entity.getSQLTable());
0748:
0749:                _fromIds.add(id);
0750:            }
0751:
0752:            /**
0753:             * Parses a collection-valued table identifier.
0754:             */
0755:            private void parseFromCollection() throws ConfigException {
0756:                Expr expr = parseDotExpr();
0757:
0758:                if (scanToken() != ')')
0759:                    throw error(L
0760:                            .l(
0761:                                    "expected ')' at {0} while parsing IN(<collection-path>).",
0762:                                    tokenName(_token)));
0763:
0764:                if (!(expr instanceof  CollectionExpr))
0765:                    throw error(L.l(
0766:                            "expected <collection-path> expression at '{0}'",
0767:                            expr));
0768:
0769:                CollectionExpr collectionExpr = (CollectionExpr) expr;
0770:
0771:                if (peekToken() == AS)
0772:                    scanToken();
0773:
0774:                int token = scanToken();
0775:                if (token != IDENTIFIER)
0776:                    throw error(L
0777:                            .l(
0778:                                    "expected identifier expression at {0} while parsing 'IN({1}) AS id'",
0779:                                    tokenName(token), expr));
0780:
0781:                String name = lexeme;
0782:
0783:                CollectionIdExpr idExpr;
0784:                idExpr = new CollectionIdExpr(this , name, collectionExpr);
0785:
0786:                addIdentifier(name, idExpr);
0787:
0788:                _fromIds.add(idExpr);
0789:            }
0790:
0791:            /**
0792:             * Parses the next expression.
0793:             *
0794:             * <pre>
0795:             * expr ::= or-expr
0796:             * </pre>
0797:             *
0798:             * @return the parsed expression
0799:             */
0800:            private Expr parseExpr() throws ConfigException {
0801:                return parseOrExpr();
0802:            }
0803:
0804:            /**
0805:             * Parses an or expression.
0806:             *
0807:             * <pre>
0808:             * or-expr ::= or-expr AND and-expr
0809:             *         ::= and-expr
0810:             * </pre>
0811:             *
0812:             * @return the parsed expression
0813:             */
0814:            private Expr parseOrExpr() throws ConfigException {
0815:                Expr expr = parseAndExpr();
0816:
0817:                int token = peekToken();
0818:                while ((token = peekToken()) == OR) {
0819:                    scanToken();
0820:
0821:                    expr = new BinaryExpr(this , token, expr, parseAndExpr());
0822:                }
0823:
0824:                return expr;
0825:            }
0826:
0827:            /**
0828:             * Parses an and expression.
0829:             *
0830:             * <pre>
0831:             * and-expr ::= and-expr AND not-expr
0832:             *          ::= not-expr
0833:             * </pre>
0834:             *
0835:             * @return the parsed expression
0836:             */
0837:            private Expr parseAndExpr() throws ConfigException {
0838:                AndExpr oldAnd = _andExpr;
0839:
0840:                AndExpr andExpr = new AndExpr(this );
0841:
0842:                if (_isWhere)
0843:                    _andExpr = andExpr;
0844:
0845:                Expr expr = parseNotExpr();
0846:
0847:                andExpr.add(expr);
0848:
0849:                int token = peekToken();
0850:                while ((token = peekToken()) == AND) {
0851:                    scanToken();
0852:
0853:                    expr = parseNotExpr();
0854:
0855:                    andExpr.add(expr);
0856:                }
0857:
0858:                _andExpr = oldAnd;
0859:
0860:                return andExpr.getSingleExpr();
0861:            }
0862:
0863:            /**
0864:             * Parses a not expression.
0865:             *
0866:             * <pre>
0867:             * not-expr ::= NOT? cmp-expr
0868:             * </pre>
0869:             *
0870:             * @return the parsed expression
0871:             */
0872:            private Expr parseNotExpr() throws ConfigException {
0873:                int token = peekToken();
0874:                if (token == NOT) {
0875:                    scanToken();
0876:
0877:                    Expr expr = parseCmpExpr();
0878:
0879:                    return new UnaryExpr(NOT, expr);
0880:                } else
0881:                    return parseCmpExpr();
0882:            }
0883:
0884:            /**
0885:             * Parses a comparison expression.
0886:             *
0887:             * <pre>
0888:             * cmp-expr ::= add-expr '=' add-expr is-term?
0889:             *          ::= add-expr 'NOT'? 'BETWEEN' add-expr 'AND' add-expr is-term?
0890:             *          ::= add-expr 'NOT'? 'LIKE' string ('ESCAPE' string)? is-term?
0891:             *          ::= add-expr 'NOT'? 'IN' ('lit-1', ..., 'lit-n')
0892:             *          ::= add-expr
0893:             * </pre>
0894:             *
0895:             * @return the parsed expression
0896:             */
0897:            private Expr parseCmpExpr() throws ConfigException {
0898:                int token = peekToken();
0899:                boolean isNot = false;
0900:
0901:                Expr expr = parseArithmeticExpr();
0902:
0903:                token = peekToken();
0904:
0905:                if (token == NOT) {
0906:                    scanToken();
0907:                    isNot = true;
0908:                    token = peekToken();
0909:                }
0910:
0911:                if (token >= EQ && token <= GE) {
0912:                    scanToken();
0913:
0914:                    return parseIs(new BinaryExpr(this , token, expr,
0915:                            parseAddExpr()));
0916:                } else if (token == BETWEEN) {
0917:                    scanToken();
0918:
0919:                    Expr a = parseArithmeticExpr();
0920:
0921:                    if ((token = scanToken()) != AND)
0922:                        throw error(L.l("Expected 'AND' at {0}",
0923:                                tokenName(token)));
0924:
0925:                    Expr b = parseArithmeticExpr();
0926:
0927:                    return parseIs(new BetweenExpr(expr, a, b, isNot));
0928:                } else if (token == LIKE) {
0929:                    scanToken();
0930:
0931:                    Expr pattern = parseArithmeticExpr();
0932:
0933:                    String escape = null;
0934:                    if (peekToken() == ESCAPE) {
0935:                        scanToken();
0936:
0937:                        if ((token = scanToken()) != STRING)
0938:                            throw error(L.l("Expected string at {0}",
0939:                                    tokenName(token)));
0940:
0941:                        escape = lexeme.toString();
0942:                    }
0943:
0944:                    return parseIs(new LikeExpr(expr, pattern, escape, isNot));
0945:                } else if (token == IN) {
0946:                    scanToken();
0947:                    token = scanToken();
0948:
0949:                    if (token != '(')
0950:                        throw error(L.l("Expected '(' after IN at {0}",
0951:                                tokenName(token)));
0952:
0953:                    ArrayList<Expr> args = new ArrayList<Expr>();
0954:                    while ((token = peekToken()) > 0 && token != ')') {
0955:                        Expr arg = parseArithmeticExpr();
0956:
0957:                        args.add(arg);
0958:
0959:                        token = peekToken();
0960:                        if (token == ',') {
0961:                            scanToken();
0962:                            token = peekToken();
0963:                        }
0964:                    }
0965:
0966:                    if (peekToken() != ')')
0967:                        throw error(L.l("Expected ')' after IN at {0}",
0968:                                tokenName(token)));
0969:
0970:                    scanToken();
0971:
0972:                    return new InExpr(this , expr, args, isNot);
0973:                } else if (token == IS) {
0974:                    scanToken();
0975:
0976:                    if (isNot)
0977:                        throw error(L.l("'NOT IS' is an invalid expression."));
0978:
0979:                    token = scanToken();
0980:                    if (token == NOT) {
0981:                        isNot = true;
0982:                        token = scanToken();
0983:                    }
0984:
0985:                    if (token == NULL)
0986:                        return parseIs(new IsExpr(this , expr, NULL, isNot));
0987:                    else if (token == EMPTY) {
0988:                        if (!(expr instanceof  CollectionExpr))
0989:                            throw error(L
0990:                                    .l(
0991:                                            "IS EMPTY requires collection path at '{0}'",
0992:                                            expr));
0993:                        return parseIs(new EmptyExpr(expr, isNot));
0994:                    } else
0995:                        throw error(L.l("'{0}' unexpected after IS.",
0996:                                tokenName(token)));
0997:                } else if (token == MEMBER) {
0998:                    scanToken();
0999:
1000:                    token = peekToken();
1001:                    if (token == OF)
1002:                        token = scanToken();
1003:
1004:                    Expr collection = parseDotExpr();
1005:
1006:                    return parseIs(new MemberExpr(isNot, expr, collection));
1007:                } else
1008:                    return expr;
1009:            }
1010:
1011:            /**
1012:             * Parses an 'IS' term
1013:             *
1014:             * <pre>
1015:             * is-term ::= IS NOT? (TRUE|FALSE|UNKNOWN)
1016:             * </pre>
1017:             */
1018:            private Expr parseIs(Expr base) throws ConfigException {
1019:                if (peekToken() != IS)
1020:                    return base;
1021:
1022:                scanToken();
1023:                boolean isNot = peekToken() == NOT;
1024:                if (isNot)
1025:                    scanToken();
1026:
1027:                int token = scanToken();
1028:                if (token == UNKNOWN)
1029:                    return new IsExpr(this , base, NULL, isNot);
1030:                else if (token == TRUE)
1031:                    return isNot ? new UnaryExpr(NOT, base) : base;
1032:                else if (token == FALSE)
1033:                    return isNot ? base : new UnaryExpr(NOT, base);
1034:
1035:                throw error(L.l("expected TRUE or FALSE at {0}",
1036:                        tokenName(token)));
1037:            }
1038:
1039:            /**
1040:             * Parses an arithmetic expression.
1041:             *
1042:             * <pre>
1043:             * arithmetic-expr ::= add-expr
1044:             * </pre>
1045:             */
1046:            private Expr parseArithmeticExpr() throws ConfigException {
1047:                return parseAddExpr();
1048:            }
1049:
1050:            /**
1051:             * Parses an addition expression.
1052:             *
1053:             * <pre>
1054:             * add-expr ::= add-expr ('+' | '-') mul-expr
1055:             *          ::= mul-expr
1056:             * </pre>
1057:             *
1058:             * @return the parsed expression
1059:             */
1060:            private Expr parseAddExpr() throws ConfigException {
1061:                Expr expr = parseMulExpr();
1062:
1063:                int token = peekToken();
1064:                while ((token = peekToken()) == '-' || token == '+') {
1065:                    scanToken();
1066:
1067:                    expr = new BinaryExpr(this , token, expr, parseMulExpr());
1068:                }
1069:
1070:                return expr;
1071:            }
1072:
1073:            /**
1074:             * Parses a multiplication/division expression.
1075:             *
1076:             * <pre>
1077:             * mul-expr ::= mul-expr ('*' | '/') unary-expr
1078:             *          ::= unary-expr
1079:             * </pre>
1080:             *
1081:             * @return the parsed expression
1082:             */
1083:            private Expr parseMulExpr() throws ConfigException {
1084:                Expr expr = parseUnaryExpr();
1085:
1086:                int token = peekToken();
1087:                while ((token = peekToken()) == '*' || token == '/') {
1088:                    scanToken();
1089:
1090:                    expr = new BinaryExpr(this , token, expr, parseUnaryExpr());
1091:                }
1092:
1093:                return expr;
1094:            }
1095:
1096:            /**
1097:             * Parses a unary +/-
1098:             *
1099:             * <pre>
1100:             * unary-expr ::= ('+'|'-')? path-expr
1101:             * </pre>
1102:             *
1103:             * @return the parsed expression
1104:             */
1105:            private Expr parseUnaryExpr() throws ConfigException {
1106:                int token = peekToken();
1107:
1108:                if (token == '+' || token == '-') {
1109:                    scanToken();
1110:                    return new UnaryExpr(token, parseRefExpr());
1111:                } else
1112:                    return parseRefExpr();
1113:            }
1114:
1115:            /**
1116:             * Parses a path expression.
1117:             *
1118:             * <pre>
1119:             * ref-expr ::= path-expr '=>' IDENTIFIER
1120:             *          ::= path-expr
1121:             * </pre>
1122:             *
1123:             * @return the parsed expression
1124:             */
1125:            private Expr parseRefExpr() throws ConfigException {
1126:                Expr expr = parseDotExpr();
1127:
1128:                int token;
1129:                if ((token = peekToken()) == EXTERNAL_DOT) {
1130:                    scanToken();
1131:
1132:                    token = scanToken();
1133:
1134:                    if (token != IDENTIFIER)
1135:                        throw error(L.l("expected field identifier at {0}",
1136:                                tokenName(token)));
1137:
1138:                    expr = expr.newField(lexeme);
1139:                    expr.evalTypes();
1140:
1141:                    if (!expr.isExternal())
1142:                        throw error(L.l(
1143:                                "'{0}' must refer to an external entity bean",
1144:                                expr));
1145:                }
1146:
1147:                return expr;
1148:            }
1149:
1150:            /**
1151:             * Parses a path expression.
1152:             *
1153:             * <pre>
1154:             * path-expr ::= path-expr '.' IDENTIFIER
1155:             *           ::= term
1156:             * </pre>
1157:             *
1158:             * @return the parsed expression
1159:             */
1160:            private Expr parseDotExpr() throws ConfigException {
1161:                Expr expr = parseTerm();
1162:
1163:                int token;
1164:                while ((token = peekToken()) == '.') {
1165:                    scanToken();
1166:
1167:                    token = scanToken();
1168:
1169:                    if (token != IDENTIFIER)
1170:                        throw error(L.l("expected field identifier at {0}",
1171:                                tokenName(token)));
1172:
1173:                    expr.evalTypes();
1174:                    if (expr.isExternal())
1175:                        throw error(L
1176:                                .l(
1177:                                        "'{0}' must not refer to an external entity bean",
1178:                                        expr));
1179:                    Expr field = expr.newField(lexeme);
1180:                    expr = field;
1181:
1182:                    Expr equiv = _pathMap.get(field);
1183:                    if (equiv != null)
1184:                        expr = equiv;
1185:                    else
1186:                        _pathMap.put(field, field);
1187:                }
1188:
1189:                return expr;
1190:            }
1191:
1192:            /**
1193:             * Parses a term
1194:             *
1195:             * <pre>
1196:             * term ::= IDENTIFIER | INTEGER | LONG | DOUBLE | STRING
1197:             *      ::= THIS '.' IDENTIFIER
1198:             *      ::= IDENTIFIER '(' args ')'
1199:             *      ::= '(' args ')'
1200:             * </pre>
1201:             */
1202:            private Expr parseTerm() throws ConfigException {
1203:                int token = scanToken();
1204:
1205:                switch (token) {
1206:                case IDENTIFIER:
1207:                    String name = lexeme.toString();
1208:                    if (peekToken() != '(')
1209:                        return getIdentifier(name);
1210:                    else
1211:                        return parseFunction(name);
1212:
1213:                case FALSE:
1214:                    return new LiteralExpr(_booleanFalse, boolean.class);
1215:
1216:                case TRUE:
1217:                    return new LiteralExpr(_booleanTrue, boolean.class);
1218:
1219:                case INTEGER:
1220:                    return new LiteralExpr(lexeme, int.class);
1221:
1222:                case LONG:
1223:                    return new LiteralExpr(lexeme, long.class);
1224:
1225:                case DOUBLE:
1226:                    return new LiteralExpr(lexeme, double.class);
1227:
1228:                case STRING:
1229:                    return new LiteralExpr(lexeme, String.class);
1230:
1231:                case ARG: {
1232:                    ArgExpr arg = new ArgExpr(this , Integer.parseInt(lexeme));
1233:                    if (_addArgToQuery)
1234:                        addArg(arg);
1235:                    return arg;
1236:                }
1237:
1238:                case THIS: {
1239:                    if (_this Expr == null) {
1240:                        _this Expr = new IdExpr(this , "caucho_this", _bean);
1241:                        addFromItem("caucho_this", _bean.getSQLTable());
1242:                        _fromIds.add(_this Expr);
1243:                        _argList.add(0, new ThisExpr(this , _bean));
1244:                    }
1245:
1246:                    return _this Expr;
1247:                }
1248:
1249:                case '(':
1250:                    Expr expr = parseExpr();
1251:                    if ((token = scanToken()) != ')')
1252:                        throw error(L
1253:                                .l("expected ')' at {0}", tokenName(token)));
1254:
1255:                    return expr;
1256:
1257:                default:
1258:                    throw error(L.l("expected term at {0}", tokenName(token)));
1259:                }
1260:            }
1261:
1262:            /**
1263:             * Parses a function
1264:             *
1265:             * <pre>
1266:             * function ::= IDENTIFIER '(' expr (',' expr)* ')'
1267:             *          ::= IDENTIFIER '(' ')'
1268:             * </pre>
1269:             */
1270:            private Expr parseFunction(String name) throws ConfigException {
1271:                ArrayList<Expr> args = new ArrayList<Expr>();
1272:
1273:                int token;
1274:                if ((token = scanToken()) != '(')
1275:                    throw error(L.l(
1276:                            "expected '(' at {0} while parsing function {1}()",
1277:                            tokenName(token), name));
1278:
1279:                while ((token = peekToken()) != ')' && token > 0) {
1280:                    Expr expr = parseExpr();
1281:
1282:                    args.add(expr);
1283:
1284:                    if ((token = peekToken()) == ',')
1285:                        scanToken();
1286:                }
1287:
1288:                if (token != ')')
1289:                    throw error(L.l(
1290:                            "expected ')' at {0} while parsing function {1}",
1291:                            tokenName(token), name));
1292:
1293:                scanToken();
1294:
1295:                if (name.equalsIgnoreCase("object")) {
1296:                    if (args.size() != 1)
1297:                        throw error(L.l("OBJECT() requires a single argument"));
1298:
1299:                    Expr expr = args.get(0);
1300:
1301:                    if (!EntityBean.class.isAssignableFrom(expr.getJavaType())
1302:                            && !EJBLocalObject.class.isAssignableFrom(expr
1303:                                    .getJavaType()))
1304:                        throw error(L
1305:                                .l(
1306:                                        "OBJECT({0}) requires an entity bean as its argument at '{1}'",
1307:                                        expr, expr.getJavaType()));
1308:
1309:                    return expr;
1310:                } else {
1311:                    try {
1312:                        return new FunExpr(name, args, _functions);
1313:                    } catch (ConfigException e) {
1314:                        throw error(e.getMessage());
1315:                    }
1316:                }
1317:            }
1318:
1319:            /**
1320:             * Adds a new identifier
1321:             *
1322:             * @param name the name of the identifier
1323:             *
1324:             * @return the IdExpr corresponding to the identifier
1325:             */
1326:            void addIdentifier(String name, PathExpr expr)
1327:                    throws ConfigException {
1328:                Expr oldExpr = _idMap.get(name);
1329:
1330:                if (oldExpr != null)
1331:                    throw error(L.l("'{0}' is defined twice", name));
1332:
1333:                _idMap.put(name, expr);
1334:            }
1335:
1336:            /**
1337:             * Adds a new identifier
1338:             *
1339:             * @param name the name of the identifier
1340:             *
1341:             * @return the IdExpr corresponding to the identifier
1342:             */
1343:            PathExpr getIdentifier(String name) throws ConfigException {
1344:                PathExpr expr = _idMap.get(name);
1345:
1346:                if (expr == null)
1347:                    throw error(L.l("'{0}' is an unknown identifier", name));
1348:
1349:                return expr;
1350:            }
1351:
1352:            /**
1353:             * Peeks the next token
1354:             *
1355:             * @return integer code for the token
1356:             */
1357:            private int peekToken() throws ConfigException {
1358:                if (_token > 0)
1359:                    return _token;
1360:
1361:                _token = scanToken();
1362:
1363:                return _token;
1364:            }
1365:
1366:            /**
1367:             * Scan the next token.  If the lexeme is a string, its string
1368:             * representation is in "lexeme".
1369:             *
1370:             * @return integer code for the token
1371:             */
1372:            private int scanToken() throws ConfigException {
1373:                if (_token > 0) {
1374:                    int value = _token;
1375:                    _token = -1;
1376:                    return value;
1377:                }
1378:
1379:                int sign = 1;
1380:                int ch;
1381:
1382:                for (ch = read(); Character.isWhitespace((char) ch); ch = read()) {
1383:                }
1384:
1385:                switch (ch) {
1386:                case -1:
1387:                case '(':
1388:                case ')':
1389:                case '.':
1390:                case '*':
1391:                case '/':
1392:                case ',':
1393:                    return ch;
1394:
1395:                case '+':
1396:                    if ((ch = read()) >= '0' && ch <= '9')
1397:                        break;
1398:                    else {
1399:                        unread(ch);
1400:                        return '+';
1401:                    }
1402:
1403:                case '-':
1404:                    if ((ch = read()) >= '0' && ch <= '9') {
1405:                        sign = -1;
1406:                        break;
1407:                    } else {
1408:                        unread(ch);
1409:                        return '-';
1410:                    }
1411:
1412:                case '=':
1413:                    if ((ch = read()) == '>')
1414:                        return EXTERNAL_DOT;
1415:                    else {
1416:                        unread(ch);
1417:                        return EQ;
1418:                    }
1419:
1420:                case '<':
1421:                    if ((ch = read()) == '=')
1422:                        return LE;
1423:                    else if (ch == '>')
1424:                        return NE;
1425:                    else {
1426:                        unread(ch);
1427:                        return LT;
1428:                    }
1429:
1430:                case '>':
1431:                    if ((ch = read()) == '=')
1432:                        return GE;
1433:                    else {
1434:                        unread(ch);
1435:                        return GT;
1436:                    }
1437:
1438:                case '?':
1439:                    CharBuffer cb = CharBuffer.allocate();
1440:                    int index = 0;
1441:                    for (ch = read(); ch >= '0' && ch <= '9'; ch = read()) {
1442:                        cb.append((char) ch);
1443:                        index = 10 * index + ch - '0';
1444:                    }
1445:                    unread(ch);
1446:
1447:                    lexeme = cb.close();
1448:
1449:                    if (index <= 0)
1450:                        throw error(L.l(
1451:                                "'{0}' must refer to a positive argument", "?"
1452:                                        + lexeme));
1453:
1454:                    if (_maxArg < index)
1455:                        _maxArg = index;
1456:
1457:                    return ARG;
1458:
1459:                    // @@ is useless?
1460:                case '@':
1461:                    if ((ch = read()) != '@')
1462:                        throw error(L.l("'@' expected at {0}", charName(ch)));
1463:                    return scanToken();
1464:                }
1465:
1466:                if (Character.isJavaIdentifierStart((char) ch)) {
1467:                    CharBuffer cb = CharBuffer.allocate();
1468:
1469:                    for (; ch > 0 && Character.isJavaIdentifierPart((char) ch); ch = read())
1470:                        cb.append((char) ch);
1471:
1472:                    unread(ch);
1473:
1474:                    lexeme = cb.close();
1475:                    String lower = lexeme.toLowerCase();
1476:
1477:                    int token = _reserved.get(lower);
1478:
1479:                    if (token > 0)
1480:                        return token;
1481:                    else
1482:                        return IDENTIFIER;
1483:                } else if (ch >= '0' && ch <= '9') {
1484:                    CharBuffer cb = CharBuffer.allocate();
1485:
1486:                    int type = INTEGER;
1487:
1488:                    if (sign < 0)
1489:                        cb.append('-');
1490:
1491:                    for (; ch >= '0' && ch <= '9'; ch = read())
1492:                        cb.append((char) ch);
1493:
1494:                    if (ch == '.') {
1495:                        type = DOUBLE;
1496:
1497:                        cb.append('.');
1498:                        for (ch = read(); ch >= '0' && ch <= '9'; ch = read())
1499:                            cb.append((char) ch);
1500:                    }
1501:
1502:                    if (ch == 'e' || ch == 'E') {
1503:                        type = DOUBLE;
1504:
1505:                        cb.append('e');
1506:                        if ((ch = read()) == '+' || ch == '-') {
1507:                            cb.append((char) ch);
1508:                            ch = read();
1509:                        }
1510:
1511:                        if (!(ch >= '0' && ch <= '9'))
1512:                            throw error(L.l("exponent needs digits at {0}",
1513:                                    charName(ch)));
1514:
1515:                        for (; ch >= '0' && ch <= '9'; ch = read())
1516:                            cb.append((char) ch);
1517:                    }
1518:
1519:                    if (ch == 'F' || ch == 'D')
1520:                        type = DOUBLE;
1521:                    else if (ch == 'L') {
1522:                        type = LONG;
1523:                    } else
1524:                        unread(ch);
1525:
1526:                    lexeme = cb.close();
1527:
1528:                    return type;
1529:                } else if (ch == '\'') {
1530:                    CharBuffer cb = CharBuffer.allocate();
1531:
1532:                    cb.append("'");
1533:                    for (ch = read(); ch >= 0; ch = read()) {
1534:                        if (ch == '\'') {
1535:                            if ((ch = read()) == '\'')
1536:                                cb.append("''");
1537:                            else {
1538:                                unread(ch);
1539:                                break;
1540:                            }
1541:                        } else
1542:                            cb.append((char) ch);
1543:                    }
1544:                    cb.append("'");
1545:
1546:                    lexeme = cb.close();
1547:
1548:                    return STRING;
1549:                }
1550:
1551:                throw error(L.l("unexpected char at {0}", "" + (char) ch));
1552:            }
1553:
1554:            /**
1555:             * Returns the next character.
1556:             */
1557:            private int read() {
1558:                if (_parseIndex < _query.length())
1559:                    return _query.charAt(_parseIndex++);
1560:                else
1561:                    return -1;
1562:            }
1563:
1564:            /**
1565:             * Unread the last character.
1566:             */
1567:            private void unread(int ch) {
1568:                if (ch >= 0)
1569:                    _parseIndex--;
1570:            }
1571:
1572:            /**
1573:             * Returns a full method name with arguments.
1574:             */
1575:            private String getFullMethodName(ApiMethod method) {
1576:                return method.getFullName();
1577:            }
1578:
1579:            /**
1580:             * Returns a full method name with arguments.
1581:             */
1582:            private String getFullMethodName(String methodName, Class[] params) {
1583:                String name = methodName + "(";
1584:
1585:                for (int i = 0; i < params.length; i++) {
1586:                    if (i != 0)
1587:                        name += ", ";
1588:
1589:                    name += params[i].getSimpleName();
1590:                }
1591:
1592:                return name + ")";
1593:            }
1594:
1595:            /**
1596:             * Returns a printable version of a class.
1597:             */
1598:            private String getClassName(Class cl) {
1599:                if (cl.isArray())
1600:                    return getClassName(cl.getComponentType()) + "[]";
1601:                else if (cl.getName().startsWith("java")) {
1602:                    int p = cl.getName().lastIndexOf('.');
1603:
1604:                    return cl.getName().substring(p + 1);
1605:                } else
1606:                    return cl.getName();
1607:            }
1608:
1609:            /**
1610:             * Creates an error.
1611:             */
1612:            public ConfigException error(String msg) {
1613:                msg += "\nin \"" + _query + "\"";
1614:                /*
1615:                if (_qlConfig != null)
1616:                  return new SelectLineParseException(_qlConfig.getFilename() + ":" +
1617:                				  _qlConfig.getLine() + ": " +
1618:                				  msg);
1619:                 */
1620:                if (_location != null)
1621:                    return new LineConfigException(_location + msg);
1622:                else
1623:                    return new ConfigException(msg);
1624:            }
1625:
1626:            /**
1627:             * Returns the name for a character
1628:             */
1629:            private String charName(int ch) {
1630:                if (ch < 0)
1631:                    return L.l("end of query");
1632:                else
1633:                    return String.valueOf((char) ch);
1634:            }
1635:
1636:            /**
1637:             * Returns the name of a token
1638:             */
1639:            private String tokenName(int token) {
1640:                switch (token) {
1641:                case AS:
1642:                    return "AS";
1643:                case FROM:
1644:                    return "FROM";
1645:                case IN:
1646:                    return "IN";
1647:                case SELECT:
1648:                    return "SELECT";
1649:                case WHERE:
1650:                    return "WHERE";
1651:                case OR:
1652:                    return "OR";
1653:                case AND:
1654:                    return "AND";
1655:                case NOT:
1656:                    return "NOT";
1657:                case BETWEEN:
1658:                    return "BETWEEN";
1659:                case THIS:
1660:                    return "THIS";
1661:                case TRUE:
1662:                    return "FALSE";
1663:                case EMPTY:
1664:                    return "EMPTY";
1665:                case MEMBER:
1666:                    return "MEMBER";
1667:                case OF:
1668:                    return "OF";
1669:                case NULL:
1670:                    return "NULL";
1671:                case ORDER:
1672:                    return "ORDER";
1673:                case BY:
1674:                    return "BY";
1675:                case ASC:
1676:                    return "ASC";
1677:                case DESC:
1678:                    return "DESC";
1679:                case LIMIT:
1680:                    return "LIMIT";
1681:
1682:                case EXTERNAL_DOT:
1683:                    return "=>";
1684:
1685:                case -1:
1686:                    return L.l("end of query");
1687:
1688:                default:
1689:                    if (token < 128)
1690:                        return "'" + String.valueOf((char) token) + "'";
1691:                    else
1692:                        return "'" + lexeme + "'";
1693:                }
1694:            }
1695:
1696:            public static ArrayList<FunctionSignature> getStandardFunctions() {
1697:                return FunExpr.getStandardFunctions();
1698:            }
1699:
1700:            /**
1701:             * Returns a debuggable description of the select.
1702:             */
1703:            public String toString() {
1704:                return "QLParser[" + getMethod() + "]";
1705:            }
1706:
1707:            public boolean equals(Object b) {
1708:                if (!(b instanceof  QLParser))
1709:                    return false;
1710:
1711:                QLParser bSel = (QLParser) b;
1712:
1713:                if (_bean != bSel._bean)
1714:                    return false;
1715:
1716:                return getMethod().equals(bSel.getMethod());
1717:            }
1718:
1719:            static boolean methodEquals(ApiMethod a, ApiMethod b) {
1720:                return a.equals(b);
1721:            }
1722:
1723:            static class FromItem {
1724:                String _id;
1725:                String _table;
1726:
1727:                FromItem(String id, String table) {
1728:                    _id = id;
1729:                    _table = table;
1730:                }
1731:            }
1732:
1733:            static class LinkItem {
1734:                String columnA;
1735:                String tableA;
1736:
1737:                String columnB;
1738:                String tableB;
1739:
1740:                LinkItem(String tableA, String columnA, String tableB,
1741:                        String columnB) {
1742:                    this .columnA = columnA;
1743:                    this .tableA = tableA;
1744:                    this .columnB = columnB;
1745:                    this .tableB = tableB;
1746:                }
1747:
1748:                public boolean equals(Object o) {
1749:                    if (!(o instanceof  LinkItem))
1750:                        return false;
1751:
1752:                    LinkItem link = (LinkItem) o;
1753:
1754:                    if (tableA.equals(link.tableA)
1755:                            && columnA.equals(link.columnA)
1756:                            && tableB.equals(link.tableB)
1757:                            && columnB.equals(link.columnB))
1758:                        return true;
1759:                    else if (tableA.equals(link.tableB)
1760:                            && columnA.equals(link.columnB)
1761:                            && tableB.equals(link.tableA)
1762:                            && columnB.equals(link.columnA))
1763:                        return true;
1764:                    else
1765:                        return false;
1766:                }
1767:            }
1768:
1769:            static {
1770:                _reserved = new IntMap();
1771:                _reserved.put("as", AS);
1772:                _reserved.put("from", FROM);
1773:                _reserved.put("in", IN);
1774:                _reserved.put("select", SELECT);
1775:                _reserved.put("distinct", DISTINCT);
1776:                _reserved.put("where", WHERE);
1777:                _reserved.put("order", ORDER);
1778:                _reserved.put("by", BY);
1779:                _reserved.put("asc", ASC);
1780:                _reserved.put("desc", DESC);
1781:                _reserved.put("limit", LIMIT);
1782:                _reserved.put("offset", OFFSET);
1783:
1784:                _reserved.put("or", OR);
1785:                _reserved.put("and", AND);
1786:                _reserved.put("not", NOT);
1787:
1788:                _reserved.put("between", BETWEEN);
1789:                _reserved.put("like", LIKE);
1790:                _reserved.put("escape", ESCAPE);
1791:                _reserved.put("is", IS);
1792:
1793:                _reserved.put("this", THIS);
1794:                _reserved.put("true", TRUE);
1795:                _reserved.put("false", FALSE);
1796:                _reserved.put("unknown", UNKNOWN);
1797:                _reserved.put("empty", EMPTY);
1798:                _reserved.put("member", MEMBER);
1799:                _reserved.put("of", OF);
1800:                _reserved.put("null", NULL);
1801:            }
1802:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.