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());
