KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > internal > parsing > DotNode


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21 // Copyright (c) 1998, 2006, Oracle. All rights reserved.
22
package oracle.toplink.essentials.internal.parsing;
23
24 import oracle.toplink.essentials.exceptions.EJBQLException;
25 import oracle.toplink.essentials.expressions.*;
26 import oracle.toplink.essentials.internal.expressions.*;
27 import oracle.toplink.essentials.mappings.DatabaseMapping;
28 import oracle.toplink.essentials.mappings.DirectToFieldMapping;
29 import oracle.toplink.essentials.queryframework.ObjectLevelReadQuery;
30 import oracle.toplink.essentials.queryframework.ReportQuery;
31
32 /**
33  * INTERNAL
34  * <p><b>Purpose</b>: This node represents an 'DOT' (i.e. '.') on the input
35  * stream. The left and right will depend on the input stream.
36  * <p><b>Responsibilities</b>:<ul>
37  * </ul>
38  * @author Jon Driscoll and Joel Lucuik
39  * @since TopLink 4.0
40  */

41 public class DotNode extends LogicalOperatorNode {
42
43     private Object JavaDoc enumConstant;
44
45     /**
46      * INTERNAL
47      * Apply this node to the passed query
48      */

49     public void applyToQuery(ObjectLevelReadQuery theQuery, GenerationContext context) {
50         if (theQuery.isReportQuery()){
51             ReportQuery reportQuery = (ReportQuery)theQuery;
52             reportQuery.addAttribute(resolveAttribute(), generateExpression(context));
53             reportQuery.dontRetrievePrimaryKeys();
54         }
55     }
56
57     /**
58      * INTERNAL
59      * Validate node and calculate its type.
60      * Check for enum literals.
61      */

62     public void validate(ParseTreeContext context) {
63         TypeHelper typeHelper = context.getTypeHelper();
64         // check for fully qualified type names
65
Node leftMost = getLeftMostNode();
66         if (isDeclaredVariable(leftMost, context)) {
67             Object JavaDoc attributeType = null;
68             left.validate(context);
69             Object JavaDoc leftType = left.getType();
70             if (!typeHelper.isEntityClass(leftType) &&
71                 !typeHelper.isEnumType(leftType)) {
72                 throw EJBQLException.invalidNavigation(
73                     this.getAsString(), left.getAsString(),
74                     typeHelper.getTypeName(leftType));
75             } else {
76                 String JavaDoc name = ((AttributeNode)right).getAttributeName();
77                 attributeType = typeHelper.resolveAttribute(leftType, name);
78                 if (attributeType == null) {
79                     // could not resolve attribute
80
throw EJBQLException.unknownAttribute(
81                         name, typeHelper.getTypeName(leftType));
82                 }
83             }
84             setType(attributeType);
85             right.setType(attributeType);
86         } else {
87             // Check for enum literal access
88
String JavaDoc typeName = left.getAsString();
89             String JavaDoc name = ((AttributeNode)right).getAttributeName();
90             Object JavaDoc type = resolveEnumTypeName(typeName, typeHelper);
91             if ((type != null) && typeHelper.isEnumType(type)) {
92                 enumConstant = typeHelper.resolveEnumConstant(type, name);
93                 if (enumConstant == null) {
94                     throw EJBQLException.invalidEnumLiteral(typeName, name);
95                 }
96             }
97         }
98     }
99     
100     /** */
101     private boolean isDeclaredVariable(Node node, ParseTreeContext context) {
102         if (node.isVariableNode()) {
103             String JavaDoc name = ((VariableNode)node).getCanonicalVariableName();
104             return context.isVariable(name);
105         }
106         return false;
107     }
108
109     /**
110      * INTERNAL
111      * Return a TopLink expression by getting the required variables using the
112      * left and right nodes
113      * "emp.address.city" = builder.get("address").get("city")
114      */

115     public Expression generateExpression(GenerationContext context) {
116         Node left = getLeft();
117         Node right = getRight();
118
119         if (enumConstant != null) {
120             // enum literal access
121
return new ConstantExpression(enumConstant, new ExpressionBuilder());
122         } else {
123             // Get the left expression
124
Expression whereClause = getLeft().generateExpression(context);
125             
126             // Calculate the mapping and pass it to the right expression
127
if (right.isAttributeNode()) {
128                 ((AttributeNode)right).setMapping(resolveMapping(context));
129             }
130             
131             // Or it with whatever the right expression is
132
whereClause = right.addToExpression(whereClause, context);
133             
134             // and return the expression...
135
return whereClause;
136         }
137     }
138
139     /**
140      * INTERNAL
141      * Yes, this is a dot node
142      */

143     public boolean isDotNode() {
144         return true;
145     }
146
147     /**
148      * INTERNAL
149      * ():
150      * Answer true if the SELECTed node has a left and right, and the right represents
151      * a direct-to-field mapping.
152      */

153     public boolean endsWithDirectToField(GenerationContext context) {
154         DatabaseMapping mapping = resolveMapping(context);
155         return (mapping != null) && mapping.isDirectToFieldMapping();
156     }
157
158     /**
159      * INTERNAL
160      * Returns the attribute type if the right represents a direct-to-field mapping.
161      */

162     public Class JavaDoc getTypeOfDirectToField(GenerationContext context) {
163         DatabaseMapping mapping = resolveMapping(context);
164         if ((mapping != null) && mapping.isDirectToFieldMapping()) {
165             return ((DirectToFieldMapping)mapping).getAttributeClassification();
166         }
167         return null;
168     }
169
170     /**
171      * INTERNAL
172      * ():
173      * Answer true if the node has a left and right, and the right represents
174      * a collection mapping.
175      */

176     public boolean endsWithCollectionField(GenerationContext context) {
177         DatabaseMapping mapping = resolveMapping(context);
178         return (mapping != null) && mapping.isCollectionMapping();
179     }
180
181     /**
182      * INTERNAL
183      * Answer the name of the attribute which is represented by the receiver's
184      * right node.
185      */

186     public String JavaDoc resolveAttribute() {
187         return ((AttributeNode)getRight()).getAttributeName();
188     }
189
190     /**
191      * INTERNAL
192      * Answer the mapping resulting from traversing the receiver's nodes
193      */

194     public DatabaseMapping resolveMapping(GenerationContext context) {
195         Class JavaDoc leftClass = getLeft().resolveClass(context);
196         return getRight().resolveMapping(context, leftClass);
197     }
198
199     /**
200     * resolveClass: Answer the class which results from traversing the mappings for the receiver's nodes
201     */

202     public Class JavaDoc resolveClass(GenerationContext context) {
203         Class JavaDoc leftClass = getLeft().resolveClass(context);
204         return getRight().resolveClass(context, leftClass);
205     }
206     
207     /**
208      * INTERNAL
209      * Get the string representation of this node.
210      */

211     public String JavaDoc getAsString() {
212         return left.getAsString() + "." + right.getAsString();
213     }
214
215     /**
216      * INTERNAL
217      * Return the left most node of a dot expr, so return 'a' for 'a.b.c'.
218      */

219     private Node getLeftMostNode() {
220         return left.isDotNode() ? ((DotNode)left).getLeftMostNode() : left;
221     }
222
223     /**
224      * INTERNAL
225      * Returns the type representation for the specified type name. The method
226      * looks for inner classes if it cannot resolve the type name.
227      */

228     private Object JavaDoc resolveEnumTypeName(String JavaDoc name, TypeHelper helper) {
229         Object JavaDoc type = helper.resolveTypeName(name);
230         if (type == null) {
231             // check for inner enum type
232
int index = name.lastIndexOf('.');
233             if (index != -1) {
234                 name = name.substring(0, index) + '$' + name.substring(index+1);
235                 type = helper.resolveTypeName(name);
236             }
237         }
238         return type;
239     }
240 }
241
Popular Tags