Repository: olingo-odata4
Updated Branches:
  refs/heads/master fd71b7ebd -> 53881c2ac


[OLINGO-663] Generic Precondition Required Handling


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

Branch: refs/heads/master
Commit: 53881c2acf6f725b3e2d631ef083baf3cb225525
Parents: fd71b7e
Author: Christian Amend <[email protected]>
Authored: Mon Jun 1 13:52:52 2015 +0200
Committer: Christian Amend <[email protected]>
Committed: Mon Jun 1 13:58:10 2015 +0200

----------------------------------------------------------------------
 .../olingo/server/api/CustomETagSupport.java    |  32 ++-
 .../core/PreconditionRequiredException.java     |   3 +-
 .../server/core/PreconditionsValidator.java     | 112 +++++-----
 .../olingo/server/tecsvc/ETagSupport.java       |  19 +-
 .../server/core/PreconditionsValidatorTest.java | 211 +++++++++++++++----
 5 files changed, 264 insertions(+), 113 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/53881c2a/lib/server-api/src/main/java/org/apache/olingo/server/api/CustomETagSupport.java
----------------------------------------------------------------------
diff --git 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/CustomETagSupport.java
 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/CustomETagSupport.java
index 2644b28..5e4f500 100644
--- 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/CustomETagSupport.java
+++ 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/CustomETagSupport.java
@@ -18,6 +18,8 @@
  */
 package org.apache.olingo.server.api;
 
+import org.apache.olingo.commons.api.edm.EdmBindingTarget;
+
 /**
  * <p>Processors that would like to support etags for certain entity sets can 
implement this
  * interface.</p>
@@ -32,19 +34,41 @@ public interface CustomETagSupport {
    * If this method returns true and an header is not specified we will return 
a "Precondition Required" response.
    * Validation has to be performed inside the processor methods after the 
dispatching.
    * If this method returns false and an header is specified we will ignore 
the header.
-   * @param entitySetName
+   * @param entitySetOrSingleton
    * @return true if the entity set specified needs an if-match/if-none-match 
header
    */
-  boolean hasETag(String entitySetName);
+  boolean hasETag(EdmBindingTarget entitySetOrSingleton);
 
   /**
    * This method will be called for update requests which target a media 
entity value.
    * If this method returns true and an header is not specified we will return 
a "Precondition Required" response.
    * Validation has to be performed inside the processor methods after the 
dispatching.
    * If this method returns false and an header is specified we will ignore 
the header.
-   * @param entitySetName
+   * @param entitySetOrSingleton
    * @return true if the entity set specified needs an if-match/if-none-match 
header
    */
