Repository: olingo-odata4
Updated Branches:
  refs/heads/master 981084fe1 -> 9333c090f


[OLINGO-916] more robust simple-key parsing

Signed-off-by: Christian Amend <[email protected]>


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

Branch: refs/heads/master
Commit: 9333c090fd9fc99dcbb9e5b40fe15dc2671055db
Parents: 981084f
Author: Klaus Straubinger <[email protected]>
Authored: Tue Mar 29 10:55:21 2016 +0200
Committer: Christian Amend <[email protected]>
Committed: Tue Mar 29 12:31:19 2016 +0200

----------------------------------------------------------------------
 .../olingo/server/core/ODataHandlerImpl.java    |  2 +-
 .../server/core/uri/parser/ExpandParser.java    | 37 ++-------
 .../core/uri/parser/ExpressionParser.java       | 39 ++++-----
 .../server/core/uri/parser/ParserHelper.java    | 86 +++++++++++---------
 .../core/uri/testutil/ExpandValidator.java      |  8 +-
 5 files changed, 76 insertions(+), 96 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9333c090/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerImpl.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerImpl.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerImpl.java
index da4856a..921124c 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerImpl.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerImpl.java
@@ -133,7 +133,7 @@ public class ODataHandlerImpl implements ODataHandler {
       throw e;
     }
 
