You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by mi...@apache.org on 2016/02/13 07:33:57 UTC

[03/22] olingo-odata4 git commit: OLINGO-864: Refining the Edm.Date and Edm.Time behavior not to assume GMT

OLINGO-864: Refining the Edm.Date and Edm.Time behavior not to assume GMT


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

Branch: refs/heads/OLINGO-832_StreamSerializerPoC
Commit: f63bba70ad4c63a621b5a8e8186d50c172263989
Parents: b317b90 382ec16
Author: Ramesh Reddy <ra...@jboss.org>
Authored: Wed Feb 3 11:48:04 2016 -0600
Committer: Ramesh Reddy <ra...@jboss.org>
Committed: Wed Feb 3 11:48:04 2016 -0600

----------------------------------------------------------------------
 .../client/AbstractParamTecSvcITCase.java       | 14 ++++
 .../commons/core/edm/primitivetype/EdmDate.java |  5 +-
 .../edm/primitivetype/EdmDateTimeOffset.java    | 75 +++++++++++++-------
 .../core/edm/primitivetype/EdmTimeOfDay.java    | 20 ++----
 .../core/edm/primitivetype/EdmDateTest.java     |  1 -
 .../primitivetype/EdmDateTimeOffsetTest.java    |  9 ++-
 .../edm/primitivetype/EdmTimeOfDayTest.java     | 23 ++++--
 .../olingo/server/tecsvc/data/DataProvider.java |  6 ++
 .../server/tecsvc/data/DataProviderTest.java    | 14 ++++
 9 files changed, 115 insertions(+), 52 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f63bba70/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/AbstractParamTecSvcITCase.java
----------------------------------------------------------------------
diff --cc fit/src/test/java/org/apache/olingo/fit/tecsvc/client/AbstractParamTecSvcITCase.java
index d6e35a3,0000000..a4d8a67
mode 100644,000000..100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/AbstractParamTecSvcITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/AbstractParamTecSvcITCase.java
@@@ -1,66 -1,0 +1,80 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements. See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership. The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License. You may obtain a copy of the License at
 + *
 + * http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied. See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.olingo.fit.tecsvc.client;
 +
 +import static org.hamcrest.CoreMatchers.startsWith;
 +import static org.junit.Assert.assertEquals;
 +import static org.junit.Assert.assertThat;
 +import static org.junit.Assert.assertTrue;
 +
 +import java.util.Arrays;
 +import java.util.List;
++import java.util.TimeZone;
 +
 +import org.apache.olingo.commons.api.format.ContentType;
++import org.apache.olingo.server.tecsvc.data.DataProvider;
++import org.junit.After;
++import org.junit.Before;
 +import org.junit.runner.RunWith;
 +import org.junit.runners.Parameterized;
 +
 +@RunWith(Parameterized.class)
 +public abstract class AbstractParamTecSvcITCase extends AbstractTecSvcITCase {
 +
 +  @Parameterized.Parameter
 +  public ContentType contentType;
 +
 +  /**
 +   * Returns a list of parameter arrays, in this case a list of one-element arrays
 +   * containing the content types to be used.
 +   */
 +  @Parameterized.Parameters(name = "{0}")
 +  public static List<ContentType[]> parameters() {
 +    return Arrays.asList(new ContentType[] { ContentType.APPLICATION_JSON },
 +        new ContentType[] { ContentType.APPLICATION_XML });
 +  }
 +
 +  @Override
 +  protected ContentType getContentType() {
 +    return contentType;
 +  }
 +
 +  protected void assertContentType(final String content) {
 +    assertThat(content, startsWith(contentType.toContentTypeString()));
 +  }
 +
 +  protected boolean isJson() {
 +    return ContentType.JSON.isCompatible(contentType);
 +  }
 +
 +  protected void assertShortOrInt(final int value, final Object n) {
 +    assertTrue(n instanceof Number);
 +    assertEquals(value, ((Number) n).intValue());
 +  }
++  
++  @Before
++  public void setup() {
++    DataProvider.setDefaultTimeZone("GMT");
++  }
++  
++  @After
++  public void teardown() {
++    DataProvider.setDefaultTimeZone(TimeZone.getDefault().getID());
++  }  
 +}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f63bba70/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDate.java
