001: package org.apache.ojb.broker.query;
002:
003: /* Copyright 2002-2005 The Apache Software Foundation
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /**
019: * Model a Like Criteria</br>
020: * Escape Processing by Paul R. Nase
021: * <p>
022: * The pattern string is a simple pattern string using % or * as a wildcard.
023: * So Ander* would match Anderson and Anderton. The _ or ? character is used to match a single occurence
024: * of a character. The '\' is used to escape the wildcard characters so that we can search for
025: * strings containing * and ?.
026: * <p>
027: * To change the escape character use setEscapeCharacter.
028: * @see LikeCriteria#setEscapeCharacter(char)
029: *
030: * @author <a href="mailto:jbraeuchi@gmx.ch">Jakob Braeuchi </a>
031: * @author <a href="mailto:Nase.Paul@mayo.edu">Paul Nase </a>
032: * @version $Id: LikeCriteria.java,v 1.11.2.2 2005/12/21 22:27:09 tomdz Exp $
033: */
034: public class LikeCriteria extends ValueCriteria {
035: /**
036: * The Dfault-Character used for Escaping Wildcards
037: */
038: public static final char DEFAULT_ESCPAPE_CHARACTER = '\\';
039:
040: /**
041: * The Character used for Escaping Wildcards
042: */
043: private static char escapeCharacter = DEFAULT_ESCPAPE_CHARACTER;
044:
045: /**
046: * @param anAttribute
047: * @param aValue
048: * @param aClause
049: * @param anAlias
050: */
051: public LikeCriteria(Object anAttribute, Object aValue,
052: String aClause, String anAlias) {
053: super (anAttribute, generateSQLSearchPattern(aValue), aClause,
054: anAlias);
055: }
056:
057: /**
058: * @param anAttribute
059: * @param aValue
060: * @param aClause
061: * @param anAlias
062: */
063: public LikeCriteria(Object anAttribute, Object aValue,
064: String aClause, UserAlias anAlias) {
065: super (anAttribute, generateSQLSearchPattern(aValue), aClause,
066: anAlias);
067: }
068:
069: /**
070: * @see org.apache.ojb.broker.query.SelectionCriteria#bind(java.lang.Object)
071: */
072: public void bind(Object newValue) {
073: super .bind(generateSQLSearchPattern(newValue));
074: }
075:
076: /**
077: * Generate a SQL search string from the pattern string passed.
078: * The pattern string is a simple pattern string using % or * as a wildcard.
079: * So Ander* would match Anderson and Anderton. The _ or ? character is used to match a single occurence
080: * of a character. The escapeCharacter is used to escape the wildcard characters so that we can search for
081: * strings containing * and ?. This method converts the criteria wildcard strings to SQL wildcards.
082: *
083: * @param pattern a criteria search pattern containing optional wildcards
084: * @return a SQL search pattern string with all escape codes processed.
085: */
086: private static String generateSQLSearchPattern(Object pattern) {
087: if (pattern == null) {
088: return null;
089: } else {
090: StringBuffer sqlpattern = new StringBuffer();
091: char[] chars = pattern.toString().toCharArray();
092:
093: for (int i = 0; i < chars.length; i++) {
094: if (chars[i] == escapeCharacter) {
095: // for the escape character add the next char as is.
096: // find the next non-escape character.
097: int x = i + 1;
098: for (; (x < chars.length); x++) {
099: if (chars[x] != escapeCharacter) {
100: break;
101: }
102: }
103: boolean oddEscapes = (((x - i) % 2) > 0) ? true
104: : false;
105: if (oddEscapes) {
106: // only escape characters allowed are '%', '_', and '\'
107: // if the escaped character is a '\', then oddEscapes
108: // will be false.
109: // if the character following this last escape is not a
110: // '%' or an '_', eat this escape character.
111: if ((x < chars.length)
112: && ((chars[x] == '%') || (chars[x] == '_'))) {
113: // leave the escape character in, along with the following char
114: x++;
115: } else {
116: // remove the escape character, will cause problems in sql statement.
117: i++; // removing the first escape character.
118: if ((x < chars.length)
119: && ((chars[x] == '*') || (chars[x] == '?'))) {
120: // but if it is a '*' or a '?', we want to keep these
121: // characters as is, they were 'escaped' out.
122: x++; // include the first non-escape character.
123: }
124: }
125: }
126: if (i < chars.length) {
127: sqlpattern.append(chars, i, x - i);
128: }
129: i = x - 1; // set index to last character copied.
130: } else if (chars[i] == '*') {
131: sqlpattern.append("%");
132: } else if (chars[i] == '?') {
133: sqlpattern.append("_");
134: } else {
135: sqlpattern.append(chars[i]);
136: }
137: }
138: return sqlpattern.toString();
139: }
140: }
141:
142: /**
143: * @return Returns the escapeCharacter.
144: */
145: public static char getEscapeCharacter() {
146: return escapeCharacter;
147: }
148:
149: /**
150: * Global change of the escapeCharacter
151: * @param escChar The escapeCharacter to set.
152: */
153: public static void setEscapeCharacter(char escChar) {
154: escapeCharacter = escChar;
155: }
156:
157: }
|