CAY-1971 Variants of Property.like(..) : contains(..), startsWith(..), 
endsWith(..)


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/9587d047
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/9587d047
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/9587d047

Branch: refs/heads/CAY-1946_1
Commit: 9587d0475b3c3f44150fcf8fc50ea772e9ea40ea
Parents: f11fc5c
Author: aadamchik <aadamc...@apache.org>
Authored: Sat Nov 22 14:46:31 2014 +0300
Committer: aadamchik <aadamc...@apache.org>
Committed: Sat Nov 22 16:25:50 2014 +0300

----------------------------------------------------------------------
 .../apache/cayenne/exp/ExpressionFactory.java   | 179 ++++++++++++-------
 .../cayenne/exp/LikeExpressionHelper.java       |  73 ++++++++
 .../java/org/apache/cayenne/exp/Property.java   |  99 +++++++++-
 .../org/apache/cayenne/exp/PropertyTest.java    |  21 +++
 4 files changed, 298 insertions(+), 74 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/9587d047/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java
index dc1d815..cbef42d 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java
@@ -93,20 +93,14 @@ public class ExpressionFactory {
 
                // make sure all types are small integers, then we can use
                // them as indexes in lookup array
-               int[] allTypes = new int[] { Expression.AND, Expression.OR,
-                               Expression.NOT, Expression.EQUAL_TO, 
Expression.NOT_EQUAL_TO,
-                               Expression.LESS_THAN, Expression.GREATER_THAN,
-                               Expression.LESS_THAN_EQUAL_TO,
-                               Expression.GREATER_THAN_EQUAL_TO, 
Expression.BETWEEN,
-                               Expression.IN, Expression.LIKE, 
Expression.LIKE_IGNORE_CASE,
-                               Expression.ADD, Expression.SUBTRACT, 
Expression.MULTIPLY,
-                               Expression.DIVIDE, Expression.NEGATIVE, 
Expression.OBJ_PATH,
-                               Expression.DB_PATH, Expression.LIST, 
Expression.NOT_BETWEEN,
-                               Expression.NOT_IN, Expression.NOT_LIKE,
-                               Expression.NOT_LIKE_IGNORE_CASE, 
Expression.TRUE,
-                               Expression.FALSE, Expression.BITWISE_NOT,
-                               Expression.BITWISE_AND, Expression.BITWISE_OR,
-                               Expression.BITWISE_XOR, 
Expression.BITWISE_LEFT_SHIFT,
+               int[] allTypes = new int[] { Expression.AND, Expression.OR, 
Expression.NOT, Expression.EQUAL_TO,
+                               Expression.NOT_EQUAL_TO, Expression.LESS_THAN, 
Expression.GREATER_THAN, Expression.LESS_THAN_EQUAL_TO,
+                               Expression.GREATER_THAN_EQUAL_TO, 
Expression.BETWEEN, Expression.IN, Expression.LIKE,
+                               Expression.LIKE_IGNORE_CASE, Expression.ADD, 
Expression.SUBTRACT, Expression.MULTIPLY,
+                               Expression.DIVIDE, Expression.NEGATIVE, 
Expression.OBJ_PATH, Expression.DB_PATH, Expression.LIST,
+                               Expression.NOT_BETWEEN, Expression.NOT_IN, 
Expression.NOT_LIKE, Expression.NOT_LIKE_IGNORE_CASE,
+                               Expression.TRUE, Expression.FALSE, 
Expression.BITWISE_NOT, Expression.BITWISE_AND,
+                               Expression.BITWISE_OR, Expression.BITWISE_XOR, 
Expression.BITWISE_LEFT_SHIFT,
                                Expression.BITWISE_RIGHT_SHIFT };
 
                int max = 0;
@@ -322,19 +316,15 @@ public class ExpressionFactory {
 
                        int splitEnd = path.indexOf(Entity.PATH_SEPARATOR, 
split + 1);
 
-                       String beforeSplit = split > 0 ? path.substring(0, 
split) + "."
-                                       : "";
-                       String afterSplit = splitEnd > 0 ? "."
-                                       + path.substring(splitEnd + 1) : "";
+                       String beforeSplit = split > 0 ? path.substring(0, 
split) + "." : "";
+                       String afterSplit = splitEnd > 0 ? "." + 
path.substring(splitEnd + 1) : "";
                        String aliasBase = "split" + autoAliasId++ + "_";
-                       String splitChunk = splitEnd > 0 ? path.substring(split 
+ 1,
-                                       splitEnd) : path.substring(split + 1);
+                       String splitChunk = splitEnd > 0 ? path.substring(split 
+ 1, splitEnd) : path.substring(split + 1);
 
                        // fix the path - replace split with dot if it's in the 
middle, or
                        // strip it if
                        // it's in the beginning
-                       path = split == 0 ? path.substring(1) : path.replace(
-                                       SPLIT_SEPARATOR, '.');
+                       path = split == 0 ? path.substring(1) : 
path.replace(SPLIT_SEPARATOR, '.');
 
                        int i = 0;
                        for (Object value : values) {
@@ -344,8 +334,7 @@ public class ExpressionFactory {
                                i++;
 
                                ASTPath pathExp = new ASTObjPath(aliasedPath);
-                               
pathExp.setPathAliases(Collections.singletonMap(alias,
-                                               splitChunk));
+                               
pathExp.setPathAliases(Collections.singletonMap(alias, splitChunk));
                                matches.add(new ASTEqual(pathExp, value));
                        }
                } else {
@@ -572,8 +561,7 @@ public class ExpressionFactory {
        /**
         * A convenience shortcut for building BETWEEN expressions.
         */
-       public static Expression betweenExp(String pathSpec, Object value1,
-                       Object value2) {
+       public static Expression betweenExp(String pathSpec, Object value1, 
Object value2) {
                return new ASTBetween(new ASTObjPath(pathSpec), value1, value2);
        }
 
@@ -582,16 +570,14 @@ public class ExpressionFactory {
         * 
         * @since 3.0
         */
-       public static Expression betweenDbExp(String pathSpec, Object value1,
-                       Object value2) {
+       public static Expression betweenDbExp(String pathSpec, Object value1, 
Object value2) {
                return new ASTBetween(new ASTDbPath(pathSpec), value1, value2);
        }
 
        /**
         * A convenience shortcut for building NOT_BETWEEN expressions.
         */
-       public static Expression notBetweenExp(String pathSpec, Object value1,
-                       Object value2) {
+       public static Expression notBetweenExp(String pathSpec, Object value1, 
Object value2) {
                return new ASTNotBetween(new ASTObjPath(pathSpec), value1, 
value2);
        }
 
@@ -600,8 +586,7 @@ public class ExpressionFactory {
         * 
         * @since 3.0
         */
-       public static Expression notBetweenDbExp(String pathSpec, Object value1,
-                       Object value2) {
+       public static Expression notBetweenDbExp(String pathSpec, Object 
value1, Object value2) {
                return new ASTNotBetween(new ASTDbPath(pathSpec), value1, 
value2);
        }
 
@@ -609,7 +594,7 @@ public class ExpressionFactory {
         * A convenience shortcut for building LIKE expression.
         */
        public static Expression likeExp(String pathSpec, Object value) {
-               return new ASTLike(new ASTObjPath(pathSpec), value);
+               return likeExpInternal(pathSpec, value, (char) 0);
        }
 
        /**
@@ -624,8 +609,11 @@ public class ExpressionFactory {
         * 
         * @since 3.0.1
         */
-       public static Expression likeExp(String pathSpec, Object value,
-                       char escapeChar) {
+       public static Expression likeExp(String pathSpec, Object value, char 
escapeChar) {
+               return likeExpInternal(pathSpec, value, escapeChar);
+       }
+
+       static ASTLike likeExpInternal(String pathSpec, Object value, char 
escapeChar) {
                return new ASTLike(new ASTObjPath(pathSpec), value, escapeChar);
        }
 
@@ -650,8 +638,7 @@ public class ExpressionFactory {
         * 
         * @since 3.0.1
         */
-       public static Expression likeDbExp(String pathSpec, Object value,
-                       char escapeChar) {
+       public static Expression likeDbExp(String pathSpec, Object value, char 
escapeChar) {
                return new ASTLike(new ASTDbPath(pathSpec), value, escapeChar);
        }
 
@@ -674,8 +661,7 @@ public class ExpressionFactory {
         * 
         * @since 3.0.1
         */
-       public static Expression notLikeExp(String pathSpec, Object value,
-                       char escapeChar) {
+       public static Expression notLikeExp(String pathSpec, Object value, char 
escapeChar) {
                return new ASTNotLike(new ASTObjPath(pathSpec), value, 
escapeChar);
        }
 
@@ -700,8 +686,7 @@ public class ExpressionFactory {
         * 
         * @since 3.0.1
         */
-       public static Expression notLikeDbExp(String pathSpec, Object value,
-                       char escapeChar) {
+       public static Expression notLikeDbExp(String pathSpec, Object value, 
char escapeChar) {
                return new ASTNotLike(new ASTDbPath(pathSpec), value, 
escapeChar);
        }
 
@@ -709,7 +694,7 @@ public class ExpressionFactory {
         * A convenience shortcut for building LIKE_IGNORE_CASE expression.
         */
        public static Expression likeIgnoreCaseExp(String pathSpec, Object 
value) {
-               return new ASTLikeIgnoreCase(new ASTObjPath(pathSpec), value);
+               return likeIgnoreCaseExpInternal(pathSpec, value, (char) 0);
        }
 
        /**
@@ -724,10 +709,12 @@ public class ExpressionFactory {
         * 
         * @since 3.0.1
         */
-       public static Expression likeIgnoreCaseExp(String pathSpec, Object 
value,
-                       char escapeChar) {
-               return new ASTLikeIgnoreCase(new ASTObjPath(pathSpec), value,
-                               escapeChar);
+       public static Expression likeIgnoreCaseExp(String pathSpec, Object 
value, char escapeChar) {
+               return likeIgnoreCaseExpInternal(pathSpec, value, escapeChar);
+       }
+
+       static ASTLikeIgnoreCase likeIgnoreCaseExpInternal(String pathSpec, 
Object value, char escapeChar) {
+               return new ASTLikeIgnoreCase(new ASTObjPath(pathSpec), value, 
escapeChar);
        }
 
        /**
@@ -751,8 +738,7 @@ public class ExpressionFactory {
         * 
         * @since 3.0.1
         */
-       public static Expression likeIgnoreCaseDbExp(String pathSpec, Object 
value,
-                       char escapeChar) {
+       public static Expression likeIgnoreCaseDbExp(String pathSpec, Object 
value, char escapeChar) {
                return new ASTLikeIgnoreCase(new ASTDbPath(pathSpec), value, 
escapeChar);
        }
 
@@ -775,10 +761,8 @@ public class ExpressionFactory {
         * 
         * @since 3.0.1
         */
-       public static Expression notLikeIgnoreCaseExp(String pathSpec,
-                       Object value, char escapeChar) {
-               return new ASTNotLikeIgnoreCase(new ASTObjPath(pathSpec), value,
-                               escapeChar);
+       public static Expression notLikeIgnoreCaseExp(String pathSpec, Object 
value, char escapeChar) {
+               return new ASTNotLikeIgnoreCase(new ASTObjPath(pathSpec), 
value, escapeChar);
        }
 
        /**
@@ -786,8 +770,7 @@ public class ExpressionFactory {
         * 
         * @since 3.0
         */
-       public static Expression notLikeIgnoreCaseDbExp(String pathSpec,
-                       Object value) {
+       public static Expression notLikeIgnoreCaseDbExp(String pathSpec, Object 
value) {
                return new ASTNotLikeIgnoreCase(new ASTDbPath(pathSpec), value);
        }
 
@@ -803,10 +786,77 @@ public class ExpressionFactory {
         * 
         * @since 3.0.1
         */
-       public static Expression notLikeIgnoreCaseDbExp(String pathSpec,
-                       Object value, char escapeChar) {
-               return new ASTNotLikeIgnoreCase(new ASTDbPath(pathSpec), value,
-                               escapeChar);
+       public static Expression notLikeIgnoreCaseDbExp(String pathSpec, Object 
value, char escapeChar) {
+               return new ASTNotLikeIgnoreCase(new ASTDbPath(pathSpec), value, 
escapeChar);
+       }
+
+       /**
+        * @return An expression for a database "LIKE" query with the value
+        *         converted to a pattern matching anywhere in the String.
+        * @since 4.0
+        */
+       public static Expression containsExp(String pathSpec, String value) {
+               ASTLike like = likeExpInternal(pathSpec, value, (char) 0);
+               LikeExpressionHelper.toContains(like);
+               return like;
+       }
+
+       /**
+        * @return An expression for a database "LIKE" query with the value
+        *         converted to a pattern matching the beginning of the String.
+        * @since 4.0
+        */
+       public static Expression startsWithExp(String pathSpec, String value) {
+               ASTLike like = likeExpInternal(pathSpec, value, (char) 0);
+               LikeExpressionHelper.toStartsWith(like);
+               return like;
+       }
+
+       /**
+        * @return An expression for a database "LIKE" query with the value
+        *         converted to a pattern matching the beginning of the String.
+        * @since 4.0
+        */
+       public static Expression endsWithExp(String pathSpec, String value) {
+               ASTLike like = likeExpInternal(pathSpec, value, (char) 0);
+               LikeExpressionHelper.toEndsWith(like);
+               return like;
+       }
+
+       /**
+        * Same as {@link #containsExp(String, String)} only using 
case-insensitive
+        * comparison.
+        * 
+        * @since 4.0
+        */
+       public static Expression containsIgnoreCaseExp(String pathSpec, String 
value) {
+               ASTLikeIgnoreCase like = likeIgnoreCaseExpInternal(pathSpec, 
value, (char) 0);
+               LikeExpressionHelper.toContains(like);
+               return like;
+       }
+
+       /**
+        * Same as {@link #startsWithExp(String, String)} only using
+        * case-insensitive comparison.
+        * 
+        * @since 4.0
+        */
+       public static Expression startsWithIgnoreCaseExp(String pathSpec, 
String value) {
+               ASTLikeIgnoreCase like = likeIgnoreCaseExpInternal(pathSpec, 
value, (char) 0);
+               LikeExpressionHelper.toStartsWith(like);
+               return like;
+       }
+
+       /**
+        * Same as {@link #endsWithExp(String, String)} only using 
case-insensitive
+        * comparison.
+        * 
+        * @since 4.0
+        */
+       public static Expression endsWithIgnoreCaseExp(String pathSpec, String 
value) {
+               ASTLikeIgnoreCase like = likeIgnoreCaseExpInternal(pathSpec, 
value, (char) 0);
+               LikeExpressionHelper.toEndsWith(like);
+               return like;
        }
 
        /**
@@ -837,8 +887,7 @@ public class ExpressionFactory {
         * expression would match any of the expressions.
         * </p>
         */
-       public static Expression joinExp(int type,
-                       Collection<Expression> expressions) {
+       public static Expression joinExp(int type, Collection<Expression> 
expressions) {
                int len = expressions.size();
                if (len == 0) {
                        return null;
@@ -872,8 +921,7 @@ public class ExpressionFactory {
         * <code>object</code>.
         */
        public static Expression matchExp(Persistent object) {
-               return matchAllDbExp(object.getObjectId().getIdSnapshot(),
-                               Expression.EQUAL_TO);
+               return matchAllDbExp(object.getObjectId().getIdSnapshot(), 
Expression.EQUAL_TO);
        }
 
        /**
@@ -971,12 +1019,11 @@ public class ExpressionFactory {
                // optimizing parser buffers per CAY-1667...
                // adding 1 extra char to the buffer size above the String 
length, as
                // otherwise resizing still occurs at the end of the stream
-               int bufferSize = expressionString.length() > 
PARSE_BUFFER_MAX_SIZE ? PARSE_BUFFER_MAX_SIZE
-                               : expressionString.length() + 1;
+               int bufferSize = expressionString.length() > 
PARSE_BUFFER_MAX_SIZE ? PARSE_BUFFER_MAX_SIZE : expressionString
+                               .length() + 1;
                Reader reader = new StringReader(expressionString);
                JavaCharStream stream = new JavaCharStream(reader, 1, 1, 
bufferSize);
-               ExpressionParserTokenManager tm = new 
ExpressionParserTokenManager(
-                               stream);
+               ExpressionParserTokenManager tm = new 
ExpressionParserTokenManager(stream);
                ExpressionParser parser = new ExpressionParser(tm);
 
                try {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/9587d047/cayenne-server/src/main/java/org/apache/cayenne/exp/LikeExpressionHelper.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/exp/LikeExpressionHelper.java 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/LikeExpressionHelper.java
new file mode 100644
index 0000000..7725dc9
--- /dev/null
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/LikeExpressionHelper.java
@@ -0,0 +1,73 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.exp;
+
+import org.apache.cayenne.exp.parser.PatternMatchNode;
+
+/**
+ * @since 4.0
+ */
+class LikeExpressionHelper {
+
+       // presumably only "?" can't be an escape char
+       private static final char[] ESCAPE_ALPHABET = new char[] { '\\', '|', 
'/', ' ' };
+
+       private static final String WILDCARD_SEQUENCE = "%";
+       private static final String WILDCARD_ONE = "_";
+
+       static void toContains(PatternMatchNode exp) {
+               escape(exp);
+               wrap(exp, true, true);
+       }
+
+       static void toStartsWith(PatternMatchNode exp) {
+               escape(exp);
+               wrap(exp, false, true);
+       }
+
+       static void toEndsWith(PatternMatchNode exp) {
+               escape(exp);
+               wrap(exp, true, false);
+       }
+
+       static void escape(PatternMatchNode exp) {
+
+       }
+
+       static void wrap(PatternMatchNode exp, boolean start, boolean end) {
+
+               Object pattern = exp.getOperand(1);
+               if (pattern instanceof String) {
+
+                       StringBuilder buffer = new StringBuilder();
+                       if (start) {
+                               buffer.append(WILDCARD_SEQUENCE);
+                       }
+
+                       buffer.append(pattern);
+
+                       if (end) {
+                               buffer.append(WILDCARD_SEQUENCE);
+                       }
+
+                       exp.setOperand(1, buffer.toString());
+               }
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/9587d047/cayenne-server/src/main/java/org/apache/cayenne/exp/Property.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/Property.java 
b/cayenne-server/src/main/java/org/apache/cayenne/exp/Property.java
index b42e890..1676315 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/Property.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/Property.java
@@ -165,34 +165,117 @@ public class Property<E> {
        }
 
        /**
-        * @return An expression for a Database "Like" query.
+        * @param pattern
+        *            a pattern matching property value. Pattern may include 
"_" and
+        *            "%" wildcard symbols to match any single character or a
+        *            sequence of characters. To prevent "_" and "%" from being
+        *            treated as wildcards, they need to be escaped and escape 
char
+        *            passed with {@link #like(String, char)} method.
+        * @return An expression for a Database "LIKE" query.
         */
-       public Expression like(E value) {
-               return ExpressionFactory.likeExp(getName(), value);
+       public Expression like(String pattern) {
+               return ExpressionFactory.likeExp(getName(), pattern);
        }
 
        /**
-        * @return An expression for a case insensitive "Like" query.
+        * @param pattern
+        *            a properly escaped pattern matching property value. 
Pattern
+        *            may include "_" and "%" wildcard symbols to match any 
single
+        *            character or a sequence of characters.
+        * @param escapeChar
+        *            an escape character used in the pattern to escape "%" and 
"_".
+        * 
+        * @return An expression for a Database "LIKE" query.
+        */
+       public Expression like(String pattern, char escapeChar) {
+               return ExpressionFactory.likeExp(getName(), pattern, 
escapeChar);
+       }
+
+       /**
+        * @return An expression for a case insensitive "LIKE" query.
         */
-       public Expression likeInsensitive(E value) {
-               return ExpressionFactory.likeIgnoreCaseExp(getName(), value);
+       public Expression likeInsensitive(String pattern) {
+               return ExpressionFactory.likeIgnoreCaseExp(getName(), pattern);
        }
 
        /**
         * @return An expression for a Database "NOT LIKE" query.
         */
-       public Expression nlike(E value) {
+       public Expression nlike(String value) {
                return ExpressionFactory.notLikeExp(getName(), value);
        }
 
        /**
         * @return An expression for a case insensitive "NOT LIKE" query.
         */
-       public Expression nlikeInsensitive(E value) {
+       public Expression nlikeInsensitive(String value) {
                return ExpressionFactory.notLikeIgnoreCaseExp(getName(), value);
        }
 
        /**
+        * Creates an expression for a database "LIKE" query with the value
+        * converted to a pattern matching anywhere in the String.
+        * 
+        * @param substring
+        *            a String to match against property value. "_" and "%" 
symbols
+        *            are NOT treated as wildcards and are escaped when 
converted to
+        *            a LIKE expression.
+        */
+       public Expression contains(String substring) {
+               return ExpressionFactory.containsExp(getName(), substring);
+       }
+
+       /**
+        * Creates an expression for a database "LIKE" query with the value
+        * converted to a pattern matching the beginning of a String.
+        * 
+        * @param substring
+        *            a String to match against property value. "_" and "%" 
symbols
+        *            are NOT treated as wildcards and are escaped when 
converted to
+        *            a LIKE expression.
+        */
+       public Expression startsWith(String value) {
+               return ExpressionFactory.startsWithExp(getName(), value);
+       }
+
+       /**
+        * Creates an expression for a database "LIKE" query with the value
+        * converted to a pattern matching the tail of a String.
+        * 
+        * @param substring
+        *            a String to match against property value. "_" and "%" 
symbols
+        *            are NOT treated as wildcards and are escaped when 
converted to
+        *            a LIKE expression.
+        */
+       public Expression endsWith(String value) {
+               return ExpressionFactory.endsWithExp(getName(), value);
+       }
+
+       /**
+        * Same as {@link #contains(String)}, only using case-insensitive
+        * comparison.
+        */
+       public Expression icontains(String value) {
+               return ExpressionFactory.containsIgnoreCaseExp(getName(), 
value);
+       }
+
+       /**
+        * Same as {@link #startsWith(String)}, only using case-insensitive
+        * comparison.
+        */
+       public Expression istartsWith(String value) {
+               return ExpressionFactory.startsWithIgnoreCaseExp(getName(), 
value);
+       }
+
+       /**
+        * Same as {@link #endsWith(String)}, only using case-insensitive
+        * comparison.
+        */
+       public Expression iendsWith(String value) {
+               return ExpressionFactory.endsWithIgnoreCaseExp(getName(), 
value);
+       }
+
+       /**
         * @return An expression checking for objects between a lower and upper
         *         bound inclusive
         * 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/9587d047/cayenne-server/src/test/java/org/apache/cayenne/exp/PropertyTest.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/exp/PropertyTest.java 
b/cayenne-server/src/test/java/org/apache/cayenne/exp/PropertyTest.java
index 1144449..70fd3ce 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/exp/PropertyTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/PropertyTest.java
@@ -192,4 +192,25 @@ public class PropertyTest {
        Expression e = p.like("ab%c");
        assertEquals("prop like \"ab%c\"", e.toString());
     }
+    
+    @Test
+    public void testContains() {
+       Property<String> p = new Property<String>("prop");
+       Expression e = p.contains("abc");
+       assertEquals("prop like \"%abc%\"", e.toString());
+    }
+    
+    @Test
+    public void testStartsWith() {
+       Property<String> p = new Property<String>("prop");
+       Expression e = p.startsWith("abc");
+       assertEquals("prop like \"abc%\"", e.toString());
+    }
+    
+    @Test
+    public void testEndsWith() {
+       Property<String> p = new Property<String>("prop");
+       Expression e = p.endsWith("abc");
+       assertEquals("prop like \"%abc\"", e.toString());
+    }
 }

Reply via email to