001: /*
002: * Copyright 2004 Outerthought bvba and Schaubroeck nv
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.outerj.daisy.query.model;
017:
018: import org.outerj.daisy.repository.query.QueryException;
019: import org.outerj.daisy.query.EvaluationInfo;
020:
021: import java.sql.PreparedStatement;
022: import java.sql.SQLException;
023:
024: // Note: this class is used as a delegate inside MultiArgPredicate
025: // It implements both "has all" and "has exactly"
026: public class HasAll extends AbstractMultiArgPredicate {
027: private boolean exactCount;
028: private ValueExpr valueCountExpr;
029: private ValueExpr[] exprPerArgument;
030:
031: /**
032: * Used in case of SQL generation to keep list of argument values between generate and bind phases.
033: */
034: protected Object[] argumentValues;
035:
036: public HasAll(
037: MultiArgPredicate.MultiArgPredicateContext multiArgContext,
038: boolean exactCount) {
039: super (multiArgContext);
040: this .exactCount = exactCount;
041: }
042:
043: public boolean evaluate(ExprDocData data,
044: EvaluationInfo evaluationInfo) throws QueryException {
045: Object[] values = (Object[]) valueExpr.evaluate(valueType,
046: data, evaluationInfo);
047: if (values == null)
048: return false;
049:
050: Object[] argumentValues = getExpandedArgumentList(data,
051: evaluationInfo);
052:
053: if (exactCount) {
054: return EvaluationUtil.hasExactly(values, argumentValues);
055: } else {
056: return EvaluationUtil.hasAll(values, argumentValues);
057: }
058: }
059:
060: public void generateSql(StringBuilder sql,
061: SqlGenerationContext context) throws QueryException {
062: argumentValues = getExpandedArgumentList(null, context
063: .getEvaluationInfo());
064: exprPerArgument = new ValueExpr[argumentValues.length];
065: sql.append(" (");
066: for (int i = 0; i < argumentValues.length; i++) {
067: if (i > 0)
068: sql.append(" and ");
069:
070: exprPerArgument[i] = valueExpr.clone();
071: String preCond = exprPerArgument[i]
072: .getSqlPreConditions(context);
073: if (preCond != null)
074: sql.append(preCond).append(" and ");
075: exprPerArgument[i].generateSqlValueExpr(sql, context);
076: sql.append(" = ?");
077: }
078: sql.append(" ) ");
079:
080: if (exactCount) {
081: retrieveValueCountIdentifier();
082: sql.append(" and ");
083: String preCond = valueCountExpr
084: .getSqlPreConditions(context);
085: if (preCond != null)
086: sql.append(preCond).append(" and ");
087: valueCountExpr.generateSqlValueExpr(sql, context);
088: sql.append(" = ").append(argumentValues.length).append(" ");
089: }
090: }
091:
092: private void retrieveValueCountIdentifier() {
093: // MultiArgPredicate verifies that this operator can only be used on valueExpr with
094: // an underlying identifier, which also has a valueCountIdentifier
095: Identifier identifier = ValueExprUtil.getIdentifier(valueExpr);
096: valueCountExpr = identifier.getValueCountIdentifier();
097: // If valueExpr is a dereferenced thing, than the valueCount identifier should go through the same deref chain
098: if (valueExpr instanceof Dereference) {
099: Dereference deref = (Dereference) valueExpr;
100: deref.clone();
101: deref.changeDerefValueExpr(valueCountExpr);
102: valueCountExpr = deref;
103: }
104: }
105:
106: public int bindSql(PreparedStatement stmt, int bindPos,
107: EvaluationInfo evaluationInfo) throws SQLException,
108: QueryException {
109: for (int i = 0; i < argumentValues.length; i++) {
110: bindPos = exprPerArgument[i].bindPreConditions(stmt,
111: bindPos, evaluationInfo);
112: bindPos = exprPerArgument[i].bindValueExpr(stmt, bindPos,
113: valueType, evaluationInfo);
114: bindPos = Literal
115: .bindLiteral(stmt, bindPos, valueType,
116: argumentValues[i], evaluationInfo
117: .getQueryContext());
118: }
119:
120: if (valueCountExpr != null) {
121: bindPos = valueCountExpr.bindPreConditions(stmt, bindPos,
122: evaluationInfo);
123: bindPos = valueCountExpr.bindValueExpr(stmt, bindPos, null,
124: evaluationInfo);
125: }
126:
127: return bindPos;
128: }
129:
130: public AclConditionViolation isAclAllowed() {
131: return null;
132: }
133:
134: public Tristate appliesTo(ExprDocData data,
135: EvaluationInfo evaluationInfo) {
136: return Tristate.MAYBE;
137: }
138: }
|