KickJava   Java API By Example, From Geeks To Geeks.

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


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.util.regex.Pattern JavaDoc;
25 import java.util.regex.Matcher JavaDoc;
26 import java.sql.PreparedStatement JavaDoc;
27 import java.sql.SQLException JavaDoc;
28
29 public class Like extends AbstractPredicateExpr {
30     private final ValueExpr valueExpr;
31     private final Literal literal;
32     private final boolean not;
33     private Pattern JavaDoc likePattern;
34
35     public Like(boolean not, ValueExpr valueExpr, Literal literal) {
36         this.valueExpr = valueExpr;
37         this.literal = literal;
38         this.not = not;
39     }
40
41     public void prepare(QueryContext context) throws QueryException {
42         valueExpr.prepare(context);
43         if (valueExpr.isSymbolicIdentifier())
44             throw new QueryException("A symbolic identifier cannot be used with LIKE");
45
46         if (valueExpr.getValueType() != QValueType.STRING && valueExpr.getValueType() != QValueType.UNDEFINED) {
47             throw new QueryException("LIKE can only be used for strings.");
48         }
49     }
50
51     public boolean evaluate(Document document, Version version, EvaluationContext evaluationContext) throws QueryException {
52         Object JavaDoc value = valueExpr.evaluate(QValueType.STRING, document, version, evaluationContext);
53         if (value instanceof Object JavaDoc[]) {
54             // multivalue fields: true if one of the values yields true
55
Object JavaDoc[] values = (Object JavaDoc[])value;
56             for (int i = 0; i < values.length; i++) {
57                 if (evaluate(values[i]))
58                     return true;
59             }
60             return false;
61         } else {
62             return evaluate(value);
63         }
64     }
65
66     private boolean evaluate(Object JavaDoc value) throws QueryException {
67         compileLikePattern();
68         Matcher JavaDoc matcher = likePattern.matcher((String JavaDoc)value);
69         boolean matches = matcher.matches();
70         return not? !matches :matches;
71     }
72
73     public Tristate appliesTo(Document document) throws QueryException {
74         if (valueExpr.canTestAppliesTo()) {
75             boolean result = evaluate(valueExpr.evaluate(QValueType.STRING, document, null, new EvaluationContext()));
76             return result ? Tristate.YES : Tristate.NO;
77         } else {
78             return Tristate.MAYBE;
79         }
80     }
81
82     /**
83      * Converts the SQL LIKE pattern to a regexp, to avoid having to write
84      * our own algorithm.
85      */

86     private void compileLikePattern() throws QueryException {
87         if (likePattern != null)
88             return;
89
90         String JavaDoc likeExpr = (String JavaDoc)literal.evaluate(QValueType.STRING);
91         StringBuffer JavaDoc pattern = new StringBuffer JavaDoc((likeExpr.length() * 4) + 10);
92
93         boolean inEscape = false;
94         for (int i = 0; i < likeExpr.length(); i++) {
95             char c = likeExpr.charAt(i);
96             switch (c) {
97                 case '%':
98                     if (inEscape) {
99                         inEscape = false;
100                         pattern.append('%');
101                     } else {
102                         pattern.append(".*");
103                     }
104                     break;
105                 case '_':
106                     if (inEscape) {
107                         inEscape = false;
108                         pattern.append('_');
109                     } else {
110                         pattern.append('.');
111                     }
112                     break;
113                 case '\\':
114                     // NOTE: currently no way to \ itself in there
115
inEscape = true;
116                     break;
117                 default:
118                     char ch1 = Character.forDigit((c >> 4) & 0xF, 16);
119                     char ch2 = Character.forDigit(c & 0xF, 16);
120                     pattern.append('\\').append('u').append('0').append('0').append(ch1).append(ch2);
121                     break;
122             }
123         }
124         likePattern = Pattern.compile(pattern.toString());
125     }
126
127     public AclConditionViolation isAclAllowed() {
128         return valueExpr.isAclAllowed();
129     }
130
131     public void generateSql(StringBuffer JavaDoc sql, SqlGenerationContext context) throws QueryException {
132         sql.append(" (");
133         String JavaDoc preCond = valueExpr.getSqlPreConditions(context);
134         if (preCond != null)
135             sql.append(preCond).append(" AND ");
136         valueExpr.generateSqlValueExpr(sql, context);
137         if (not)
138             sql.append(" NOT LIKE ");
139         else
140             sql.append(" LIKE ");
141         sql.append(" ?) ");
142     }
143
144     public int bindSql(PreparedStatement JavaDoc stmt, int bindPos, EvaluationContext evaluationContext) throws SQLException JavaDoc, QueryException {
145         bindPos = valueExpr.bindPreConditions(stmt, bindPos);
146         bindPos = valueExpr.bindValueExpr(stmt, bindPos, QValueType.STRING, evaluationContext);
147         bindPos = literal.bindValueExpr(stmt, bindPos, QValueType.STRING, evaluationContext);
148         return bindPos;
149     }
150 }
151
Popular Tags