You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by il...@apache.org on 2014/03/24 10:42:08 UTC

[19/50] [abbrv] git commit: [OLINGO-214] Using Timestamp consistently for both V4 and V3 datetime types

[OLINGO-214] Using Timestamp consistently for both V4 and V3 datetime types


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

Branch: refs/heads/master
Commit: 130a49fed20c32a4f4d8272919e9bae4c9427d55
Parents: 5a15155
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Sat Mar 22 16:11:36 2014 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Sat Mar 22 16:11:36 2014 +0100

----------------------------------------------------------------------
 .../core/edm/primitivetype/EdmDateTime.java     | 89 +++++++++++---------
 .../edm/primitivetype/EdmDateTimeOffset.java    | 68 +++++++++++++--
 .../core/edm/primitivetype/EdmTimeOfDay.java    | 45 ++++++++--
 3 files changed, 147 insertions(+), 55 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/130a49fe/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTime.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTime.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTime.java
index e061388..af2793b 100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTime.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTime.java
@@ -54,37 +54,43 @@ public final class EdmDateTime extends SingletonPrimitiveType {
           final Boolean isNullable, final Integer maxLength, final Integer precision,
           final Integer scale, final Boolean isUnicode, final Class<T> returnType) throws EdmPrimitiveTypeException {
 
-    Calendar calendar = null;
-    Timestamp timestamp = null;
-
     final String[] dateParts = value.split("\\.");
+
+    final Date date;
     try {
-      final Date date = DATE_FORMAT.get().parse(dateParts[0]);
-      if (dateParts.length > 1) {
-        int idx = dateParts[1].indexOf('+');
-        if (idx == -1) {
-          idx = dateParts[1].indexOf('-');
-        }
-        if (idx == -1) {
-          calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
-          calendar.setTime(date);
-
-          timestamp = new Timestamp(calendar.getTimeInMillis());
-          timestamp.setNanos(Integer.parseInt(dateParts[1]));
-        } else {
-          calendar = Calendar.getInstance(TimeZone.getTimeZone(dateParts[1].substring(idx)));
-          calendar.setTime(date);
-
-          timestamp = new Timestamp(calendar.getTimeInMillis());
-          timestamp.setNanos(Integer.parseInt(dateParts[1].substring(0, idx)));
-        }
-      } else {
-        timestamp = new Timestamp(date.getTime());
-      }
+      date = DATE_FORMAT.get().parse(dateParts[0]);
     } catch (Exception e) {
       throw new EdmPrimitiveTypeException("EdmPrimitiveTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value)", e);
     }
 
+    TimeZone timezone = null;
+    Integer fractionalSecs = null;
+    if (dateParts.length > 1) {
+      int idx = dateParts[1].indexOf('+');
+      if (idx == -1) {
+        idx = dateParts[1].indexOf('-');
+      }
+      if (idx == -1) {
+        fractionalSecs = Integer.parseInt(dateParts[1]);
+      } else {
+        timezone = TimeZone.getTimeZone(dateParts[1].substring(idx));
+        fractionalSecs = Integer.parseInt(dateParts[1].substring(0, idx));
+      }
+    }
+
+    if (fractionalSecs != null && String.valueOf(fractionalSecs).length() > (precision == null ? 0 : precision)) {
+      throw new EdmPrimitiveTypeException(
+              "EdmPrimitiveTypeException.LITERAL_FACETS_NOT_MATCHED.addContent(value, facets)");
+    }
+
+    final Calendar calendar = timezone == null ? Calendar.getInstance() : Calendar.getInstance(timezone);
+    calendar.setTime(date);
+    final Timestamp timestamp = new Timestamp(date.getTime());
+    if (fractionalSecs != null) {
+      calendar.set(Calendar.MILLISECOND, fractionalSecs);
+      timestamp.setNanos(fractionalSecs);
+    }
+
     if (returnType.isAssignableFrom(Calendar.class)) {
       return returnType.cast(calendar);
     } else if (returnType.isAssignableFrom(Timestamp.class)) {
@@ -100,25 +106,32 @@ public final class EdmDateTime extends SingletonPrimitiveType {
           final Boolean isNullable, final Integer maxLength, final Integer precision,
           final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {
 
+    Date date = null;
+    Integer fractionalSecs = null;
     if (value instanceof Calendar) {
       final Calendar calendar = (Calendar) value;
-
-      final StringBuilder formatted = new StringBuilder().append(DATE_FORMAT.get().format(calendar.getTime()));
-      formatted.append(calendar.getTimeZone());
-
-      return formatted.toString();
-    } else if (value instanceof Timestamp) {
+      date = calendar.getTime();
+      fractionalSecs = calendar.get(Calendar.MILLISECOND);
+    }
+    if (value instanceof Timestamp) {
       final Timestamp timestamp = (Timestamp) value;
+      date = new Date(timestamp.getTime());
+      fractionalSecs = timestamp.getNanos();
+    }
 
-      final StringBuilder formatted = new StringBuilder().append(DATE_FORMAT.get().format(timestamp));
-      if (timestamp.getNanos() > 0) {
-        formatted.append('.').append(String.valueOf(timestamp.getNanos()));
-      }
+    final StringBuilder result = new StringBuilder().append(DATE_FORMAT.get().format(date));
 
-      return formatted.toString();
-    } else {
+    try {
+      if (value instanceof Timestamp) {
+        EdmDateTimeOffset.appendFractionalSeconds(result, fractionalSecs, precision);
+      } else {
+        EdmDateTimeOffset.appendMilliseconds(result, fractionalSecs, precision);
+      }
+    } catch (final IllegalArgumentException e) {
       throw new EdmPrimitiveTypeException(
-              "EdmPrimitiveTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(value.getClass())");
+              "EdmPrimitiveTypeException.VALUE_FACETS_NOT_MATCHED.addContent(value, facets)", e);
     }
+
+    return result.toString();
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/130a49fe/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java
----------------------------------------------------------------------
diff --git 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
index 7a511d6..f1b707f 100644
--- 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,6 +18,7 @@
  */
 package org.apache.olingo.commons.core.edm.primitivetype;
 
+import java.sql.Timestamp;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.TimeZone;
@@ -33,7 +34,7 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
 
   private static final Pattern PATTERN = Pattern.compile(
           "(-?\\p{Digit}{4,})-(\\p{Digit}{2})-(\\p{Digit}{2})"
-          + "T(\\p{Digit}{2}):(\\p{Digit}{2})(?::(\\p{Digit}{2})(\\.(\\p{Digit}{0,3}?)0*)?)?"
+          + "T(\\p{Digit}{2}):(\\p{Digit}{2})(?::(\\p{Digit}{2})(\\.(\\p{Digit}{0,12}?)0*)?)?"
           + "(Z|([-+]\\p{Digit}{2}:\\p{Digit}{2}))?");
 
   private static final EdmDateTimeOffset INSTANCE = new EdmDateTimeOffset();
@@ -74,6 +75,10 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
             Byte.parseByte(matcher.group(5)),
             matcher.group(6) == null ? 0 : Byte.parseByte(matcher.group(6)));
 
+    // cloning the original Calendar instance to avoid vanishing the Calendar value check - triggered by any
+    // get method - empowered by the convertDateTime() method below
+    final Timestamp timestamp = new Timestamp(((Calendar) dateTimeValue.clone()).getTimeInMillis());
+
     if (matcher.group(7) != null) {
       if (matcher.group(7).length() == 1 || matcher.group(7).length() > 13) {
         throw new EdmPrimitiveTypeException(
@@ -84,18 +89,28 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
         throw new EdmPrimitiveTypeException(
                 "EdmPrimitiveTypeException.LITERAL_FACETS_NOT_MATCHED.addContent(value, facets)");
       }
-      final String milliSeconds = decimals + "000".substring(decimals.length());
+      final String milliSeconds = decimals.length() > 3
+                                  ? decimals.substring(0, 3)
+                                  : decimals + "000".substring(decimals.length());
       dateTimeValue.set(Calendar.MILLISECOND, Short.parseShort(milliSeconds));
+
+      if (!decimals.isEmpty()) {
+        timestamp.setNanos(Integer.parseInt(decimals));
+      }
+    }
+
+    if (returnType.isAssignableFrom(Timestamp.class)) {
+      return returnType.cast(timestamp);
     }
 
     try {
       return convertDateTime(dateTimeValue, returnType);
     } catch (final IllegalArgumentException e) {
       throw new EdmPrimitiveTypeException(
-              "EdmPrimitiveTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value), e");
+              "EdmPrimitiveTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value)", e);
     } catch (final ClassCastException e) {
       throw new EdmPrimitiveTypeException(
-              "EdmPrimitiveTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType), e");
+              "EdmPrimitiveTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType)", e);
     }
   }
 
