001: /**********************************************************************
002: Copyright (c) 2004 Andy Jefferson 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: Contributors:
016: ...
017: **********************************************************************/package org.jpox.store.expression;
018:
019: import java.util.ArrayList;
020: import java.util.Collection;
021: import java.util.Iterator;
022: import java.util.List;
023: import java.util.Map;
024:
025: import org.jpox.store.DatastoreAdapter;
026: import org.jpox.store.mapping.JavaTypeMapping;
027:
028: /**
029: * An SQL expression that will test if a column of a table falls within the
030: * given Map's values. This is used for Querys where a transient Map is passed
031: * in as a parameter.
032: *
033: * @version $Revision: 1.11 $
034: */
035: public class MapValueLiteral extends ScalarExpression {
036: private final boolean isEmpty;
037: private final boolean containsNull;
038: private final DatastoreAdapter dba;
039: /** ScalarExpressions for all elements in the Map **/
040: private List scalarExpressions;
041:
042: /**
043: * Constructor.
044: * @param qs The QueryStatement the MapValueLiteral will be used in.
045: * @param mapping The mapping to the Map
046: * @param map The transient Map that is the value.
047: */
048: public MapValueLiteral(QueryExpression qs, JavaTypeMapping mapping,
049: Map map) {
050: super (qs);
051: this .mapping = mapping;
052: containsNull = (map != null) && map.containsValue(null);
053: dba = qs.getStoreManager().getDatastoreAdapter();
054:
055: // We'll consider the Map to be empty if it is null, is really
056: // empty, or only contains null.
057: // If it contains null we need a special case when creating the SQL.
058: isEmpty = (map == null) || (map.isEmpty())
059: || (map.size() == 1 && containsNull);
060:
061: // If the Map is empty, don't build the list of SQLExpressions.
062: if (!isEmpty) {
063: scalarExpressions = new ArrayList();
064: st.append("(");
065:
066: boolean hadPrev = false;
067:
068: Collection values = map.values();
069: for (Iterator it = values.iterator(); it.hasNext();) {
070: Object current = it.next();
071: if (null != current) {
072: JavaTypeMapping m = dba.getMapping(current
073: .getClass(), qs.getStoreManager(), qs
074: .getClassLoaderResolver());
075: ScalarExpression expr = m.newLiteral(qs, current);
076:
077: // Append the SQLExpression (should be a literal) for the
078: // current element.
079: st.append(hadPrev ? "," : "");
080: st.append(expr);
081: scalarExpressions.add(expr);
082:
083: hadPrev = true;
084: }
085: }
086:
087: st.append(")");
088: }
089: }
090:
091: /**
092: * Method to check the containing of a key in the Map.
093: * Return the BooleanExpression that results from
094: * MapValueLiteral.contains(SQLExpression).
095: * @param expr The SQLExpression that is checked for membership in the Map.
096: * @return The BooleanExpression that results from
097: * MapValueLiteral.contains(SQLExpression).
098: */
099: public BooleanExpression containsMethod(ScalarExpression expr) {
100: if (isEmpty) {
101: return new BooleanLiteral(qs, mapping, false);
102: }
103: BooleanExpression bExpr = null;
104: for (int i = 0; i < scalarExpressions.size(); i++) {
105: if (bExpr == null) {
106: bExpr = ((ScalarExpression) scalarExpressions.get(i))
107: .eq(expr);
108: } else {
109: bExpr = bExpr.ior(((ScalarExpression) scalarExpressions
110: .get(i)).eq(expr));
111: }
112: }
113: bExpr.encloseWithInParentheses();
114: return bExpr;
115: }
116:
117: /**
118: * Method to check for emptiness of the collection.
119: * @return The BooleanExpression.
120: **/
121: public BooleanExpression isEmptyMethod() {
122: return new BooleanLiteral(qs, mapping, isEmpty);
123: }
124: }
|