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: 2003 Andy Jefferson - addition of equalsMethod()
019: ...
020: **********************************************************************/package org.jpox.store.expression;
021:
022: import java.math.BigDecimal;
023: import java.math.BigInteger;
024: import java.util.ArrayList;
025: import java.util.List;
026:
027: import org.jpox.store.mapping.JavaTypeMapping;
028:
029: /**
030: * Representation of an expression with a string.
031: *
032: * @version $Revision: 1.24 $
033: **/
034: public class StringExpression extends ScalarExpression {
035: protected StringExpression(QueryExpression qs) {
036: super (qs);
037: }
038:
039: /**
040: *
041: * @param qs the QueryExpression
042: * @param mapping the mapping associated to this expression
043: * @param te the TableExpression where this expression refers to
044: */
045: public StringExpression(QueryExpression qs,
046: JavaTypeMapping mapping, LogicSetExpression te) {
047: super (qs, mapping, te);
048: }
049:
050: /**
051: * Generates statement as e.g. FUNCTION_NAME(arg[,argN])
052: * @param functionName
053: * @param args ScalarExpression list
054: */
055: public StringExpression(String functionName, List args) {
056: super (functionName, args);
057: }
058:
059: /**
060: * Generates statement as e.g. FUNCTION_NAME(arg AS type[,argN as typeN])
061: * @param functionName Name of function
062: * @param args ScalarExpression list
063: * @param types String or ScalarExpression list
064: */
065: public StringExpression(String functionName, List args, List types) {
066: super (functionName, args, types);
067: }
068:
069: /**
070: * Performs a function on two arguments.
071: * op(operand1,operand2)
072: * operand1 op operand2
073: * @param operand1 the first expression
074: * @param op the operator between operands
075: * @param operand2 the second expression
076: */
077: public StringExpression(ScalarExpression operand1,
078: DyadicOperator op, ScalarExpression operand2) {
079: super (operand1, op, operand2);
080: }
081:
082: public BooleanExpression eq(ScalarExpression expr) {
083: // Allow for parameter comparison
084: assertValidTypeForParameterComparison(expr,
085: StringExpression.class);
086: expr = getConsistentTypeForParameterComparison(expr);
087:
088: if (expr instanceof NullLiteral) {
089: return expr.eq(this );
090: } else if (expr instanceof CharacterLiteral) {
091: return new BooleanExpression(this , OP_EQ, expr);
092: } else if (expr instanceof StringExpression) {
093: return new BooleanExpression(this , OP_EQ, expr);
094: } else if (expr instanceof ByteLiteral) {
095: int value = ((BigInteger) ((ByteLiteral) expr).getValue())
096: .intValue();
097: CharacterLiteral literal = new CharacterLiteral(qs,
098: mapping, String.valueOf((char) value));
099: return new BooleanExpression(this , OP_EQ, literal);
100: } else if (expr instanceof IntegerLiteral) {
101: int value = ((Number) ((IntegerLiteral) expr).getValue())
102: .intValue();
103: CharacterLiteral literal = new CharacterLiteral(qs,
104: mapping, String.valueOf((char) value));
105: return new BooleanExpression(this , OP_EQ, literal);
106: } else if (expr instanceof FloatingPointLiteral) {
107: int value = ((BigDecimal) ((FloatingPointLiteral) expr)
108: .getValue()).intValue();
109: CharacterLiteral literal = new CharacterLiteral(qs,
110: mapping, String.valueOf((char) value));
111: return new BooleanExpression(this , OP_EQ, literal);
112: } else if (expr instanceof NumericExpression) {
113: return new BooleanExpression(this , OP_EQ, expr);
114: } else if (expr instanceof SqlTemporalExpression) {
115: return new BooleanExpression(this , OP_EQ, expr);
116: } else {
117: return super .eq(expr);
118: }
119: }
120:
121: public BooleanExpression noteq(ScalarExpression expr) {
122: // Allow for parameter comparison
123: assertValidTypeForParameterComparison(expr,
124: StringExpression.class);
125: expr = getConsistentTypeForParameterComparison(expr);
126:
127: if (expr instanceof NullLiteral) {
128: return expr.noteq(this );
129: } else if (expr instanceof CharacterLiteral) {
130: return new BooleanExpression(this , OP_NOTEQ, expr);
131: } else if (expr instanceof StringExpression) {
132: return new BooleanExpression(this , OP_NOTEQ, expr);
133: } else if (expr instanceof ByteLiteral) {
134: int value = ((BigInteger) ((ByteLiteral) expr).getValue())
135: .intValue();
136: CharacterLiteral literal = new CharacterLiteral(qs,
137: mapping, String.valueOf((char) value));
138: return new BooleanExpression(this , OP_NOTEQ, literal);
139: } else if (expr instanceof IntegerLiteral) {
140: int value = ((Number) ((IntegerLiteral) expr).getValue())
141: .intValue();
142: CharacterLiteral literal = new CharacterLiteral(qs,
143: mapping, String.valueOf((char) value));
144: return new BooleanExpression(this , OP_NOTEQ, literal);
145: } else if (expr instanceof FloatingPointLiteral) {
146: int value = ((BigDecimal) ((FloatingPointLiteral) expr)
147: .getValue()).intValue();
148: CharacterLiteral literal = new CharacterLiteral(qs,
149: mapping, String.valueOf((char) value));
150: return new BooleanExpression(this , OP_NOTEQ, literal);
151: } else if (expr instanceof NumericExpression) {
152: return new BooleanExpression(this , OP_NOTEQ, expr);
153: } else if (expr instanceof SqlTemporalExpression) {
154: return new BooleanExpression(this , OP_NOTEQ, expr);
155: } else {
156: return super .noteq(expr);
157: }
158: }
159:
160: public BooleanExpression lt(ScalarExpression expr) {
161: if (expr instanceof NullLiteral) {
162: return expr.lt(this );
163: } else if (expr instanceof CharacterLiteral) {
164: return new BooleanExpression(this , OP_LT, expr);
165: } else if (expr instanceof StringExpression) {
166: return new BooleanExpression(this , OP_LT, expr);
167: } else if (expr instanceof ByteLiteral) {
168: int value = ((BigInteger) ((ByteLiteral) expr).getValue())
169: .intValue();
170: CharacterLiteral literal = new CharacterLiteral(qs,
171: mapping, String.valueOf((char) value));
172: return new BooleanExpression(this , OP_LT, literal);
173: } else if (expr instanceof IntegerLiteral) {
174: int value = ((Number) ((IntegerLiteral) expr).getValue())
175: .intValue();
176: CharacterLiteral literal = new CharacterLiteral(qs,
177: mapping, String.valueOf((char) value));
178: return new BooleanExpression(this , OP_LT, literal);
179: } else if (expr instanceof FloatingPointLiteral) {
180: int value = ((BigDecimal) ((FloatingPointLiteral) expr)
181: .getValue()).intValue();
182: CharacterLiteral literal = new CharacterLiteral(qs,
183: mapping, String.valueOf((char) value));
184: return new BooleanExpression(this , OP_LT, literal);
185: } else if (expr instanceof NumericExpression) {
186: return new BooleanExpression(this , OP_LT, expr);
187: } else {
188: return super .lt(expr);
189: }
190: }
191:
192: public BooleanExpression lteq(ScalarExpression expr) {
193: if (expr instanceof NullLiteral) {
194: return expr.lteq(this );
195: } else if (expr instanceof CharacterLiteral) {
196: return new BooleanExpression(this , OP_LTEQ, expr);
197: } else if (expr instanceof StringExpression) {
198: return new BooleanExpression(this , OP_LTEQ, expr);
199: } else if (expr instanceof ByteLiteral) {
200: int value = ((BigInteger) ((ByteLiteral) expr).getValue())
201: .intValue();
202: CharacterLiteral literal = new CharacterLiteral(qs,
203: mapping, String.valueOf((char) value));
204: return new BooleanExpression(this , OP_LTEQ, literal);
205: } else if (expr instanceof IntegerLiteral) {
206: int value = ((Number) ((IntegerLiteral) expr).getValue())
207: .intValue();
208: CharacterLiteral literal = new CharacterLiteral(qs,
209: mapping, String.valueOf((char) value));
210: return new BooleanExpression(this , OP_LTEQ, literal);
211: } else if (expr instanceof FloatingPointLiteral) {
212: int value = ((BigDecimal) ((FloatingPointLiteral) expr)
213: .getValue()).intValue();
214: CharacterLiteral literal = new CharacterLiteral(qs,
215: mapping, String.valueOf((char) value));
216: return new BooleanExpression(this , OP_LTEQ, literal);
217: } else if (expr instanceof NumericExpression) {
218: return new BooleanExpression(this , OP_LTEQ, expr);
219: } else {
220: return super .lteq(expr);
221: }
222: }
223:
224: public BooleanExpression gt(ScalarExpression expr) {
225: if (expr instanceof NullLiteral) {
226: return expr.gt(this );
227: } else if (expr instanceof CharacterLiteral) {
228: return new BooleanExpression(this , OP_GT, expr);
229: } else if (expr instanceof StringExpression) {
230: return new BooleanExpression(this , OP_GT, expr);
231: } else if (expr instanceof ByteLiteral) {
232: int value = ((BigInteger) ((ByteLiteral) expr).getValue())
233: .intValue();
234: CharacterLiteral literal = new CharacterLiteral(qs,
235: mapping, String.valueOf((char) value));
236: return new BooleanExpression(this , OP_GT, literal);
237: } else if (expr instanceof IntegerLiteral) {
238: int value = ((Number) ((IntegerLiteral) expr).getValue())
239: .intValue();
240: CharacterLiteral literal = new CharacterLiteral(qs,
241: mapping, String.valueOf((char) value));
242: return new BooleanExpression(this , OP_GT, literal);
243: } else if (expr instanceof FloatingPointLiteral) {
244: int value = ((BigDecimal) ((FloatingPointLiteral) expr)
245: .getValue()).intValue();
246: CharacterLiteral literal = new CharacterLiteral(qs,
247: mapping, String.valueOf((char) value));
248: return new BooleanExpression(this , OP_GT, literal);
249: } else if (expr instanceof NumericExpression) {
250: return new BooleanExpression(this , OP_GT, expr);
251: } else {
252: return super .gt(expr);
253: }
254: }
255:
256: public BooleanExpression gteq(ScalarExpression expr) {
257: if (expr instanceof NullLiteral) {
258: return expr.gteq(this );
259: } else if (expr instanceof CharacterLiteral) {
260: return new BooleanExpression(this , OP_GTEQ, expr);
261: } else if (expr instanceof StringExpression) {
262: return new BooleanExpression(this , OP_GTEQ, expr);
263: } else if (expr instanceof ByteLiteral) {
264: int value = ((BigInteger) ((ByteLiteral) expr).getValue())
265: .intValue();
266: CharacterLiteral literal = new CharacterLiteral(qs,
267: mapping, String.valueOf((char) value));
268: return new BooleanExpression(this , OP_GTEQ, literal);
269: } else if (expr instanceof IntegerLiteral) {
270: int value = ((Number) ((IntegerLiteral) expr).getValue())
271: .intValue();
272: CharacterLiteral literal = new CharacterLiteral(qs,
273: mapping, String.valueOf((char) value));
274: return new BooleanExpression(this , OP_GTEQ, literal);
275: } else if (expr instanceof FloatingPointLiteral) {
276: int value = ((BigDecimal) ((FloatingPointLiteral) expr)
277: .getValue()).intValue();
278: CharacterLiteral literal = new CharacterLiteral(qs,
279: mapping, String.valueOf((char) value));
280: return new BooleanExpression(this , OP_GTEQ, literal);
281: } else if (expr instanceof NumericExpression) {
282: return new BooleanExpression(this , OP_GTEQ, expr);
283: } else {
284: return super .gteq(expr);
285: }
286: }
287:
288: public ScalarExpression add(ScalarExpression expr) {
289: if (expr instanceof StringLiteral) {
290: return new StringExpression(this , OP_CONCAT,
291: new StringLiteral(qs, expr.mapping,
292: (String) ((StringLiteral) expr).getValue()));
293: } else if (expr instanceof StringExpression) {
294: return new StringExpression(this , OP_CONCAT, expr);
295: } else if (expr instanceof CharacterExpression) {
296: return new StringExpression(this , OP_CONCAT, expr);
297: } else if (expr instanceof NumericExpression) {
298: return new StringExpression(this , OP_CONCAT, qs
299: .getStoreManager().getDatastoreAdapter()
300: .toStringExpression((NumericExpression) expr));
301: } else if (expr instanceof NullLiteral) {
302: return expr;
303: } else {
304: return new StringExpression(this , OP_CONCAT, expr);
305: }
306: }
307:
308: public BooleanExpression in(ScalarExpression expr) {
309: return new BooleanExpression(this , OP_IN, expr);
310: }
311:
312: /**
313: * Returns whether this string is equal to the expression. This is provided
314: * as an operation on String.
315: * @param expr The expression to compare against.
316: * @return Expression whether they are equal.
317: **/
318: public BooleanExpression equalsMethod(ScalarExpression expr) {
319: return eq(expr);
320: }
321:
322: /**
323: * Returns the character at a position.
324: * @param index The position of the character required.
325: * @return The expression.
326: **/
327: public StringExpression charAtMethod(ScalarExpression index) {
328: if (!(index instanceof NumericExpression)) {
329: throw new IllegalArgumentTypeException(index);
330: }
331:
332: NumericExpression begin = (NumericExpression) index;
333: NumericExpression end = (NumericExpression) begin
334: .add(new IntegerLiteral(qs, mapping, BigInteger.ONE));
335: return substringMethod(begin, end);
336: }
337:
338: /**
339: * Returns whether this string ends with the specified string.
340: * @param str The string to compare against.
341: * @return Whether it ends with the string.
342: **/
343: public BooleanExpression endsWithMethod(ScalarExpression str) {
344: if (!(str instanceof StringExpression)) {
345: throw new IllegalArgumentTypeException(str);
346: }
347:
348: return qs.getStoreManager().getDatastoreAdapter()
349: .endsWithMethod(this , str);
350: }
351:
352: /**
353: * Returns the index within this string of the first occurrence of the
354: * specified string.
355: * @param str The string to find the index of
356: * @return The index of the string.
357: **/
358: public NumericExpression indexOfMethod(ScalarExpression str) {
359: if (!(str instanceof StringExpression)
360: && !(str instanceof CharacterLiteral)) {
361: throw new IllegalArgumentTypeException(str);
362: }
363:
364: return qs.getStoreManager().getDatastoreAdapter()
365: .indexOfMethod(this , str, null);
366: }
367:
368: /**
369: * Returns the index within this string of the first occurrence of the
370: * specified character, starting the search at the specified index.
371: * @param str The string to find the index of
372: * @param fromIndex the index to start the search from.
373: * @return The index of the string.
374: **/
375: public NumericExpression indexOfMethod(ScalarExpression str,
376: ScalarExpression fromIndex) {
377: if (!(str instanceof StringExpression)
378: && !(str instanceof CharacterLiteral)) {
379: throw new IllegalArgumentTypeException(str);
380: }
381: if (!(fromIndex instanceof NumericExpression)) {
382: throw new IllegalArgumentTypeException(fromIndex);
383: }
384:
385: return qs
386: .getStoreManager()
387: .getDatastoreAdapter()
388: .indexOfMethod(this , str, (NumericExpression) fromIndex);
389: }
390:
391: /**
392: * Method to handle the starts with operation.
393: * @return The expression.
394: **/
395: public NumericExpression lengthMethod() {
396: return qs.getStoreManager().getDatastoreAdapter().lengthMethod(
397: this );
398: }
399:
400: /**
401: * Method to handle the starts with operation.
402: * @param str The string to compare against
403: * @return The expression.
404: **/
405: public BooleanExpression startsWithMethod(ScalarExpression str) {
406: if (!(str instanceof StringExpression)) {
407: throw new IllegalArgumentTypeException(str);
408: }
409:
410: return qs.getStoreManager().getDatastoreAdapter()
411: .startsWithMethod(this , str);
412: }
413:
414: /**
415: * Method to handle the starts with operation.
416: * @param str The string to compare against
417: * @param toffset The offset
418: * @return The expression.
419: **/
420: public BooleanExpression startsWithMethod(ScalarExpression str,
421: ScalarExpression toffset) {
422: return substringMethod(toffset).startsWithMethod(str);
423: }
424:
425: /**
426: * Method to handle the substring operation.
427: * @param begin The start position
428: * @return The expression.
429: **/
430: public StringExpression substringMethod(ScalarExpression begin) {
431: if (!(begin instanceof NumericExpression)) {
432: throw new IllegalArgumentTypeException(begin);
433: }
434:
435: return qs.getStoreManager().getDatastoreAdapter()
436: .substringMethod(this , (NumericExpression) begin);
437: }
438:
439: /**
440: * Method to handle the substring operation.
441: * @param begin The start position
442: * @param end The end position
443: * @return The expression.
444: **/
445: public StringExpression substringMethod(ScalarExpression begin,
446: ScalarExpression end) {
447: if (!(begin instanceof NumericExpression)) {
448: throw new IllegalArgumentTypeException(begin);
449: }
450: if (!(end instanceof NumericExpression)) {
451: throw new IllegalArgumentTypeException(end);
452: }
453:
454: return qs.getStoreManager().getDatastoreAdapter()
455: .substringMethod(this , (NumericExpression) begin,
456: (NumericExpression) end);
457: }
458:
459: /**
460: * Method to translate all chars in this expression to the <code>fromExpr</code> which
461: * corresponds to <code>toExpr</code>.
462: * @return The expression.
463: **/
464: public StringExpression translateMethod(ScalarExpression toExpr,
465: ScalarExpression fromExpr) {
466: return qs.getStoreManager().getDatastoreAdapter()
467: .translateMethod(this , toExpr, fromExpr);
468: }
469:
470: /**
471: * Method to handle the lower case operation.
472: * @return The expression.
473: **/
474: public StringExpression toLowerCaseMethod() {
475: ArrayList args = new ArrayList();
476: args.add(this );
477:
478: return new StringExpression("LOWER", args);
479: }
480:
481: /**
482: * Method to handle the upper case operation.
483: * @return The expression.
484: **/
485: public StringExpression toUpperCaseMethod() {
486: ArrayList args = new ArrayList();
487: args.add(this );
488:
489: return new StringExpression("UPPER", args);
490: }
491:
492: /**
493: * Matches this to the argument expression pattern. Use "." to find any
494: * character and ".*" for wildcard matches. A global case-insensitive flag
495: * "(?i)" can be set for the pattern. If used, the global case-insensitive
496: * flag must prefix the pattern. The pattern passed to matches must be a
497: * literal or parameter.
498: * @param expr The literal expression with the pattern.
499: * @return the match expression.
500: */
501: public BooleanExpression matchesMethod(ScalarExpression expr) {
502: if (expr instanceof StringLiteral) {
503: //expr = qs.getStoreManager().getDatastoreAdapter().getEscapedPatternExpression(expr);
504: String pattern = (String) ((Literal) expr).getValue();
505: boolean caseSensitive = false;
506: if (pattern.startsWith("(?i)")) {
507: caseSensitive = true;
508: pattern = pattern.substring(4);
509: }
510: MatchExpressionParser parser = new MatchExpressionParser(
511: pattern, qs.getStoreManager().getDatastoreAdapter()
512: .getPatternExpressionZeroMoreCharacters()
513: .charAt(0), qs.getStoreManager()
514: .getDatastoreAdapter()
515: .getPatternExpressionAnyCharacter().charAt(
516: 0), qs.getStoreManager()
517: .getDatastoreAdapter().getEscapeCharacter()
518: .charAt(0));
519: if (caseSensitive) {
520: StringLiteral patternExpr = new StringLiteral(qs,
521: mapping, parser.parsePattern().toLowerCase());
522: //StringExpression escapedExpr = (StringExpression) qs.getStoreManager().getDatastoreAdapter().getEscapedPatternExpression(patternExpr);
523: return new LikeExpression(this .toLowerCaseMethod(),
524: ScalarExpression.OP_LIKE, patternExpr);
525: } else {
526: StringLiteral patternExpr = new StringLiteral(qs,
527: mapping, parser.parsePattern());
528: //StringExpression escapedExpr = (StringExpression) qs.getStoreManager().getDatastoreAdapter().getEscapedPatternExpression(patternExpr);
529: return new LikeExpression(this ,
530: ScalarExpression.OP_LIKE, patternExpr);
531: }
532: } else if (expr instanceof StringExpression) {
533: return qs.getStoreManager().getDatastoreAdapter()
534: .matchesMethod(this , (StringExpression) expr);
535: }
536: throw new IllegalOperationException(this , "matches", expr);
537: }
538:
539: /**
540: * Perform a database "like" operation
541: * @param expr The expression with the pattern.
542: * @return the match expression.
543: */
544: public BooleanExpression likeMethod(ScalarExpression expr) {
545: return new LikeExpression(this , OP_LIKE, expr);
546: }
547:
548: /**
549: * Method to handle trimming of both ends of a string.
550: * @return The expression.
551: */
552: public StringExpression trimMethod() {
553: return qs.getStoreManager().getDatastoreAdapter().trimMethod(
554: this , true, true);
555: }
556:
557: /**
558: * Method to handle trimming of the left side of a string (leading spaces).
559: * @return The expression.
560: */
561: public StringExpression trimLeftMethod() {
562: return qs.getStoreManager().getDatastoreAdapter().trimMethod(
563: this , true, false);
564: }
565:
566: /**
567: * Method to handle trimming of the right side of a string (trailing spaces).
568: * @return The expression.
569: */
570: public StringExpression trimRightMethod() {
571: return qs.getStoreManager().getDatastoreAdapter().trimMethod(
572: this , false, true);
573: }
574: }
|