KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > outerj > daisy > query > model > UnaryPredicateExpr


1 /*
2  * Copyright 2004 Outerthought bvba and Schaubroeck nv
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.outerj.daisy.query.model;
17
18 import org.outerj.daisy.query.QueryContext;
19 import org.outerj.daisy.repository.query.QueryException;
20 import org.outerj.daisy.repository.query.EvaluationContext;
21 import org.outerj.daisy.repository.Document;
22 import org.outerj.daisy.repository.Version;
23
24 import java.sql.PreparedStatement JavaDoc;
25 import java.sql.SQLException JavaDoc;
26
27 public abstract class UnaryPredicateExpr extends AbstractPredicateExpr {
28     protected final ValueExpr valueExpr1;
29     protected final ValueExpr valueExpr2;
30
31     public UnaryPredicateExpr(ValueExpr valueExpr1, ValueExpr valueExpr2) {
32         this.valueExpr1 = valueExpr1;
33         this.valueExpr2 = valueExpr2;
34     }
35
36     public void prepare(QueryContext context) throws QueryException {
37         valueExpr1.prepare(context);
38         valueExpr2.prepare(context);
39
40         if (valueExpr1.isSymbolicIdentifier() && valueExpr2.isSymbolicIdentifier())
41             throw new QueryException("Two symbolic identifiers cannot be compared with each other: \"" + valueExpr1.getExpression() + "\" and \"" + valueExpr2.getExpression() + "\".");
42
43         if ( (valueExpr1.isSymbolicIdentifier() && (valueExpr2.getValueType() == null || valueExpr2.getValueType() == QValueType.STRING))
44                 || (valueExpr2.isSymbolicIdentifier() && (valueExpr1.getValueType() == null || valueExpr1.getValueType() == QValueType.STRING))) {
45             // then it is OK
46
} else if (!valueExpr1.getValueType().isCompatible(valueExpr2.getValueType())) {
47             throw new QueryException("Cannot use a comparison operator on two different types of data: expression \"" + valueExpr1.getExpression() + "\" is of type " + valueExpr1.getValueType() + " and expression \"" + valueExpr2.getExpression() + "\" is of type " + valueExpr2.getValueType());
48         }
49
50         if ( (valueExpr1.getValueType() == QValueType.BOOLEAN || valueExpr2.getValueType() == QValueType.BOOLEAN
51               || valueExpr1.isSymbolicIdentifier() || valueExpr2.isSymbolicIdentifier()
52               || valueExpr1.isMultiValue() || valueExpr2.isMultiValue())
53              && !makesSenseForNonOrderedValues()) {
54             throw new QueryException("The operator \"" + getOperatorSqlSymbol() + "\" is used between expressions that have no order-relation: \"" + valueExpr1.getExpression() + "\" and \"" + valueExpr2.getExpression() + "\".");
55         }
56     }
57
58     protected boolean makesSenseForNonOrderedValues() {
59         return false;
60     }
61
62     public void generateSql(StringBuffer JavaDoc sql, SqlGenerationContext context) throws QueryException {
63         sql.append(" (");
64
65         String JavaDoc valueExpr1PreCond = valueExpr1.getSqlPreConditions(context);
66         String JavaDoc valueExpr2PreCond = valueExpr2.getSqlPreConditions(context);
67
68         if (valueExpr1PreCond != null)
69             sql.append(' ').append(valueExpr1PreCond);
70         if (valueExpr2PreCond != null) {
71             if (valueExpr1PreCond != null)
72                 sql.append(" and ");
73             sql.append(' ').append(valueExpr2PreCond);
74         }
75
76         if (valueExpr1PreCond != null || valueExpr2PreCond != null)
77             sql.append(" and ");
78
79         valueExpr1.generateSqlValueExpr(sql, context);
80         sql.append(getOperatorSqlSymbol());
81         valueExpr2.generateSqlValueExpr(sql, context);
82
83         sql.append(")");
84     }
85
86     protected abstract String JavaDoc getOperatorSqlSymbol();
87
88     public int bindSql(PreparedStatement JavaDoc stmt, int bindPos, EvaluationContext evaluationContext) throws SQLException JavaDoc, QueryException {
89         bindPos = valueExpr1.bindPreConditions(stmt, bindPos);
90         bindPos = valueExpr2.bindPreConditions(stmt, bindPos);
91
92         QValueType valueType = determineValueType();
93
94         if (valueExpr1.isSymbolicIdentifier() && valueExpr2.isSymbolicIdentifier()) {
95             // this should never occur as it is check in the prepare()
96
throw new QueryException("Assertion error: cannot compare two symbolic identifiers: \"" + valueExpr1.getExpression() + "\" and \"" + valueExpr2.getExpression() + "\".");
97         } else if (valueExpr1.isSymbolicIdentifier()) {
98             bindPos = valueExpr1.bindValueExpr(stmt, bindPos, valueType, evaluationContext);
99             bindPos = Literal.bindLiteral(stmt, bindPos, valueType, valueExpr1.translateSymbolic(valueExpr2, evaluationContext));
100         } else if (valueExpr2.isSymbolicIdentifier()) {
101             bindPos = Literal.bindLiteral(stmt, bindPos, valueType, valueExpr2.translateSymbolic(valueExpr1, evaluationContext));
102             bindPos = valueExpr2.bindValueExpr(stmt, bindPos, valueType, evaluationContext);
103         } else if (valueExpr1.isSymbolicIdentifier() && valueExpr2.isSymbolicIdentifier()) {
104             // (only makes sense when comparing the same thing)
105
bindPos = Literal.bindLiteral(stmt, bindPos, valueType, valueExpr2.translateSymbolic(valueExpr1, evaluationContext));
106             bindPos = Literal.bindLiteral(stmt, bindPos, valueType, valueExpr1.translateSymbolic(valueExpr2, evaluationContext));
107         } else {
108             bindPos = valueExpr1.bindValueExpr(stmt, bindPos, valueType, evaluationContext);
109             bindPos = valueExpr2.bindValueExpr(stmt, bindPos, valueType, evaluationContext);
110         }
111
112         return bindPos;
113     }
114
115     private QValueType determineValueType() throws QueryException {
116         QValueType valueType;
117         if (valueExpr1.getValueType() == QValueType.UNDEFINED && valueExpr2.getValueType() == QValueType.UNDEFINED) {
118             // this is normally only the cases when comparing literals, which is little meaningful
119
// We could throw an exception, or let it just be handled as strings.
120
valueType = QValueType.STRING;
121         } else if (valueExpr1.getValueType() == QValueType.UNDEFINED || valueExpr2.isSymbolicIdentifier()) {
122             valueType = valueExpr2.getValueType();
123         } else if (valueExpr2.getValueType() == QValueType.UNDEFINED || valueExpr1.isSymbolicIdentifier()) {
124             valueType = valueExpr1.getValueType();
125         } else {
126             // value types should be the same here, since checked in prepare()
127
if (valueExpr1.getValueType() != valueExpr2.getValueType())
128                 throw new QueryException("Assertion error: value types not the same.");
129             valueType = valueExpr1.getValueType();
130         }
131         return valueType;
132     }
133
134     public AclConditionViolation isAclAllowed() {
135         AclConditionViolation violation = valueExpr1.isAclAllowed();
136         if (violation != null)
137             return violation;
138         else
139             return valueExpr2.isAclAllowed();
140     }
141
142     private boolean evaluateInt(Object JavaDoc value1, Object JavaDoc value2) {
143         if (value1 instanceof Object JavaDoc[] || value2 instanceof Object JavaDoc[]) {
144             // behaviour for multivalue fields is: if there's one value that satisfies the condition, the result is true
145
Object JavaDoc[] values1 = assureArray(value1);
146             Object JavaDoc[] values2 = assureArray(value2);
147             for (int i = 0; i < values1.length; i++) {
148                 for (int j = 0; j < values2.length; j++) {
149                     if (evaluate(values1[i], values2[j]))
150                         return true;
151                 }
152             }
153             return false;
154         } else {
155             return evaluate(value1, value2);
156         }
157     }
158
159     private Object JavaDoc[] assureArray(Object JavaDoc value) {
160         if (value instanceof Object JavaDoc[]) {
161             return (Object JavaDoc[])value;
162         } else {
163             return new Object JavaDoc[] { value };
164         }
165     }
166
167     protected abstract boolean evaluate(Object JavaDoc value1, Object JavaDoc value2);
168
169     public boolean evaluate(Document document, Version version, EvaluationContext evaluationContext) throws QueryException {
170         QValueType valueType = determineValueType();
171         Object JavaDoc value1, value2;
172         if (valueExpr1.isSymbolicIdentifier() && valueExpr2.isSymbolicIdentifier()) {
173             // this should never occur as it is check in the prepare()
174
throw new QueryException("Assertion error: cannot compare two symbolic identifiers: \"" + valueExpr1.getExpression() + "\" and \"" + valueExpr2.getExpression() + "\".");
175         } else if (valueExpr1.isSymbolicIdentifier()) {
176             value1 = valueExpr1.evaluate(valueType, document, version, evaluationContext);
177             value2 = valueExpr1.translateSymbolic(valueExpr2, evaluationContext);
178         } else if (valueExpr2.isSymbolicIdentifier()) {
179             value1 = valueExpr2.translateSymbolic(valueExpr1, evaluationContext);
180             value2 = valueExpr2.evaluate(valueType, document, version, evaluationContext);
181         } else {
182             value1 = valueExpr1.evaluate(valueType, document, version, evaluationContext);
183             value2 = valueExpr2.evaluate(valueType, document, version, evaluationContext);
184         }
185
186         if (value1 == null || value2 == null)
187             return false;
188
189         return evaluateInt(value1, value2);
190     }
191
192     public Tristate appliesTo(Document document) throws QueryException {
193         if (valueExpr1.canTestAppliesTo() && valueExpr2.canTestAppliesTo()) {
194             return evaluate(document, null, new EvaluationContext()) ? Tristate.YES : Tristate.NO;
195         } else {
196             return Tristate.MAYBE;
197         }
198     }
199 }
200
Popular Tags