-  boolean hasMediaETag(String entitySetName);
+  boolean hasMediaETag(EdmBindingTarget entitySetOrSingleton);
+
+  /**
+   * Since the Olingo library cannot generate a metadata document etag in a 
generic way we call this method to retrieve
+   * an application specific etag for the metadata document. If this interface 
is registered applications can return an
+   * etag or null here to provide caching support for clients. If a client 
sends a GET request to the metadata document
+   * and this method delivers an etag we will match it to the request. If 
there has been no modification we will return
+   * a 304 NOT MODIFIED status code. If this interface is not registered or 
delivers null we just send back the usual
+   * metadata response.
+   * @return the application generated etag for the metadata document
+   */
+  String getMetadataETag();
+
+  /**
+   * Since the Olingo library cannot generate a service document etag in a 
generic way we call this method to retrieve
+   * an application specific etag for the service document. If this interface 
is registered applications can return an
+   * etag or null here to provide caching support for clients. If a client 
sends a GET request to the service document
+   * and this method delivers an etag we will match it to the request. If 
there has been no modification we will return
+   * a 304 NOT MODIFIED status code. If this interface is not registered or 
delivers null we just send back the usual
+   * service document response.
+   * @return the application generated etag for the service document
+   */
+  String getServiceDocumentETag();
 
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/53881c2a/lib/server-core/src/main/java/org/apache/olingo/server/core/PreconditionRequiredException.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/PreconditionRequiredException.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/PreconditionRequiredException.java
index 4fb527f..c42f7df 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/PreconditionRequiredException.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/PreconditionRequiredException.java
@@ -24,7 +24,8 @@ public class PreconditionRequiredException extends 
ODataTranslatedException {
   private static final long serialVersionUID = -8112658467394158700L;
 
   public static enum MessageKeys implements MessageKey {
-    MISSING_HEADER;
+    MISSING_HEADER, 
+    INVALID_URI;
 
     @Override
     public String getKey() {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/53881c2a/lib/server-core/src/main/java/org/apache/olingo/server/core/PreconditionsValidator.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/PreconditionsValidator.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/PreconditionsValidator.java
index 81be05b..1ca8993 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/PreconditionsValidator.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/PreconditionsValidator.java
@@ -18,9 +18,7 @@
  */
 package org.apache.olingo.server.core;
 
-import java.util.List;
-
-import org.apache.olingo.commons.api.edm.EdmEntitySet;
+import org.apache.olingo.commons.api.edm.EdmBindingTarget;
 import org.apache.olingo.commons.api.edm.EdmFunctionImport;
 import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
 import org.apache.olingo.server.api.CustomETagSupport;
@@ -28,8 +26,8 @@ import org.apache.olingo.server.api.uri.UriInfo;
 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.UriResourceKind;
 import org.apache.olingo.server.api.uri.UriResourceNavigation;
+import org.apache.olingo.server.api.uri.UriResourceSingleton;
 
 public class PreconditionsValidator {
 
@@ -48,10 +46,10 @@ public class PreconditionsValidator {
   }
 
   public void validatePreconditions(boolean isMediaValue) throws 
PreconditionRequiredException {
-    EdmEntitySet affectedEntitySet = extractInformation();
-    if (affectedEntitySet != null) {
-      if ((isMediaValue && 
customETagSupport.hasMediaETag(affectedEntitySet.getName())) ||
-          (!isMediaValue && 
customETagSupport.hasETag(affectedEntitySet.getName()))) {
+    EdmBindingTarget affectedEntitySetOrSingleton = extractInformation();
+    if (affectedEntitySetOrSingleton != null) {
+      if ((isMediaValue && 
customETagSupport.hasMediaETag(affectedEntitySetOrSingleton)) ||
+          (!isMediaValue && 
customETagSupport.hasETag(affectedEntitySetOrSingleton))) {
         checkETagHeaderPresent();
       }
     }
@@ -64,75 +62,69 @@ public class PreconditionsValidator {
     }
   }
 
-  private EdmEntitySet extractInformation() {
-    EdmEntitySet affectedEntitySet = null;
-    List<UriResource> uriResourceParts = uriInfo.getUriResourceParts();
-    if (uriResourceParts.size() > 0) {
-      UriResource uriResourcePart = 
uriResourceParts.get(uriResourceParts.size() - 1);
+  private EdmBindingTarget extractInformation() throws 
PreconditionRequiredException {
+    EdmBindingTarget lastFoundEntitySetOrSingleton = null;
+    int counter = 0;
+    for (UriResource uriResourcePart : uriInfo.getUriResourceParts()) {
       switch (uriResourcePart.getKind()) {
+      case function:
+        lastFoundEntitySetOrSingleton = 
getEnitySetFromFunctionImport(uriResourcePart);
+        break;
+      case singleton:
+        lastFoundEntitySetOrSingleton = ((UriResourceSingleton) 
uriResourcePart).getSingleton();
+        break;
       case entitySet:
-        affectedEntitySet = ((UriResourceEntitySet) 
uriResourcePart).getEntitySet();
+        lastFoundEntitySetOrSingleton = getEntitySet(uriResourcePart);
         break;
       case navigationProperty:
-        affectedEntitySet = getEntitySetFromBeginning();
+        lastFoundEntitySetOrSingleton = 
getEntitySetFromNavigation(lastFoundEntitySetOrSingleton, uriResourcePart);
         break;
       case value:
-        affectedEntitySet = 
getEntitySetOrNavigationEntitySet(uriResourceParts);
-        break;
       case action:
-        affectedEntitySet = 
getEntitySetOrNavigationEntitySet(uriResourceParts);
+        // This should not be possible since the URI Parser validates this but 
to be sure we throw an exception.
+        if (counter != uriInfo.getUriResourceParts().size() - 1) {
+          throw new PreconditionRequiredException("$Value or Action must be 
the last segment in the URI.",
+              PreconditionRequiredException.MessageKeys.INVALID_URI);
+        }
         break;
       default:
-        // TODO: Cannot happen but should we throw an exception?
+        lastFoundEntitySetOrSingleton = null;
+        break;
+      }
+      if (lastFoundEntitySetOrSingleton == null) {
+        // Once we loose track of the entity set there is no way to retrieve 
it.
         break;
       }
-    } else {
-      // TODO: Cannot happen but should we throw an exception?
+      counter++;
     }
-    return affectedEntitySet;
+    return lastFoundEntitySetOrSingleton;
   }
 
-  private EdmEntitySet getEntitySetOrNavigationEntitySet(List<UriResource> 
uriResourceParts) {
-    EdmEntitySet affectedEntitySet = null;
-    UriResource previousResourcePart = 
uriResourceParts.get(uriResourceParts.size() - 2);
-    if (previousResourcePart.getKind() == UriResourceKind.entitySet) {
-      affectedEntitySet = ((UriResourceEntitySet) 
previousResourcePart).getEntitySet();
-    } else if (previousResourcePart.getKind() == 
UriResourceKind.navigationProperty) {
-      affectedEntitySet = getEntitySetFromBeginning();
+  private EdmBindingTarget getEnitySetFromFunctionImport(UriResource 
uriResourcePart) {
+    UriResourceFunction uriResourceFunction = (UriResourceFunction) 
uriResourcePart;
+    EdmFunctionImport functionImport = uriResourceFunction.getFunctionImport();
+    if (functionImport != null && functionImport.getReturnedEntitySet() != null
+        && !uriResourceFunction.isCollection()) {
+      return functionImport.getReturnedEntitySet();
     }
-    return affectedEntitySet;
+    return null;
   }
 
-  private EdmEntitySet getEntitySetFromBeginning() {
-    EdmEntitySet lastFoundES = null;
-    for (UriResource uriResourcePart : uriInfo.getUriResourceParts()) {
-      if (UriResourceKind.function == uriResourcePart.getKind()) {
-        EdmFunctionImport functionImport = ((UriResourceFunction) 
uriResourcePart).getFunctionImport();
-        if (functionImport != null && functionImport.getReturnedEntitySet() != 
null) {
-          lastFoundES = functionImport.getReturnedEntitySet();
-        } else {
-          lastFoundES = null;
-          break;
-        }
-      } else if (UriResourceKind.entitySet == uriResourcePart.getKind()) {
-        lastFoundES = ((UriResourceEntitySet) uriResourcePart).getEntitySet();
-      } else if (UriResourceKind.navigationProperty == 
uriResourcePart.getKind()) {
-        EdmNavigationProperty navProp = ((UriResourceNavigation) 
uriResourcePart).getProperty();
-        if (lastFoundES != null) {
-          lastFoundES = (EdmEntitySet) 
lastFoundES.getRelatedBindingTarget(navProp.getName());
-          if (lastFoundES == null) {
-            break;
-          }
-        }
-      } else if (UriResourceKind.value == uriResourcePart.getKind()
-          || UriResourceKind.action == uriResourcePart.getKind()) {
-        // TODO: Should we validate that we are at the end of the resource path
-        break;
-      } else {
-        lastFoundES = null;
-        break;
-      }
+  private EdmBindingTarget getEntitySet(UriResource uriResourcePart) {
+    UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) 
uriResourcePart;
+    if (!uriResourceEntitySet.isCollection()) {
+      return uriResourceEntitySet.getEntitySet();
+    }
+    return null;
+  }
+
+  private EdmBindingTarget getEntitySetFromNavigation(EdmBindingTarget 
lastFoundEntitySetOrSingleton,
+      UriResource uriResourcePart) {
+    UriResourceNavigation uriResourceNavigation = (UriResourceNavigation) 
uriResourcePart;
+    if (lastFoundEntitySetOrSingleton != null && 
!uriResourceNavigation.isCollection()) {
+      EdmNavigationProperty navProp = uriResourceNavigation.getProperty();
+      return 
lastFoundEntitySetOrSingleton.getRelatedBindingTarget(navProp.getName());
     }
-    return lastFoundES;
+    return null;
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/53881c2a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/ETagSupport.java
----------------------------------------------------------------------
diff --git 
a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/ETagSupport.java
 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/ETagSupport.java
index 825032d..9011107 100644
--- 
a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/ETagSupport.java
+++ 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/ETagSupport.java
@@ -18,17 +18,28 @@
  */
 package org.apache.olingo.server.tecsvc;
 
+import org.apache.olingo.commons.api.edm.EdmBindingTarget;
 import org.apache.olingo.server.api.CustomETagSupport;
 
 public class ETagSupport implements CustomETagSupport {
 
   @Override
-  public boolean hasETag(final String entitySetName) {
-    return entitySetName.equals("ESCompAllPrim");
+  public boolean hasETag(final EdmBindingTarget entitySetOrSingleton) {
+    return entitySetOrSingleton.getName().equals("ESCompAllPrim");
   }
 
   @Override
-  public boolean hasMediaETag(final String entitySetName) {
-    return entitySetName.equals("ESMedia");
+  public boolean hasMediaETag(final EdmBindingTarget entitySetOrSingleton) {
+    return entitySetOrSingleton.getName().equals("ESMedia");
+  }
+
+  @Override
+  public String getMetadataETag() {
+    return null;
+  }
+
+  @Override
+  public String getServiceDocumentETag() {
+    return null;
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/53881c2a/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 3dc07c7..033f9af 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
@@ -22,15 +22,23 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
 import org.apache.olingo.commons.api.edm.Edm;
+import org.apache.olingo.commons.api.edm.EdmBindingTarget;
+import org.apache.olingo.commons.api.http.HttpMethod;
 import org.apache.olingo.commons.core.edm.EdmProviderImpl;
 import org.apache.olingo.server.api.CustomETagSupport;
 import org.apache.olingo.server.api.uri.UriInfo;
 import org.apache.olingo.server.core.uri.parser.Parser;
+import org.apache.olingo.server.core.uri.parser.UriParserException;
+import org.apache.olingo.server.core.uri.parser.UriParserSemanticException;
+import org.apache.olingo.server.core.uri.validator.UriValidator;
 import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
+import org.junit.Ignore;
 import org.junit.Test;
 
 public class PreconditionsValidatorTest {
 
+  // -------------- POSITIVE TESTS 
--------------------------------------------------------------------------------
+
   @Test
   public void simpleEntity() throws Exception {
     UriInfo uriInfo = new Parser().parseUri("ESAllPrim(1)", null, null, 
getEdm());
@@ -38,16 +46,75 @@ public class PreconditionsValidatorTest {
   }
 
   @Test
+  public void simpleEntityValue() throws Exception {
+    UriInfo uriInfo = new Parser().parseUri("ESMedia(1)/$value", null, null, 
getEdm());
+    new PreconditionsValidator(new ETagSupport(), uriInfo, "*", 
"*").validatePreconditions(true);
+  }
+
+  @Test
+  public void EntityAndToOneNavigation() throws Exception {
+    UriInfo uriInfo = new 
Parser().parseUri("ESAllPrim(1)/NavPropertyETTwoPrimOne", null, null, getEdm());
+    new PreconditionsValidator(new ETagSupport("ESTwoPrim"), uriInfo, "*", 
"*").validatePreconditions(false);
+  }
+
+  @Test
+  public void EntityAndToManyNavigationWithKey() throws Exception {
+    UriInfo uriInfo = new 
Parser().parseUri("ESAllPrim(1)/NavPropertyETTwoPrimMany(1)", null, null, 
getEdm());
+    new PreconditionsValidator(new ETagSupport("ESTwoPrim"), uriInfo, "*", 
"*").validatePreconditions(false);
+  }
+
+  @Test
+  public void EntityAndToOneNavigationValue() throws Exception {
+    UriInfo uriInfo = new 
Parser().parseUri("ESKeyNav(1)/NavPropertyETMediaOne/$value", null, null, 
getEdm());
+    new PreconditionsValidator(new ETagSupport("ESMedia"), uriInfo, "*", 
"*").validatePreconditions(true);
+  }
+
+  @Test
   public void boundActionOnEsKeyNav() throws Exception {
     UriInfo uriInfo =
         new 
Parser().parseUri("ESKeyNav(1)/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav", 
null, null, getEdm());
-    new PreconditionsValidator(new ETagSupport(), uriInfo, "*", 
"*").validatePreconditions(false);
+    new PreconditionsValidator(new ETagSupport("ESKeyNav"), uriInfo, "*", 
"*").validatePreconditions(false);
   }
 
   @Test
-  public void simpleEntityValue() throws Exception {
-    UriInfo uriInfo = new Parser().parseUri("ESMedia(1)/$value", null, null, 
getEdm());
-    new PreconditionsValidator(new ETagSupport(), uriInfo, "*", 
"*").validatePreconditions(true);
+  public void boundActionOnEsKeyNavWithNavigation() throws Exception {
+    UriInfo uriInfo =
+        new 
Parser().parseUri("ESKeyNav(1)/NavPropertyETKeyNavOne/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav",
 null,
+            null, getEdm());
+    new PreconditionsValidator(new ETagSupport("ESKeyNav"), uriInfo, "*", 
"*").validatePreconditions(false);
+  }
+
+  @Test
+  public void singleton() throws Exception {
+    UriInfo uriInfo = new Parser().parseUri("SI", null, null, getEdm());
+    new PreconditionsValidator(new ETagSupport("SI"), uriInfo, "*", 
"*").validatePreconditions(false);
+  }
+
+  @Test
+  public void singletonWithNavigation() throws Exception {
+    UriInfo uriInfo = new Parser().parseUri("SINav/NavPropertyETKeyNavOne", 
null, null, getEdm());
+    new PreconditionsValidator(new ETagSupport("ESKeyNav"), uriInfo, "*", 
"*").validatePreconditions(false);
+  }
+
+  @Test
+  public void singletonWithNavigationValue() throws Exception {
+    UriInfo uriInfo =
+        new 
Parser().parseUri("SINav/NavPropertyETKeyNavOne/NavPropertyETMediaOne/$value", 
null, null, getEdm());
+    new PreconditionsValidator(new ETagSupport("ESMedia"), uriInfo, "*", 
"*").validatePreconditions(false);
+  }
+
+  @Test
+  public void singletonWithAction() throws Exception {
+    UriInfo uriInfo = new 
Parser().parseUri("SINav/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav", null, 
null, getEdm());
+    new PreconditionsValidator(new ETagSupport("SINav"), uriInfo, "*", 
"*").validatePreconditions(false);
+  }
+
+  @Test
+  public void singletonWithActionAndNavigation() throws Exception {
+    UriInfo uriInfo =
+        new 
Parser().parseUri("SINav/NavPropertyETKeyNavOne/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav",
 null, null,
+            getEdm());
+    new PreconditionsValidator(new ETagSupport("ESKeyNav"), uriInfo, "*", 
"*").validatePreconditions(false);
   }
 
   @Test
@@ -56,51 +123,99 @@ public class PreconditionsValidatorTest {
     new PreconditionsValidator(new ETagSupport(true, false), uriInfo, null, 
null).validatePreconditions(true);
   }
 
+  // -------------- IGNORE VALIDATION TESTS 
-----------------------------------------------------------------------
+
   @Test
-  public void EntityAndToOneNavigation() throws Exception {
-    UriInfo uriInfo = new 
Parser().parseUri("ESAllPrim(1)/NavPropertyETTwoPrimOne", null, null, getEdm());
-    new PreconditionsValidator(new ETagSupport("ESTwoPrim"), uriInfo, "*", 
"*").validatePreconditions(false);
+  public void entitySetMustNotLeadToException() throws Exception {
+    UriInfo uriInfo = new Parser().parseUri("ESAllPrim", null, null, getEdm());
+    new PreconditionsValidator(new ETagSupport(), uriInfo, null, 
null).validatePreconditions(false);
   }
 
   @Test
-  public void simpleEntityPreconditionsReqException() throws Exception {
-    UriInfo uriInfo = new Parser().parseUri("ESAllPrim(1)", null, null, 
getEdm());
-    try {
-      new PreconditionsValidator(new ETagSupport(), uriInfo, null, 
null).validatePreconditions(false);
-      fail("Expected a PreconditionRequiredException but was not thrown");
-    } catch (PreconditionRequiredException e) {
-      assertEquals(PreconditionRequiredException.MessageKeys.MISSING_HEADER, 
e.getMessageKey());
-    }
+  public void propertyMustNotLeadToException() throws Exception {
+    UriInfo uriInfo = new Parser().parseUri("ESAllPrim(1)/PropertyInt16", 
null, null, getEdm());
+    new PreconditionsValidator(new ETagSupport(), uriInfo, null, 
null).validatePreconditions(false);
+  }
+
+  @Test
+  public void propertyValueMustNotLeadToException() throws Exception {
+    UriInfo uriInfo = new 
Parser().parseUri("ESAllPrim(1)/PropertyInt16/$value", null, null, getEdm());
+    new PreconditionsValidator(new ETagSupport(), uriInfo, null, 
null).validatePreconditions(true);
+  }
+
+  @Test
+  public void navigationToManyMustNotLeadToException() throws Exception {
+    UriInfo uriInfo = new 
Parser().parseUri("ESAllPrim(1)/NavPropertyETTwoPrimMany", null, null, 
getEdm());
+    new PreconditionsValidator(new ETagSupport(), uriInfo, null, 
null).validatePreconditions(false);
   }
 
   @Test
-  public void boundActionOnEsKeyNavPreconditionsRequired() throws Exception {
+  public void navigationOnPropertyMustNotLeadToException() throws Exception {
+    UriInfo uriInfo = new 
Parser().parseUri("ESAllPrim(1)/NavPropertyETTwoPrimOne/PropertyInt16", null, 
null, getEdm());
+    new PreconditionsValidator(new ETagSupport(), uriInfo, null, 
null).validatePreconditions(false);
+  }
+
+  @Test
+  public void navigationToManyOnActionMustNotLeadToException() throws 
Exception {
     UriInfo uriInfo =
-        new 
Parser().parseUri("ESKeyNav(1)/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav", 
null, null, getEdm());
-    try {
-      new PreconditionsValidator(new ETagSupport("ESKeyNav"), uriInfo, null, 
null).validatePreconditions(false);
-      fail("Expected a PreconditionRequiredException but was not thrown");
-    } catch (PreconditionRequiredException e) {
-      assertEquals(PreconditionRequiredException.MessageKeys.MISSING_HEADER, 
e.getMessageKey());
-    }
+        new 
Parser().parseUri("ESTwoPrim(1)/NavPropertyETAllPrimMany/Namespace1_Alias.BAESAllPrimRTETAllPrim",
 null,
+            null, getEdm());
+    new PreconditionsValidator(new ETagSupport(), uriInfo, null, 
null).validatePreconditions(false);
   }
 
   @Test
-  public void simpleEntityValuePreconditionsRequired() throws Exception {
-    UriInfo uriInfo = new Parser().parseUri("ESMedia(1)/$value", null, null, 
getEdm());
-    try {
-      new PreconditionsValidator(new ETagSupport(), uriInfo, null, 
null).validatePreconditions(true);
-      fail("Expected a PreconditionRequiredException but was not thrown");
-    } catch (PreconditionRequiredException e) {
-      assertEquals(PreconditionRequiredException.MessageKeys.MISSING_HEADER, 
e.getMessageKey());
-    }
+  public void navigationWithoutBindingMustNotLeadToAnException() throws 
Exception {
+    UriInfo uriInfo =
+        new Parser()
+            .parseUri(
+                "ESTwoBaseTwoKeyNav(PropertyInt16=1,PropertyString='test')"
+                    + 
"/NavPropertyETBaseTwoKeyNavMany(PropertyInt16=1,PropertyString='test')",
+                null, null, getEdm());
+    new PreconditionsValidator(new ETagSupport(), uriInfo, null, 
null).validatePreconditions(false);
   }
 
+  // -------------- NEGATIVE TESTS 
--------------------------------------------------------------------------------
+
   @Test
-  public void EntityAndToOneNavigationPreconditionsRequired() throws Exception 
{
-    UriInfo uriInfo = new 
Parser().parseUri("ESAllPrim(1)/NavPropertyETTwoPrimOne", null, null, getEdm());
+  public void positiveTestsMustLeadToAnExceptionIfNoHeaderIsPresent() throws 
Exception {
+    runException("ESAllPrim(1)", null);
+    runException("ESMedia(1)/$value", null);
+    runException("ESAllPrim(1)/NavPropertyETTwoPrimOne", null);
+    runException("ESAllPrim(1)/NavPropertyETTwoPrimMany(1)", null);
+    runException("ESKeyNav(1)/NavPropertyETMediaOne/$value", null);
+    runException("ESKeyNav(1)/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav", 
null);
+    
runException("ESKeyNav(1)/NavPropertyETKeyNavOne/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav",
 null);
+
+    runException("SI", null);
+    runException("SINav/NavPropertyETKeyNavOne", null);
+    runException("SINav/NavPropertyETKeyNavOne/NavPropertyETMediaOne/$value", 
null);
+    runException("SINav/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav", null);
+    
runException("SINav/NavPropertyETKeyNavOne/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav",
 null);
+  }
+
+  @Ignore
+  @Test
+  public void resourceSegmentAfterActionMustLeadToUriParserException() throws 
Exception {
+    //TODO: Check with URI Parser
+    UriInfo uriInfo =
+        new 
Parser().parseUri("ESKeyNav(1)/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav/PropertyInt16",
 null, null,
+            getEdm());
+    new UriValidator().validate(uriInfo, HttpMethod.GET);
+    new PreconditionsValidator(new ETagSupport("ESKeyNav"), uriInfo, "*", 
"*").validatePreconditions(false);
+  }
+
+  @Test(expected = UriParserSemanticException.class)
+  public void valueMustBeLastSegment() throws Exception {
+    new Parser().parseUri("ESMedia(1)/$value/PropertyInt16", null, null, 
getEdm());
+  }
+
+  private void runException(String uri, String expectedEntitySet) throws 
UriParserException {
+    UriInfo uriInfo = new Parser().parseUri(uri, null, null, getEdm());
     try {
-      new PreconditionsValidator(new ETagSupport(), uriInfo, null, 
null).validatePreconditions(false);
+      CustomETagSupport etagSupport =
+          expectedEntitySet == null ? new ETagSupport() : new 
ETagSupport(expectedEntitySet);
+      boolean isMedia = uri.endsWith("$value");
+      new PreconditionsValidator(etagSupport, uriInfo, null, 
null).validatePreconditions(isMedia);
       fail("Expected a PreconditionRequiredException but was not thrown");
     } catch (PreconditionRequiredException e) {
       assertEquals(PreconditionRequiredException.MessageKeys.MISSING_HEADER, 
e.getMessageKey());
@@ -117,33 +232,41 @@ public class PreconditionsValidatorTest {
     private boolean mediaETag = true;
     private String entitySetName;
 
-    public ETagSupport() {
-    }
+    public ETagSupport() {}
 
     public ETagSupport(String entitySetName) {
       this.entitySetName = entitySetName;
-    }    
+    }
 
     public ETagSupport(boolean eTag, boolean mediaETag) {
       this.eTag = eTag;
       this.mediaETag = mediaETag;
     }
-    
 
     @Override
-    public boolean hasETag(String entitySetName) {
-      if(this.entitySetName != null){
-        assertEquals(this.entitySetName, entitySetName);
+    public boolean hasETag(EdmBindingTarget entitySetOrSingeton) {
+      if (this.entitySetName != null) {
+        assertEquals(this.entitySetName, entitySetOrSingeton.getName());
       }
       return eTag;
     }
 
     @Override
-    public boolean hasMediaETag(String entitySetName) {
-      if(this.entitySetName != null){
-        assertEquals(this.entitySetName, entitySetName);
+    public boolean hasMediaETag(EdmBindingTarget entitySetOrSingelton) {
+      if (this.entitySetName != null) {
+        assertEquals(this.entitySetName, entitySetOrSingelton.getName());
       }
       return mediaETag;
     }
+
+    @Override
+    public String getMetadataETag() {
+      return null;
+    }
+
+    @Override
+    public String getServiceDocumentETag() {
+      return null;
+    }
   }
 }

Reply via email to