----------------------------------------------------------------------
diff --cc lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDate.java
index 3eddca0,fb3f4ad..8588a5c
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDate.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDate.java
@@@ -18,8 -18,9 +18,7 @@@
   */
  package org.apache.olingo.commons.core.edm.primitivetype;
  
 -import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 -
  import java.util.Calendar;
- import java.util.TimeZone;
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
  

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f63bba70/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java
----------------------------------------------------------------------
diff --cc lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java
index a7f57d1,95b0fa5..63c2c3c
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java
@@@ -18,16 -18,17 +18,17 @@@
   */
  package org.apache.olingo.commons.core.edm.primitivetype;
  
+ import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+ 
  import java.sql.Time;
  import java.sql.Timestamp;
 -import java.text.DecimalFormat;
  import java.util.Calendar;
  import java.util.Date;
  import java.util.TimeZone;
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
  
- import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 +
  /**
   * Implementation of the EDM primitive type DateTimeOffset.
   */
@@@ -60,8 -68,8 +61,9 @@@ public final class EdmDateTimeOffset ex
      }
  
      final String timeZoneOffset = matcher.group(9) == null || matcher.group(10) == null
 -            || matcher.group(10).matches("[-+]0+:0+") ? null : matcher.group(10);
 -    final Calendar dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT" + timeZoneOffset));
 +        || matcher.group(10).matches("[-+]0+:0+") ? null : matcher.group(10);
-     final Calendar dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT" + timeZoneOffset));
++    final TimeZone tz = TimeZone.getTimeZone("GMT" + ((timeZoneOffset == null) ? "" : timeZoneOffset));
++    final Calendar dateTimeValue = Calendar.getInstance(tz);
      if (dateTimeValue.get(Calendar.ZONE_OFFSET) == 0 && timeZoneOffset != null) {
        throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.");
      }
@@@ -150,19 -170,12 +165,12 @@@
  
    @Override
    protected <T> String internalValueToString(final T value,
 -          final Boolean isNullable, final Integer maxLength, final Integer precision,
 -          final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {
 +      final Boolean isNullable, final Integer maxLength, final Integer precision,
 +      final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {
  
-     Calendar dateTimeValue;
-     if (value instanceof Timestamp) {
-       final Calendar tmp = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
-       tmp.setTimeInMillis(((Timestamp) value).getTime());
-       dateTimeValue = createDateTime(tmp);
-     } else {
-       dateTimeValue = createDateTime(value);
-     }
- 
-     StringBuilder result = new StringBuilder();
+     final Calendar dateTimeValue = createDateTime(value, false);
+     
+     final StringBuilder result = new StringBuilder();
      final int year = dateTimeValue.get(Calendar.YEAR);
      appendTwoDigits(result, year / 100);
      appendTwoDigits(result, year % 100);
@@@ -269,4 -286,49 +283,17 @@@
        }
      }
    }
+ 
+   /**
 -   * Appends the given fractional seconds to the given string builder.
 -   *
 -   * @param result a {@link StringBuilder}
 -   * @param fractionalSeconds fractional seconds
 -   * @param precision the upper limit for decimal digits (optional, defaults to zero)
 -   * @throws IllegalArgumentException if precision is not met
 -   */
 -  protected static void appendFractionalSeconds(final StringBuilder result, final int fractionalSeconds,
 -          final Integer precision) throws IllegalArgumentException {
 -
 -    if (fractionalSeconds > 0) {
 -      String formatted = NANO_FORMAT.get().format(fractionalSeconds);
 -      int actualLength = formatted.length();
 -      boolean nonZeroFound = false;
 -      for (int i = formatted.length() - 1; i >= 0 && !nonZeroFound; i--) {
 -        if ('0' == formatted.charAt(i)) {
 -          actualLength--;
 -        } else {
 -          nonZeroFound = true;
 -        }
 -      }
 -
 -      if (precision == null || precision < actualLength) {
 -        throw new IllegalArgumentException();
 -      }
 -
 -      result.append('.').append(formatted.substring(0, actualLength));
 -    }
 -  }
 -  
 -  /**
+    * When the Timezone information is absent on the date time types, like EdmDate, EDMTimeOfDay, EdmDateTimeOffset
+    * this method defines the default timezone that should be used parse and output payload.
+    * User should set system property "defaultTimeZoneForEdmDateTypes" to control this. The default would be
+    * Java VM default if not defined.
+    *   
+    * @return Timezone
+    */
+   protected static TimeZone getDefaultTimeZone() {
+     String tz = System.getProperty("defaultTimeZoneForEdmDateTypes");
 -	return (tz != null)?TimeZone.getTimeZone(tz):TimeZone.getDefault();
 -  }
 -    
