Source Code Cross Referenced for ReportQuery.java in  » Database-ORM » toplink » oracle » toplink » essentials » queryframework » 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 ORM » toplink » oracle.toplink.essentials.queryframework 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         * 
0004:         * // Copyright (c) 1998, 2007, Oracle. All rights reserved.
0005:         * 
0006:         *
0007:         * The contents of this file are subject to the terms of either the GNU
0008:         * General Public License Version 2 only ("GPL") or the Common Development
0009:         * and Distribution License("CDDL") (collectively, the "License").  You
0010:         * may not use this file except in compliance with the License. You can obtain
0011:         * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
0012:         * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
0013:         * language governing permissions and limitations under the License.
0014:         * 
0015:         * When distributing the software, include this License Header Notice in each
0016:         * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
0017:         * Sun designates this particular file as subject to the "Classpath" exception
0018:         * as provided by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code.  If applicable, add the following below the License
0020:         * Header, with the fields enclosed by brackets [] replaced by your own
0021:         * identifying information: "Portions Copyrighted [year]
0022:         * [name of copyright owner]"
0023:         * 
0024:         * Contributor(s):
0025:         * 
0026:         * If you wish your version of this file to be governed by only the CDDL or
0027:         * only the GPL Version 2, indicate your decision by adding "[Contributor]
0028:         * elects to include this software in this distribution under the [CDDL or GPL
0029:         * Version 2] license."  If you don't indicate a single choice of license, a
0030:         * recipient has the option to distribute your version of this file under
0031:         * either the CDDL, the GPL Version 2 or to extend the choice of license to
0032:         * its licensees as provided above.  However, if you add GPL Version 2 code
0033:         * and therefore, elected the GPL Version 2 license, then the option applies
0034:         * only if the new code is made subject to such option by the copyright
0035:         * holder.
0036:         */
0037:        package oracle.toplink.essentials.queryframework;
0038:
0039:        import java.util.*;
0040:        import oracle.toplink.essentials.expressions.*;
0041:        import oracle.toplink.essentials.internal.expressions.*;
0042:        import oracle.toplink.essentials.internal.queryframework.*;
0043:        import oracle.toplink.essentials.exceptions.*;
0044:        import oracle.toplink.essentials.internal.helper.*;
0045:        import oracle.toplink.essentials.mappings.*;
0046:        import oracle.toplink.essentials.internal.security.PrivilegedAccessHelper;
0047:        import oracle.toplink.essentials.internal.sessions.AbstractRecord;
0048:        import oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl;
0049:        import oracle.toplink.essentials.internal.sessions.AbstractSession;
0050:        import oracle.toplink.essentials.descriptors.ClassDescriptor;
0051:
0052:        /**
0053:         * <b>Purpose</b>: Query for information about a set of objects instead of the objects themselves.
0054:         * This supports select single attributes, nested attributes, aggregation functions and group bys.<p>
0055:         *
0056:         * <b>Attribute Types</b>:<ol>
0057:         * <li>addAttribute("directQueryKey") is a short cut method to add an attribute with the same name as its corresponding direct query key.
0058:         * <li>addAttribute("attributeName", expBuilder.get("oneToOneMapping").get("directQueryKey")) is the full approach for get values through joined 1:1 relationships.
0059:         * <li>addAttribute("attributeName", expBuilder.getField("TABLE.FIELD")) allows the addition of raw values or values which were not mapped in the object model directly (i.e. FK attributes).
0060:         * <li>addAttribute("attributeName", null) Leave a place holder (NULL) value in the result (used for included values from other systems or calculated values).
0061:         * </ol>
0062:         * <b>Retrieving Primary Keys</b>:     It is possble to retrieve the primary key raw values within each result, but stored in a separate (internal) vector. This
0063:         *                                            primary key vector can later be used to retrieve the real object.
0064:         *                                            @see #retrievePrimaryKeys()
0065:         *                                            @see ReportQueryResult#readObject(Class, Session)
0066:         *                                            If the values are wanted in the result array then they must be added as attributes. For primary keys which are not mapped directly
0067:         *                                            you can add them as DatabaseFields (see above).
0068:         *
0069:         * @author Doug Clarke
0070:         * @since TOPLink/Java 2.0
0071:         */
0072:        public class ReportQuery extends ReadAllQuery {
0073:
0074:            /** Simplifies the result by only returning the first result. */
0075:            public static final int ShouldReturnSingleResult = 1;
0076:
0077:            /** Simplifies the result by only returning one value. */
0078:            public static final int ShouldReturnSingleValue = 2;
0079:
0080:            /** Simplifies the result by only returning the single attribute(as opposed to wrapping in a
0081:            ReportQueryResult). */
0082:            public static final int ShouldReturnSingleAttribute = 3;
0083:
0084:            /** For EJB 3 support returns results without using the ReportQueryResult */
0085:            public static final int ShouldReturnWithoutReportQueryResult = 4;
0086:
0087:            /** Specifies whether to retreive primary keys, first primary key, or no primary key.*/
0088:            public static final int FULL_PRIMARY_KEY = 2;
0089:            public static final int FIRST_PRIMARY_KEY = 1;
0090:            public static final int NO_PRIMARY_KEY = 0;
0091:
0092:            //GF_ISSUE_395
0093:            protected static final Boolean RESULT_IGNORED = Boolean
0094:                    .valueOf(true);
0095:            //end GF_ISSUE
0096:
0097:            /** Flag indicating wether the primary key values should also be retrieved for the reference class. */
0098:            protected int shouldRetrievePrimaryKeys;
0099:
0100:            /** Collection of names for use by results. */
0101:            protected Vector names;
0102:
0103:            /** Items to be selected, these could be attributes or aggregate functions. */
0104:            protected Vector items;
0105:
0106:            /** Expressions representing fields to be used in the GROUP BY clause. */
0107:            protected Vector groupByExpressions;
0108:
0109:            /** Expression representing the HAVING clause. */
0110:            protected Expression havingExpression;
0111:
0112:            /** Can be one of (ShouldReturnSingleResult, ShouldReturnSingleValue, ShouldReturnSingleAttribute)
0113:             ** Simplifies the result by only returning the first result, first value, or all attribute values
0114:             */
0115:            protected int returnChoice;
0116:
0117:            /** flag to allow items to be added to the last ConstructorReportItem **/
0118:            protected boolean addToConstructorItem;
0119:            protected Class resultConstructorClass;
0120:            protected Class[] constructorArgTypes;
0121:            protected List constructorMappings;
0122:
0123:            /* GF_ISSUE_395 this attribute stores a set of unique keys that identity results.
0124:             * Used when distinct has been set on the query.  For use in TCK
0125:             */
0126:            protected HashSet returnedKeys;
0127:
0128:            /**
0129:             * INTERNAL:
0130:             * The builder should be provided.
0131:             */
0132:            public ReportQuery() {
0133:                this .queryMechanism = new ExpressionQueryMechanism(this );
0134:                this .items = new Vector();
0135:                this .shouldRetrievePrimaryKeys = NO_PRIMARY_KEY;
0136:                this .groupByExpressions = new Vector(3);
0137:                this .havingExpression = null;
0138:                this .addToConstructorItem = false;
0139:
0140:                // overwrite the lock mode to NO_LOCK, this prevents the report query to lock
0141:                // when DEFAULT_LOCK_MODE and a pessimistic locking policy are used.
0142:                this .setLockMode(ObjectBuildingQuery.NO_LOCK);
0143:            }
0144:
0145:            public ReportQuery(Class javaClass, Expression expression) {
0146:                this ();
0147:                this .defaultBuilder = expression.getBuilder();
0148:                setReferenceClass(javaClass);
0149:                setSelectionCriteria(expression);
0150:            }
0151:
0152:            /**
0153:             * PUBLIC:
0154:             * The report query is require to be constructor with an expression builder.
0155:             * This build must be used for the selection critiera, any item expressions, group bys and order bys.
0156:             */
0157:            public ReportQuery(Class javaClass, ExpressionBuilder builder) {
0158:                this ();
0159:                this .defaultBuilder = builder;
0160:                setReferenceClass(javaClass);
0161:            }
0162:
0163:            /**
0164:             * PUBLIC:
0165:             * The report query is require to be constructor with an expression builder.
0166:             * This build must be used for the selection critiera, any item expressions, group bys and order bys.
0167:             */
0168:            public ReportQuery(ExpressionBuilder builder) {
0169:                this ();
0170:                this .defaultBuilder = builder;
0171:            }
0172:
0173:            /**
0174:             * PUBLIC:
0175:             * Add the attribute from the reference class to be included in the result.
0176:             * EXAMPLE: reportQuery.addAttribute("firstName");
0177:             */
0178:            public void addAttribute(String itemName) {
0179:                addItem(itemName, getExpressionBuilder().get(itemName));
0180:            }
0181:
0182:            /**
0183:             * PUBLIC:
0184:             * Add the attribute to be included in the result.
0185:             * EXAMPLE: reportQuery.addAttribute("city", expBuilder.get("address").get("city"));
0186:             */
0187:            public void addAttribute(String itemName,
0188:                    Expression attributeExpression) {
0189:                addItem(itemName, attributeExpression);
0190:            }
0191:
0192:            /**
0193:             * PUBLIC:
0194:             * Add the attribute to be included in the result.  Return the result as the provided class
0195:             * EXAMPLE: reportQuery.addAttribute("city", expBuilder.get("period").get("startTime"), Time.class);
0196:             */
0197:            public void addAttribute(String itemName,
0198:                    Expression attributeExpression, Class type) {
0199:                addItem(itemName, attributeExpression, type);
0200:            }
0201:
0202:            /**
0203:             * PUBLIC:
0204:             * Add the average value of the attribute to be included in the result.
0205:             * Aggregation functions can be used with a group by, or on the entire result set.
0206:             * EXAMPLE: reportQuery.addAverage("salary");
0207:             */
0208:            public void addAverage(String itemName) {
0209:                addAverage(itemName, getExpressionBuilder().get(itemName));
0210:            }
0211:
0212:            /**
0213:             * PUBLIC:
0214:             * Add the average value of the attribute to be included in the result and
0215:             * return it as the specified resultType.
0216:             * Aggregation functions can be used with a group by, or on the entire result set.
0217:             * EXAMPLE: reportQuery.addAverage("salary", Float.class);
0218:             */
0219:            public void addAverage(String itemName, Class resultType) {
0220:                addAverage(itemName, getExpressionBuilder().get(itemName),
0221:                        resultType);
0222:            }
0223:
0224:            /**
0225:             * PUBLIC:
0226:             * Add the average value of the attribute to be included in the result.
0227:             * Aggregation functions can be used with a group by, or on the entire result set.
0228:             * EXAMPLE: reportQuery.addAverage("managerSalary", expBuilder.get("manager").get("salary"));
0229:             */
0230:            public void addAverage(String itemName,
0231:                    Expression attributeExpression) {
0232:                addItem(itemName, attributeExpression.average());
0233:            }
0234:
0235:            /**
0236:             * PUBLIC:
0237:             * Add the average value of the attribute to be included in the result and
0238:             * return it as the specified resultType.
0239:             * Aggregation functions can be used with a group by, or on the entire result set.
0240:             * EXAMPLE: reportQuery.addAverage("managerSalary", expBuilder.get("manager").get("salary"), Double.class);
0241:             */
0242:            public void addAverage(String itemName,
0243:                    Expression attributeExpression, Class resultType) {
0244:                addItem(itemName, attributeExpression.average(), resultType);
0245:            }
0246:
0247:            /**
0248:             * PUBLIC: 
0249:             * Add a ConstructorReportItem to this query's set of return values.
0250:             * @param ConstructorReportItem - used to specify a class constructor and values to pass in from this query
0251:             * @see ConstructorReportItem
0252:             */
0253:            public void addConstructorReportItem(ConstructorReportItem item) {
0254:                addItem(item);
0255:            }
0256:
0257:            /**
0258:             * PUBLIC:
0259:             * Include the number of rows returned by the query in the result.
0260:             * Aggregation functions can be used with a group by, or on the entire result set.
0261:             * EXAMPLE:
0262:             * Java:
0263:             *     reportQuery.addCount();
0264:             * SQL:
0265:             *     SELECT COUNT (*) FROM ...
0266:             * @see #addCount(java.lang.String)
0267:             */
0268:            public void addCount() {
0269:                addCount("COUNT", getExpressionBuilder());
0270:            }
0271:
0272:            /**
0273:             * PUBLIC:
0274:             * Include the number of rows returned by the query in the result, where attributeExpression is not null.
0275:             * Aggregation functions can be used with a group by, or on the entire result set.
0276:             * <p>Example:
0277:             * <pre><blockquote>
0278:             * TopLink:    reportQuery.addCount("id");
0279:             * SQL: SELECT COUNT (t0.EMP_ID) FROM EMPLOYEE t0, ...
0280:             * </blockquote></pre>
0281:             * @param attributeName the number of rows where attributeName is not null will be returned.
0282:             * @see #addCount(java.lang.String, oracle.toplink.essentials.expressions.Expression)
0283:             */
0284:            public void addCount(String attributeName) {
0285:                addCount(attributeName, getExpressionBuilder().get(
0286:                        attributeName));
0287:            }
0288:
0289:            /**
0290:             * PUBLIC:
0291:             * Include the number of rows returned by the query in the result, where attributeExpression is not null.
0292:             * Aggregation functions can be used with a group by, or on the entire result set.
0293:             * Set the count to be returned as the specified resultType.
0294:             * <p>Example:
0295:             * <pre><blockquote>
0296:             * TopLink:    reportQuery.addCount("id", Long.class);
0297:             * SQL: SELECT COUNT (t0.EMP_ID) FROM EMPLOYEE t0, ...
0298:             * </blockquote></pre>
0299:             * @param attributeName the number of rows where attributeName is not null will be returned.
0300:             * @see #addCount(java.lang.String, oracle.toplink.essentials.expressions.Expression)
0301:             */
0302:            public void addCount(String attributeName, Class resultType) {
0303:                addCount(attributeName, getExpressionBuilder().get(
0304:                        attributeName), resultType);
0305:            }
0306:
0307:            /**
0308:             * PUBLIC:
0309:             * Include the number of rows returned by the query in the result, where attributeExpression
0310:             * is not null.
0311:             * Aggregation functions can be used with a group by, or on the entire result set.
0312:             * <p>Example:
0313:             * <pre><blockquote>
0314:             * TopLink:    reportQuery.addCount("Count", getExpressionBuilder().get("id"));
0315:             * SQL: SELECT COUNT (t0.EMP_ID) FROM EMPLOYEE t0, ...
0316:             * </blockquote></pre>
0317:             * <p>Example: counting only distinct values of an attribute.
0318:             * <pre><blockquote>
0319:             *  TopLink: reportQuery.addCount("Count", getExpressionBuilder().get("address").distinct());
0320:             *  SQL: SELECT COUNT (DISTINCT t0.ADDR_ID) FROM EMPLOYEE t0, ...
0321:             * </blockquote></pre>
0322:             * objectAttributes can be specified also, even accross many to many
0323:             * mappings.
0324:             * @see #addCount()
0325:             */
0326:            public void addCount(String itemName, Expression attributeExpression) {
0327:                addItem(itemName, attributeExpression.count());
0328:            }
0329:
0330:            /**
0331:             * PUBLIC:
0332:             * Include the number of rows returned by the query in the result, where attributeExpression
0333:             * is not null.
0334:             * Aggregation functions can be used with a group by, or on the entire result set.
0335:             * Set the count to be returned as the specified resultType.
0336:             * <p>Example:
0337:             * <pre><blockquote>
0338:             * TopLink:    reportQuery.addCount("Count", getExpressionBuilder().get("id"), Integer.class);
0339:             * SQL: SELECT COUNT (t0.EMP_ID) FROM EMPLOYEE t0, ...
0340:             * </blockquote></pre>
0341:             * <p>Example: counting only distinct values of an attribute.
0342:             * <pre><blockquote>
0343:             *  TopLink: reportQuery.addCount("Count", getExpressionBuilder().get("address").distinct());
0344:             *  SQL: SELECT COUNT (DISTINCT t0.ADDR_ID) FROM EMPLOYEE t0, ...
0345:             * </blockquote></pre>
0346:             * objectAttributes can be specified also, even accross many to many
0347:             * mappings.
0348:             * @see #addCount()
0349:             */
0350:            public void addCount(String itemName,
0351:                    Expression attributeExpression, Class resultType) {
0352:                addItem(itemName, attributeExpression.count(), resultType);
0353:            }
0354:
0355:            /**
0356:             * ADVANCED:
0357:             * Add the function against the attribute expression to be included in the result.
0358:             * Aggregation functions can be used with a group by, or on the entire result set.
0359:             * Example: reportQuery.addFunctionItem("average", expBuilder.get("salary"), "average");
0360:             */
0361:            public void addFunctionItem(String itemName,
0362:                    Expression attributeExpression, String functionName) {
0363:                Expression functionExpression = attributeExpression;
0364:                functionExpression = attributeExpression
0365:                        .getFunction(functionName);
0366:
0367:                ReportItem item = new ReportItem(itemName, functionExpression);
0368:                addItem(item);
0369:
0370:            }
0371:
0372:            /**
0373:             * PUBLIC:
0374:             * Add the attribute to the group by expressions.
0375:             * This will group the result set on that attribute and is normally used in conjunction with aggregation functions.
0376:             * Example: reportQuery.addGrouping("lastName")
0377:             */
0378:            public void addGrouping(String attributeName) {
0379:                addGrouping(getExpressionBuilder().get(attributeName));
0380:            }
0381:
0382:            /**
0383:             * PUBLIC:
0384:             * Add the attribute expression to the group by expressions.
0385:             * This will group the result set on that attribute and is normally used in conjunction with aggregation functions.
0386:             * Example: reportQuery.addGrouping(expBuilder.get("address").get("country"))
0387:             */
0388:            public void addGrouping(Expression expression) {
0389:                getGroupByExpressions().addElement(expression);
0390:                //Bug2804042 Must un-prepare if prepared as the SQL may change.
0391:                setIsPrepared(false);
0392:            }
0393:
0394:            /**
0395:             * PUBLIC:
0396:             * Add the expression to the query to be used in the HAVING clause.
0397:             * This epression will be used to filter the result sets after they are grouped.  It must be used in conjunction with the GROUP BY clause.
0398:             * Example: reportQuery.setHavingExpression(expBuilder.get("address").get("country").equal("Canada"))
0399:             */
0400:            public void setHavingExpression(Expression expression) {
0401:                havingExpression = expression;
0402:                setIsPrepared(false);
0403:            }
0404:
0405:            /**
0406:             * INTERNAL:
0407:             * Method used to abstract addToConstructorItem behavour from the public addItem methods
0408:             */
0409:            private void addItem(ReportItem item) {
0410:                if (addToConstructorItem
0411:                        && (getItems().size() > 0)
0412:                        && (((ReportItem) getItems().lastElement())
0413:                                .isContructorItem())) {
0414:                    ((ConstructorReportItem) getItems().lastElement())
0415:                            .addItem(item);
0416:                } else {
0417:                    getItems().addElement(item);
0418:                }
0419:                //Bug2804042 Must un-prepare if prepared as the SQL may change.
0420:                setIsPrepared(false);
0421:            }
0422:
0423:            /**
0424:             * ADVANCED:
0425:             * Add the expression value to be included in the result.
0426:             * EXAMPLE: reportQuery.addItem("name", expBuilder.get("firstName").toUpperCase());
0427:             */
0428:            public void addItem(String itemName, Expression attributeExpression) {
0429:                ReportItem item = new ReportItem(itemName, attributeExpression);
0430:                addItem(item);
0431:            }
0432:
0433:            /**
0434:             * ADVANCED:
0435:             * Add the expression value to be included in the result.
0436:             * EXAMPLE: reportQuery.addItem("name", expBuilder.get("firstName").toUpperCase());
0437:             */
0438:            public void addItem(String itemName,
0439:                    Expression attributeExpression, List joinedExpressions) {
0440:                ReportItem item = new ReportItem(itemName, attributeExpression);
0441:                item.getJoinedAttributeManager()
0442:                        .setJoinedAttributeExpressions_(joinedExpressions);
0443:                addItem(item);
0444:            }
0445:
0446:            /**
0447:             * INTERNAL:
0448:             * Add the expression value to be included in the result.
0449:             * EXAMPLE: reportQuery.addItem("name", expBuilder.get("firstName").toUpperCase());
0450:             * The resultType can be specified to support EJBQL that adheres to the
0451:             * EJB 3.0 spec.
0452:             */
0453:            protected void addItem(String itemName,
0454:                    Expression attributeExpression, Class resultType) {
0455:                ReportItem item = new ReportItem(itemName, attributeExpression);
0456:                item.setResultType(resultType);
0457:                addItem(item);
0458:            }
0459:
0460:            /**
0461:             * PUBLIC:
0462:             * Add the maximum value of the attribute to be included in the result.
0463:             * Aggregation functions can be used with a group by, or on the entire result set.
0464:             * EXAMPLE: reportQuery.addMaximum("salary");
0465:             */
0466:            public void addMaximum(String itemName) {
0467:                addMaximum(itemName, getExpressionBuilder().get(itemName));
0468:            }
0469:
0470:            /**
0471:             * PUBLIC:
0472:             * Add the maximum value of the attribute to be included in the result.
0473:             * Aggregation functions can be used with a group by, or on the entire result set.
0474:             * EXAMPLE: reportQuery.addMaximum("managerSalary", expBuilder.get("manager").get("salary"));
0475:             */
0476:            public void addMaximum(String itemName,
0477:                    Expression attributeExpression) {
0478:                addItem(itemName, attributeExpression.maximum());
0479:            }
0480:
0481:            /**
0482:             * PUBLIC:
0483:             * Add the minimum value of the attribute to be included in the result.
0484:             * Aggregation functions can be used with a group by, or on the entire result set.
0485:             * EXAMPLE: reportQuery.addMinimum("salary");
0486:             */
0487:            public void addMinimum(String itemName) {
0488:                addMinimum(itemName, getExpressionBuilder().get(itemName));
0489:            }
0490:
0491:            /**
0492:             * PUBLIC:
0493:             * Add the minimum value of the attribute to be included in the result.
0494:             * Aggregation functions can be used with a group by, or on the entire result set.
0495:             * EXAMPLE: reportQuery.addMinimum("managerSalary", expBuilder.get("manager").get("salary"));
0496:             */
0497:            public void addMinimum(String itemName,
0498:                    Expression attributeExpression) {
0499:                addItem(itemName, attributeExpression.minimum());
0500:            }
0501:
0502:            /**
0503:             * PUBLIC:
0504:             * Add the standard deviation value of the attribute to be included in the result.
0505:             * Aggregation functions can be used with a group by, or on the entire result set.
0506:             * EXAMPLE: reportQuery.addStandardDeviation("salary");
0507:             */
0508:            public void addStandardDeviation(String itemName) {
0509:                addStandardDeviation(itemName, getExpressionBuilder().get(
0510:                        itemName));
0511:            }
0512:
0513:            /**
0514:             * PUBLIC:
0515:             * Add the standard deviation value of the attribute to be included in the result.
0516:             * Aggregation functions can be used with a group by, or on the entire result set.
0517:             * EXAMPLE: reportQuery.addStandardDeviation("managerSalary", expBuilder.get("manager").get("salary"));
0518:             */
0519:            public void addStandardDeviation(String itemName,
0520:                    Expression attributeExpression) {
0521:                addItem(itemName, attributeExpression.standardDeviation());
0522:            }
0523:
0524:            /**
0525:             * PUBLIC:
0526:             * Add the sum value of the attribute to be included in the result.
0527:             * Aggregation functions can be used with a group by, or on the entire result set.
0528:             * EXAMPLE: reportQuery.addSum("salary");
0529:             */
0530:            public void addSum(String itemName) {
0531:                addSum(itemName, getExpressionBuilder().get(itemName));
0532:            }
0533:
0534:            /**
0535:             * PUBLIC:
0536:             * Add the sum value of the attribute to be included in the result and
0537:             * return it as the specified resultType.
0538:             * Aggregation functions can be used with a group by, or on the entire result set.
0539:             * EXAMPLE: reportQuery.addSum("salary", Float.class);
0540:             */
0541:            public void addSum(String itemName, Class resultType) {
0542:                addSum(itemName, getExpressionBuilder().get(itemName),
0543:                        resultType);
0544:            }
0545:
0546:            /**
0547:             * PUBLIC:
0548:             * Add the sum value of the attribute to be included in the result.
0549:             * Aggregation functions can be used with a group by, or on the entire result set.
0550:             * EXAMPLE: reportQuery.addSum("managerSalary", expBuilder.get("manager").get("salary"));
0551:             */
0552:            public void addSum(String itemName, Expression attributeExpression) {
0553:                addItem(itemName, attributeExpression.sum());
0554:            }
0555:
0556:            /**
0557:             * PUBLIC:
0558:             * Add the sum value of the attribute to be included in the result and
0559:             * return it as the specified resultType.
0560:             * Aggregation functions can be used with a group by, or on the entire result set.
0561:             * EXAMPLE: reportQuery.addSum("managerSalary", expBuilder.get("manager").get("salary"), Float.class);
0562:             */
0563:            public void addSum(String itemName, Expression attributeExpression,
0564:                    Class resultType) {
0565:                addItem(itemName, attributeExpression.sum(), resultType);
0566:            }
0567:
0568:            /**
0569:             * PUBLIC:
0570:             * Add the variance value of the attribute to be included in the result.
0571:             * Aggregation functions can be used with a group by, or on the entire result set.
0572:             * EXAMPLE: reportQuery.addVariance("salary");
0573:             */
0574:            public void addVariance(String itemName) {
0575:                addVariance(itemName, getExpressionBuilder().get(itemName));
0576:            }
0577:
0578:            /**
0579:             * PUBLIC:
0580:             * Add the variance value of the attribute to be included in the result.
0581:             * Aggregation functions can be used with a group by, or on the entire result set.
0582:             * EXAMPLE: reportQuery.addVariance("managerSalary", expBuilder.get("manager").get("salary"));
0583:             */
0584:            public void addVariance(String itemName,
0585:                    Expression attributeExpression) {
0586:                addItem(itemName, attributeExpression.variance());
0587:            }
0588:
0589:            /**
0590:             * PUBLIC: Call a constructor for the given class with the results of this query.
0591:             * @param constructorClass 
0592:             */
0593:            public ConstructorReportItem beginAddingConstructorArguments(
0594:                    Class constructorClass) {
0595:                ConstructorReportItem citem = new ConstructorReportItem(
0596:                        constructorClass.getName());
0597:                citem.setResultType(constructorClass);
0598:                //add directly to avoid addToConstructorItem behaviour
0599:                getItems().add(citem);
0600:                //Bug2804042 Must un-prepare if prepared as the SQL may change.
0601:                setIsPrepared(false);
0602:                this .addToConstructorItem = true;
0603:                return citem;
0604:            }
0605:
0606:            /**
0607:             * PUBLIC: Call a constructor for the given class with the results of this query.
0608:             * @param constructorClass 
0609:             * @param constructorArgTypes - sets the argument types to be passed to the constructor.
0610:             */
0611:            public ConstructorReportItem beginAddingConstructorArguments(
0612:                    Class constructorClass, Class[] constructorArgTypes) {
0613:                ConstructorReportItem citem = beginAddingConstructorArguments(constructorClass);
0614:                citem.setConstructorArgTypes(constructorArgTypes);
0615:                return citem;
0616:            }
0617:
0618:            /**
0619:             * INTERNAL:
0620:             * Construct a result from a row. Either return a ReportQueryResult or just the attribute.
0621:             */
0622:            public Object buildObject(AbstractRecord row, Vector toManyJoinData) {
0623:                ReportQueryResult reportQueryResult = new ReportQueryResult(
0624:                        this , row, toManyJoinData);
0625:                //GF_ISSUE_395
0626:                if (this .returnedKeys != null) {
0627:                    if (this .returnedKeys.contains(reportQueryResult
0628:                            .getResultKey())) {
0629:                        return RESULT_IGNORED; //distinguish between null values and thrown away duplicates
0630:                    } else {
0631:                        this .returnedKeys.add(reportQueryResult.getResultKey());
0632:                    }
0633:                }
0634:                //end GF_ISSUE_395
0635:                if (this .shouldReturnSingleAttribute()) {
0636:                    return reportQueryResult.getResults().firstElement();
0637:                }
0638:                if (this .shouldReturnWithoutReportQueryResult()) {
0639:                    if (reportQueryResult.getResults().size() == 1) {
0640:                        return reportQueryResult.getResults().firstElement();
0641:                    }
0642:                    return reportQueryResult.toArray();
0643:                }
0644:                return reportQueryResult;
0645:            }
0646:
0647:            /**
0648:             * INTERNAL:
0649:             * Construct a container of ReportQueryResult from the rows.
0650:             * If only one result or value was asked for only return that.
0651:             */
0652:            public Object buildObjects(Vector rows) {
0653:                if (shouldReturnSingleResult() || shouldReturnSingleValue()) {
0654:                    if (rows.isEmpty()) {
0655:                        return null;
0656:                    }
0657:                    ReportQueryResult result = (ReportQueryResult) buildObject(
0658:                            (AbstractRecord) rows.firstElement(), rows);
0659:                    if (shouldReturnSingleValue()) {
0660:                        return result.elements().nextElement();
0661:                    }
0662:                    return result;
0663:                }
0664:
0665:                ContainerPolicy containerPolicy = getContainerPolicy();
0666:                Object reportResults = containerPolicy.containerInstance(rows
0667:                        .size());
0668:                // GF_ISSUE_395
0669:                if (shouldDistinctBeUsed()) {
0670:                    this .returnedKeys = new HashSet();
0671:                }
0672:                //end GF_ISSUE
0673:                //If only the attribute is desired, then buildObject will only get the first attribute each time
0674:                for (Enumeration rowsEnum = rows.elements(); rowsEnum
0675:                        .hasMoreElements();) {
0676:                    // GF_ISSUE_395
0677:                    Object result = buildObject((AbstractRecord) rowsEnum
0678:                            .nextElement(), rows);
0679:                    if (result != RESULT_IGNORED) {
0680:                        containerPolicy.addInto(result, reportResults,
0681:                                getSession());
0682:                    }
0683:                    //end GF_ISSUE
0684:                }
0685:                return reportResults;
0686:            }
0687:
0688:            /**
0689:             * INTERNAL:
0690:             * The cache check is done before the prepare as a hit will not require the work to be done.
0691:             */
0692:            protected Object checkEarlyReturnImpl(AbstractSession session,
0693:                    AbstractRecord translationRow) {
0694:                // Check for in-memory only query.
0695:                if (shouldCheckCacheOnly()) {
0696:                    throw QueryException
0697:                            .cannotSetShouldCheckCacheOnlyOnReportQuery();
0698:                } else {
0699:                    return null;
0700:                }
0701:            }
0702:
0703:            /**
0704:             * INTERNAL: Required for a very special case of bug 2612185:
0705:             * ReportItems from parallelExpressions, on a ReportQuery which is a subQuery,
0706:             * which is being batch read.
0707:             * In a batch query the selection criteria is effectively cloned twice, meaning
0708:             * the ReportItems need to be cloned an extra time also to stay in sync.
0709:             * Each call to copiedVersionFrom() will take O(1) time as the expression was
0710:             * already cloned.
0711:             */
0712:            public void copyReportItems(Dictionary alreadyDone) {
0713:                items = (Vector) items.clone();
0714:                for (int i = items.size() - 1; i >= 0; i--) {
0715:                    ReportItem item = (ReportItem) items.elementAt(i);
0716:                    Expression expression = item.getAttributeExpression();
0717:                    if ((expression != null)
0718:                            && (alreadyDone.get(expression.getBuilder()) != null)) {
0719:                        expression = expression.copiedVersionFrom(alreadyDone);
0720:                    }
0721:                    items.set(i, new ReportItem(item.getName(), expression));
0722:                }
0723:                if (groupByExpressions != null) {
0724:                    groupByExpressions = (Vector) groupByExpressions.clone();
0725:                    for (int i = groupByExpressions.size() - 1; i >= 0; i--) {
0726:                        Expression item = (Expression) groupByExpressions
0727:                                .elementAt(i);
0728:                        if (alreadyDone.get(item.getBuilder()) != null) {
0729:                            groupByExpressions.set(i, item
0730:                                    .copiedVersionFrom(alreadyDone));
0731:                        }
0732:                    }
0733:                }
0734:                if (orderByExpressions != null) {
0735:                    for (int i = orderByExpressions.size() - 1; i >= 0; i--) {
0736:                        Expression item = (Expression) orderByExpressions
0737:                                .elementAt(i);
0738:                        if (alreadyDone.get(item.getBuilder()) != null) {
0739:                            orderByExpressions.set(i, item
0740:                                    .copiedVersionFrom(alreadyDone));
0741:                        }
0742:                    }
0743:                }
0744:            }
0745:
0746:            /**
0747:             * PUBLIC:
0748:             * Set if the query results should contain the primary keys or each associated object.
0749:             * This make retrieving the real object easier.
0750:             * By default they are not retrieved.
0751:             */
0752:            public void dontRetrievePrimaryKeys() {
0753:                setShouldRetrievePrimaryKeys(false);
0754:                //Bug2804042 Must un-prepare if prepared as the SQL may change.
0755:                setIsPrepared(false);
0756:            }
0757:
0758:            /**
0759:             * PUBLIC:
0760:             * Don't simplify the result by returning the single attribute. Wrap in a ReportQueryResult.
0761:             */
0762:            public void dontReturnSingleAttribute() {
0763:                if (shouldReturnSingleAttribute()) {
0764:                    returnChoice = 0;
0765:                }
0766:            }
0767:
0768:            /**
0769:             * PUBLIC:
0770:             * Simplifies the result by only returning the first result.
0771:             * This can be used if it known that only one row is returned by the report query.
0772:             */
0773:            public void dontReturnSingleResult() {
0774:                if (shouldReturnSingleResult()) {
0775:                    returnChoice = 0;
0776:                }
0777:            }
0778:
0779:            /**
0780:             * PUBLIC:
0781:             * Simplifies the result by only returning a single value.
0782:             * This can be used if it known that only one row is returned by the report query and only a single item is added
0783:             * to the report.
0784:             */
0785:            public void dontReturnSingleValue() {
0786:                if (shouldReturnSingleValue()) {
0787:                    returnChoice = 0;
0788:                }
0789:            }
0790:
0791:            /**
0792:             * PUBLIC:
0793:             * Simplifies the result by only returning a single value.
0794:             * This can be used if it known that only one row is returned by the report query and only a single item is added
0795:             * to the report.
0796:             */
0797:            public void dontReturnWithoutReportQueryResult() {
0798:                if (shouldReturnWithoutReportQueryResult()) {
0799:                    returnChoice = 0;
0800:                }
0801:            }
0802:
0803:            /**
0804:             * PUBLIC:
0805:             * Used in conjunction with beginAddingConstructorArguments to signal that expressions should no longer be 
0806:             * be added to the collection used in the constructor
0807:             * 
0808:             * Get the rows and build the object from the rows.
0809:             * @exception  DatabaseException - an error has occurred on the database
0810:             * @return Vector - collection of objects resulting from execution of query.
0811:             */
0812:            public void endAddingToConstructorItem() {
0813:                this .addToConstructorItem = false;
0814:            }
0815:
0816:            /**
0817:             * INTERNAL:
0818:             * Execute the query.
0819:             * Get the rows and build the object from the rows.
0820:             * @exception  DatabaseException - an error has occurred on the database
0821:             * @return Vector - collection of objects resulting from execution of query.
0822:             */
0823:            public Object executeDatabaseQuery() throws DatabaseException {
0824:                // ensure a pessimistic locking query will go down the write connection
0825:                if (isLockQuery() && getSession().isUnitOfWork()) {
0826:                    UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl) getSession();
0827:                    // Note if a nested unit of work this will recursively start a
0828:                    // transaction early on the parent also.
0829:                    if (isLockQuery()) {
0830:                        if ((!unitOfWork.getCommitManager().isActive())
0831:                                && (!unitOfWork
0832:                                        .wasTransactionBegunPrematurely())) {
0833:                            unitOfWork.beginTransaction();
0834:                            unitOfWork.setWasTransactionBegunPrematurely(true);
0835:                        }
0836:                    }
0837:                }
0838:
0839:                if (getContainerPolicy().overridesRead()) {
0840:                    return getContainerPolicy().execute();
0841:                }
0842:
0843:                if (getQueryId() == 0) {
0844:                    setQueryId(getSession().getNextQueryId());
0845:                }
0846:
0847:                Vector rows = getQueryMechanism().selectAllReportQueryRows();
0848:                // If using -m joins, must set all rows.
0849:                return buildObjects(rows);
0850:            }
0851:
0852:            /**
0853:             * INTERNAL:
0854:             * Return the group bys.
0855:             */
0856:            public Vector getGroupByExpressions() {
0857:                return groupByExpressions;
0858:            }
0859:
0860:            /**
0861:             * INTERNAL:
0862:             * Return the Having expression.
0863:             */
0864:            public Expression getHavingExpression() {
0865:                return havingExpression;
0866:            }
0867:
0868:            /**
0869:             * INTERNAL:
0870:             * return a collection of expressions if PK's are used.
0871:             */
0872:            public Vector getQueryExpressions() {
0873:                Vector fieldExpressions = new Vector(getItems().size());
0874:
0875:                // For bug 3115576 and an EXISTS subquery only need to return a single field.
0876:                if (shouldRetrieveFirstPrimaryKey()) {
0877:                    if (!getDescriptor().getPrimaryKeyFields().isEmpty()) {
0878:                        fieldExpressions.addElement(getDescriptor()
0879:                                .getPrimaryKeyFields().get(0));
0880:                    }
0881:                }
0882:                if (shouldRetrievePrimaryKeys()) {
0883:                    fieldExpressions.addAll(getDescriptor()
0884:                            .getPrimaryKeyFields());
0885:                }
0886:
0887:                return fieldExpressions;
0888:            }
0889:
0890:            /**
0891:             * INTERNAL:
0892:             * return a collection of expressions from the items. Ignore the null (place holders).
0893:             */
0894:            public Vector getItemExpressions() {
0895:                Vector fieldExpressions = new Vector(getItems().size());
0896:
0897:                // For bug 3115576 and an EXISTS subquery only need to return a single field.
0898:                if (shouldRetrieveFirstPrimaryKey()) {
0899:                    if (!getDescriptor().getPrimaryKeyFields().isEmpty()) {
0900:                        fieldExpressions.addElement(getDescriptor()
0901:                                .getPrimaryKeyFields().get(0));
0902:                    }
0903:                }
0904:                if (shouldRetrievePrimaryKeys()) {
0905:                    fieldExpressions.addAll(getDescriptor()
0906:                            .getPrimaryKeyFields());
0907:                }
0908:
0909:                for (Enumeration itemsEnum = getItems().elements(); itemsEnum
0910:                        .hasMoreElements();) {
0911:                    ReportItem item = (ReportItem) itemsEnum.nextElement();
0912:                    Expression fieldExpression = item.getAttributeExpression();
0913:                    if (fieldExpression != null) {
0914:                        fieldExpressions.addElement(fieldExpression);
0915:                    }
0916:                }
0917:                return fieldExpressions;
0918:            }
0919:
0920:            /**
0921:             * INTERNAL:
0922:             * @return ReportQueryItems defining the attributes to be read
0923:             */
0924:            public Vector getItems() {
0925:                return items;
0926:            }
0927:
0928:            /**
0929:             * INTERNAL:
0930:             * Clear the ReportQueryItems
0931:             */
0932:            public void clearItems() {
0933:                items = new Vector();
0934:                setIsPrepared(false);
0935:            }
0936:
0937:            /**
0938:             * INTERNAL:
0939:             * Lazily initialize and return the names of the items requested for use in each result object
0940:             */
0941:            public Vector getNames() {
0942:                if (names == null) {
0943:                    names = new Vector();
0944:                    for (Enumeration e = getItems().elements(); e
0945:                            .hasMoreElements();) {
0946:                        names.addElement(((ReportItem) e.nextElement())
0947:                                .getName());
0948:                    }
0949:                }
0950:                return names;
0951:            }
0952:
0953:            /**
0954:             * PUBLIC:
0955:             * Return if this is a report query.
0956:             */
0957:            public boolean isReportQuery() {
0958:                return true;
0959:            }
0960:
0961:            /**
0962:             * INTERNAL:
0963:             * Prepare the receiver for execution in a session.
0964:             * Initialize each item with its DTF mapping
0965:             */
0966:            protected void prepare() throws QueryException {
0967:                // Oct 19, 2000 JED
0968:                // Added exception to be thrown if no attributes have been added to the query
0969:                if (getItems().size() > 0) {
0970:                    try {
0971:                        for (Enumeration itemsEnum = getItems().elements(); itemsEnum
0972:                                .hasMoreElements();) {
0973:                            ((ReportItem) itemsEnum.nextElement())
0974:                                    .initialize(this );
0975:                        }
0976:                    } catch (QueryException exception) {
0977:                        exception.setQuery(this );
0978:                        throw exception;
0979:                    }
0980:                } else {
0981:                    if ((!shouldRetrievePrimaryKeys())
0982:                            && (!shouldRetrieveFirstPrimaryKey())) {
0983:                        throw QueryException.noAttributesForReportQuery(this );
0984:                    }
0985:                }
0986:
0987:                super .prepare();
0988:
0989:            }
0990:
0991:            /**
0992:             * INTERNAL:
0993:             * Prepare a report query with a count defined on an object attribute.
0994:             * Added to fix bug 3268040, addCount(objectAttribute) not supported.
0995:             */
0996:            protected void prepareObjectAttributeCount(
0997:                    Dictionary clonedExpressions) {
0998:                prepareObjectAttributeCount(getItems(), clonedExpressions);
0999:            }
1000:
1001:            private void prepareObjectAttributeCount(List items,
1002:                    Dictionary clonedExpressions) {
1003:                int numOfReportItems = items.size();
1004:                //gf675: need to loop through all items to fix all count(..) instances
1005:                for (int i = 0; i < numOfReportItems; i++) {
1006:                    ReportItem item = (ReportItem) items.get(i);
1007:                    if (item == null) {
1008:                        continue;
1009:                    } else if (item instanceof  ConstructorReportItem) {
1010:                        // recursive call to process child ReportItems
1011:                        prepareObjectAttributeCount(
1012:                                ((ConstructorReportItem) item).getReportItems(),
1013:                                clonedExpressions);
1014:                    } else if (item.getAttributeExpression() instanceof  FunctionExpression) {
1015:                        FunctionExpression count = (FunctionExpression) item
1016:                                .getAttributeExpression();
1017:                        if (count.getOperator().getSelector() == ExpressionOperator.Count) {
1018:                            Expression baseExp = count.getBaseExpression();
1019:                            boolean distinctUsed = false;
1020:                            if (baseExp.isFunctionExpression()
1021:                                    && (((FunctionExpression) baseExp)
1022:                                            .getOperator().getSelector() == ExpressionOperator.Distinct)) {
1023:                                distinctUsed = true;
1024:                                baseExp = ((FunctionExpression) baseExp)
1025:                                        .getBaseExpression();
1026:                            }
1027:                            boolean outerJoin = false;
1028:                            ClassDescriptor newDescriptor = null;
1029:                            if (baseExp.isQueryKeyExpression()) {
1030:                                // now need to find out if it is a direct to field or something else.
1031:                                DatabaseMapping mapping = getLeafMappingFor(
1032:                                        baseExp, getDescriptor());
1033:                                if ((mapping != null)
1034:                                        && !mapping.isDirectToFieldMapping()) {
1035:                                    newDescriptor = mapping
1036:                                            .getReferenceDescriptor();
1037:                                    outerJoin = ((QueryKeyExpression) baseExp)
1038:                                            .shouldUseOuterJoin();
1039:                                }
1040:                            } else if (baseExp.isExpressionBuilder()) {
1041:                                newDescriptor = getSession().getDescriptor(
1042:                                        ((ExpressionBuilder) baseExp)
1043:                                                .getQueryClass());
1044:                            }
1045:
1046:                            if (newDescriptor != null) {
1047:                                // At this point we are committed to rewriting the query.
1048:                                if (newDescriptor.hasSimplePrimaryKey()) {
1049:                                    // case 1: simple PK =>
1050:                                    // treat COUNT(entity) as COUNT(entity.pk)
1051:                                    DatabaseMapping pk = getMappingOfFirstPrimaryKey(newDescriptor);
1052:                                    Expression countArg = baseExp.get(pk
1053:                                            .getAttributeName());
1054:                                    if (distinctUsed) {
1055:                                        countArg = countArg.distinct();
1056:                                    }
1057:                                    count.setBaseExpression(countArg);
1058:                                    count.getChildren().setElementAt(countArg,
1059:                                            0);
1060:                                } else if (!distinctUsed) {
1061:                                    // case 2: composite PK, but no DISTINCT =>
1062:                                    // pick a PK column for the COUNT aggregate
1063:                                    DatabaseMapping pk = getMappingOfFirstPrimaryKey(newDescriptor);
1064:                                    Expression countArg = baseExp.get(pk
1065:                                            .getAttributeName());
1066:                                    while (pk.isAggregateObjectMapping()) {
1067:                                        newDescriptor = ((AggregateObjectMapping) pk)
1068:                                                .getReferenceDescriptor();
1069:                                        pk = getMappingOfFirstPrimaryKey(newDescriptor);
1070:                                        countArg = countArg.get(pk
1071:                                                .getAttributeName());
1072:                                    }
1073:                                    count.setBaseExpression(countArg);
1074:                                    count.getChildren().setElementAt(countArg,
1075:                                            0);
1076:                                } else if (!outerJoin) {
1077:                                    // case 3: composite PK and DISTINCT, but no
1078:                                    // outer join => previous solution using
1079:                                    // COUNT(*) and EXISTS subquery
1080:
1081:                                    // If this is a subselect baseExp is yet uncloned,
1082:                                    // and will miss out if moved now from items into a selection criteria.
1083:                                    if (clonedExpressions != null) {
1084:                                        if (clonedExpressions.get(baseExp
1085:                                                .getBuilder()) != null) {
1086:                                            baseExp = (QueryKeyExpression) baseExp
1087:                                                    .copiedVersionFrom(clonedExpressions);
1088:                                        } else {
1089:                                            baseExp = (QueryKeyExpression) baseExp
1090:                                                    .rebuildOn(getExpressionBuilder());
1091:                                        }
1092:                                    }
1093:
1094:                                    // Now the reference class of the query needs to be reversed.
1095:                                    // See the bug description for an explanation.
1096:                                    ExpressionBuilder countBuilder = baseExp
1097:                                            .getBuilder();
1098:                                    ExpressionBuilder outerBuilder = new ExpressionBuilder();
1099:
1100:                                    ReportQuery subSelect = new ReportQuery(
1101:                                            getReferenceClass(), countBuilder);
1102:                                    subSelect
1103:                                            .setShouldRetrieveFirstPrimaryKey(true);
1104:
1105:                                    // Make sure the outerBuilder does not appear on the left of the subselect.
1106:                                    // Putting a builder on the left is desirable to trigger an optimization.
1107:                                    if (getSelectionCriteria() != null) {
1108:                                        outerBuilder
1109:                                                .setQueryClass(newDescriptor
1110:                                                        .getJavaClass());
1111:                                        subSelect
1112:                                                .setSelectionCriteria(baseExp
1113:                                                        .equal(outerBuilder)
1114:                                                        .and(
1115:                                                                getSelectionCriteria()));
1116:                                    } else {
1117:                                        subSelect.setSelectionCriteria(baseExp
1118:                                                .equal(outerBuilder));
1119:                                    }
1120:                                    setSelectionCriteria(outerBuilder
1121:                                            .exists(subSelect));
1122:                                    count.setBaseExpression(outerBuilder);
1123:                                    count.getChildren().setElementAt(
1124:                                            outerBuilder, 0);
1125:                                    setReferenceClass(newDescriptor
1126:                                            .getJavaClass());
1127:                                    changeDescriptor(getSession());
1128:                                } else {
1129:                                    // case 4: composite PK, DISTINCT, outer join => 
1130:                                    // not supported, throw exception
1131:                                    throw QueryException
1132:                                            .distinctCountOnOuterJoinedCompositePK(
1133:                                                    newDescriptor, this );
1134:                                }
1135:                            }
1136:                        }
1137:                    }
1138:                }
1139:            }
1140:
1141:            /** */
1142:            private DatabaseMapping getMappingOfFirstPrimaryKey(
1143:                    ClassDescriptor descriptor) {
1144:                if (descriptor != null) {
1145:                    for (Iterator i = descriptor.getMappings().iterator(); i
1146:                            .hasNext();) {
1147:                        DatabaseMapping m = (DatabaseMapping) i.next();
1148:                        if (m.isPrimaryKeyMapping()) {
1149:                            return m;
1150:                        }
1151:                    }
1152:                }
1153:                return null;
1154:            }
1155:
1156:            /**
1157:             * INTERNAL:
1158:             * Prepare the mechanism.
1159:             */
1160:            protected void prepareSelectAllRows() {
1161:                prepareObjectAttributeCount(null);
1162:
1163:                getQueryMechanism().prepareReportQuerySelectAllRows();
1164:            }
1165:
1166:            /**
1167:             * INTERNAL:
1168:             * Prepare the receiver for being printed inside a subselect.
1169:             * This prepares the statement but not the call.
1170:             */
1171:            public synchronized void prepareSubSelect(AbstractSession session,
1172:                    AbstractRecord translationRow, Dictionary clonedExpressions)
1173:                    throws QueryException {
1174:                if (isPrepared()) {
1175:                    return;
1176:                }
1177:
1178:                setIsPrepared(true);
1179:                setSession(session);
1180:                setTranslationRow(translationRow);
1181:
1182:                checkDescriptor(getSession());
1183:
1184:                if (descriptor.isAggregateDescriptor()) {
1185:                    // Not allowed
1186:                    throw QueryException
1187:                            .aggregateObjectCannotBeDeletedOrWritten(
1188:                                    descriptor, this );
1189:                }
1190:
1191:                try {
1192:                    for (Enumeration itemsEnum = getItems().elements(); itemsEnum
1193:                            .hasMoreElements();) {
1194:                        ((ReportItem) itemsEnum.nextElement()).initialize(this );
1195:                    }
1196:                } catch (QueryException exception) {
1197:                    exception.setQuery(this );
1198:                    throw exception;
1199:                }
1200:
1201:                prepareObjectAttributeCount(clonedExpressions);
1202:
1203:                getQueryMechanism().prepareReportQuerySubSelect();
1204:
1205:                setSession(null);
1206:                setTranslationRow(null);
1207:            }
1208:
1209:            /**
1210:             * PUBLIC:
1211:             * Set if the query results should contain the primary keys or each associated object.
1212:             * This make retrieving the real object easier.
1213:             * By default they are not retrieved.
1214:             */
1215:            public void retrievePrimaryKeys() {
1216:                setShouldRetrievePrimaryKeys(true);
1217:                //Bug2804042 Must un-prepare if prepared as the SQL may change.
1218:                setIsPrepared(false);
1219:            }
1220:
1221:            /**
1222:             * PUBLIC:
1223:             * Simplify the result by returning a single attribute. Don't wrap in a ReportQueryResult.
1224:             */
1225:            public void returnSingleAttribute() {
1226:                returnChoice = ShouldReturnSingleAttribute;
1227:            }
1228:
1229:            /**
1230:             * PUBLIC:
1231:             * Simplifies the result by only returning the first result.
1232:             * This can be used if it known that only one row is returned by the report query.
1233:             */
1234:            public void returnSingleResult() {
1235:                returnChoice = ShouldReturnSingleResult;
1236:            }
1237:
1238:            /**
1239:             * PUBLIC:
1240:             * Simplifies the result by only returning a single value.
1241:             * This can be used if it known that only one row is returned by the report query and only a single item is added
1242:             * to the report.
1243:             */
1244:            public void returnSingleValue() {
1245:                returnChoice = ShouldReturnSingleValue;
1246:            }
1247:
1248:            /**
1249:             * PUBLIC:
1250:             * Simplifies the result by only returning a single value.
1251:             * This can be used if it known that only one row is returned by the report query and only a single item is added
1252:             * to the report.
1253:             */
1254:            public void returnWithoutReportQueryResult() {
1255:                this .returnChoice = ShouldReturnWithoutReportQueryResult;
1256:            }
1257:
1258:            /**
1259:             * PUBLIC:
1260:             * Set if the query results should contain the primary keys or each associated object.
1261:             * This make retrieving the real object easier.
1262:             * By default they are not retrieved.
1263:             */
1264:            public void setShouldRetrievePrimaryKeys(
1265:                    boolean shouldRetrievePrimaryKeys) {
1266:                this .shouldRetrievePrimaryKeys = (shouldRetrievePrimaryKeys ? FULL_PRIMARY_KEY
1267:                        : NO_PRIMARY_KEY);
1268:            }
1269:
1270:            /**
1271:             * ADVANCED:
1272:             * Sets if the query results should contain the first primary key of each associated object.
1273:             * Usefull if this is an EXISTS subquery and you don't care what fields are returned
1274:             * so long as it is a single field.
1275:             * The default value is false.
1276:             * This should only be used with a subquery.
1277:             */
1278:            public void setShouldRetrieveFirstPrimaryKey(
1279:                    boolean shouldRetrieveFirstPrimaryKey) {
1280:                this .shouldRetrievePrimaryKeys = (shouldRetrieveFirstPrimaryKey ? FIRST_PRIMARY_KEY
1281:                        : NO_PRIMARY_KEY);
1282:            }
1283:
1284:            /**
1285:             * PUBLIC:
1286:             * Simplifies the result by only returning the attribute (as opposed to wrapping in a ReportQueryResult).
1287:             * This can be used if it is known that only one attribute is returned by the report query.
1288:             */
1289:            public void setShouldReturnSingleAttribute(boolean newChoice) {
1290:                if (newChoice) {
1291:                    returnSingleAttribute();
1292:                } else {
1293:                    dontReturnSingleAttribute();
1294:                }
1295:            }
1296:
1297:            /**
1298:             * PUBLIC:
1299:             * Simplifies the result by only returning the first result.
1300:             * This can be used if it known that only one row is returned by the report query.
1301:             */
1302:            public void setShouldReturnSingleResult(boolean newChoice) {
1303:                if (newChoice) {
1304:                    returnSingleResult();
1305:                } else {
1306:                    dontReturnSingleResult();
1307:                }
1308:            }
1309:
1310:            /**
1311:             * PUBLIC:
1312:             * Simplifies the result by only returning a single value.
1313:             * This can be used if it known that only one row is returned by the report query and only a single item is added
1314:             * to the report.
1315:             */
1316:            public void setShouldReturnSingleValue(boolean newChoice) {
1317:                if (newChoice) {
1318:                    returnSingleValue();
1319:                } else {
1320:                    dontReturnSingleValue();
1321:                }
1322:            }
1323:
1324:            /**
1325:             * PUBLIC:
1326:             * Simplifies the result by returning a nested list instead of the ReportQueryResult.
1327:             * This is used by EJB 3.
1328:             */
1329:            public void setShouldReturnWithoutReportQueryResult(
1330:                    boolean newChoice) {
1331:                if (newChoice) {
1332:                    returnWithoutReportQueryResult();
1333:                } else {
1334:                    dontReturnWithoutReportQueryResult();
1335:                }
1336:            }
1337:
1338:            /**
1339:             * PUBLIC:
1340:             * Return if the query results should contain the primary keys or each associated object.
1341:             * This make retrieving the real object easier.
1342:             */
1343:            public boolean shouldRetrievePrimaryKeys() {
1344:                return (shouldRetrievePrimaryKeys == FULL_PRIMARY_KEY);
1345:            }
1346:
1347:            /**
1348:             * PUBLIC:
1349:             * Return if the query results should contain the first primary key of each associated object.
1350:             * Usefull if this is an EXISTS subquery and you don't care what fields are returned
1351:             * so long as it is a single field.
1352:             */
1353:            public boolean shouldRetrieveFirstPrimaryKey() {
1354:                return (shouldRetrievePrimaryKeys == FIRST_PRIMARY_KEY);
1355:            }
1356:
1357:            /**
1358:             * PUBLIC:
1359:             * Answer if we are only returning the attribute (as opposed to wrapping in a ReportQueryResult).
1360:             * This can be used if it is known that only one attribute is returned by the report query.
1361:             */
1362:            public boolean shouldReturnSingleAttribute() {
1363:                return returnChoice == ShouldReturnSingleAttribute;
1364:            }
1365:
1366:            /**
1367:             * PUBLIC:
1368:             * Simplifies the result by only returning the first result.
1369:             * This can be used if it known that only one row is returned by the report query.
1370:             */
1371:            public boolean shouldReturnSingleResult() {
1372:                return returnChoice == ShouldReturnSingleResult;
1373:            }
1374:
1375:            /**
1376:             * PUBLIC:
1377:             * Simplifies the result by only returning a single value.
1378:             * This can be used if it known that only one row is returned by the report query and only a single item is added
1379:             * to the report.
1380:             */
1381:            public boolean shouldReturnSingleValue() {
1382:                return returnChoice == ShouldReturnSingleValue;
1383:            }
1384:
1385:            /**
1386:             * PUBLIC:
1387:             * Simplifies the result by returning a nested list instead of the ReportQueryResult.
1388:             * This is used by EJB 3.
1389:             */
1390:            public boolean shouldReturnWithoutReportQueryResult() {
1391:                return returnChoice == ShouldReturnWithoutReportQueryResult;
1392:            }
1393:
1394:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.