@@ -138,9 +153,19 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
           final Boolean isNullable, final Integer maxLength, final Integer precision,
           final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {
 
-    final Calendar dateTimeValue = createDateTime(value);
+    final Calendar dateTimeValue;
+    final int fractionalSecs;
+    if (value instanceof Timestamp) {
+      final Calendar tmp = Calendar.getInstance();
+      tmp.setTimeInMillis(((Timestamp) value).getTime());
+      dateTimeValue = createDateTime(tmp);
+      fractionalSecs = ((Timestamp) value).getNanos();
+    } else {
+      dateTimeValue = createDateTime(value);
+      fractionalSecs = dateTimeValue.get(Calendar.MILLISECOND);
+    }
 
-    final StringBuilder result = new StringBuilder(23); // 23 characters are enough for millisecond precision.
+    final StringBuilder result = new StringBuilder();
     final int year = dateTimeValue.get(Calendar.YEAR);
     appendTwoDigits(result, year / 100);
     appendTwoDigits(result, year % 100);
@@ -156,10 +181,14 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
     appendTwoDigits(result, dateTimeValue.get(Calendar.SECOND));
 
     try {
-      appendMilliseconds(result, dateTimeValue.get(Calendar.MILLISECOND), precision);
+      if (value instanceof Timestamp) {
+        appendFractionalSeconds(result, fractionalSecs, precision);
+      } else {
+        appendMilliseconds(result, fractionalSecs, precision);
+      }
     } catch (final IllegalArgumentException e) {
       throw new EdmPrimitiveTypeException(
-              "EdmPrimitiveTypeException.VALUE_FACETS_NOT_MATCHED.addContent(value, facets), e");
+              "EdmPrimitiveTypeException.VALUE_FACETS_NOT_MATCHED.addContent(value, facets)", e);
     }
 
     final int offsetInMinutes = (dateTimeValue.get(Calendar.ZONE_OFFSET)
@@ -218,8 +247,9 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
    * @param result a {@link StringBuilder}
    * @param milliseconds an integer that must satisfy <code>0 &lt;= milliseconds &lt;= 999</code>
    * @param precision the upper limit for decimal digits (optional, defaults to zero)
+   * @throws IllegalArgumentException if precision is not met
    */
-  protected static void appendMilliseconds(final StringBuilder result, final long milliseconds,
+  protected static void appendMilliseconds(final StringBuilder result, final int milliseconds,
           final Integer precision) throws IllegalArgumentException {
     final int digits = milliseconds % 1000 == 0 ? 0 : milliseconds % 100 == 0 ? 1 : milliseconds % 10 == 0 ? 2 : 3;
     if (digits > 0) {
@@ -236,4 +266,24 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
       }
     }
   }
+
+  /**
+   * 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) {
+      if (precision == null || precision < String.valueOf(fractionalSeconds).length()) {
+        throw new IllegalArgumentException();
+      }
+
+      result.append('.').append(fractionalSeconds);
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata4/blob/130a49fe/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java
----------------------------------------------------------------------
diff --git 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
index 7d8cf9e..2003b09 100644
--- 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,6 +18,7 @@
  */
 package org.apache.olingo.commons.core.edm.primitivetype;
 
+import java.sql.Timestamp;
 import java.util.Calendar;
 import java.util.TimeZone;
 import java.util.regex.Matcher;
@@ -28,7 +29,7 @@ import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 public final class EdmTimeOfDay extends SingletonPrimitiveType {
 
   private static final Pattern PATTERN = Pattern.compile(
-          "(\\p{Digit}{2}):(\\p{Digit}{2})(?::(\\p{Digit}{2})(\\.(\\p{Digit}{0,3}?)0*)?)?");
+          "(\\p{Digit}{2}):(\\p{Digit}{2})(?::(\\p{Digit}{2})(\\.(\\p{Digit}{0,}?)0*)?)?");
 
   private static final EdmTimeOfDay INSTANCE = new EdmTimeOfDay();
 
@@ -57,6 +58,10 @@ public final class EdmTimeOfDay extends SingletonPrimitiveType {
     dateTimeValue.set(Calendar.MINUTE, Byte.parseByte(matcher.group(2)));
     dateTimeValue.set(Calendar.SECOND, matcher.group(3) == null ? 0 : Byte.parseByte(matcher.group(3)));
 
+    // cloning the original Calendar instance to avoid vanishing the Calendar value check - triggered by any
+    // get method - empowered by the convertDateTime() method below
+    final Timestamp timestamp = new Timestamp(((Calendar) dateTimeValue.clone()).getTimeInMillis());
+
     if (matcher.group(4) != null) {
       if (matcher.group(4).length() == 1 || matcher.group(4).length() > 13) {
         throw new EdmPrimitiveTypeException("EdmPrimitiveTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value)");
@@ -66,18 +71,28 @@ public final class EdmTimeOfDay extends SingletonPrimitiveType {
         throw new EdmPrimitiveTypeException(
                 "EdmPrimitiveTypeException.LITERAL_FACETS_NOT_MATCHED.addContent(value, facets)");
       }
-      final String milliSeconds = decimals + "000".substring(decimals.length());
+      final String milliSeconds = decimals.length() > 3
+                                  ? decimals.substring(0, 3)
+                                  : decimals + "000".substring(decimals.length());
       dateTimeValue.set(Calendar.MILLISECOND, Short.parseShort(milliSeconds));
+
+      if (!decimals.isEmpty()) {
+        timestamp.setNanos(Integer.parseInt(decimals));
+      }
+    }
+
+    if (returnType.isAssignableFrom(Timestamp.class)) {
+      return returnType.cast(timestamp);
     }
 
     try {
       return EdmDateTimeOffset.convertDateTime(dateTimeValue, returnType);
     } catch (final IllegalArgumentException e) {
       throw new EdmPrimitiveTypeException(
-              "EdmPrimitiveTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value), e");
+              "EdmPrimitiveTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value)", e);
     } catch (final ClassCastException e) {
       throw new EdmPrimitiveTypeException(
-              "EdmPrimitiveTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType), e");
+              "EdmPrimitiveTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType)", e);
     }
   }
 
