001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * // Copyright (c) 1998, 2007, Oracle. All rights reserved.
005: *
006: *
007: * The contents of this file are subject to the terms of either the GNU
008: * General Public License Version 2 only ("GPL") or the Common Development
009: * and Distribution License("CDDL") (collectively, the "License"). You
010: * may not use this file except in compliance with the License. You can obtain
011: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
012: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
013: * language governing permissions and limitations under the License.
014: *
015: * When distributing the software, include this License Header Notice in each
016: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
017: * Sun designates this particular file as subject to the "Classpath" exception
018: * as provided by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the License
020: * Header, with the fields enclosed by brackets [] replaced by your own
021: * identifying information: "Portions Copyrighted [year]
022: * [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * If you wish your version of this file to be governed by only the CDDL or
027: * only the GPL Version 2, indicate your decision by adding "[Contributor]
028: * elects to include this software in this distribution under the [CDDL or GPL
029: * Version 2] license." If you don't indicate a single choice of license, a
030: * recipient has the option to distribute your version of this file under
031: * either the CDDL, the GPL Version 2 or to extend the choice of license to
032: * its licensees as provided above. However, if you add GPL Version 2 code
033: * and therefore, elected the GPL Version 2 license, then the option applies
034: * only if the new code is made subject to such option by the copyright
035: * holder.
036: */
037: package oracle.toplink.essentials.internal.parsing;
038:
039: import oracle.toplink.essentials.descriptors.ClassDescriptor;
040: import oracle.toplink.essentials.exceptions.EJBQLException;
041: import oracle.toplink.essentials.expressions.*;
042: import oracle.toplink.essentials.mappings.DatabaseMapping;
043:
044: /**
045: * INTERNAL
046: * <p><b>Purpose</b>: Represent a attribute.
047: *
048: * <p><b>Responsibilities</b>:<ul>
049: * </ul>
050: */
051: public class AttributeNode extends Node {
052:
053: /** The attribute name. */
054: private String name;
055:
056: /** Flag indicating outer join */
057: private boolean outerJoin;
058:
059: /** */
060: private boolean requiresCollectionAttribute;
061:
062: /** */
063: private DatabaseMapping mapping;
064:
065: /**
066: * Create a new AttributeNode
067: */
068: public AttributeNode() {
069: super ();
070: }
071:
072: /**
073: * Create a new AttributeNode with the passed name
074: * @param name the attribute name
075: */
076: public AttributeNode(String name) {
077: setAttributeName(name);
078: }
079:
080: /**
081: * INTERNAL
082: * If called this AttributeNode represents an unqualified field access.
083: * The method returns a DotNode representing a qualified field access with
084: * the base variable as left child node and the attribute as right child
085: * node.
086: */
087: public Node qualifyAttributeAccess(ParseTreeContext context) {
088: return (Node) context.getNodeFactory()
089: .newQualifiedAttribute(getLine(), getColumn(),
090: context.getBaseVariable(), name);
091: }
092:
093: /**
094: * INTERNAL
095: * Validate the current node and calculates its type.
096: */
097: public void validate(ParseTreeContext context) {
098: // The type is calculated in the parent DotNode.
099: }
100:
101: /** */
102: public Expression addToExpression(Expression parentExpression,
103: GenerationContext context) {
104: if (isCollectionAttribute()) {
105: //special case for NOT MEMBER OF
106: if (context.hasMemberOfNode()) {
107: return parentExpression
108: .noneOf(name, new ExpressionBuilder()
109: .equal(context.getMemberOfNode()
110: .getLeftExpression()));
111: }
112: return outerJoin ? parentExpression.anyOfAllowingNone(name)
113: : parentExpression.anyOf(name);
114: } else {
115: // check whether collection attribute is required
116: if (requiresCollectionAttribute()) {
117: throw EJBQLException.invalidCollectionMemberDecl(
118: context.getParseTreeContext().getQueryInfo(),
119: getLine(), getColumn(), name);
120: }
121:
122: if (context.shouldUseOuterJoins() || isOuterJoin()) {
123: return parentExpression.getAllowingNull(name);
124: } else {
125: return parentExpression.get(name);
126: }
127: }
128: }
129:
130: /**
131: * INTERNAL
132: * Is this node an AttributeNode
133: */
134: public boolean isAttributeNode() {
135: return true;
136: }
137:
138: /** */
139: public String getAttributeName() {
140: return name;
141: }
142:
143: /** */
144: public void setAttributeName(String name) {
145: this .name = name;
146: }
147:
148: /** */
149: public boolean isOuterJoin() {
150: return outerJoin;
151: }
152:
153: /** */
154: public void setOuterJoin(boolean outerJoin) {
155: this .outerJoin = outerJoin;
156: }
157:
158: /** */
159: public boolean requiresCollectionAttribute() {
160: return requiresCollectionAttribute;
161: }
162:
163: /** */
164: public void setRequiresCollectionAttribute(
165: boolean requiresCollectionAttribute) {
166: this .requiresCollectionAttribute = requiresCollectionAttribute;
167: }
168:
169: /** */
170: public DatabaseMapping getMapping() {
171: return mapping;
172: }
173:
174: /** */
175: public void setMapping(DatabaseMapping mapping) {
176: this .mapping = mapping;
177: }
178:
179: /** */
180: public boolean isCollectionAttribute() {
181: DatabaseMapping mapping = getMapping();
182: return (mapping != null) && mapping.isCollectionMapping();
183: }
184:
185: /**
186: * resolveMapping: Answer the mapping which corresponds to my variableName.
187: */
188: public DatabaseMapping resolveMapping(GenerationContext context,
189: Class ownerClass) {
190: ClassDescriptor descriptor = context.getSession()
191: .getDescriptor(ownerClass);
192: return (descriptor == null) ? null : descriptor
193: .getMappingForAttributeName(getAttributeName());
194: }
195:
196: /**
197: * resolveClass: Answer the class for the mapping associated with the my variableName in the ownerClass.
198: * Answer null if the node represents a mapping that doesn't exist
199: */
200: public Class resolveClass(GenerationContext context,
201: Class ownerClass) {
202: DatabaseMapping mapping;
203:
204: mapping = resolveMapping(context, ownerClass);
205:
206: // if we are working with a direct-to-field, or the mapping's null,
207: // return the owner class
208: // Returning the ownerClass when the mapping is null delegates error handling
209: // to the query rather than me
210: if ((mapping == null) || (mapping.isDirectToFieldMapping())) {
211: return ownerClass;
212: }
213:
214: ClassDescriptor descriptor = mapping.getReferenceDescriptor();
215: return (descriptor == null) ? null : descriptor.getJavaClass();
216: //return mapping.getReferenceDescriptor().getJavaClass();
217: }
218:
219: public String toString(int indent) {
220: StringBuffer buffer = new StringBuffer();
221: toStringIndent(indent, buffer);
222: buffer.append(toStringDisplayName() + "[" + getAttributeName()
223: + "]");
224: return buffer.toString();
225: }
226:
227: /**
228: * INTERNAL
229: * Get the string representation of this node.
230: */
231: public String getAsString() {
232: return getAttributeName();
233: }
234: }
|