-    final int measurementUriParser = 
debugger.startRuntimeMeasurement("UriParser", "parseUri");
+    final int measurementUriParser = 
debugger.startRuntimeMeasurement("Parser", "parseUri");
     try {
       uriInfo = new Parser(serviceMetadata.getEdm(), odata)
           .parseUri(request.getRawODataPath(), request.getRawQueryPath(), 
null);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9333c090/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java
index bae2bdd..1da143a 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java
@@ -22,11 +22,9 @@ import java.util.Collection;
 import java.util.Map;
 
 import org.apache.olingo.commons.api.edm.Edm;
-import org.apache.olingo.commons.api.edm.EdmEntityType;
 import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
 import org.apache.olingo.commons.api.edm.EdmProperty;
 import org.apache.olingo.commons.api.edm.EdmStructuredType;
-import org.apache.olingo.commons.api.edm.FullQualifiedName;
 import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
 import org.apache.olingo.commons.api.ex.ODataRuntimeException;
 import org.apache.olingo.server.api.OData;
@@ -127,13 +125,13 @@ public class ExpandParser {
       }
 
     } else {
-      final EdmStructuredType typeCast = parseTypeCast(tokenizer, 
referencedType);
+      final EdmStructuredType typeCast = ParserHelper.parseTypeCast(tokenizer, 
edm, referencedType);
       if (typeCast != null) {
         item.setTypeFilter(typeCast);
         ParserHelper.requireNext(tokenizer, TokenKind.SLASH);
       }
 
-      UriInfoImpl resource = parseExpandPath(tokenizer, referencedType, item);
+      UriInfoImpl resource = parseExpandPath(tokenizer, edm, referencedType, 
item);
 
       UriResourcePartTyped lastPart = (UriResourcePartTyped) 
resource.getLastResourcePart();
 
@@ -143,7 +141,8 @@ public class ExpandParser {
         if (lastPart instanceof UriResourceNavigation) {
           UriResourceNavigationPropertyImpl navigationResource = 
(UriResourceNavigationPropertyImpl) lastPart;
           final EdmNavigationProperty navigationProperty = 
navigationResource.getProperty();
-          final EdmStructuredType typeCastSuffix = parseTypeCast(tokenizer, 
navigationProperty.getType());
+          final EdmStructuredType typeCastSuffix = 
ParserHelper.parseTypeCast(tokenizer, edm,
+              navigationProperty.getType());
           if (typeCastSuffix != null) {
             if (navigationProperty.isCollection()) {
               navigationResource.setCollectionTypeFilter(typeCastSuffix);
@@ -178,34 +177,12 @@ public class ExpandParser {
     return item;
   }
 
-  private EdmStructuredType parseTypeCast(UriTokenizer tokenizer, final 
EdmStructuredType referencedType)
-      throws UriParserException {
-    if (tokenizer.next(TokenKind.QualifiedName)) {
-      final FullQualifiedName qualifiedName = new 
FullQualifiedName(tokenizer.getText());
-      final EdmStructuredType type = referencedType instanceof EdmEntityType ?
-          edm.getEntityType(qualifiedName) :
-          edm.getComplexType(qualifiedName);
-      if (type == null) {
-        throw new UriParserSemanticException("Type '" + qualifiedName + "' not 
found.",
-            UriParserSemanticException.MessageKeys.UNKNOWN_PART, 
qualifiedName.getFullQualifiedNameAsString());
-      } else {
-        if (!type.compatibleTo(referencedType)) {
-          throw new UriParserSemanticException("The type cast '" + 
qualifiedName + "' is not compatible.",
-              UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER, 
type.getName());
-        }
-      }
-      return type;
-    }
-    return null;
-  }
-
-  private UriInfoImpl parseExpandPath(UriTokenizer tokenizer, final 
EdmStructuredType referencedType,
-      ExpandItemImpl item) throws UriParserException {
+  protected static UriInfoImpl parseExpandPath(UriTokenizer tokenizer, final 
Edm edm,
+      final EdmStructuredType referencedType, ExpandItemImpl item) throws 
UriParserException {
     UriInfoImpl resource = new UriInfoImpl().setKind(UriInfoKind.resource);
 
     EdmStructuredType type = referencedType;
     String name = null;
-
     while (tokenizer.next(TokenKind.ODataIdentifier)) {
       name = tokenizer.getText();
       final EdmProperty property = referencedType.getStructuralProperty(name);
@@ -213,7 +190,7 @@ public class ExpandParser {
         type = (EdmStructuredType) property.getType();
         UriResourceComplexPropertyImpl complexResource = new 
UriResourceComplexPropertyImpl(property);
         ParserHelper.requireNext(tokenizer, TokenKind.SLASH);
-        final EdmStructuredType typeCast = parseTypeCast(tokenizer, type);
+        final EdmStructuredType typeCast = 
ParserHelper.parseTypeCast(tokenizer, edm, type);
         if (typeCast != null) {
           complexResource.setTypeFilter(typeCast);
           ParserHelper.requireNext(tokenizer, TokenKind.SLASH);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9333c090/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
index ee83a53..c9f8b21 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpressionParser.java
@@ -286,14 +286,8 @@ public class ExpressionParser {
     // Null for everything other than MUL or DIV or MOD
     while (operatorTokenKind != null) {
       final Expression right = parseExprUnary();
-      checkType(left,
-          EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, 
EdmPrimitiveTypeKind.Int64,
-          EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte,
-          EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, 
EdmPrimitiveTypeKind.Double);
-      checkType(right,
-          EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, 
EdmPrimitiveTypeKind.Int64,
-          EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte,
-          EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, 
EdmPrimitiveTypeKind.Double);
+      checkNumericType(left);
+      checkNumericType(right);
       left = new BinaryImpl(left, 
tokenToBinaryOperator.get(operatorTokenKind), right,
           odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Double));
       operatorTokenKind = ParserHelper.next(tokenizer,
@@ -305,11 +299,9 @@ public class ExpressionParser {
   private Expression parseExprUnary() throws UriParserException, 
UriValidationException {
     if (tokenizer.next(TokenKind.MinusOperator)) {
       final Expression expression = parseExprPrimary();
-      checkType(expression,
-          EdmPrimitiveTypeKind.Int16, EdmPrimitiveTypeKind.Int32, 
EdmPrimitiveTypeKind.Int64,
-          EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte,
-          EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, 
EdmPrimitiveTypeKind.Double,
-          EdmPrimitiveTypeKind.Duration);
+      if (!isType(getType(expression), EdmPrimitiveTypeKind.Duration)) {
+        checkNumericType(expression);
+      }
       return new UnaryImpl(UnaryOperatorKind.MINUS, expression, 
getType(expression));
     } else if (tokenizer.next(TokenKind.NotOperator)) {
       final Expression expression = parseExprPrimary();
@@ -538,15 +530,11 @@ public class ExpressionParser {
       parameters.add(parameterFirst);
       ParserHelper.requireNext(tokenizer, TokenKind.COMMA);
       final Expression parameterSecond = parseExpression();
-      checkType(parameterSecond,
-          EdmPrimitiveTypeKind.Int64, EdmPrimitiveTypeKind.Int32, 
EdmPrimitiveTypeKind.Int16,
-          EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte);
+      checkIntegerType(parameterSecond);
       parameters.add(parameterSecond);
       if (tokenizer.next(TokenKind.COMMA)) {
         final Expression parameterThird = parseExpression();
-        checkType(parameterThird,
-            EdmPrimitiveTypeKind.Int64, EdmPrimitiveTypeKind.Int32, 
EdmPrimitiveTypeKind.Int16,
-            EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte);
+        checkIntegerType(parameterThird);
         parameters.add(parameterThird);
       }
       break;
@@ -1084,6 +1072,19 @@ public class ExpressionParser {
     }
   }
 
+  protected void checkIntegerType(final Expression expression) throws 
UriParserException {
+    checkType(expression,
+        EdmPrimitiveTypeKind.Int64, EdmPrimitiveTypeKind.Int32, 
EdmPrimitiveTypeKind.Int16,
+        EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte);
+  }
+
+  protected void checkNumericType(final Expression expression) throws 
UriParserException {
+    checkType(expression,
+        EdmPrimitiveTypeKind.Int64, EdmPrimitiveTypeKind.Int32, 
EdmPrimitiveTypeKind.Int16,
+        EdmPrimitiveTypeKind.Byte, EdmPrimitiveTypeKind.SByte,
+        EdmPrimitiveTypeKind.Decimal, EdmPrimitiveTypeKind.Single, 
EdmPrimitiveTypeKind.Double);
+  }
+
   private void checkEqualityTypes(final Expression left, final Expression 
right) throws UriParserException {
     final EdmType leftType = getType(left);
     final EdmType rightType = getType(right);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9333c090/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
index 0ca0ce6..f952c80 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ParserHelper.java
@@ -38,8 +38,10 @@ import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
 import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmStructuredType;
 import org.apache.olingo.commons.api.edm.EdmType;
 import org.apache.olingo.commons.api.edm.EdmTypeDefinition;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
 import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
 import org.apache.olingo.server.api.OData;
 import org.apache.olingo.server.api.uri.UriParameter;
@@ -306,17 +308,24 @@ public class ParserHelper {
       }
     }
 
-    if(tokenizer.next(TokenKind.GuidValue)) {
-      keys.add(parseSimpleKey(tokenizer, edm, referringType, aliases, 
keyPropertyRefs, referencedNames, true));
-    } else if (tokenizer.next(TokenKind.ODataIdentifier)) {
-      keys.addAll(compoundKey(tokenizer, edmEntityType, edm, referringType, 
aliases));
-    } else if (keyPropertyRefs.size() - referencedNames.size() == 1) {
-      keys.add(parseSimpleKey(tokenizer, edm, referringType, aliases, 
keyPropertyRefs, referencedNames, false));
-    } else {
-      throw new UriParserSemanticException(
-          "Expected " + (keyPropertyRefs.size() -referencedNames.size()) + " 
key predicates but found one.",
-          
UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
-          Integer.toString(keyPropertyRefs.size() - referencedNames.size()), 
"1");
+    if (keyPropertyRefs.size() - referencedNames.size() == 1) {
+      for (final EdmKeyPropertyRef candidate : keyPropertyRefs) {
+        if (referencedNames.get(candidate.getName()) == null) {
+          final UriParameter simpleKey = simpleKey(tokenizer, candidate, edm, 
referringType, aliases);
+          if (simpleKey != null) {
+            keys.add(simpleKey);
+          }
+          break;
+        }
+      }
+    }
+    if (keys.isEmpty()) {
+      if (tokenizer.next(TokenKind.ODataIdentifier)) {
+        keys.addAll(compoundKey(tokenizer, edmEntityType, edm, referringType, 
aliases));
+      } else {
+        throw new UriParserSemanticException("The key value is not valid.",
+            UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, "");
+      }
     }
 
     if (keys.size() < keyPropertyRefs.size() && partner != null) {
@@ -346,42 +355,18 @@ public class ParserHelper {
     }
   }
 
-  private static UriParameter parseSimpleKey(final UriTokenizer tokenizer, 
final Edm edm, final EdmType referringType,
-                                             final Map<String, 
AliasQueryOption> aliases,
-                                             final List<EdmKeyPropertyRef> 
keyPropertyRefs,
-                                             final Map<String, String> 
referencedNames, final boolean tokenConsumed)
-      throws UriParserException, UriValidationException {
-
-    for (final EdmKeyPropertyRef candidate : keyPropertyRefs) {
-      if (referencedNames.get(candidate.getName()) == null) {
-        return simpleKey(tokenizer, candidate, edm, referringType, aliases, 
tokenConsumed);
-      }
-    }
-    throw new UriParserSemanticException("No suitable key found.",
-        UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
-        "0", String.valueOf(keyPropertyRefs.size()));
-  }
-
   private static UriParameter simpleKey(UriTokenizer tokenizer, final 
EdmKeyPropertyRef edmKeyPropertyRef,
-                                        final Edm edm, final EdmType 
referringType,
-                                        final Map<String, AliasQueryOption> 
aliases, final boolean tokenConsumed)
+      final Edm edm, final EdmType referringType, final Map<String, 
AliasQueryOption> aliases)
       throws UriParserException, UriValidationException {
     final EdmProperty edmProperty = edmKeyPropertyRef == null ? null : 
edmKeyPropertyRef.getProperty();
-    final EdmPrimitiveType primitiveType = edmProperty == null ? null : 
(EdmPrimitiveType) edmProperty.getType();
-    final boolean nullable = edmProperty != null && edmProperty.isNullable();
-
-    boolean primitiveTypeAvailable = tokenConsumed;
-    if(!tokenConsumed) {
-      primitiveTypeAvailable = nextPrimitiveTypeValue(tokenizer, 
primitiveType, nullable);
-    }
-    if (primitiveTypeAvailable) {
+    if (nextPrimitiveTypeValue(tokenizer,
+        edmProperty == null ? null : (EdmPrimitiveType) edmProperty.getType(),
+        edmProperty == null ? false : edmProperty.isNullable())) {
       final String literalValue = tokenizer.getText();
       ParserHelper.requireNext(tokenizer, TokenKind.CLOSE);
       return createUriParameter(edmProperty, edmKeyPropertyRef.getName(), 
literalValue, edm, referringType, aliases);
     } else {
-      String keyPropertyRefName = edmKeyPropertyRef == null ? "NULL 
EdmKeyPropertyRef" : edmKeyPropertyRef.getName();
-      throw new UriParserSemanticException("The key value is not valid.",
-          UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, 
keyPropertyRefName);
+      return null;
     }
   }
 
@@ -548,6 +533,27 @@ public class ParserHelper {
     return names;
   }
 
+  protected static EdmStructuredType parseTypeCast(UriTokenizer tokenizer, 
final Edm edm,
+      final EdmStructuredType referencedType) throws UriParserException {
+    if (tokenizer.next(TokenKind.QualifiedName)) {
+      final FullQualifiedName qualifiedName = new 
FullQualifiedName(tokenizer.getText());
+      final EdmStructuredType type = referencedType instanceof EdmEntityType ?
+          edm.getEntityType(qualifiedName) :
+          edm.getComplexType(qualifiedName);
+      if (type == null) {
+        throw new UriParserSemanticException("Type '" + qualifiedName + "' not 
found.",
+            UriParserSemanticException.MessageKeys.UNKNOWN_PART, 
qualifiedName.getFullQualifiedNameAsString());
+      } else {
+        if (!type.compatibleTo(referencedType)) {
+          throw new UriParserSemanticException("The type cast '" + 
qualifiedName + "' is not compatible.",
+              UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER, 
type.getName());
+        }
+      }
+      return type;
+    }
+    return null;
+  }
+
   protected static EdmType getTypeInformation(final UriResourcePartTyped 
resourcePart) {
     EdmType type = null;
     if (resourcePart instanceof UriResourceWithKeysImpl) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9333c090/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ExpandValidator.java
----------------------------------------------------------------------
diff --git 
a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ExpandValidator.java
 
b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ExpandValidator.java
index 35245b4..104b156 100644
--- 
a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ExpandValidator.java
+++ 
b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/testutil/ExpandValidator.java
@@ -109,12 +109,8 @@ public class ExpandValidator implements TestValidator {
 
   public ExpandValidator next() {
     expandItemIndex++;
-
-    try {
-      expandItem = expandOption.getExpandItems().get(expandItemIndex);
-    } catch (IndexOutOfBoundsException ex) {
-      fail("not enough segments");
-    }
+    assertTrue("not enough segments", expandItemIndex < 
expandOption.getExpandItems().size());
+    expandItem = expandOption.getExpandItems().get(expandItemIndex);
     return this;
   }
 

Reply via email to