@@ -86,9 +101,19 @@ public final class EdmTimeOfDay extends SingletonPrimitiveType {
           final Boolean isNullable, final Integer maxLength, final Integer precision,
           final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {
 
-    final Calendar dateTimeValue = EdmDateTimeOffset.createDateTime(value);
+    final Calendar dateTimeValue;
+    final int fractionalSecs;
+    if (value instanceof Timestamp) {
+      final Calendar tmp = Calendar.getInstance();
+      tmp.setTimeInMillis(((Timestamp) value).getTime());
+      dateTimeValue = EdmDateTimeOffset.createDateTime(tmp);
+      fractionalSecs = ((Timestamp) value).getNanos();
+    } else {
+      dateTimeValue = EdmDateTimeOffset.createDateTime(value);
+      fractionalSecs = dateTimeValue.get(Calendar.MILLISECOND);
+    }
 
-    final StringBuilder result = new StringBuilder(8); // Eight characters are enough for "normal" times.
+    final StringBuilder result = new StringBuilder();
     EdmDateTimeOffset.appendTwoDigits(result, dateTimeValue.get(Calendar.HOUR_OF_DAY));
     result.append(':');
     EdmDateTimeOffset.appendTwoDigits(result, dateTimeValue.get(Calendar.MINUTE));
@@ -96,10 +121,14 @@ public final class EdmTimeOfDay extends SingletonPrimitiveType {
     EdmDateTimeOffset.appendTwoDigits(result, dateTimeValue.get(Calendar.SECOND));
 
     try {
-      EdmDateTimeOffset.appendMilliseconds(result, dateTimeValue.get(Calendar.MILLISECOND), precision);
+      if (value instanceof Timestamp) {
+        EdmDateTimeOffset.appendFractionalSeconds(result, fractionalSecs, precision);
+      } else {
+        EdmDateTimeOffset.appendMilliseconds(result, fractionalSecs, precision);
+      }
     } catch (final IllegalArgumentException e) {
       throw new EdmPrimitiveTypeException(
-              "EdmPrimitiveTypeException.VALUE_FACETS_NOT_MATCHED.addContent(value, facets), e");
+              "EdmPrimitiveTypeException.VALUE_FACETS_NOT_MATCHED.addContent(value, facets)", e);
     }
 
     return result.toString();