You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ch...@apache.org on 2015/09/30 15:12:03 UTC

[1/3] olingo-odata4 git commit: [OLINGO-782] Functions with key predicates get validated

Repository: olingo-odata4
Updated Branches:
  refs/heads/master c66b65922 -> b9403cd39


[OLINGO-782] Functions with key predicates get validated


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

Branch: refs/heads/master
Commit: 64388ecf2bda2d4ed0854cc0addc8d2d65c62475
Parents: c66b659
Author: Christia Holzer <c....@sap.com>
Authored: Tue Sep 29 15:34:47 2015 +0200
Committer: Christia Holzer <c....@sap.com>
Committed: Wed Sep 30 15:04:22 2015 +0200

----------------------------------------------------------------------
 .../core/uri/parser/UriParseTreeVisitor.java    | 280 +++++++++++--------
 .../server/core/uri/validator/UriValidator.java |  23 +-
 .../server/core/PreconditionsValidatorTest.java |   2 +-
 .../core/uri/antlr/TestFullResourcePath.java    | 127 ++++++++-
 4 files changed, 305 insertions(+), 127 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/64388ecf/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
index bedfaf2..edd6058 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
@@ -40,16 +40,19 @@ import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
 import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmReturnType;
 import org.apache.olingo.commons.api.edm.EdmSingleton;
 import org.apache.olingo.commons.api.edm.EdmStructuredType;
 import org.apache.olingo.commons.api.edm.EdmType;
 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.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
 import org.apache.olingo.server.api.uri.UriInfoKind;
 import org.apache.olingo.server.api.uri.UriInfoResource;
 import org.apache.olingo.server.api.uri.UriResource;
 import org.apache.olingo.server.api.uri.UriResourceEntitySet;
+import org.apache.olingo.server.api.uri.UriResourceFunction;
 import org.apache.olingo.server.api.uri.UriResourceNavigation;
 import org.apache.olingo.server.api.uri.UriResourcePartTyped;
 import org.apache.olingo.server.api.uri.UriResourceRoot;
@@ -77,7 +80,9 @@ import org.apache.olingo.server.core.uri.UriResourceStartingTypeFilterImpl;
 import org.apache.olingo.server.core.uri.UriResourceTypedImpl;
 import org.apache.olingo.server.core.uri.UriResourceValueImpl;
 import org.apache.olingo.server.core.uri.UriResourceWithKeysImpl;
-import org.apache.olingo.server.core.uri.antlr.*;
+import org.apache.olingo.server.core.uri.antlr.UriLexer;
+import org.apache.olingo.server.core.uri.antlr.UriParserBaseVisitor;
+import org.apache.olingo.server.core.uri.antlr.UriParserParser;
 import org.apache.olingo.server.core.uri.antlr.UriParserParser.AllEOFContext;
 import org.apache.olingo.server.core.uri.antlr.UriParserParser.AllExprContext;
 import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltAddContext;
