[OLINGO-663] conditional header required for property updates

Signed-off-by: Christian Amend <christian.amend@sap.com>
This commit is contained in:
Klaus Straubinger 2015-06-19 16:29:47 +02:00 committed by Christian Amend
parent 01425faf1c
commit bfb5c93836
6 changed files with 141 additions and 129 deletions

View File

@ -194,6 +194,15 @@ public final class ConditionalITCase extends AbstractBaseTestITCase {
assertEquals(HttpStatusCode.NOT_MODIFIED.getStatusCode(), request.execute().getStatusCode());
}
@Test
public void updatePropertyWithoutIfMatch() throws Exception {
final ODataPropertyUpdateRequest request = client.getCUDRequestFactory().getPropertyPrimitiveValueUpdateRequest(
uriProperty,
client.getObjectFactory().newPrimitiveProperty("PropertyDuration",
client.getObjectFactory().newPrimitiveValueBuilder().buildString("PT42S")));
executeAndExpectError(request, HttpStatusCode.PRECONDITION_REQUIRED);
}
@Test
public void updatePropertyWithWrongIfMatch() throws Exception {
ODataPropertyUpdateRequest request = client.getCUDRequestFactory().getPropertyPrimitiveValueUpdateRequest(
@ -204,6 +213,15 @@ public final class ConditionalITCase extends AbstractBaseTestITCase {
executeAndExpectError(request, HttpStatusCode.PRECONDITION_FAILED);
}
@Test
public void updatePropertyValueWithoutIfMatch() throws Exception {
final ODataValueUpdateRequest request = client.getCUDRequestFactory().getValueUpdateRequest(
uriPropertyValue,
UpdateType.REPLACE,
client.getObjectFactory().newPrimitiveValueBuilder().buildString("PT42S"));
executeAndExpectError(request, HttpStatusCode.PRECONDITION_REQUIRED);
}
@Test
public void updatePropertyValueWithWrongIfMatch() throws Exception {
ODataValueUpdateRequest request = client.getCUDRequestFactory().getValueUpdateRequest(
@ -214,6 +232,12 @@ public final class ConditionalITCase extends AbstractBaseTestITCase {
executeAndExpectError(request, HttpStatusCode.PRECONDITION_FAILED);
}
@Test
public void deletePropertyWithoutIfMatch() throws Exception {
final ODataDeleteRequest request = client.getCUDRequestFactory().getDeleteRequest(uriProperty);
executeAndExpectError(request, HttpStatusCode.PRECONDITION_REQUIRED);
}
@Test
public void deletePropertyWithWrongIfMatch() throws Exception {
ODataDeleteRequest request = client.getCUDRequestFactory().getDeleteRequest(uriProperty);
@ -231,6 +255,12 @@ public final class ConditionalITCase extends AbstractBaseTestITCase {
assertNotEquals(request.getIfMatch(), response.getETag());
}
@Test
public void deletePropertyValueWithoutIfMatch() throws Exception {
final ODataDeleteRequest request = client.getCUDRequestFactory().getDeleteRequest(uriPropertyValue);
executeAndExpectError(request, HttpStatusCode.PRECONDITION_REQUIRED);
}
@Test
public void deletePropertyValueWithWrongIfMatch() throws Exception {
ODataDeleteRequest request = client.getCUDRequestFactory().getDeleteRequest(uriPropertyValue);

View File

@ -33,6 +33,7 @@ import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.ODataLibraryException;
import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.etag.CustomETagSupport;
import org.apache.olingo.server.api.etag.PreconditionException;
import org.apache.olingo.server.api.processor.ActionComplexCollectionProcessor;
import org.apache.olingo.server.api.processor.ActionComplexProcessor;
@ -203,7 +204,7 @@ public class ODataDispatcher {
final UriResourceAction uriResourceAction) throws ODataApplicationException, ODataLibraryException {
final EdmAction action = uriResourceAction.getAction();
if (action.isBound()) {
// Only bound actions can have etag control for the binding parameter
// Only bound actions can have ETag control for the binding parameter.
validatePreconditions(request, false);
}
final EdmReturnType returnType = action.getReturnType();
@ -322,6 +323,7 @@ public class ODataDispatcher {
handler.selectProcessor(PrimitiveValueProcessor.class)
.readPrimitiveValue(request, response, uriInfo, requestedContentType);
} else if (method == HttpMethod.PUT && resource instanceof UriResourceProperty) {
validatePreconditions(request, false);
final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
checkContentTypeSupport(requestFormat, valueRepresentationType);
final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
@ -329,6 +331,7 @@ public class ODataDispatcher {
handler.selectProcessor(PrimitiveValueProcessor.class)
.updatePrimitiveValue(request, response, uriInfo, requestFormat, responseFormat);
} else if (method == HttpMethod.DELETE && resource instanceof UriResourceProperty) {
validatePreconditions(request, false);
handler.selectProcessor(PrimitiveValueProcessor.class)
.deletePrimitiveValue(request, response, uriInfo);
} else {
@ -375,6 +378,7 @@ public class ODataDispatcher {
.readComplex(request, response, uriInfo, requestedContentType);
}
} else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
validatePreconditions(request, false);
final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
checkContentTypeSupport(requestFormat, complexRepresentationType);
final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
@ -387,6 +391,7 @@ public class ODataDispatcher {
.updateComplex(request, response, uriInfo, requestFormat, responseFormat);
}
} else if (method == HttpMethod.DELETE) {
validatePreconditions(request, false);
if (isCollection) {
handler.selectProcessor(ComplexCollectionProcessor.class)
.deleteComplexCollection(request, response, uriInfo);
@ -416,6 +421,7 @@ public class ODataDispatcher {
.readPrimitive(request, response, uriInfo, requestedContentType);
}
} else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
validatePreconditions(request, false);
final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE));
checkContentTypeSupport(requestFormat, representationType);
final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
@ -428,6 +434,7 @@ public class ODataDispatcher {
.updatePrimitive(request, response, uriInfo, requestFormat, responseFormat);
}
} else if (method == HttpMethod.DELETE) {
validatePreconditions(request, false);
if (isCollection) {
handler.selectProcessor(PrimitiveCollectionProcessor.class)
.deletePrimitiveCollection(request, response, uriInfo);
@ -443,27 +450,21 @@ public class ODataDispatcher {
private void handleCountDispatching(final ODataRequest request, final ODataResponse response,
final int lastPathSegmentIndex) throws ODataApplicationException, ODataLibraryException {
final HttpMethod method = request.getMethod();
if (method == HttpMethod.GET) {
final UriResource resource = uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1);
if (resource instanceof UriResourceEntitySet
|| resource instanceof UriResourceNavigation
|| resource instanceof UriResourceFunction
&& ((UriResourceFunction) resource).getType().getKind() == EdmTypeKind.ENTITY) {
handler.selectProcessor(CountEntityCollectionProcessor.class)
.countEntityCollection(request, response, uriInfo);
} else if (resource instanceof UriResourcePrimitiveProperty
|| resource instanceof UriResourceFunction
&& ((UriResourceFunction) resource).getType().getKind() == EdmTypeKind.PRIMITIVE) {
handler.selectProcessor(CountPrimitiveCollectionProcessor.class)
.countPrimitiveCollection(request, response, uriInfo);
} else {
handler.selectProcessor(CountComplexCollectionProcessor.class)
.countComplexCollection(request, response, uriInfo);
}
final UriResource resource = uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1);
if (resource instanceof UriResourceEntitySet
|| resource instanceof UriResourceNavigation
|| resource instanceof UriResourceFunction
&& ((UriResourceFunction) resource).getType().getKind() == EdmTypeKind.ENTITY) {
handler.selectProcessor(CountEntityCollectionProcessor.class)
.countEntityCollection(request, response, uriInfo);
} else if (resource instanceof UriResourcePrimitiveProperty
|| resource instanceof UriResourceFunction
&& ((UriResourceFunction) resource).getType().getKind() == EdmTypeKind.PRIMITIVE) {
handler.selectProcessor(CountPrimitiveCollectionProcessor.class)
.countPrimitiveCollection(request, response, uriInfo);
} else {
throw new ODataHandlerException("HTTP method " + method + " is not allowed for count.",
ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString());
handler.selectProcessor(CountComplexCollectionProcessor.class)
.countComplexCollection(request, response, uriInfo);
}
}
@ -517,12 +518,16 @@ public class ODataDispatcher {
}
}
private void validatePreconditions(ODataRequest request, boolean isMediaValue) throws PreconditionException {
// If needed perform preconditions validation
if (handler.getCustomETagSupport() != null) {
new PreconditionsValidator(handler.getCustomETagSupport(), uriInfo,
request.getHeader(HttpHeader.IF_MATCH),
request.getHeader(HttpHeader.IF_NONE_MATCH)).validatePreconditions(isMediaValue);
private void validatePreconditions(final ODataRequest request, final boolean isMediaValue)
throws PreconditionException {
// If needed perform preconditions validation.
final CustomETagSupport eTagSupport = handler.getCustomETagSupport();
if (eTagSupport != null
&& new PreconditionsValidator(uriInfo).mustValidatePreconditions(eTagSupport, isMediaValue)
&& request.getHeader(HttpHeader.IF_MATCH) == null
&& request.getHeader(HttpHeader.IF_NONE_MATCH) == null) {
throw new PreconditionException("Expected an if-match or if-none-match header.",
PreconditionException.MessageKeys.MISSING_HEADER);
}
}

View File

@ -32,37 +32,20 @@ import org.apache.olingo.server.api.uri.UriResourceSingleton;
public class PreconditionsValidator {
private final CustomETagSupport customETagSupport;
private final UriInfo uriInfo;
private final String ifMatch;
private final String ifNoneMatch;
private final EdmBindingTarget affectedEntitySetOrSingleton;
public PreconditionsValidator(CustomETagSupport customETagSupport, UriInfo uriInfo, String ifMatch,
String ifNoneMatch) {
this.customETagSupport = customETagSupport;
this.uriInfo = uriInfo;
this.ifMatch = ifMatch;
this.ifNoneMatch = ifNoneMatch;
public PreconditionsValidator(final UriInfo uriInfo) throws PreconditionException {
affectedEntitySetOrSingleton = extractInformation(uriInfo);
}
public void validatePreconditions(boolean isMediaValue) throws PreconditionException {
EdmBindingTarget affectedEntitySetOrSingleton = extractInformation();
if (affectedEntitySetOrSingleton != null) {
if ((isMediaValue && customETagSupport.hasMediaETag(affectedEntitySetOrSingleton)) ||
(!isMediaValue && customETagSupport.hasETag(affectedEntitySetOrSingleton))) {
checkETagHeaderPresent();
}
}
public boolean mustValidatePreconditions(final CustomETagSupport customETagSupport, final boolean isMediaValue) {
return affectedEntitySetOrSingleton != null
&& (isMediaValue ?
customETagSupport.hasMediaETag(affectedEntitySetOrSingleton) :
customETagSupport.hasETag(affectedEntitySetOrSingleton));
}
private void checkETagHeaderPresent() throws PreconditionException {
if (ifMatch == null && ifNoneMatch == null) {
throw new PreconditionException("Expected an if-match or if-none-match header",
PreconditionException.MessageKeys.MISSING_HEADER);
}
}
private EdmBindingTarget extractInformation() throws PreconditionException {
private EdmBindingTarget extractInformation(final UriInfo uriInfo) throws PreconditionException {
EdmBindingTarget lastFoundEntitySetOrSingleton = null;
int counter = 0;
for (UriResource uriResourcePart : uriInfo.getUriResourceParts()) {
@ -78,13 +61,16 @@ public class PreconditionsValidator {
break;
case navigationProperty:
lastFoundEntitySetOrSingleton = getEntitySetFromNavigation(lastFoundEntitySetOrSingleton,
(UriResourceNavigation) uriResourcePart);
(UriResourceNavigation) uriResourcePart);
break;
case primitiveProperty:
case complexProperty:
break;
case value:
case action:
// 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 PreconditionException("$Value or Action must be the last segment in the URI.",
throw new PreconditionException("$value or Action must be the last segment in the URI.",
PreconditionException.MessageKeys.INVALID_URI);
}
break;
@ -111,14 +97,11 @@ public class PreconditionsValidator {
}
private EdmBindingTarget getEntitySet(UriResourceEntitySet uriResourceEntitySet) {
if (!uriResourceEntitySet.isCollection()) {
return uriResourceEntitySet.getEntitySet();
}
return null;
return uriResourceEntitySet.isCollection() ? null : uriResourceEntitySet.getEntitySet();
}
private EdmBindingTarget getEntitySetFromNavigation(EdmBindingTarget lastFoundEntitySetOrSingleton,
UriResourceNavigation uriResourceNavigation) {
UriResourceNavigation uriResourceNavigation) {
if (lastFoundEntitySetOrSingleton != null && !uriResourceNavigation.isCollection()) {
EdmNavigationProperty navProp = uriResourceNavigation.getProperty();
return lastFoundEntitySetOrSingleton.getRelatedBindingTarget(navProp.getName());

View File

@ -371,7 +371,7 @@ public class EntityTypeProvider {
PropertyProvider.collectionNavPropertyETKeyNavMany_ETKeyNav,
PropertyProvider.navPropertyETTwoKeyNavOne_ETTwoKeyNav,
PropertyProvider.collectionNavPropertyETTwoKeyNavMany_ETTwoKeyNav,
PropertyProvider.collectionNavPropertySINav));
PropertyProvider.navPropertySINav));
} else if (entityTypeName.equals(nameETBaseTwoKeyNav)) {
return new CsdlEntityType()

View File

@ -687,9 +687,9 @@ public class PropertyProvider {
.setType(EntityTypeProvider.nameETAllPrim)
.setCollection(true);
public static final CsdlNavigationProperty collectionNavPropertySINav = new CsdlNavigationProperty()
public static final CsdlNavigationProperty navPropertySINav = new CsdlNavigationProperty()
.setName("NavPropertySINav")
.setCollection(true)
.setCollection(false)
.setType(EntityTypeProvider.nameETTwoKeyNav);
public static final CsdlNavigationProperty collectionNavPropertyETKeyNavContMany_CT_ETKeyNav =

View File

@ -19,7 +19,8 @@
package org.apache.olingo.server.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@ -52,144 +53,146 @@ public class PreconditionsValidatorTest {
@Test
public void simpleEntity() throws Exception {
validate("ESAllPrim(1)", null, "*", "*");
assertTrue(mustValidate("ESAllPrim(1)", "ESAllPrim"));
}
@Test
public void simpleEntityValue() throws Exception {
validate("ESMedia(1)/$value", null, "*", "*");
assertTrue(mustValidate("ESMedia(1)/$value", "ESMedia"));
}
@Test
public void property() throws Exception {
assertTrue(mustValidate("ESAllPrim(1)/PropertyInt16", "ESAllPrim"));
assertTrue(mustValidate("ESMixPrimCollComp(0)/PropertyComp", "ESMixPrimCollComp"));
assertTrue(mustValidate("ESMixPrimCollComp(0)/PropertyComp/PropertyString", "ESMixPrimCollComp"));
}
@Test
public void propertyValue() throws Exception {
assertTrue(mustValidate("ESAllPrim(1)/PropertyInt16/$value", "ESAllPrim"));
assertTrue(mustValidate("ESMixPrimCollComp(0)/PropertyComp/PropertyString/$value", "ESMixPrimCollComp"));
}
@Test
public void EntityAndToOneNavigation() throws Exception {
validate("ESAllPrim(1)/NavPropertyETTwoPrimOne", "ESTwoPrim", "*", "*");
assertTrue(mustValidate("ESAllPrim(1)/NavPropertyETTwoPrimOne", "ESTwoPrim"));
}
@Test
public void EntityAndToManyNavigationWithKey() throws Exception {
validate("ESAllPrim(1)/NavPropertyETTwoPrimMany(1)", "ESTwoPrim", "*", "*");
assertTrue(mustValidate("ESAllPrim(1)/NavPropertyETTwoPrimMany(1)", "ESTwoPrim"));
}
@Test
public void EntityAndToOneNavigationValue() throws Exception {
validate("ESKeyNav(1)/NavPropertyETMediaOne/$value", "ESMedia", "*", "*");
assertTrue(mustValidate("ESKeyNav(1)/NavPropertyETMediaOne/$value", "ESMedia"));
}
@Test
public void navigationOnProperty() throws Exception {
assertTrue(mustValidate("ESAllPrim(1)/NavPropertyETTwoPrimOne/PropertyInt16", "ESTwoPrim"));
}
@Test
public void navigationOnFunction() throws Exception {
assertTrue(mustValidate("FICRTESTwoKeyNav()(PropertyInt16=1,PropertyString='1')/NavPropertySINav", "SINav"));
}
@Test
public void boundActionOnEsKeyNav() throws Exception {
validate("ESKeyNav(1)/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav", "ESKeyNav", "*", "*");
assertTrue(mustValidate("ESKeyNav(1)/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav", "ESKeyNav"));
}
@Test
public void boundActionOnEsKeyNavWithNavigation() throws Exception {
validate("ESKeyNav(1)/NavPropertyETKeyNavOne/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav",
"ESKeyNav", "*", "*");
assertTrue(
mustValidate("ESKeyNav(1)/NavPropertyETKeyNavOne/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav", "ESKeyNav"));
}
@Test
public void singleton() throws Exception {
validate("SI", "SI", "*", "*");
assertTrue(mustValidate("SI", "SI"));
}
@Test
public void singletonWithNavigation() throws Exception {
validate("SINav/NavPropertyETKeyNavOne", "ESKeyNav", "*", "*");
assertTrue(mustValidate("SINav/NavPropertyETKeyNavOne", "ESKeyNav"));
}
@Test
public void singletonWithNavigationValue() throws Exception {
validate("SINav/NavPropertyETKeyNavOne/NavPropertyETMediaOne/$value", "ESMedia", "*", "*");
assertTrue(mustValidate("SINav/NavPropertyETKeyNavOne/NavPropertyETMediaOne/$value", "ESMedia"));
}
@Test
public void singletonWithAction() throws Exception {
validate("SINav/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav", "SINav", "*", "*");
assertTrue(mustValidate("SINav/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav", "SINav"));
}
@Test
public void singletonWithActionAndNavigation() throws Exception {
validate("SINav/NavPropertyETKeyNavOne/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav", "ESKeyNav", "*", "*");
assertTrue(mustValidate("SINav/NavPropertyETKeyNavOne/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav", "ESKeyNav"));
}
@Test
public void simpleEntityValueValidationNotActiveForMedia() throws Exception {
final UriInfo uriInfo = new Parser().parseUri("ESMedia(1)/$value", null, null, edm);
CustomETagSupport support = mock(CustomETagSupport.class);
when(support.hasETag(any(EdmBindingTarget.class))).thenReturn(true);
when(support.hasMediaETag(any(EdmBindingTarget.class))).thenReturn(false);
final UriInfo uriInfo = new Parser().parseUri("ESMedia(1)/$value", null, null, edm);
new PreconditionsValidator(support, uriInfo, null, null).validatePreconditions(true);
assertFalse(new PreconditionsValidator(uriInfo).mustValidatePreconditions(support, true));
}
// -------------- IGNORE VALIDATION TESTS -----------------------------------------------------------------------
@Test
public void entitySetMustNotLeadToException() throws Exception {
validate("ESAllPrim", null, null, null);
public void entitySetMustBeIgnored() throws Exception {
assertFalse(mustValidate("ESAllPrim", "ESAllPrim"));
}
@Test
public void propertyMustNotLeadToException() throws Exception {
validate("ESAllPrim(1)/PropertyInt16", null, null, null);
public void navigationToManyMustBeIgnored() throws Exception {
assertFalse(mustValidate("ESAllPrim(1)/NavPropertyETTwoPrimMany", "ESTwoPrim"));
}
@Test
public void propertyValueMustNotLeadToException() throws Exception {
validate("ESAllPrim(1)/PropertyInt16/$value", null, null, null);
public void navigationOnFunctionWithoutEntitySetMustBeIgnored() throws Exception {
assertFalse(mustValidate("FICRTETTwoKeyNavParam(ParameterInt16=1)/NavPropertyETKeyNavOne", null));
}
@Test
public void navigationToManyMustNotLeadToException() throws Exception {
validate("ESAllPrim(1)/NavPropertyETTwoPrimMany", null, null, null);
public void navigationToManyToActionMustBeIgnored() throws Exception {
assertFalse(mustValidate("ESTwoPrim(1)/NavPropertyETAllPrimMany/Namespace1_Alias.BAESAllPrimRTETAllPrim", null));
}
@Test
public void navigationOnPropertyMustNotLeadToException() throws Exception {
validate("ESAllPrim(1)/NavPropertyETTwoPrimOne/PropertyInt16", null, null, null);
}
@Test
public void navigationToManyOnActionMustNotLeadToException() throws Exception {
validate("ESTwoPrim(1)/NavPropertyETAllPrimMany/Namespace1_Alias.BAESAllPrimRTETAllPrim", null, null, null);
}
@Test
public void navigationWithoutBindingMustNotLeadToException() throws Exception {
validate("ESTwoBaseTwoKeyNav(PropertyInt16=1,PropertyString='test')"
public void navigationWithoutBindingMustBeIgnored() throws Exception {
assertFalse(mustValidate("ESTwoBaseTwoKeyNav(PropertyInt16=1,PropertyString='test')"
+ "/NavPropertyETBaseTwoKeyNavMany(PropertyInt16=1,PropertyString='test')",
null, null, null);
null));
}
// -------------- NEGATIVE TESTS --------------------------------------------------------------------------------
@Test
public void positiveTestsMustLeadToAnExceptionIfNoHeaderIsPresent() throws Exception {
runException("ESAllPrim(1)");
runException("ESMedia(1)/$value");
runException("ESAllPrim(1)/NavPropertyETTwoPrimOne");
runException("ESAllPrim(1)/NavPropertyETTwoPrimMany(1)");
runException("ESKeyNav(1)/NavPropertyETMediaOne/$value");
runException("ESKeyNav(1)/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav");
runException("ESKeyNav(1)/NavPropertyETKeyNavOne/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav");
runException("SI");
runException("SINav/NavPropertyETKeyNavOne");
runException("SINav/NavPropertyETKeyNavOne/NavPropertyETMediaOne/$value");
runException("SINav/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav");
runException("SINav/NavPropertyETKeyNavOne/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav");
public void referencesMustBeIgnored() throws Exception {
assertFalse(mustValidate("ESAllPrim(1)/NavPropertyETTwoPrimOne/$ref", "ESTwoPrim"));
assertFalse(mustValidate("ESAllPrim(1)/NavPropertyETTwoPrimMany(1)/$ref", "ESTwoPrim"));
assertFalse(mustValidate("SINav/NavPropertyETKeyNavOne/$ref", "ESKeyNav"));
}
@Test(expected = UriParserSemanticException.class)
public void resourceSegmentAfterActionMustLeadToUriParserException() throws Exception {
validate("ESKeyNav(1)/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav/PropertyInt16", "ESKeyNav", "*", "*");
mustValidate("ESKeyNav(1)/Namespace1_Alias.BAETTwoKeyNavRTETTwoKeyNav/PropertyInt16", "ESKeyNav");
}
@Test(expected = UriParserSemanticException.class)
public void valueMustBeLastSegment() throws Exception {
validate("ESMedia(1)/$value/PropertyInt16", null, null, null);
mustValidate("ESMedia(1)/$value/PropertyInt16", "ESMedia");
}
private void validate(final String uri, final String entitySetName, final String ifMatch, final String ifNoneMatch)
private boolean mustValidate(final String uri, final String entitySetName)
throws UriParserException, PreconditionException {
final UriInfo uriInfo = new Parser().parseUri(uri, null, null, edm);
final List<UriResource> parts = uriInfo.getUriResourceParts();
@ -207,15 +210,6 @@ public class PreconditionsValidatorTest {
when(support.hasETag(any(EdmBindingTarget.class))).thenAnswer(answer);
when(support.hasMediaETag(any(EdmBindingTarget.class))).thenAnswer(answer);
new PreconditionsValidator(support, uriInfo, ifMatch, ifNoneMatch).validatePreconditions(isMedia);
}
private void runException(final String uri) throws UriParserException {
try {
validate(uri, null, null, null);
fail("Expected a PreconditionRequiredException but was not thrown");
} catch (final PreconditionException e) {
assertEquals(PreconditionException.MessageKeys.MISSING_HEADER, e.getMessageKey());
}
return new PreconditionsValidator(uriInfo).mustValidatePreconditions(support, isMedia);
}
}