001: /**********************************************************************
002: Copyright (c) 2002 Mike Martin (TJDO) 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:
016: Contributors:
017: 2003 Andy Jefferson - coding standards
018: 2005 Andy Jefferson - added contrib from Guillaume Bodet for escape of single-quote
019: ...
020: **********************************************************************/package org.jpox.store.expression;
021:
022: import java.math.BigInteger;
023:
024: import org.jpox.store.DatastoreAdapter;
025: import org.jpox.store.mapping.JavaTypeMapping;
026: import org.jpox.store.query.StatementText;
027: import org.jpox.util.StringUtils;
028:
029: /**
030: * Representation of a string literal.
031: *
032: * @version $Revision: 1.19 $
033: **/
034: public class StringLiteral extends StringExpression implements Literal {
035: private final String value;
036:
037: /** Raw value that this literal represents. */
038: Object rawValue;
039:
040: private StatementText stUsingParameter = new StatementText();
041:
042: /**
043: * Constructor that takes a char. TODO we should not accept chars in String literal
044: * @param qs The QueryExpression
045: * @param mapping The mapping to the java type
046: * @param value The value that is further converted to a String
047: */
048: public StringLiteral(QueryExpression qs, JavaTypeMapping mapping,
049: char value) {
050: this (qs, mapping, String.valueOf(value));
051: }
052:
053: /**
054: * Constructor
055: * @param qs The QueryExpression
056: * @param mapping The mapping to the java type. null mapping is accepted
057: * @param value The value
058: */
059: public StringLiteral(QueryExpression qs, JavaTypeMapping mapping,
060: String value) {
061: super (qs);
062:
063: this .mapping = mapping;
064: this .value = value;
065: // Escape any single-quotes
066: st.append('\'')
067: .append(StringUtils.replaceAll(value, "'", "''"))
068: .append('\'');
069:
070: if (mapping == null) {
071: DatastoreAdapter dba = qs.getStoreManager()
072: .getDatastoreAdapter();
073: stUsingParameter.appendParameter(dba.getMapping(
074: String.class, qs.getStoreManager(), qs
075: .getClassLoaderResolver()), value);
076: } else {
077: stUsingParameter.appendParameter(mapping, value);
078: }
079: }
080:
081: /**
082: * Convenience method to generate the statement without any quotes.
083: * This is called when we create a literal using a mapping, and dont want quotes
084: * because the string is an SQL keyword.
085: */
086: public void generateStatementWithoutQuotes() {
087: st.clearStatement();
088: st.append(StringUtils.replaceAll(value, "'", "''"));
089: }
090:
091: public Object getValue() {
092: return value;
093: }
094:
095: public BooleanExpression eq(ScalarExpression expr) {
096: assertValidTypeForParameterComparison(expr,
097: StringExpression.class);
098:
099: if (expr instanceof StringLiteral) {
100: return new BooleanLiteral(qs, mapping, value
101: .equals(((StringLiteral) expr).value));
102: } else {
103: return super .eq(expr);
104: }
105: }
106:
107: public BooleanExpression noteq(ScalarExpression expr) {
108: assertValidTypeForParameterComparison(expr,
109: StringExpression.class);
110:
111: if (expr instanceof StringLiteral) {
112: return new BooleanLiteral(qs, mapping, !value
113: .equals(((StringLiteral) expr).value));
114: } else {
115: return super .noteq(expr);
116: }
117: }
118:
119: public BooleanExpression lt(ScalarExpression expr) {
120: if (expr instanceof StringLiteral) {
121: return new BooleanLiteral(qs, mapping, value
122: .compareTo(((StringLiteral) expr).value) < 0);
123: } else {
124: return super .lt(expr);
125: }
126: }
127:
128: public BooleanExpression lteq(ScalarExpression expr) {
129: if (expr instanceof StringLiteral) {
130: return new BooleanLiteral(qs, mapping, value
131: .compareTo(((StringLiteral) expr).value) <= 0);
132: } else {
133: return super .lteq(expr);
134: }
135: }
136:
137: public BooleanExpression gt(ScalarExpression expr) {
138: if (expr instanceof StringLiteral) {
139: return new BooleanLiteral(qs, mapping, value
140: .compareTo(((StringLiteral) expr).value) > 0);
141: } else {
142: return super .gt(expr);
143: }
144: }
145:
146: public BooleanExpression gteq(ScalarExpression expr) {
147: if (expr instanceof StringLiteral) {
148: return new BooleanLiteral(qs, mapping, value
149: .compareTo(((StringLiteral) expr).value) >= 0);
150: } else {
151: return super .gteq(expr);
152: }
153: }
154:
155: public ScalarExpression add(ScalarExpression expr) {
156: if (expr instanceof StringLiteral) {
157: return new StringLiteral(qs, mapping, value
158: .concat(((StringLiteral) expr).value));
159: } else if (expr instanceof CharacterLiteral) {
160: return new StringLiteral(qs, mapping, value
161: .concat(((Literal) expr).getValue().toString()));
162: } else if (expr instanceof IntegerLiteral
163: || expr instanceof FloatingPointLiteral
164: || expr instanceof BooleanLiteral) {
165: return new StringLiteral(qs, mapping, value
166: .concat(((Literal) expr).getValue().toString()));
167: } else {
168: return super .add(expr);
169: }
170: }
171:
172: public BooleanExpression endsWithMethod(ScalarExpression str) {
173: if (str instanceof StringLiteral) {
174: return new BooleanLiteral(qs, mapping, value
175: .endsWith(((StringLiteral) str).value));
176: } else {
177: return super .endsWithMethod(str);
178: }
179: }
180:
181: public NumericExpression indexOfMethod(ScalarExpression str) {
182: if (str instanceof StringLiteral) {
183: return new IntegerLiteral(qs, mapping,
184: BigInteger.valueOf(value
185: .indexOf(((StringLiteral) str).value)));
186: } else {
187: return super .indexOfMethod(str);
188: }
189: }
190:
191: public NumericExpression lengthMethod() {
192: return new IntegerLiteral(qs, mapping, BigInteger.valueOf(value
193: .length()));
194: }
195:
196: public BooleanExpression startsWithMethod(ScalarExpression str) {
197: if (str instanceof StringLiteral) {
198: return new BooleanLiteral(qs, mapping, value
199: .startsWith(((StringLiteral) str).value));
200: } else {
201: return super .startsWithMethod(str);
202: }
203: }
204:
205: public BooleanExpression startsWithMethod(ScalarExpression str,
206: ScalarExpression toffset) {
207: if (str instanceof StringLiteral
208: && toffset instanceof IntegerLiteral) {
209: return new BooleanLiteral(qs, mapping, value.startsWith(
210: ((StringLiteral) str).value,
211: ((Number) ((IntegerLiteral) toffset).getValue())
212: .intValue()));
213: } else {
214: return super .startsWithMethod(str, toffset);
215: }
216: }
217:
218: /**
219: * Method to handle the substring operation.
220: * @param begin The start position
221: * @return The expression.
222: **/
223: public StringExpression substringMethod(NumericExpression begin) {
224: if (begin instanceof IntegerLiteral) {
225: return new StringLiteral(qs, mapping, value
226: .substring(((Number) ((IntegerLiteral) begin)
227: .getValue()).intValue()));
228: } else {
229: return super .substringMethod(begin);
230: }
231: }
232:
233: /**
234: * Method to handle the substring operation.
235: * @param begin The start position
236: * @param end The end position
237: * @return The expression.
238: **/
239: public StringExpression substringMethod(NumericExpression begin,
240: NumericExpression end) {
241: if (begin instanceof IntegerLiteral
242: && end instanceof IntegerLiteral) {
243: return new StringLiteral(qs, mapping, value.substring(
244: ((Number) ((IntegerLiteral) begin).getValue())
245: .intValue(),
246: ((Number) ((IntegerLiteral) end).getValue())
247: .intValue()));
248: } else {
249: return super .substringMethod(begin, end);
250: }
251: }
252:
253: /**
254: * Method to handle the lower case operation.
255: * @return The expression.
256: **/
257: public StringExpression toLowerCaseMethod() {
258: return new StringLiteral(qs, mapping, value.toLowerCase());
259: }
260:
261: /**
262: * Method to handle the upper case operation.
263: * @return The expression.
264: **/
265: public StringExpression toUpperCaseMethod() {
266: return new StringLiteral(qs, mapping, value.toUpperCase());
267: }
268:
269: /**
270: * Method to handle trimming of a string.
271: * @return The expression.
272: */
273: public StringExpression trimMethod() {
274: return new StringLiteral(qs, mapping, value.trim());
275: }
276:
277: public StatementText toStatementText(int mode) {
278: if (mode == ScalarExpression.FILTER) {
279: return stUsingParameter;
280: }
281: return super .toStatementText(mode);
282: }
283:
284: /**
285: * Method to save a "raw" value that this literal represents.
286: * This value differs from the literal value since that is of the same type as this literal.
287: * @param val The raw value
288: */
289: public void setRawValue(Object val) {
290: this .rawValue = val;
291: }
292:
293: /**
294: * Accessor for the "raw" value that this literal represents.
295: * This value differs from the literal value since that is of the same type as this literal.
296: * @return The raw value
297: */
298: public Object getRawValue() {
299: return rawValue;
300: }
301: }
|