@@ -1564,6 +1569,7 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
   @Override
   public Object visitNameValueOptList(final NameValueOptListContext ctx) {
     if (ctx.vVO != null) {
+      // This branch is chosen if the key predicate is a common expression e.g. EntitySet(0)
 
       // is single key predicate without a name
       String valueText = ctx.vVO.getText();
@@ -1580,67 +1586,98 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
       if (!(last instanceof UriResourcePartTyped)) {
         throw wrap(new UriParserSemanticException("Parameters list on untyped resource path segment not allowed",
             UriParserSemanticException.MessageKeys.PARAMETERS_LIST_ONLY_FOR_TYPED_PARTS));
-      }
-      EdmEntityType lastType = (EdmEntityType) ((UriResourcePartTyped) last).getType();
-
-      // get list of keys for lastType
-      List<String> lastKeyPredicates = lastType.getKeyPredicateNames();
-
-      // If there is exactly one key defined in the EDM, then this key is the key written in the URI,
-      // so fill the keylist with this key and return.
-      if (lastKeyPredicates.size() == 1) {
-        return Collections.singletonList(new UriParameterImpl()
-            .setName(lastKeyPredicates.get(0))
-            .setText(valueText)
-            .setExpression(expression));
-      }
 
-      // There are more keys defined in the EDM, but only one is written in the URI. This is allowed only if
-      // referential constraints are defined on this navigation property which can be used to fill up all
-      // required keys.
-      // For using referential constraints the last resource part must be a navigation property.
-      if (!(context.contextUriInfo.getLastResourcePart() instanceof UriResourceNavigationPropertyImpl)) {
-        throw wrap(new UriParserSemanticException("Wrong number of key properties.",
-            UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
-            Integer.toString(lastKeyPredicates.size()), "1"));
-      }
-      UriResourceNavigationPropertyImpl lastNav = (UriResourceNavigationPropertyImpl) last;
+      } else if (last instanceof UriResourceFunction) {
+        // Handle functions
+        final UriResourceFunction uriResourceFunction =
+            (UriResourceFunction) context.contextUriInfo.getLastResourcePart();
+        final EdmReturnType returnType = uriResourceFunction.getFunction().getReturnType();
 
-      // get the partner of the navigation property
-      EdmNavigationProperty partner = lastNav.getProperty().getPartner();
-      if (partner == null) {
-        throw wrap(new UriParserSemanticException("Wrong number of key properties.",
-            UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
-            Integer.toString(lastKeyPredicates.size()), "1"));
-      }
+        if (returnType.getType().getKind() != EdmTypeKind.ENTITY || !returnType.isCollection()) {
+          throw wrap(new UriParserSemanticException("No keys allowed",
+              UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED));
+        } else {
+          // The functions returns a collection of entities
+          // Get the EDM Type and determine how many key predicates are needed. In this case only one 
+          // key predicate is allowed. If the entity type needs more than one key predicate, the client
+          // has to use the key value syntax e.g. EntitySet(ID=1,Order=2)
+          final EdmEntityType entityType = (EdmEntityType) uriResourceFunction.getFunction().getReturnType().getType();
+          final List<String> lastKeyPredicates = entityType.getKeyPredicateNames();
+
+          if (lastKeyPredicates.size() == 1) {
+            return Collections.singletonList(new UriParameterImpl()
+                .setName(lastKeyPredicates.get(0))
+                .setText(valueText)
+                .setExpression(expression));
+          } else {
+            throw wrap(new UriParserSemanticException("Wrong number of key properties.",
+                UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
+                Integer.toString(lastKeyPredicates.size()), "1"));
+          }
+        }
+      } else {
+        // Handle EntitySets
+        EdmEntityType lastType = (EdmEntityType) ((UriResourcePartTyped) last).getType();
+
+        // get list of keys for lastType
+        List<String> lastKeyPredicates = lastType.getKeyPredicateNames();
+
+        // If there is exactly one key defined in the EDM, then this key is the key written in the URI,
+        // so fill the keylist with this key and return.
+        if (lastKeyPredicates.size() == 1) {
+          return Collections.singletonList(new UriParameterImpl()
+              .setName(lastKeyPredicates.get(0))
+              .setText(valueText)
+              .setExpression(expression));
+        }
 
-      // create the keylist
-      List<UriParameterImpl> list = new ArrayList<UriParameterImpl>();
+        // There are more keys defined in the EDM, but only one is written in the URI. This is allowed only if
+        // referential constraints are defined on this navigation property which can be used to fill up all
+        // required keys.
+        // For using referential constraints the last resource part must be a navigation property.
+        if (!(context.contextUriInfo.getLastResourcePart() instanceof UriResourceNavigationPropertyImpl)) {
+          throw wrap(new UriParserSemanticException("Wrong number of key properties.",
+              UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
+              Integer.toString(lastKeyPredicates.size()), "1"));
+        }
+        UriResourceNavigationPropertyImpl lastNav = (UriResourceNavigationPropertyImpl) last;
+
+        // get the partner of the navigation property
+        EdmNavigationProperty partner = lastNav.getProperty().getPartner();
+        if (partner == null) {
+          throw wrap(new UriParserSemanticException("Wrong number of key properties.",
+              UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
+              Integer.toString(lastKeyPredicates.size()), "1"));
+        }
 
-      // Find the keys not filled by referential constraints
-      // and collect the other keys filled by referential constraints.
-      String missedKey = null;
-      for (String item : lastKeyPredicates) {
-        String property = partner.getReferencingPropertyName(item);
-        if (property != null) {
-          list.add(new UriParameterImpl().setName(item).setRefencedProperty(property));
-        } else {
-          if (missedKey == null) {
-            missedKey = item;
+        // create the keylist
+        List<UriParameterImpl> list = new ArrayList<UriParameterImpl>();
+
+        // Find the keys not filled by referential constraints
+        // and collect the other keys filled by referential constraints.
+        String missedKey = null;
+        for (String item : lastKeyPredicates) {
+          String property = partner.getReferencingPropertyName(item);
+          if (property != null) {
+            list.add(new UriParameterImpl().setName(item).setRefencedProperty(property));
           } else {
-            // two of more keys are missing
-            throw wrap(new UriParserSemanticException("Not enough referential constraints defined",
-                UriParserSemanticException.MessageKeys.NOT_ENOUGH_REFERENTIAL_CONSTRAINTS));
+            if (missedKey == null) {
+              missedKey = item;
+            } else {
+              // two of more keys are missing
+              throw wrap(new UriParserSemanticException("Not enough referential constraints defined",
+                  UriParserSemanticException.MessageKeys.NOT_ENOUGH_REFERENTIAL_CONSTRAINTS));
+            }
           }
         }
-      }
 
-      // the missing key is the one which is defined in the URI
-      list.add(new UriParameterImpl().setName(missedKey).setText(valueText).setExpression(expression));
+        // the missing key is the one which is defined in the URI
+        list.add(new UriParameterImpl().setName(missedKey).setText(valueText).setExpression(expression));
 
-      return list;
+        return list;
+      }
     } else if (ctx.vNVL != null) {
-
+      // The client provided a list of key values pairs e.g. EntitySet(ID=1,Order=2)
       List<UriParameterImpl> list = new ArrayList<UriParameterImpl>();
 
       for (ParseTree c : ctx.vNVL.vlNVP) {
@@ -1652,83 +1689,102 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
       }
 
       UriResource last = context.contextUriInfo.getLastResourcePart();
-      // if the last resource part is a function
-      /*
-       * if (last instanceof UriResourceFunctionImpl) {
-       * UriResourceFunctionImpl function = (UriResourceFunctionImpl) last;
-       * if (!function.isParameterListFilled()) {
-       * return list;
-       * }
-       * }
-       */
 
       // get type of last resource part
       if (!(last instanceof UriResourcePartTyped)) {
         throw wrap(new UriParserSemanticException("Parameters list on untyped resource path segment not allowed",
             UriParserSemanticException.MessageKeys.PARAMETERS_LIST_ONLY_FOR_TYPED_PARTS));
       }
-      EdmEntityType lastType = (EdmEntityType) ((UriResourcePartTyped) last).getType();
-
-      // get list of keys for lastType
-      List<String> lastKeyPredicates = lastType.getKeyPredicateNames();
-
-      // check if all key are filled from the URI
-      if (list.size() == lastKeyPredicates.size()) {
-        return list;
-      }
+      if(last instanceof UriResourceFunction) {
+        final UriResourceFunction uriResourceFunction = (UriResourceFunction) context.contextUriInfo
+            .getLastResourcePart();
+        final EdmReturnType returnType = uriResourceFunction.getFunction().getReturnType();
 
-      // if not, check if the missing key predicates can be satisfied with help of the defined
-      // referential constraints
-      // for using referential constraints the last resource part must be a navigation property
-      if (!(context.contextUriInfo.getLastResourcePart() instanceof UriResourceNavigationPropertyImpl)) {
-        throw wrap(new UriParserSemanticException("Wrong number of key properties.",
-            UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
-            Integer.toString(lastKeyPredicates.size()), Integer.toString(list.size())));
-      }
-      UriResourceNavigationPropertyImpl lastNav = (UriResourceNavigationPropertyImpl) last;
-
-      // get the partner of the navigation property
-      EdmNavigationProperty partner = lastNav.getProperty().getPartner();
-      if (partner == null) {
-        throw wrap(new UriParserSemanticException("Wrong number of key properties.",
-            UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
-            Integer.toString(lastKeyPredicates.size()), Integer.toString(list.size())));
-      }
-
-      // fill missing keys from referential constraints
-      for (String key : lastKeyPredicates) {
-        boolean found = false;
-        for (UriParameterImpl item : list) {
-          if (item.getName().equals(key)) {
-            found = true;
-            break;
+        if (returnType.getType().getKind() != EdmTypeKind.ENTITY || !returnType.isCollection()) {
+          throw wrap(new UriParserSemanticException("No keys allowed",
+              UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED));
+        } else {
+          // The functions returns a collection of entities
+          // Get the EDM Type and determine how many key predicates are needed. 
+          // In case of functions all key predicates must be provided by the client.
+          final EdmEntityType entityType = (EdmEntityType) uriResourceFunction.getFunction().getReturnType().getType();
+          final List<String> lastKeyPredicates = entityType.getKeyPredicateNames();
+          
+          if(lastKeyPredicates.size() == list.size()) {
+            return list;
+          } else {
+            throw wrap(new UriParserSemanticException("Wrong number of key properties.",
+                UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
+                Integer.toString(lastKeyPredicates.size()), "1"));
           }
         }
-
-        if (!found) {
-          String property = partner.getReferencingPropertyName(key);
-          if (property != null) {
-            // store the key name as referenced property
-            list.add(0, new UriParameterImpl().setName(key).setRefencedProperty(property));
+      } else {
+        // Handle entity sets
+        EdmEntityType lastType = (EdmEntityType) ((UriResourcePartTyped) last).getType();
+  
+        // get list of keys for lastType
+        List<String> lastKeyPredicates = lastType.getKeyPredicateNames();
+  
+        // check if all key are filled from the URI
+        if (list.size() == lastKeyPredicates.size()) {
+          return list;
+        }
+  
+        // if not, check if the missing key predicates can be satisfied with help of the defined
+        // referential constraints
+        // for using referential constraints the last resource part must be a navigation property
+        if (!(context.contextUriInfo.getLastResourcePart() instanceof UriResourceNavigationPropertyImpl)) {
+          throw wrap(new UriParserSemanticException("Wrong number of key properties.",
+              UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
+              Integer.toString(lastKeyPredicates.size()), Integer.toString(list.size())));
+        }
+        UriResourceNavigationPropertyImpl lastNav = (UriResourceNavigationPropertyImpl) last;
+  
+        // get the partner of the navigation property
+        EdmNavigationProperty partner = lastNav.getProperty().getPartner();
+        if (partner == null) {
+          throw wrap(new UriParserSemanticException("Wrong number of key properties.",
+              UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
+              Integer.toString(lastKeyPredicates.size()), Integer.toString(list.size())));
+        }
+  
+        // fill missing keys from referential constraints
+        for (String key : lastKeyPredicates) {
+          boolean found = false;
+          for (UriParameterImpl item : list) {
+            if (item.getName().equals(key)) {
+              found = true;
+              break;
+            }
+          }
+  
+          if (!found) {
+            String property = partner.getReferencingPropertyName(key);
+            if (property != null) {
+              // store the key name as referenced property
+              list.add(0, new UriParameterImpl().setName(key).setRefencedProperty(property));
+            }
           }
         }
-      }
-
-      // check again if all key predicates are filled from the URI
-      if (list.size() == lastKeyPredicates.size()) {
-        return list;
-      } else {
-        throw wrap(new UriParserSemanticException("Wrong number of key properties.",
-            UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
-            Integer.toString(lastKeyPredicates.size()), Integer.toString(list.size())));
+  
+        // check again if all key predicates are filled from the URI
+        if (list.size() == lastKeyPredicates.size()) {
+          return list;
+        } else {
+          throw wrap(new UriParserSemanticException("Wrong number of key properties.",
+              UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES,
+              Integer.toString(lastKeyPredicates.size()), Integer.toString(list.size())));
+        }
       }
     } else {
+      // No key predicates are provided by the client
+      
       if (context.contextReadingFunctionParameters) {
         return Collections.emptyList();
       } else {
         final UriResource last = context.contextUriInfo.getLastResourcePart();
-        final int number = last instanceof UriResourcePartTyped ?
-            ((EdmEntityType) ((UriResourcePartTyped) last).getType()).getKeyPredicateNames().size() : 0;
+        final int number = last instanceof UriResourcePartTyped ? ((EdmEntityType) ((UriResourcePartTyped) last)
+            .getType()).getKeyPredicateNames().size() : 0;
         throw wrap(new UriParserSemanticException("Wrong number of key properties.",
             UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES, Integer.toString(number), "0"));
       }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/64388ecf/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
index d793b5c..8693f1e 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
@@ -527,16 +527,20 @@ public class UriValidator {
   private void validateKeyPredicates(final UriInfo uriInfo) throws UriValidationException {
     for (UriResource pathSegment : uriInfo.getUriResourceParts()) {
       final boolean isEntitySet = pathSegment.getKind() == UriResourceKind.entitySet;
-      if (isEntitySet || pathSegment.getKind() == UriResourceKind.navigationProperty) {
+      final boolean isEntityColFunction = isEntityColFunction(pathSegment);
+      
+      if (isEntitySet || pathSegment.getKind() == UriResourceKind.navigationProperty || isEntityColFunction) {
         final List<UriParameter> keyPredicates = isEntitySet ?
             ((UriResourceEntitySet) pathSegment).getKeyPredicates() :
-            ((UriResourceNavigation) pathSegment).getKeyPredicates();
-
+              isEntityColFunction ? ((UriResourceFunction) pathSegment).getKeyPredicates()
+              : ((UriResourceNavigation) pathSegment).getKeyPredicates();
+            
         if (keyPredicates != null) {
 
           final EdmEntityType entityType = isEntitySet ?
               ((UriResourceEntitySet) pathSegment).getEntityType() :
-              (EdmEntityType) ((UriResourceNavigation) pathSegment).getType();
+              isEntityColFunction ? (EdmEntityType) ((UriResourceFunction) pathSegment).getType() 
+              : (EdmEntityType) ((UriResourceNavigation) pathSegment).getType();
           final List<String> keyPredicateNames = entityType.getKeyPredicateNames();
           Map<String, EdmKeyPropertyRef> edmKeys = new HashMap<String, EdmKeyPropertyRef>();
           for (EdmKeyPropertyRef key : entityType.getKeyPropertyRefs()) {
@@ -590,6 +594,17 @@ public class UriValidator {
     }
   }
 
+  private boolean isEntityColFunction(final UriResource pathSegment) {
+    if(pathSegment.getKind() == UriResourceKind.function) {
+      final UriResourceFunction resourceFunction = (UriResourceFunction) pathSegment;
+      final EdmReturnType returnType = resourceFunction.getFunction().getReturnType();
+      
+      return returnType.isCollection() && returnType.getType().getKind() == EdmTypeKind.ENTITY;
+    } else {
+      return false;
+    }
+  }
+  
   private void validatePropertyOperations(final UriInfo uriInfo, final HttpMethod method)
       throws UriValidationException {
     final List<UriResource> parts = uriInfo.getUriResourceParts();

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/64388ecf/lib/server-test/src/test/java/org/apache/olingo/server/core/PreconditionsValidatorTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/PreconditionsValidatorTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/PreconditionsValidatorTest.java
index e2fe3ac..cf56edf 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/PreconditionsValidatorTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/PreconditionsValidatorTest.java
@@ -96,7 +96,7 @@ public class PreconditionsValidatorTest {
 
   @Test
   public void navigationOnFunction() throws Exception {
-    assertTrue(mustValidate("FICRTESTwoKeyNav()(PropertyInt16=1,PropertyString='1')/NavPropertySINav", "SINav"));
+    assertTrue(mustValidate("FICRTESTwoKeyNav()/NavPropertySINav", "SINav"));
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/64388ecf/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
index 4cd015a..9c859db 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
@@ -1033,6 +1033,118 @@ public class TestFullResourcePath {
   }
   
   @Test
+  public void runFunctionsWithKeyPredicates() throws Exception {
+    testUri.run("FICRTCollETMixPrimCollCompTwoParam(ParameterString='1',ParameterInt16=1)")
+      .isKind(UriInfoKind.resource)
+      .goPath().first()
+      .isFunctionImport("FICRTCollETMixPrimCollCompTwoParam")
+      .isFunction("UFCRTCollETMixPrimCollCompTwoParam")
+      .isParameter(0, "ParameterString", "'1'")
+      .isParameter(1, "ParameterInt16", "1");
+    
+    testUri.run("FICRTCollETMixPrimCollCompTwoParam(ParameterString='1',ParameterInt16=1)(PropertyInt16=0)")
+     .isKind(UriInfoKind.resource)
+     .goPath().first()
+     .isFunctionImport("FICRTCollETMixPrimCollCompTwoParam")
+     .isFunction("UFCRTCollETMixPrimCollCompTwoParam")
+     .isParameter(0, "ParameterString", "'1'")
+     .isParameter(1, "ParameterInt16", "1")
+     .isKeyPredicate(0, "PropertyInt16", "0");
+    
+    testUri.run("FICRTCollETMixPrimCollCompTwoParam(ParameterString='1',ParameterInt16=1)(0)")
+      .isKind(UriInfoKind.resource)
+      .goPath().first()
+      .isFunctionImport("FICRTCollETMixPrimCollCompTwoParam")
+      .isFunction("UFCRTCollETMixPrimCollCompTwoParam")
+      .isParameter(0, "ParameterString", "'1'")
+      .isParameter(1, "ParameterInt16", "1")
+      .isKeyPredicate(0, "PropertyInt16", "0");
+    
+    testUri.runEx("FICRTCollETMixPrimCollCompTwoParam(ParameterString='1',ParameterInt16=1)(PropertyInt16 eq 0)")
+      .isExSemantic(MessageKeys.INVALID_KEY_VALUE);
+    
+    // PropertyInt32 does not exist
+    testUri.runEx("FICRTCollETMixPrimCollCompTwoParam(ParameterString='1',ParameterInt16=1)(PropertyInt32=0)")
+      .isExValidation(UriValidationException.MessageKeys.INVALID_KEY_PROPERTY);
+    
+    testUri.runEx("FICRTCollETMixPrimCollCompTwoParam(ParameterString='1',ParameterInt16=1)" 
+        + "(PropertyInt16=0,PropertyInt16=1)")
+    .isExSemantic(MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES);
+  
+    testUri.run("FICRTCollCTTwoPrimTwoParam(ParameterString='1',ParameterInt16=1)")
+      .isKind(UriInfoKind.resource)
+      .goPath().first()
+      .isFunctionImport("FICRTCollCTTwoPrimTwoParam")
+      .isFunction("UFCRTCollCTTwoPrimTwoParam")
+      .isParameter(0, "ParameterString", "'1'")
+      .isParameter(1, "ParameterInt16", "1");
+    
+    testUri.runEx("FICRTCollCTTwoPrimTwoParam(ParameterString='1',ParameterInt16=1)(PropertyInt16=1)")
+      .isExSemantic(MessageKeys.KEY_NOT_ALLOWED);
+    
+    testUri.runEx("FICRTCollCTTwoPrimTwoParam(ParameterString='1',ParameterInt16=1)(1)")
+      .isExSemantic(MessageKeys.KEY_NOT_ALLOWED);
+    
+    testUri.runEx("FICRTCollCTTwoPrimTwoParam(ParameterString='1',ParameterInt16=1)(PropertyInt32=1)")
+      .isExSemantic(MessageKeys.KEY_NOT_ALLOWED);
+    
+    testUri.runEx("FICRTCollCTTwoPrimTwoParam(ParameterString='1',ParameterInt16=1)(PropertyInt32=1,PropertyInt16=2)")
+      .isExSemantic(MessageKeys.KEY_NOT_ALLOWED);
+    
+    testUri.run("FICRTCollESTwoKeyNavParam(ParameterInt16=1)")
+      .isKind(UriInfoKind.resource)
+      .goPath().first()
+      .isFunctionImport("FICRTCollESTwoKeyNavParam")
+      .isFunction("UFCRTCollETTwoKeyNavParam")
+      .isParameter(0, "ParameterInt16", "1");
+    
+    testUri.run("FICRTCollESTwoKeyNavParam(ParameterInt16=1)(PropertyInt16=1,PropertyString='1')")
+      .isKind(UriInfoKind.resource)
+      .goPath().first()
+      .isFunctionImport("FICRTCollESTwoKeyNavParam")
+      .isFunction("UFCRTCollETTwoKeyNavParam")
+      .isParameter(0, "ParameterInt16", "1")
+      .isKeyPredicate(0, "PropertyInt16", "1")
+      .isKeyPredicate(1,"PropertyString", "'1'");
+    
+    testUri.runEx("FICRTCollESTwoKeyNavParam(ParameterInt16=1)(PropertyInt16 eq 1)")
+      .isExSemantic(MessageKeys.INVALID_KEY_VALUE);
+    
+    testUri.runEx("FICRTCollESTwoKeyNavParam(ParameterInt16=1)(PropertyInt16=1)")
+      .isExSemantic(MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES);
+    
+    testUri.runEx("FICRTCollESTwoKeyNavParam(ParameterInt16=1)(PropertyInt16=1,PropertyInt32=1,PropertyString='1')")
+      .isExSemantic(MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES);
+    
+    testUri.runEx("FICRTCollESTwoKeyNavParam(ParameterInt16=1)()")
+      .isExSemantic(MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES);
+    
+    testUri.runEx("FICRTCollESTwoKeyNavParam(ParameterInt16=1)(PropertyInt16=1,PropertyInt32=1)")
+      .isExValidation(UriValidationException.MessageKeys.INVALID_KEY_PROPERTY);
+    
+    testUri.runEx("FICRTCollESTwoKeyNavParam(ParameterInt16=1)(PropertyInt16=1,Unkown=1)")
+    .isExValidation(UriValidationException.MessageKeys.INVALID_KEY_PROPERTY);
+    
+    testUri.run("FICRTCollString()")
+      .isKind(UriInfoKind.resource)
+      .goPath().first()
+      .isFunctionImport("FICRTCollString")
+      .isFunction("UFCRTCollString");
+    
+    testUri.run("FICRTString()")
+      .isKind(UriInfoKind.resource)
+      .goPath().first()
+      .isFunctionImport("FICRTString")
+      .isFunction("UFCRTString");
+    
+    testUri.runEx("FICRTCollString()(0)")
+      .isExSemantic(MessageKeys.KEY_NOT_ALLOWED);
+    
+    testUri.runEx("FICRTString()(0)")
+      .isExSemantic(MessageKeys.KEY_NOT_ALLOWED);
+  }
+  
+  @Test
   public void runEsNameCast() throws Exception {
     testUri.run("ESTwoPrim/olingo.odata.test1.ETBase")
     .isKind(UriInfoKind.resource).goPath()
@@ -1759,14 +1871,12 @@ public class TestFullResourcePath {
     .isFunctionImport("FICRTETKeyNav")
     .isFunction("UFCRTETKeyNav")
     .isType(EntityTypeProvider.nameETKeyNav);
-
-    testUri.run("FICRTETTwoKeyNavParam(ParameterInt16=1)(PropertyInt16=2,PropertyString='3')")
+    
+    testUri.run("FICRTETTwoKeyNavParam(ParameterInt16=1)")
     .isKind(UriInfoKind.resource).goPath()
     .first()
     .isFunctionImport("FICRTETTwoKeyNavParam")
-    .isParameter(0, "ParameterInt16", "1")
-    .isKeyPredicate(0, "PropertyInt16", "2")
-    .isKeyPredicate(1, "PropertyString", "'3'");
+    .isParameter(0, "ParameterInt16", "1");
 
     testUri.run("FICRTESMedia(ParameterInt16=1)/$value")
     .isKind(UriInfoKind.resource).goPath()
@@ -1799,16 +1909,13 @@ public class TestFullResourcePath {
     .isParameter(0, "ParameterInt16", "1")
     .isType(EntityTypeProvider.nameETTwoKeyNav)
     .isTypeFilterOnEntry(EntityTypeProvider.nameETBaseTwoKeyNav);
-
-    testUri.run("FICRTETTwoKeyNavParam(ParameterInt16=1)(PropertyInt16=2,PropertyString='3')"
-            + "/olingo.odata.test1.ETBaseTwoKeyNav")
+    
+    testUri.run("FICRTETTwoKeyNavParam(ParameterInt16=1)/olingo.odata.test1.ETBaseTwoKeyNav")
         .isKind(UriInfoKind.resource).goPath()
         .first()
         .isFunctionImport("FICRTETTwoKeyNavParam")
         .isFunction("UFCRTETTwoKeyNavParam")
         .isParameter(0, "ParameterInt16", "1")
-        .isKeyPredicate(0, "PropertyInt16", "2")
-        .isKeyPredicate(1, "PropertyString", "'3'")
         .isType(EntityTypeProvider.nameETTwoKeyNav)
         .isTypeFilterOnEntry(EntityTypeProvider.nameETBaseTwoKeyNav);
 


[3/3] olingo-odata4 git commit: [OLINGO-780] The URI Parser validates if a function is composable or not

Posted by ch...@apache.org.
[OLINGO-780] The URI Parser validates if a function is composable or not


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

Branch: refs/heads/master
Commit: b9403cd39433ba6d66054c92d02974e3187f401f
Parents: b7dcae8
Author: Christia Holzer <c....@sap.com>
Authored: Wed Sep 30 11:22:29 2015 +0200
Committer: Christia Holzer <c....@sap.com>
Committed: Wed Sep 30 15:04:24 2015 +0200

----------------------------------------------------------------------
 .../uri/validator/UriValidationException.java   |  4 +-
 .../server/core/uri/validator/UriValidator.java | 36 ++++++++++-
 .../server-core-exceptions-i18n.properties      |  1 +
 .../tecsvc/provider/FunctionProvider.java       |  2 +-
 .../olingo/server/core/ODataHandlerTest.java    | 24 ++++---
 .../core/uri/antlr/TestFullResourcePath.java    | 66 ++++++++++++++++++++
 6 files changed, 120 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b9403cd3/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidationException.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidationException.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidationException.java
index 5760e88..d883b0c 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidationException.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidationException.java
@@ -52,7 +52,9 @@ public class UriValidationException extends ODataLibraryException {
     /** parameter: unallowed kind before $value */
     UNALLOWED_KIND_BEFORE_VALUE,
     /** parameter: unallowed kind before $count */
-    UNALLOWED_KIND_BEFORE_COUNT;
+    UNALLOWED_KIND_BEFORE_COUNT, 
+    /** parameter: unallowed resource path */
+    UNALLOWED_RESOURCE_PATH;
 
     @Override
     public String getKey() {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b9403cd3/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
index 8693f1e..feb52ec 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
@@ -222,7 +222,14 @@ public class UriValidator {
 
   private RowIndexForUriType rowIndexForResourceKind(final UriInfo uriInfo) throws UriValidationException {
     RowIndexForUriType idx;
-
+    
+    final int nonComposableFunctionIndex = getIndexOfLastNonComposableFunction(uriInfo);
+    if(nonComposableFunctionIndex != -1 && (uriInfo.getUriResourceParts().size() - 1) > nonComposableFunctionIndex) {
+      throw new UriValidationException("Non composable functions followed by further resource parts are not allowed", 
+          UriValidationException.MessageKeys.UNALLOWED_RESOURCE_PATH, 
+          uriInfo.getUriResourceParts().get(nonComposableFunctionIndex + 1).getSegmentValue());
+    }
+    
     int lastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 1;
     UriResource lastPathSegment = uriInfo.getUriResourceParts().get(lastPathSegmentIndex);
 
@@ -241,7 +248,11 @@ public class UriValidator {
       idx = rowIndexForEntitySet(lastPathSegment);
       break;
     case function:
-      idx = rowIndexForFunction(lastPathSegment);
+      if(nonComposableFunctionIndex == -1) {
+        idx = rowIndexForFunction(lastPathSegment);
+      } else {
+        idx = RowIndexForUriType.none;
+      }
       break;
     case primitiveProperty:
       idx = rowIndexForPrimitiveProperty(lastPathSegment);
@@ -266,6 +277,21 @@ public class UriValidator {
     return idx;
   }
 
+  private int getIndexOfLastNonComposableFunction(final UriInfo uriInfo) {
+    for(int i = 0; i < uriInfo.getUriResourceParts().size(); i++) {
+      final UriResource resourcePath = uriInfo.getUriResourceParts().get(i);
+      
+      if(resourcePath instanceof UriResourceFunction) {
+        final UriResourceFunction resourceFuntion = (UriResourceFunction) resourcePath;
+        if(!resourceFuntion.getFunction().isComposable()) {
+          return i;
+        }
+      }
+    }
+    
+    return -1;
+  }
+
   private RowIndexForUriType rowIndexForValue(final UriInfo uriInfo) throws UriValidationException {
     RowIndexForUriType idx;
     int secondLastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 2;
@@ -327,6 +353,12 @@ public class UriValidator {
     RowIndexForUriType idx;
     UriResourceFunction urf = (UriResourceFunction) lastPathSegment;
     EdmReturnType rt = urf.getFunction().getReturnType();
+
+    if(!urf.getFunction().isComposable()) {
+      return RowIndexForUriType.none;
+    }
+    
+    
     switch (rt.getType().getKind()) {
     case ENTITY:
       idx = rt.isCollection() && urf.getKeyPredicates().isEmpty() ?

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b9403cd3/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
index f7c2894..de14eb0 100644
--- a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
+++ b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
@@ -81,6 +81,7 @@ UriValidationException.LAST_SEGMENT_NOT_TYPED=The last segment '%1$s' is not typ
 UriValidationException.SECOND_LAST_SEGMENT_NOT_TYPED=The second last segment '%1$s' is not typed.
 UriValidationException.UNALLOWED_KIND_BEFORE_VALUE=The kind '%1$s' is not allowed before '$value'.
 UriValidationException.UNALLOWED_KIND_BEFORE_COUNT=The kind '%1$s' is not allowed before '$count'.
+UriValidationException.UNALLOWED_RESOURCE_PATH=The resource part '%1$s' is not allowed.
 
 ContentNegotiatorException.UNSUPPORTED_ACCEPT_TYPES=The content-type range '%1$s' is not supported as value of the Accept header.
 ContentNegotiatorException.UNSUPPORTED_CONTENT_TYPE=The content type '%1$s' is not supported.

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b9403cd3/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java
index df4cfbd..a83abab 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java
@@ -574,7 +574,7 @@ public class FunctionProvider {
               .setParameters(Arrays.asList(
                   new CsdlParameter().setName("BindingParam").setType(EntityTypeProvider.nameETBaseTwoKeyNav)
                       .setCollection(true).setNullable(false)))
-              .setComposable(true)
+              .setComposable(false)
               .setReturnType(
                   new CsdlReturnType().setType(EntityTypeProvider.nameETBaseTwoKeyNav).setCollection(true)
                       .setNullable(false))

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b9403cd3/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
index 76b7b50..d4b87d4 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
@@ -318,17 +318,16 @@ public class ODataHandlerTest {
     dispatch(HttpMethod.GET, "FICRTString()", primitiveProcessor);
     verify(primitiveProcessor).readPrimitive(
         any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
-
+    
+    // FINRTInt16 is not composable so /$value is not allowed
     final String valueUri = "FINRTInt16()/$value";
     final PrimitiveValueProcessor primitiveValueProcessor = mock(PrimitiveValueProcessor.class);
-    dispatch(HttpMethod.GET, valueUri, primitiveValueProcessor);
-    verify(primitiveValueProcessor).readPrimitiveValue(
-        any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
-    dispatchMethodNotAllowed(HttpMethod.POST, valueUri, primitiveValueProcessor);
-    dispatchMethodNotAllowed(HttpMethod.PATCH, valueUri, primitiveValueProcessor);
-    dispatchMethodNotAllowed(HttpMethod.PUT, valueUri, primitiveValueProcessor);
-    dispatchMethodNotAllowed(HttpMethod.DELETE, valueUri, primitiveValueProcessor);
-
+    dispatchMethodWithError(HttpMethod.GET, valueUri, primitiveValueProcessor, HttpStatusCode.BAD_REQUEST);
+    dispatchMethodWithError(HttpMethod.POST, valueUri, primitiveValueProcessor, HttpStatusCode.BAD_REQUEST);
+    dispatchMethodWithError(HttpMethod.PATCH, valueUri, primitiveValueProcessor, HttpStatusCode.BAD_REQUEST);
+    dispatchMethodWithError(HttpMethod.PUT, valueUri, primitiveValueProcessor, HttpStatusCode.BAD_REQUEST);
+    dispatchMethodWithError(HttpMethod.DELETE, valueUri, primitiveValueProcessor, HttpStatusCode.BAD_REQUEST);
+    
     final String primitiveCollectionUri = "FICRTCollString()";
     PrimitiveCollectionProcessor primitiveCollectionProcessor = mock(PrimitiveCollectionProcessor.class);
     dispatch(HttpMethod.GET, primitiveCollectionUri, primitiveCollectionProcessor);
@@ -759,4 +758,11 @@ public class ODataHandlerTest {
     assertEquals(HttpStatusCode.METHOD_NOT_ALLOWED.getStatusCode(), response.getStatusCode());
     assertNotNull(response.getContent());
   }
+  
+  private void dispatchMethodWithError(final HttpMethod method, final String path, final Processor processor, 
+      final HttpStatusCode statusCode) {
+    final ODataResponse response = dispatch(method, path, processor);
+    assertEquals(statusCode.getStatusCode(), response.getStatusCode());
+    assertNotNull(response.getContent());
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b9403cd3/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
index 9c859db..5c06e2c 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java
@@ -1145,6 +1145,72 @@ public class TestFullResourcePath {
   }
   
   @Test
+  public void runNonComposableFunctions() throws Exception {
+    testUri.run("FICRTCollETMixPrimCollCompTwoParam(ParameterInt16=1,ParameterString='1')")
+      .isKind(UriInfoKind.resource)
+      .goPath().first()
+      .isFunctionImport("FICRTCollETMixPrimCollCompTwoParam")
+      .isFunction("UFCRTCollETMixPrimCollCompTwoParam")
+      .isParameter(0, "ParameterInt16", "1")
+      .isParameter(1, "ParameterString", "'1'");
+    
+    testUri.run("FICRTCollETMixPrimCollCompTwoParam(ParameterInt16=1,ParameterString='1')(0)")
+      .isKind(UriInfoKind.resource)
+      .goPath().first()
+      .isFunctionImport("FICRTCollETMixPrimCollCompTwoParam")
+      .isFunction("UFCRTCollETMixPrimCollCompTwoParam")
+      .isParameter(0, "ParameterInt16", "1")
+      .isParameter(1, "ParameterString", "'1'");
+    
+    testUri.runEx("FICRTCollETMixPrimCollCompTwoParam(ParameterInt16=1,ParameterString='1')(0)/PropertyInt16")
+      .isExValidation(UriValidationException.MessageKeys.UNALLOWED_RESOURCE_PATH);
+    
+    testUri.runEx("FICRTCollETMixPrimCollCompTwoParam(ParameterInt16=1,ParameterString='1')", "$skip=1")
+      .isExValidation(UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED);
+    
+    testUri.runEx("FICRTCollETMixPrimCollCompTwoParam(ParameterInt16=1,ParameterString='1')", "$top=1")
+    .isExValidation(UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED);
+    
+    testUri.runEx("FICRTCollETMixPrimCollCompTwoParam(ParameterInt16=1,ParameterString='1')", 
+        "$filter=PropertyInt16 eq 1")
+    .isExValidation(UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED);
+    
+    testUri.runEx("FICRTCollETMixPrimCollCompTwoParam(ParameterInt16=1,ParameterString='1')", "$skip=1")
+    .isExValidation(UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED);
+    
+    testUri.runEx("FICRTCollETMixPrimCollCompTwoParam(ParameterInt16=1,ParameterString='1')", "$count=true")
+    .isExValidation(UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED);
+    
+    testUri.runEx("FICRTCollETMixPrimCollCompTwoParam(ParameterInt16=1,ParameterString='1')", "$skiptoken=5")
+    .isExValidation(UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED);
+    
+    // $search is currently not implemented. Please change this exception if the implementation is done.
+    testUri.runEx("FICRTCollETMixPrimCollCompTwoParam(ParameterInt16=1,ParameterString='1')", "$search=test")
+      .isExSemantic(MessageKeys.NOT_IMPLEMENTED);
+    
+    testUri.run("ESBaseTwoKeyNav/olingo.odata.test1.BFCESBaseTwoKeyNavRTESBaseTwoKey()")
+      .isKind(UriInfoKind.resource)
+      .goPath().first()
+      .isEntitySet("ESBaseTwoKeyNav")
+      .at(1)
+      .isFunction("BFCESBaseTwoKeyNavRTESBaseTwoKey");
+    
+    testUri.run("ESBaseTwoKeyNav/olingo.odata.test1.BFCESBaseTwoKeyNavRTESBaseTwoKey()" 
+        + "(PropertyInt16=1,PropertyString='1')")
+      .isKind(UriInfoKind.resource)
+      .goPath().first()
+      .isEntitySet("ESBaseTwoKeyNav")
+      .at(1)
+      .isFunction("BFCESBaseTwoKeyNavRTESBaseTwoKey")
+      .isKeyPredicate(0, "PropertyInt16", "1")
+      .isKeyPredicate(1, "PropertyString", "'1'");
+    
+    testUri.runEx("ESBaseTwoKeyNav/olingo.odata.test1.BFCESBaseTwoKeyNavRTESBaseTwoKey()" 
+          + "(PropertyInt16=1,PropertyString='1')/NavPropertyETBaseTwoKeyNavOne")
+      .isExValidation(UriValidationException.MessageKeys.UNALLOWED_RESOURCE_PATH);
+  }
+  
+  @Test
   public void runEsNameCast() throws Exception {
     testUri.run("ESTwoPrim/olingo.odata.test1.ETBase")
     .isKind(UriInfoKind.resource).goPath()


[2/3] olingo-odata4 git commit: [OLINGO-781] TecSvc: The atom id for functions without entity set is calculated by the URI of the function

Posted by ch...@apache.org.
[OLINGO-781] TecSvc: The atom id for functions without entity set is
calculated by the URI of the function


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

Branch: refs/heads/master
Commit: b7dcae862ae226b1f2da43270418e14199af1a06
Parents: 64388ec
Author: Christia Holzer <c....@sap.com>
Authored: Tue Sep 29 15:44:10 2015 +0200
Committer: Christia Holzer <c....@sap.com>
Committed: Wed Sep 30 15:04:23 2015 +0200

----------------------------------------------------------------------
 .../server/tecsvc/processor/TechnicalEntityProcessor.java   | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b7dcae86/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
index 59d9a2a..b9afddd 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
@@ -506,8 +506,15 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
         expand);
     expandHandler.applyExpandQueryOptions(entitySetSerialization, edmEntitySet, expand);
     final CountOption countOption = uriInfo.getCountOption();
+    
+    String id;
+    if(edmEntitySet == null) {
+      // Used for functions, function imports etc.
+      id = request.getRawODataPath();
+    } else {
+      id = request.getRawBaseUri() + edmEntitySet.getName();
+    }
 
-    final String id = request.getRawBaseUri() + edmEntitySet.getName();
     // Serialize
     final SerializerResult serializerResult = (isReference) ?
         serializeReferenceCollection(entitySetSerialization, edmEntitySet, requestedContentType, countOption) :