001: /**********************************************************************
002: Copyright (c) 2006 Erik Bengtson 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: ...
018: **********************************************************************/package org.jpox.store.expression;
019:
020: import org.jpox.ClassLoaderResolver;
021: import org.jpox.exceptions.JPOXUserException;
022: import org.jpox.store.DatastoreIdentifier;
023: import org.jpox.store.IdentifierFactory;
024: import org.jpox.store.mapping.JavaTypeMapping;
025: import org.jpox.store.scostore.ArrayStore;
026:
027: /**
028: * Representation of array expression. Either backed
029: * by ScalarExpressions, or by an array field
030: * @version $Revision: 1.6 $
031: */
032: public class ArrayExpression extends ScalarExpression {
033: /** Either <code>exprs</code> or
034: * <code>arrayStore</code> and <code>fieldName</code>
035: * are initialized
036: */
037:
038: /** ScalarExpression elements of the array **/
039: ScalarExpression[] exprs;
040:
041: /** The array Store **/
042: private ArrayStore arrayStore;
043:
044: /** The field name **/
045: private String fieldName;
046:
047: /**
048: * Constructor
049: * @param qs The query statement
050: */
051: protected ArrayExpression(QueryExpression qs) {
052: super (qs);
053: }
054:
055: /**
056: * Constructor
057: * @param qs The query statement
058: * @param expr the array of expressions
059: */
060: public ArrayExpression(QueryExpression qs, ScalarExpression[] expr) {
061: super (qs);
062: this .exprs = expr;
063: }
064:
065: /**
066: * Constructor.
067: * @param qs The Query Statement
068: * @param ownerMapping The mapping to the owner of this collection
069: * @param te The Table Expression
070: * @param arrayStore the backing store.
071: * @param fieldName Name of the field for the collection.
072: **/
073: public ArrayExpression(QueryExpression qs,
074: JavaTypeMapping ownerMapping, LogicSetExpression te,
075: ArrayStore arrayStore, String fieldName) {
076: super (qs);
077: this .mapping = ownerMapping;
078: this .arrayStore = arrayStore;
079: this .fieldName = fieldName;
080: this .te = te;
081: }
082:
083: /**
084: * Executed when the size() method is found in a query filter.
085: * @return The NumericExpression resulting from the size() method.
086: */
087: public NumericExpression sizeMethod() {
088: if (arrayStore != null) {
089: IdentifierFactory idFactory = qs.getStoreManager()
090: .getIdentifierFactory();
091: String ctIdentifier = idFactory.newIdentifier(
092: te.getAlias(), fieldName).getIdentifier();
093: DatastoreIdentifier ctRangeVar = idFactory.newIdentifier(
094: IdentifierFactory.TABLE, ctIdentifier);
095:
096: return new ContainerSizeExpression(qs, arrayStore
097: .getSizeSubquery(qs, mapping, te, ctRangeVar));
098: } else {
099: JavaTypeMapping mapping = qs.getStoreManager()
100: .getDatastoreAdapter().getMapping(Integer.class,
101: qs.getStoreManager(),
102: qs.getClassLoaderResolver());
103: return new IntegerLiteral(qs, mapping, new Integer(
104: exprs.length));
105: }
106: }
107:
108: /**
109: * Executed when the length() method is found in a query filter.
110: * @return The NumericExpression resulting from the size() method.
111: */
112: public NumericExpression lengthMethod() {
113: return sizeMethod();
114: }
115:
116: /**
117: * Access a field in an array
118: * @param subfieldName the field to be accessed in this object
119: * @param innerJoin whether to inner join
120: * @return The field expression representing the required field of this object
121: */
122: public ScalarExpression accessField(String subfieldName,
123: boolean innerJoin) {
124: if (!subfieldName.endsWith("length")) {
125: throw new JPOXUserException("The field " + subfieldName
126: + " is not accessible in an array");
127: }
128: return sizeMethod();
129: }
130:
131: /**
132: * Executed when the contains() method is found in a query filter.
133: * @param expr The ScalarExpression passed as a parameter to contains().
134: * @return The BooleanExpression resulting from the contains() method.
135: */
136: public BooleanExpression containsMethod(ScalarExpression expr) {
137: // ct... = "collection table"
138: // et... = "element table"
139:
140: IdentifierFactory idFactory = qs.getStoreManager()
141: .getIdentifierFactory();
142: if (expr instanceof NullLiteral) {
143: // JPOX doesn't currently support storing nulls in Collections so just return "1 = 0"
144: // TODO Add support for storing nulls in collections and querying for this situation
145: return new BooleanLiteral(qs, mapping, false)
146: .eq(new BooleanLiteral(qs, mapping, true));
147: } else if (exprs != null) {
148: BooleanExpression bExpr = null;
149: for (int i = 0; i < exprs.length; i++) {
150: if (bExpr == null) {
151: bExpr = exprs[i].eq(expr);
152: } else {
153: bExpr = bExpr.ior(exprs[i].eq(expr));
154: }
155: }
156: bExpr.encloseWithInParentheses();
157: return bExpr;
158: } else if (expr instanceof UnboundVariable) {
159: UnboundVariable var = (UnboundVariable) expr;
160: if (var.getVariableType() == null) {
161: //Set the variable type to be the element type for this collection
162: //implicit variable type. We now set the type to the collection type
163: var.setVariableType(qs.getClassLoaderResolver()
164: .classForName(arrayStore.getElementType()));
165: }
166: //ctJavaName += + '.' + var.getVariableName();
167: //String etJavaName = qs.getDefaultTableExpression().getRangeVariable().getJavaName() + '.' + var.getVariableName();
168:
169: String etIdentifier = "UNBOUND" + '.'
170: + var.getVariableName();
171: String ctIdentifier = idFactory.newIdentifier(
172: idFactory.newIdentifier(te.getAlias(), fieldName),
173: var.getVariableName()).getIdentifier();
174:
175: DatastoreIdentifier ctRangeVar = idFactory.newIdentifier(
176: IdentifierFactory.TABLE, ctIdentifier);
177: DatastoreIdentifier etRangeVar = idFactory.newIdentifier(
178: IdentifierFactory.TABLE, etIdentifier);
179: QueryExpression qexpr = arrayStore.getExistsSubquery(qs,
180: mapping, te, ctRangeVar);
181: var.bindTo(arrayStore.joinElementsTo(qexpr, qs, mapping,
182: te, ctRangeVar, var.getVariableType(), expr,
183: expr.te == null ? etRangeVar : expr.te.getAlias()));
184:
185: return new ExistsExpression(qs, qexpr, true);
186:
187: } else if (expr instanceof Literal) {
188: String ctIdentifier = idFactory.newIdentifier(
189: te.getAlias(), fieldName).getIdentifier();
190: DatastoreIdentifier ctRangeVar = qs.getStoreManager()
191: .getIdentifierFactory().newIdentifier(
192: IdentifierFactory.TABLE, ctIdentifier);
193: DatastoreIdentifier etRangeVar;
194: if (expr.te == null) // literals
195: {
196: int n = 0;
197:
198: do {
199: String etIdentifier = ctIdentifier + '.' + (++n);
200: etRangeVar = qs.getStoreManager()
201: .getIdentifierFactory().newIdentifier(
202: IdentifierFactory.TABLE,
203: etIdentifier);
204: } while (qs.getTableExpression(etRangeVar) != null);
205: } else {
206: etRangeVar = expr.te.getAlias();
207: }
208:
209: ClassLoaderResolver clr = qs.getClassLoaderResolver();
210: QueryExpression qexpr = arrayStore.getExistsSubquery(qs,
211: mapping, te, ctRangeVar);
212: ScalarExpression expr1 = arrayStore.joinElementsTo(qexpr,
213: qs, mapping, te, ctRangeVar, clr.classForName(expr
214: .getMapping().getType()), expr,
215: expr.te == null ? etRangeVar : expr.te.getAlias());
216: qexpr.andCondition(expr.eq(expr1));
217: return new ExistsExpression(qs, qexpr, true);
218: } else {
219: String ctIdentifier = idFactory.newIdentifier(
220: te.getAlias(), fieldName).getIdentifier();
221: DatastoreIdentifier ctRangeVar = qs.getStoreManager()
222: .getIdentifierFactory().newIdentifier(
223: IdentifierFactory.TABLE, ctIdentifier);
224: DatastoreIdentifier etRangeVar;
225: if (expr.te == null) // literals
226: {
227: int n = 0;
228:
229: do {
230: String etIdentifier = ctIdentifier + '.' + (++n);
231: etRangeVar = qs.getStoreManager()
232: .getIdentifierFactory().newIdentifier(
233: IdentifierFactory.TABLE,
234: etIdentifier);
235: } while (qs.getTableExpression(etRangeVar) != null);
236: } else {
237: etRangeVar = expr.te.getAlias();
238: }
239:
240: ClassLoaderResolver clr = qs.getClassLoaderResolver();
241: ScalarExpression joinExpr = arrayStore.joinElementsTo(expr
242: .getQueryExpression(), qs, mapping, te, ctRangeVar,
243: clr.classForName(arrayStore.getElementType()),
244: expr, etRangeVar);
245:
246: return joinExpr.eq(expr);
247: }
248: }
249: }
|