Repository: olingo-odata2
Updated Branches:
  refs/heads/master d0b3782c9 -> e04ea6a00


[OLINGO-686] Additional fix for comma in string key predicate


Project: http://git-wip-us.apache.org/repos/asf/olingo-odata2/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata2/commit/e04ea6a0
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata2/tree/e04ea6a0
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata2/diff/e04ea6a0

Branch: refs/heads/master
Commit: e04ea6a003231481439f2ce037ef8aef0a42a547
Parents: d0b3782
Author: Michael Bolz <[email protected]>
Authored: Tue Jun 9 14:43:14 2015 +0200
Committer: Michael Bolz <[email protected]>
Committed: Tue Jun 9 14:43:41 2015 +0200

----------------------------------------------------------------------
 .../olingo/odata2/core/uri/UriParserImpl.java   | 58 ++++++++++++++++++--
 .../olingo/odata2/core/uri/UriParserTest.java   | 37 +++++++++++++
 2 files changed, 90 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/e04ea6a0/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriParserImpl.java
----------------------------------------------------------------------
diff --git 
a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriParserImpl.java
 
b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriParserImpl.java
index 196375c..0f5f74f 100644
--- 
a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriParserImpl.java
+++ 
b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriParserImpl.java
@@ -79,7 +79,8 @@ public class UriParserImpl extends UriParser {
       .compile("(?:([^.()]+)\\.)?([^.()]+)(?:\\((.+)\\)|(\\(\\)))?");
   private static final Pattern NAVIGATION_SEGMENT_PATTERN = 
Pattern.compile("([^()]+)(?:\\((.+)\\)|(\\(\\)))?");
   private static final Pattern NAMED_VALUE_PATTERN = 
Pattern.compile("(?:([^=]+)=)?([^=]+)");
-  private static final Pattern STRING_KEY_PATTERN = 
Pattern.compile("'([^']*)'");
+  private static final char COMMA = ',';
+  private static final char SQUOTE = '\'';
 
   private final Edm edm;
   private final EdmSimpleTypeFacade simpleTypeFacade;
@@ -447,8 +448,7 @@ public class UriParserImpl extends UriParser {
     ArrayList<EdmProperty> parsedKeyProperties = new ArrayList<EdmProperty>();
     ArrayList<KeyPredicate> keyPredicates = new ArrayList<KeyPredicate>();
 
-    Matcher keyMatcher = STRING_KEY_PATTERN.matcher(keyPredicate);
-    String[] keys = keyMatcher.matches() ? new String[]{keyPredicate} : 
keyPredicate.split(",", -1);
+    final List<String> keys = splitKeyPredicate(keyPredicate);
     for (final String key : keys) {
       final Matcher matcher = NAMED_VALUE_PATTERN.matcher(key);
       if (!matcher.matches()) {
@@ -492,6 +492,54 @@ public class UriParserImpl extends UriParser {
     return keyPredicates;
   }
 
+  /**
+   * Split the <code>keyPredicate</code> string into separate keys (named 
keys).
+   * e.g. <b>EmployeeId='1,,,2',Test='as'</b> will result in a list with two 
elements
+   * <b>EmployeeId='1,,,2'</b> and <b>Test='as'</b>.
+   *
+   * e.g. <b>'42'</b> will result in a list with onw element <b>'42'</b>.
+   *
+   * Snippets from ABNF (odata-abnf-construction-rules)
+   *
+   * <code>
+   *   keyPredicate     = simpleKey / compoundKey
+   *   simpleKey        = OPEN keyPropertyValue CLOSE
+   *   compoundKey      = OPEN keyValuePair *( COMMA keyValuePair ) CLOSE
+   *   keyValuePair     = ( primitiveKeyProperty / keyPropertyAlias ) EQ 
keyPropertyValue
+   *   keyPropertyValue = primitiveLiteral
+   *   keyPropertyAlias = odataIdentifier
+   * </code>
+   *
+   * <code>
+   *   string           = SQUOTE *( SQUOTE-in-string / pchar-no-SQUOTE ) SQUOTE
+   *   SQUOTE-in-string = SQUOTE SQUOTE ; two consecutive single quotes 
represent one within a string literal
+   * </code>
+   *
+   * @param keyPredicate keyPredicate to split
+   * @return list of separate (named) key values
+   */
+  private List<String> splitKeyPredicate(String keyPredicate) {
+    StringBuilder b = new StringBuilder();
+    final List<String> keys = new ArrayList<String>();
+    boolean inStringKeyValue = false;
+    for (int i = 0; i < keyPredicate.length(); i++) {
+      final char curChar = keyPredicate.charAt(i);
+      if(SQUOTE == curChar) {
+        // also works with SQUOTE-in-string
+        inStringKeyValue = !inStringKeyValue;
+        b.append(curChar);
+      } else if(COMMA == curChar && !inStringKeyValue) {
+        keys.add(b.toString());
+        b = new StringBuilder();
+      } else {
+        b.append(curChar);
+      }
+    }
+    keys.add(b.toString());
+
+    return keys;
+  }
+
   private void handleFunctionImport(final EdmFunctionImport functionImport, 
final String emptyParentheses,
       final String keyPredicate) throws UriSyntaxException, 
UriNotMatchingException, EdmException {
     final EdmTyped returnType = functionImport.getReturnType();
@@ -880,13 +928,13 @@ public class UriParserImpl extends UriParser {
 
   @Override
   public FilterExpression parseFilterString(final EdmEntityType entityType, 
final String expression)
-      throws ExpressionParserException, ODataMessageException {
+      throws ODataMessageException {
     return new FilterParserImpl(entityType).parseFilterString(expression);
   }
 
   @Override
   public OrderByExpression parseOrderByString(final EdmEntityType entityType, 
final String expression)
-      throws ExpressionParserException, ODataMessageException {
+      throws ODataMessageException {
     return new OrderByParserImpl(entityType).parseOrderByString(expression);
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/e04ea6a0/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/UriParserTest.java
----------------------------------------------------------------------
diff --git 
a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/UriParserTest.java
 
b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/UriParserTest.java
index 93002fe..c419c3c 100644
--- 
a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/UriParserTest.java
+++ 
b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/uri/UriParserTest.java
@@ -266,6 +266,19 @@ public class UriParserTest extends BaseTest {
   }
 
   @Test
+  public void parseEmployeesEntityWithKeyWithSquoteInString() throws Exception 
{
+    UriInfoImpl result = parse("/Employees('1''2')");
+    assertNull(result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI2, result.getUriType());
+
+    assertEquals(1, result.getKeyPredicates().size());
+    assertEquals("1'2", result.getKeyPredicates().get(0).getLiteral());
+    assertEquals("EmployeeId", 
result.getKeyPredicates().get(0).getProperty().getName());
+  }
+
+
+  @Test
   public void parseEmployeesEntityWithKeyEncoded() throws Exception {
     UriInfoImpl result = parse("/%45mployees('1')");
     assertNull(result.getEntityContainer().getName());
@@ -302,6 +315,30 @@ public class UriParserTest extends BaseTest {
   }
 
   @Test
+  public void parseEmployeesEntityWithExplicitKeyAndComma() throws Exception {
+    UriInfoImpl result = parse("/Employees(EmployeeId='1,2')");
+    assertNull(result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI2, result.getUriType());
+
+    assertEquals(1, result.getKeyPredicates().size());
+    assertEquals("1,2", result.getKeyPredicates().get(0).getLiteral());
+    assertEquals("EmployeeId", 
result.getKeyPredicates().get(0).getProperty().getName());
+  }
+
+  @Test
+  public void parseEmployeesEntityWithExplicitKeyAndSquoteInString() throws 
Exception {
+    UriInfoImpl result = parse("/Employees(EmployeeId='1''2')");
+    assertNull(result.getEntityContainer().getName());
+    assertEquals("Employees", result.getTargetEntitySet().getName());
+    assertEquals(UriType.URI2, result.getUriType());
+
+    assertEquals(1, result.getKeyPredicates().size());
+    assertEquals("1'2", result.getKeyPredicates().get(0).getLiteral());
+    assertEquals("EmployeeId", 
result.getKeyPredicates().get(0).getProperty().getName());
+  }
+
+  @Test
   public void parseEmployeesEntityWithKeyValue() throws Exception {
     UriInfoImpl result = parse("/Employees('1')/$value");
     assertEquals("Employees", result.getTargetEntitySet().getName());

Reply via email to