++	  return (tz != null)?TimeZone.getTimeZone(tz):TimeZone.getDefault();
++  }  
  }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f63bba70/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java
----------------------------------------------------------------------
diff --cc lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java
index 7595e51,3090761..06ba239
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java
@@@ -18,9 -18,10 +18,8 @@@
   */
  package org.apache.olingo.commons.core.edm.primitivetype;
  
 -import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 -
  import java.sql.Timestamp;
  import java.util.Calendar;
- import java.util.TimeZone;
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
  
@@@ -112,7 -101,13 +101,8 @@@ public final class EdmTimeOfDay extend
      EdmDateTimeOffset.appendTwoDigits(result, dateTimeValue.get(Calendar.SECOND));
  
      try {
-       EdmDateTimeOffset.appendFractionalSeconds(result, fractionalSecs, value instanceof Timestamp, precision);
 -      if (value instanceof Timestamp) {
 -    	int fractionalSecs = ((Timestamp) value).getNanos();
 -        EdmDateTimeOffset.appendFractionalSeconds(result, fractionalSecs, precision);
 -      } else {
 -        int fractionalSecs = dateTimeValue.get(Calendar.MILLISECOND);
 -        EdmDateTimeOffset.appendMilliseconds(result, fractionalSecs, precision);
 -      }
++      EdmDateTimeOffset.appendFractionalSeconds(result,
++          dateTimeValue.get(Calendar.MILLISECOND), value instanceof Timestamp, precision);
      } catch (final IllegalArgumentException e) {
        throw new EdmPrimitiveTypeException("The value '" + value + "' does not match the facets' constraints.", e);
      }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f63bba70/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f63bba70/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffsetTest.java
----------------------------------------------------------------------
diff --cc lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffsetTest.java
index a352703,0b51925..5f2da25
--- a/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffsetTest.java
+++ b/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffsetTest.java
@@@ -18,10 -18,10 +18,9 @@@
   */
  package org.apache.olingo.commons.core.edm.primitivetype;
  
 -import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
 -import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
 -import org.junit.Test;
 +import static org.junit.Assert.assertEquals;
- import static org.junit.Assert.assertTrue;
  
 +import java.sql.Time;
  import java.sql.Timestamp;
  import java.util.Calendar;
  import java.util.Date;
@@@ -76,22 -74,12 +75,21 @@@ public class EdmDateTimeOffsetTest exte
      assertEquals("2012-02-29T23:32:03.007Z", instance.valueToString(millis, null, null, 3, null, null));
      assertEquals("1969-12-31T23:59:59.9Z", instance.valueToString(-100L, null, null, 1, null, null));
      assertEquals("1969-12-31T23:59:59.98Z", instance.valueToString(-20L, null, null, 2, null, null));
 -
 +    
 +    assertEquals("2012-02-29T23:32:03.007Z", instance.valueToString(new Time(millis), null, null, 3, null, null));
 +    assertEquals("1969-12-31T23:59:59.9Z", instance.valueToString(new Time(-100L), null, null, 1, null, null));
 +    assertEquals("1969-12-31T23:59:59.98Z", instance.valueToString(new Time(-20L), null, null, 2, null, null));
 +    
      final Date date = new Date(millis);
-     final String time = date.toString().substring(11, 19);
-     assertTrue(instance.valueToString(date, null, null, 3, null, null).contains(time));
+     assertEquals("2012-02-29T23:32:03.007Z", instance.valueToString(date, null, null, 3, null, null));
  
 +    Timestamp timestamp = new Timestamp(0);
 +    timestamp.setNanos(120);
 +    assertEquals("1970-01-01T00:00:00.00000012Z", instance.valueToString(timestamp, null, null, 8, null, null));
 +
      expectFacetsErrorInValueToString(instance, millis, null, null, null, null, null);
      expectFacetsErrorInValueToString(instance, 3L, null, null, 2, null, null);
 +    expectFacetsErrorInValueToString(instance, timestamp, null, null, 7, null, null);
  
      expectTypeErrorInValueToString(instance, 0);
    }
