001: /**********************************************************************
002: Copyright (c) 2004 Barry Haddow and others. All rights reserved.
003: Licensed under the Apache License, Version 2.0 (the "License");
004: you may not use this file except in compliance with the License.
005: You may obtain a copy of the License at
006:
007: http://www.apache.org/licenses/LICENSE-2.0
008:
009: Unless required by applicable law or agreed to in writing, software
010: distributed under the License is distributed on an "AS IS" BASIS,
011: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: See the License for the specific language governing permissions and
013: limitations under the License.
014:
015:
016: Contributors:
017: 2004 Erik Bengtson - added cast and other operators
018: 2005 Andy Jefferson - added javadoc
019: 2006 Andy Jefferson - generalised as reference expression
020: 2007 Andy Jefferson - cater for RefExpr == null
021: ...
022: **********************************************************************/package org.jpox.store.expression;
023:
024: import org.jpox.exceptions.JPOXUserException;
025: import org.jpox.store.mapping.JavaTypeMapping;
026: import org.jpox.store.mapping.NullMapping;
027: import org.jpox.store.mapping.ReferenceMapping;
028:
029: /**
030: * Represents a reference field/object (interface/object) in a JDOQL query.
031: *
032: * @version $Revision: 1.9 $
033: */
034: public class ReferenceExpression extends ScalarExpression {
035: /**
036: * Constructor for a reference expression, using the mapping of the field, and the expression for the table.
037: * @param qs The Query Statement
038: * @param mapping The mapping for the field whose interface we are expressing
039: * @param te The expression for the table of the interface.
040: */
041: public ReferenceExpression(QueryExpression qs,
042: JavaTypeMapping mapping, LogicSetExpression te) {
043: super (qs, mapping, te);
044: }
045:
046: // TODO Likely to need another constructor for 1-1 bidir/1-N bidir in the same way as ObjectExpression.
047:
048: /**
049: * Method for casting a reference expression to some other type in the query.
050: * @param castType The type to cast it to.
051: * @return The expression for the casted reference
052: */
053: public ScalarExpression cast(Class castType) {
054: JavaTypeMapping[] javaTypeMappings = ((ReferenceMapping) mapping)
055: .getJavaTypeMapping();
056: for (int i = 0; i < javaTypeMappings.length; ++i) {
057: JavaTypeMapping m = javaTypeMappings[i];
058: if (castType.getName().equals(m.getType())) {
059: return m.newScalarExpression(qs, te);
060: }
061: }
062: return super .cast(castType);
063: }
064:
065: /**
066: * Method for use when handling the equality of reference expressions.
067: * @param expr The expression to compare against
068: * @return Expression whether the expressions are equal
069: */
070: public BooleanExpression eq(ScalarExpression expr) {
071: BooleanExpression bexpr = null;
072: JavaTypeMapping[] javaTypeMappings = ((ReferenceMapping) mapping)
073: .getJavaTypeMapping();
074: if (expr.mapping instanceof ReferenceMapping) {
075: // Expression of form "ReferenceExpression == ReferenceExpression"
076: // TODO Should really split into an expression for each part and line up the JavaTypeMappings
077: for (int i = 0; i < javaTypeMappings.length; ++i) {
078: JavaTypeMapping m = javaTypeMappings[i];
079:
080: if (bexpr == null) {
081: bexpr = m.newScalarExpression(qs, te).eq(expr);
082: bexpr.encloseWithInParentheses();
083: } else {
084: bexpr = bexpr.ior(m.newScalarExpression(qs, te).eq(
085: expr).encloseWithInParentheses());
086: bexpr.encloseWithInParentheses();
087: }
088: }
089: } else if (expr.mapping instanceof NullMapping) {
090: // Expression of form "ReferenceExpression == null"
091: for (int i = 0; i < javaTypeMappings.length; ++i) {
092: JavaTypeMapping m = javaTypeMappings[i];
093: if (bexpr == null) {
094: bexpr = m.newScalarExpression(qs, te).eq(expr);
095: } else {
096: bexpr = bexpr.and(m.newScalarExpression(qs, te).eq(
097: expr));
098: }
099: }
100: } else {
101: // Expression of form "ReferenceExpression == PC"
102: for (int i = 0; i < javaTypeMappings.length; ++i) {
103: JavaTypeMapping m = javaTypeMappings[i];
104: JavaTypeMapping exprMapping = expr.mapping;
105: if (m.getNumberOfDatastoreFields() == exprMapping
106: .getNumberOfDatastoreFields()) {
107: // TODO Should apply the above check on noteq() too but in reverse
108: // If expression implementation and this implementation have same number of PK fields allow the compare
109: // TODO Should really also compare the types of the mappings
110: if (bexpr == null) {
111: bexpr = m.newScalarExpression(qs, te).eq(expr);
112: bexpr.encloseWithInParentheses();
113: } else {
114: bexpr = bexpr.ior(m.newScalarExpression(qs, te)
115: .eq(expr).encloseWithInParentheses());
116: bexpr.encloseWithInParentheses();
117: }
118: }
119: }
120: }
121:
122: bexpr.encloseWithInParentheses();
123: return bexpr;
124: }
125:
126: /**
127: * Method for use when handling the inequality of reference expressions.
128: * @param expr The expression to compare against
129: * @return Expression whether the expressions are not equal
130: */
131: public BooleanExpression noteq(ScalarExpression expr) {
132: BooleanExpression bexpr = null;
133: JavaTypeMapping[] javaTypeMappings = ((ReferenceMapping) mapping)
134: .getJavaTypeMapping();
135: if (expr.mapping instanceof NullMapping) {
136: // Expression of form "ReferenceExpression != null"
137: // So find a mapping that is not null amongst the possible impls
138: for (int i = 0; i < javaTypeMappings.length; ++i) {
139: JavaTypeMapping m = javaTypeMappings[i];
140: if (bexpr == null) {
141: bexpr = m.newScalarExpression(qs, te).noteq(expr);
142: } else {
143: bexpr = bexpr.ior(m.newScalarExpression(qs, te)
144: .noteq(expr));
145: }
146: }
147: } else {
148: for (int i = 0; i < javaTypeMappings.length; ++i) {
149: JavaTypeMapping m = javaTypeMappings[i];
150: if (bexpr == null) {
151: bexpr = m.newScalarExpression(qs, te).noteq(expr);
152: } else {
153: bexpr = bexpr.and(m.newScalarExpression(qs, te)
154: .noteq(expr));
155: }
156: }
157: }
158: bexpr.encloseWithInParentheses();
159: return bexpr;
160: }
161:
162: /**
163: * Method invoked when accessing a field in the reference.
164: * This is currently not available - you must cast it to a concrete type (since the
165: * reference doesnt have any fields!).
166: * @param fieldName Name of the field to access
167: * @param innerJoin whether to join using an inner join
168: * @return Expression representing the field of this reference
169: */
170: public ScalarExpression accessField(String fieldName,
171: boolean innerJoin) {
172: throw new JPOXUserException(LOCALISER.msg("037000", fieldName,
173: mapping.getType()));
174: }
175: }
|