@@@ -133,14 -121,7 +131,15 @@@
          Long.class));
      assertEquals(Long.valueOf(120L), instance.valueOfString("1970-01-01T00:00:00.12", null, null, 2, null, null,
          Long.class));
 -
 +    
 +    assertEquals(new Time(120000L), instance.valueOfString("1970-01-01T00:02", null, null, null, null, null,
 +        Time.class));
-     assertEquals(new Time(12L), instance.valueOfString("1970-01-01T00:00:00.012", null, null, 3, null, null,
++    // 0L because java.sql.Time does not keep track of fraction of milliseconds
++    assertEquals(new Time(0L), instance.valueOfString("1970-01-01T00:00:00.012", null, null, 3, null, null,
 +        Time.class));
-     assertEquals(new Time(120L), instance.valueOfString("1970-01-01T00:00:00.12", null, null, 2, null, null,
++    assertEquals(new Time(0L), instance.valueOfString("1970-01-01T00:00:00.12", null, null, 2, null, null,
 +        Time.class));
 +    
      expectFacetsErrorInValueOfString(instance, "2012-02-29T23:32:02.9Z", null, null, null, null, null);
      expectFacetsErrorInValueOfString(instance, "2012-02-29T23:32:02.9Z", null, null, 0, null, null);
      expectContentErrorInValueOfString(instance, "2012-02-29T23:32:02X");

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f63bba70/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDayTest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f63bba70/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
----------------------------------------------------------------------
diff --cc lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
index 20cbf94,878efce..5190c71
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
@@@ -512,151 -473,55 +512,157 @@@ public class DataProvider 
      entity.getProperties().remove(entity.getProperty(MEDIA_PROPERTY_NAME));
      entity.addProperty(DataCreator.createPrimitive(MEDIA_PROPERTY_NAME, media));
      entity.setMediaContentType(type);
 +    entity.setMediaETag("W/\"" + UUID.randomUUID() + "\"");
 +  }
 +
 +  public EntityCollection readFunctionEntityCollection(final EdmFunction function, final List<UriParameter> parameters,
 +      final UriInfoResource uriInfo) throws DataProviderException {
 +    return FunctionData.entityCollectionFunction(function.getName(),
 +        getFunctionParameters(function, parameters, uriInfo),
 +        data);
 +  }
 +
 +  public Entity readFunctionEntity(final EdmFunction function, final List<UriParameter> parameters,
 +      final UriInfoResource uriInfo) throws DataProviderException {
 +    return FunctionData.entityFunction(function.getName(),
 +        getFunctionParameters(function, parameters, uriInfo),
 +        data);
 +  }
 +
 +  public Property readFunctionPrimitiveComplex(final EdmFunction function, final List<UriParameter> parameters,
 +      final UriInfoResource uriInfo) throws DataProviderException {
 +    return FunctionData.primitiveComplexFunction(function.getName(),
 +        getFunctionParameters(function, parameters, uriInfo),
 +        data);
 +  }
 +
 +  private Map<String, Parameter> getFunctionParameters(final EdmFunction function,
 +      final List<UriParameter> parameters, final UriInfoResource uriInfo) throws DataProviderException {
 +    Map<String, Parameter> values = new HashMap<String, Parameter>();
 +    for (final UriParameter parameter : parameters) {
 +      final EdmParameter edmParameter = function.getParameter(parameter.getName());
 +      final String text = parameter.getAlias() == null ?
 +          parameter.getText() :
 +          uriInfo.getValueForAlias(parameter.getAlias());
 +      if (text != null) {
 +        try {
 +          values.put(parameter.getName(),
 +              odata.createFixedFormatDeserializer().parameter(text, edmParameter));
 +        } catch (final DeserializerException e) {
 +          throw new DataProviderException("Invalid function parameter.", HttpStatusCode.BAD_REQUEST, e);
 +        }
 +      }
 +    }
 +    return values;
    }
  
 -  public EntityCollection readFunctionEntitySet(final EdmFunction function, final List<UriParameter> parameters)
 +  public Property processActionPrimitive(final String name, final Map<String, Parameter> actionParameters)
        throws DataProviderException {
 -    return FunctionData.entityCollectionFunction(function.getName(), parameters, data);
 +    return ActionData.primitiveAction(name, actionParameters);
    }
  
 -  public Entity readFunctionEntity(final EdmFunction function, final List<UriParameter> parameters)
 +  public Property processActionComplex(final String name, final Map<String, Parameter> actionParameters)
        throws DataProviderException {
 -    return FunctionData.entityFunction(function.getName(), parameters, data);
 +    return ActionData.complexAction(name, actionParameters);
    }
  
 -  public Property readFunctionPrimitiveComplex(final EdmFunction function, final List<UriParameter> parameters)
 +  public Property processActionComplexCollection(final String name, final Map<String, Parameter> actionParameters)
        throws DataProviderException {
 -    return FunctionData.primitiveComplexFunction(function.getName(), parameters, data);
 +    return ActionData.complexCollectionAction(name, actionParameters);
    }
  
 -  public Property processActionPrimitive(String name, Map<String, Parameter> actionParameters)
 +  public Property processActionPrimitiveCollection(final String name, final Map<String, Parameter> actionParameters)
        throws DataProviderException {
 -    return ActionData.primitiveAction(name, actionParameters);
 +    return ActionData.primitiveCollectionAction(name, actionParameters, odata);
    }
  
 -  public Property processActionPrimitiveCollection(String name, Map<String, Parameter> actionParameters)
 +  public EntityActionResult processActionEntity(final String name, final Map<String, Parameter> actionParameters)
        throws DataProviderException {
 -    return ActionData.primitiveCollectionAction(name, actionParameters);
 +    return ActionData.entityAction(name, actionParameters, data, odata, edm);
    }
  
 -  public void setEdm(final Edm edm) {
 -    this.edm = edm;
 +  public EntityCollection processActionEntityCollection(final String name,
 +      final Map<String, Parameter> actionParameters) throws DataProviderException {
 +    return ActionData.entityCollectionAction(name, actionParameters, odata, edm);
    }
  
 -  public void setOData(final OData odata) {
 -    this.odata = odata;
 +  public void createReference(final Entity entity, final EdmNavigationProperty navigationProperty, final URI entityId,
 +      final String rawServiceRoot) throws DataProviderException {
 +    setLink(navigationProperty, entity, getEntityByReference(entityId.toASCIIString(), rawServiceRoot));
    }
  
 -  public static class DataProviderException extends ODataApplicationException {
 -    private static final long serialVersionUID = 5098059649321796156L;
 +  public void deleteReference(final Entity entity, final EdmNavigationProperty navigationProperty,
 +      final String entityId, final String rawServiceRoot) throws DataProviderException {
  
 -    public DataProviderException(final String message, final Throwable throwable) {
 -      super(message, HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT, throwable);
 +    if (navigationProperty.isCollection()) {
 +      final Entity targetEntity = getEntityByReference(entityId, rawServiceRoot);
 +      final Link navigationLink = entity.getNavigationLink(navigationProperty.getName());
 +
 +      if (navigationLink != null && navigationLink.getInlineEntitySet() != null
 +          && navigationLink.getInlineEntitySet().getEntities().contains(targetEntity)) {
 +
 +        // Remove partner single-valued navigation property
 +        if (navigationProperty.getPartner() != null) {
 +          final EdmNavigationProperty edmPartnerNavigationProperty = navigationProperty.getPartner();
 +          if (!edmPartnerNavigationProperty.isCollection() && !edmPartnerNavigationProperty.isNullable()) {
 +            throw new DataProviderException("Navigation property must not be null", HttpStatusCode.BAD_REQUEST);
 +          } else if (!edmPartnerNavigationProperty.isCollection()) {
 +            removeLink(edmPartnerNavigationProperty, targetEntity);
 +          } else if (edmPartnerNavigationProperty.isCollection()
 +              && edmPartnerNavigationProperty.getPartner() != null) {
 +            // Bidirectional referential constraint
 +            final Link partnerNavigationLink = targetEntity.getNavigationLink(edmPartnerNavigationProperty.getName());
 +            if (partnerNavigationLink != null && partnerNavigationLink.getInlineEntitySet() != null) {
 +              partnerNavigationLink.getInlineEntitySet().getEntities().remove(entity);
 +            }
 +          }
 +        }
 +
 +        // Remove target entity from collection-valued navigation property
 +        navigationLink.getInlineEntitySet().getEntities().remove(targetEntity);
 +      } else {
 +        throw new DataProviderException("Entity not found", HttpStatusCode.NOT_FOUND);
 +      }
 +    } else {
 +      if (navigationProperty.isNullable()) {
 +        removeLink(navigationProperty, entity);
 +      } else {
 +        throw new DataProviderException("Navigation property must not be null", HttpStatusCode.BAD_REQUEST);
 +      }
      }
 +  }
  
 -    public DataProviderException(final String message) {
 -      super(message, HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
 +  protected Entity getEntityByReference(final String entityId, final String rawServiceRoot)
 +      throws DataProviderException {
 +    try {
 +      final UriResourceEntitySet uriResource = odata.createUriHelper().parseEntityId(edm, entityId, rawServiceRoot);
 +      final Entity targetEntity = read(uriResource.getEntitySet(), uriResource.getKeyPredicates());
 +
 +      if (targetEntity != null) {
 +        return targetEntity;
 +      } else {
 +        throw new DataProviderException("Entity not found", HttpStatusCode.NOT_FOUND);
 +      }
 +    } catch (DeserializerException e) {
 +      throw new DataProviderException("Invalid entity-id", HttpStatusCode.BAD_REQUEST, e);
      }
 +  }
  
 -    public DataProviderException(final String message, HttpStatusCode statusCode) {
 +  public static class DataProviderException extends ODataApplicationException {
 +    private static final long serialVersionUID = 5098059649321796156L;
 +
 +    public DataProviderException(final String message, final HttpStatusCode statusCode) {
        super(message, statusCode.getStatusCode(), Locale.ROOT);
      }
 +
 +    public DataProviderException(final String message, final HttpStatusCode statusCode, final Throwable throwable) {
 +      super(message, statusCode.getStatusCode(), Locale.ROOT, throwable);
 +    }
    }
+ 
++  //CHECKSTYLE:OFF
++  public static void setDefaultTimeZone(String tz) {
++    System.setProperty("defaultTimeZoneForEdmDateTypes", tz);
++  }
++  //CHECKSTYLE:ON
  }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/f63bba70/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java
----------------------------------------------------------------------
diff --cc lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java
index 6bd6463,c9a8e65..b2bf587
--- a/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java
+++ b/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java
@@@ -21,6 -21,6 +21,7 @@@ package org.apache.olingo.server.tecsvc
  import java.util.Arrays;
  import java.util.Collections;
  import java.util.List;
++import java.util.TimeZone;
  
  import org.apache.olingo.commons.api.data.ComplexValue;
  import org.apache.olingo.commons.api.data.Entity;
@@@ -33,7 -34,7 +34,9 @@@ import org.apache.olingo.server.api.ODa
  import org.apache.olingo.server.api.edmx.EdmxReference;
  import org.apache.olingo.server.api.uri.UriParameter;
  import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
++import org.junit.After;
  import org.junit.Assert;
++import org.junit.Before;
  import org.junit.Test;
  import org.mockito.Mockito;
  
@@@ -52,9 -53,9 +55,19 @@@ public class DataProviderTest 
    private final EdmEntitySet esMixPrimCollComp = entityContainer.getEntitySet("ESMixPrimCollComp");
    private final EdmEntitySet esMedia = entityContainer.getEntitySet("ESMedia");
  
++  @Before
++  public void setup() {
++    DataProvider.setDefaultTimeZone("GMT");
++  }
++  
++  @After
++  public void teardown() {
++    DataProvider.setDefaultTimeZone(TimeZone.getDefault().getID());
++  }
++  
    @Test
    public void esAllPrimEntity() throws Exception {
 -    final DataProvider dataProvider = new DataProvider();
 +    final DataProvider dataProvider = new DataProvider(oData, edm);
      final Entity entity = dataProvider.readAll(esAllPrim).getEntities().get(2);
      Assert.assertEquals(16, entity.getProperties().size());
  
@@@ -82,6 -83,6 +95,7 @@@
          mockParameter("PropertySByte", "127"),
          mockParameter("PropertyString", "'First'"),
          mockParameter("PropertyTimeOfDay", "02:48:21"))));
++    
    }
  
    @Test