[OLINGO-1408] Support new date time API (#57)

* Fix usage of Calendar in tests

The tests use Calendar instances. For some test cases the time zone of a
Calendar instance is changed and then passed to the valueToString
method.

Unfortunately after just changing the time zone the Calendar only
changes the time zone but not the value of the calculated fields like
YEAR, MONTH, ... . These fields are recalculated only if they are read
by get(YEAR), get(MONTH), ... . The implementation of valueToString
clones the Calendar instance before fields are computed resulting in
a corrupt clone.

This change

1) makes sure that the test the fields in the Calendar instances used
   in the tests are computed
2) makes sure that the valueToString method triggers a computation of
the fields before cloning the Calendar

* Support types of new Date/Time API

The types of the new Date/Time API can now be used as property values.

The following mappings are now supported

EdmDateTimeOffset
- java.time.Instant
- java.time.ZonedDateTime
- java.util.Calendar
- java.util.Date
- java.sql.Timestamp
- java.lang.Long

EdmDate
- java.time.LocalDate
- java.sql.Date

EdmTimeOfDay
- java.time.LocalTime
- java.sql.Time

Only these mappings capture the semantics correctly.

For legacy reasons also supported are the following mappings are still
supported:

EdmDate
- java.util.Calendar (date component in the TZ of the calendar)
- java.util.Date     (date component in UTC)
- java.sql.Timestamp (date component in UTC)
- java.lang.Long     (date component in UTC)

EdmTimeOfDay
- java.util.Calendar (time component in the TZ of the calendar)
- java.util.Date     (time component in UTC)
- java.sql.Timestamp (time component in UTC)
- java.lang.Long     (time component in UTC)

For legacy reasons the default mapping types are unchanged (and remain
semantically incorrect):

EdmDateTimeOffset -> java.sql.Timestamp
EdmDate           -> java.util.Calendar
EdmTimeOfDay      -> java.util.Calendar

* Allow additional (but semantically wrong) conversions

EdmDate -> java.util.Date, java.sql.Timestamp
EdmTimeOfDay -> java.util.Date, java.sql.Timestamp
This commit is contained in:
Adrian Görler 2019-11-25 19:32:58 +01:00 committed by mibo
parent 98d445a874
commit 932af8fb5d
8 changed files with 760 additions and 604 deletions

View File

@ -18,9 +18,15 @@
*/
package org.apache.olingo.commons.core.edm.primitivetype;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeParseException;
import java.util.Calendar;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.GregorianCalendar;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
@ -29,65 +35,80 @@ import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
*/
public final class EdmDate extends SingletonPrimitiveType {
private static final Pattern PATTERN = Pattern.compile("(-?\\p{Digit}{4,})-(\\p{Digit}{2})-(\\p{Digit}{2})");
private static final EdmDate INSTANCE = new EdmDate();
private static final EdmDate INSTANCE = new EdmDate();
public static EdmDate getInstance() {
return INSTANCE;
}
public static EdmDate getInstance() {
return INSTANCE;
}
@Override
public Class<?> getDefaultType() {
return Calendar.class;
}
@Override
public Class<?> getDefaultType() {
return Calendar.class;
}
@SuppressWarnings("unchecked")
@Override
protected <T> T internalValueOfString(final String value, final Boolean isNullable, final Integer maxLength,
final Integer precision, final Integer scale, final Boolean isUnicode, final Class<T> returnType)
throws EdmPrimitiveTypeException {
LocalDate date;
try {
date = LocalDate.parse(value);
} catch (DateTimeParseException ex) {
throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.");
}
@Override
protected <T> T internalValueOfString(final String value,
final Boolean isNullable, final Integer maxLength, final Integer precision,
final Integer scale, final Boolean isUnicode, final Class<T> returnType) throws EdmPrimitiveTypeException {
// appropriate types
if (returnType.isAssignableFrom(LocalDate.class)) {
return (T) date;
} else if (returnType.isAssignableFrom(java.sql.Date.class)) {
return (T) java.sql.Date.valueOf(date);
}
final Calendar dateTimeValue = Calendar.getInstance();
dateTimeValue.clear();
// inappropriate types, which need to be supported for backward compatibility
ZonedDateTime zdt = LocalDateTime.of(date, LocalTime.MIDNIGHT).atZone(ZoneId.systemDefault());
if (returnType.isAssignableFrom(Calendar.class)) {
return (T) GregorianCalendar.from(zdt);
} else if (returnType.isAssignableFrom(Long.class)) {
return (T) Long.valueOf(zdt.toInstant().toEpochMilli());
} else if (returnType.isAssignableFrom(java.sql.Date.class)) {
throw new EdmPrimitiveTypeException("The value type " + returnType + " is not supported.");
} else if (returnType.isAssignableFrom(java.sql.Timestamp.class)) {
return (T) java.sql.Timestamp.from(zdt.toInstant());
} else if (returnType.isAssignableFrom(java.util.Date.class)) {
return (T) java.util.Date.from(zdt.toInstant());
} else {
throw new EdmPrimitiveTypeException("The value type " + returnType + " is not supported.");
}
}
final Matcher matcher = PATTERN.matcher(value);
if (!matcher.matches()) {
throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.");
}
dateTimeValue.set(
Integer.parseInt(matcher.group(1)),
Byte.parseByte(matcher.group(2)) - 1, // month is zero-based
Byte.parseByte(matcher.group(3)));
try {
return EdmDateTimeOffset.convertDateTime(dateTimeValue, 0, returnType);
} catch (final IllegalArgumentException e) {
throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.", e);
} catch (final ClassCastException e) {
throw new EdmPrimitiveTypeException("The value type " + returnType + " is not supported.", e);
}
}
@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 Calendar dateTimeValue = EdmDateTimeOffset.createDateTime(value, true);
final StringBuilder result = new StringBuilder(10); // Ten characters are enough for "normal" dates.
final int year = dateTimeValue.get(Calendar.YEAR);
if (year < 0 || year >= 10000) {
result.append(year);
} else {
EdmDateTimeOffset.appendTwoDigits(result, (year / 100) % 100);
EdmDateTimeOffset.appendTwoDigits(result, year % 100);
}
result.append('-');
EdmDateTimeOffset.appendTwoDigits(result, dateTimeValue.get(Calendar.MONTH) + 1); // month is zero-based
result.append('-');
EdmDateTimeOffset.appendTwoDigits(result, dateTimeValue.get(Calendar.DAY_OF_MONTH));
return result.toString();
}
@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 {
// appropriate types
if (value instanceof LocalDate) {
return value.toString();
} else if(value instanceof java.sql.Date) {
return value.toString();
}
// inappropriate types, which need to be supported for backward compatibility
if (value instanceof GregorianCalendar) {
GregorianCalendar calendar = (GregorianCalendar) value;
return calendar.toZonedDateTime().toLocalDate().toString();
}
long millis;
if (value instanceof Long) {
millis = (Long)value;
} else if (value instanceof java.util.Date) {
millis = ((java.util.Date)value).getTime();
} else {
throw new EdmPrimitiveTypeException("The value type " + value.getClass() + " is not supported.");
}
ZonedDateTime zdt = Instant.ofEpochMilli(millis).atZone(ZoneId.systemDefault());
return zdt.toLocalDate().toString();
}
}

View File

@ -18,11 +18,16 @@
*/
package org.apache.olingo.commons.core.edm.primitivetype;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import java.util.GregorianCalendar;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -33,245 +38,144 @@ import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
*/
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,12}?)0*)?)?"
+ "(Z|([-+]\\p{Digit}{2}:\\p{Digit}{2}))?");
private static final ZoneId ZULU = ZoneId.of("Z");
private static final EdmDateTimeOffset INSTANCE = new EdmDateTimeOffset();
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,12}?)0*)?)?"
+ "(Z|([-+]\\p{Digit}{2}:\\p{Digit}{2}))?");
public static EdmDateTimeOffset getInstance() {
return INSTANCE;
}
private static final EdmDateTimeOffset INSTANCE = new EdmDateTimeOffset();
@Override
public Class<?> getDefaultType() {
return Timestamp.class;
}
public static EdmDateTimeOffset getInstance() {
return INSTANCE;
}
@Override
protected <T> T internalValueOfString(final String value,
final Boolean isNullable, final Integer maxLength, final Integer precision,
final Integer scale, final Boolean isUnicode, final Class<T> returnType) throws EdmPrimitiveTypeException {
@Override
public Class<?> getDefaultType() {
return Timestamp.class;
}
final Matcher matcher = PATTERN.matcher(value);
if (!matcher.matches()) {
throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.");
}
@Override
protected <T> T internalValueOfString(final String value, final Boolean isNullable, final Integer maxLength,
final Integer precision, final Integer scale, final Boolean isUnicode, final Class<T> returnType)
throws EdmPrimitiveTypeException {
try {
ZonedDateTime zdt = parseZonedDateTime(value);
final String timeZoneOffset = matcher.group(9) == null || matcher.group(10) == null
|| matcher.group(10).matches("[-+]0+:0+") ? "" : matcher.group(10);
final Calendar dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT" + timeZoneOffset));
if (dateTimeValue.get(Calendar.ZONE_OFFSET) == 0 && !timeZoneOffset.isEmpty()) {
throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.");
}
dateTimeValue.clear();
return convertZonedDateTime(zdt, returnType);
} catch (DateTimeParseException ex) {
throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.", ex);
} catch (final ClassCastException e) {
throw new EdmPrimitiveTypeException("The value type " + returnType + " is not supported.", e);
}
}
dateTimeValue.set(
Short.parseShort(matcher.group(1)),
Byte.parseByte(matcher.group(2)) - 1, // month is zero-based
Byte.parseByte(matcher.group(3)),
Byte.parseByte(matcher.group(4)),
Byte.parseByte(matcher.group(5)),
matcher.group(6) == null ? 0 : Byte.parseByte(matcher.group(6)));
private static ZonedDateTime parseZonedDateTime(final String value) {
ZonedDateTime zdt;
try {
// ISO-8601 conform pattern
zdt = ZonedDateTime.parse(value);
} catch (DateTimeParseException ex) {
// for backward compatibility - allow patterns that don't specify a time zone
final Matcher matcher = PATTERN.matcher(value);
if (matcher.matches() && matcher.group(9) == null) {
zdt = ZonedDateTime.parse(value + "Z");
} else {
throw ex;
}
}
return zdt;
}
int nanoSeconds = 0;
if (matcher.group(7) != null) {
if (matcher.group(7).length() == 1 || matcher.group(7).length() > 13) {
throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.");
}
final String decimals = matcher.group(8);
if (decimals.length() > (precision == null ? 0 : precision)) {
throw new EdmPrimitiveTypeException("The literal '" + value + "' does not match the facets' constraints.");
}
if (returnType.isAssignableFrom(Timestamp.class)) {
if (decimals.length() <= 9) {
nanoSeconds = Integer.parseInt(decimals + "000000000".substring(decimals.length()));
} else {
throw new EdmPrimitiveTypeException("The literal '" + value
+ "' cannot be converted to value type " + returnType + ".");
}
} else {
if (decimals.length() <= 3) {
final String milliSeconds = decimals + "000".substring(decimals.length());
dateTimeValue.set(Calendar.MILLISECOND, Short.parseShort(milliSeconds));
} else {
throw new EdmPrimitiveTypeException("The literal '" + value
+ "' cannot be converted to value type " + returnType + ".");
}
}
}
@SuppressWarnings("unchecked")
private static <T> T convertZonedDateTime(ZonedDateTime zdt, Class<T> returnType) {
if (returnType == ZonedDateTime.class) {
return (T) zdt;
} else if (returnType == Instant.class) {
return (T) zdt.toInstant();
} else if (returnType.isAssignableFrom(Timestamp.class)) {
return (T) Timestamp.from(zdt.toInstant());
} else if (returnType.isAssignableFrom(java.util.Date.class)) {
return (T) java.util.Date.from(zdt.toInstant());
} else if (returnType.isAssignableFrom(java.sql.Time.class)) {
return (T) new java.sql.Time(zdt.toInstant().truncatedTo(ChronoUnit.SECONDS).toEpochMilli());
} else if (returnType.isAssignableFrom(java.sql.Date.class)) {
return (T) new java.sql.Date(zdt.toInstant().truncatedTo(ChronoUnit.SECONDS).toEpochMilli());
} else if (returnType.isAssignableFrom(Long.class)) {
return (T) Long.valueOf(zdt.toInstant().toEpochMilli());
} else if (returnType.isAssignableFrom(Calendar.class)) {
return (T) GregorianCalendar.from(zdt);
} else {
throw new ClassCastException("unsupported return type " + returnType.getSimpleName());
}
}
try {
return convertDateTime(dateTimeValue, nanoSeconds, returnType);
} catch (final IllegalArgumentException e) {
throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.", e);
} catch (final ClassCastException e) {
throw new EdmPrimitiveTypeException("The value type " + returnType + " is not supported.", e);
}
}
@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 {
ZonedDateTime zdt = createZonedDateTime(value);
/**
* <p>Converts a {@link Calendar} value into the requested return type if possible.</p>
* <p>It is expected that the {@link Calendar} value will already be in the desired time zone.</p>
* @param dateTimeValue the value
* @param nanoSeconds nanoseconds part of the value; only used for the {@link Timestamp} return type
* @param returnType the class of the returned value;
* it must be one of {@link Calendar}, {@link Long}, {@link Date},
* {@link Time}, or {@link Timestamp}
* @return the converted value
* @throws IllegalArgumentException if the Calendar value is not valid
* @throws ClassCastException if the return type is not allowed
*/
protected static <T> T convertDateTime(final Calendar dateTimeValue, final int nanoSeconds,
final Class<T> returnType) throws IllegalArgumentException, ClassCastException {
return format(zdt.toLocalDateTime(), zdt.getOffset(), zdt.getNano());
}
// The Calendar class does not check any values until a get method is called,
// so we do just that to validate the fields that may have been set,
// not because we want to return something else.
// For strict checks, the lenient mode is switched off.
dateTimeValue.setLenient(false);
private static <T> ZonedDateTime createZonedDateTime(final T value) throws EdmPrimitiveTypeException {
if (value instanceof ZonedDateTime) {
return (ZonedDateTime) value;
}
if (returnType.isAssignableFrom(Calendar.class)) {
// Ensure that all fields are recomputed.
dateTimeValue.get(Calendar.MILLISECOND); // may throw IllegalArgumentException
// Reset the lenient mode to its default.
dateTimeValue.setLenient(true);
return returnType.cast(dateTimeValue);
} else if (returnType.isAssignableFrom(Long.class)) {
return returnType.cast(dateTimeValue.getTimeInMillis()); // may throw IllegalArgumentException
} else if (returnType.isAssignableFrom(Date.class)) {
return returnType.cast(dateTimeValue.getTime()); // may throw IllegalArgumentException
} else if (returnType.isAssignableFrom(Timestamp.class)) {
Timestamp timestamp = new Timestamp(dateTimeValue.getTimeInMillis());
timestamp.setNanos(nanoSeconds);
return returnType.cast(timestamp);
} else if (returnType.isAssignableFrom(Time.class)) {
// Normalize the value.
dateTimeValue.set(Calendar.YEAR, 1970);
dateTimeValue.set(Calendar.MONTH, Calendar.JANUARY);
dateTimeValue.set(Calendar.DAY_OF_MONTH, 1);
dateTimeValue.set(Calendar.MILLISECOND, 0);
return returnType.cast(new Time(dateTimeValue.getTimeInMillis())); // may throw IllegalArgumentException
} else if (returnType.isAssignableFrom(java.sql.Date.class)) {
// Normalize the value.
dateTimeValue.set(Calendar.HOUR_OF_DAY, 0);
dateTimeValue.set(Calendar.MINUTE, 0);
dateTimeValue.set(Calendar.SECOND, 0);
dateTimeValue.set(Calendar.MILLISECOND, 0);
return returnType.cast(new java.sql.Date(dateTimeValue.getTimeInMillis())); // may throw IllegalArgumentException
} else {
throw new ClassCastException("unsupported return type " + returnType.getSimpleName());
}
}
if (value instanceof Instant) {
return ((Instant) value).atZone(ZULU);
}
@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 {
if (value instanceof GregorianCalendar) {
GregorianCalendar calendar = (GregorianCalendar) value;
ZonedDateTime zdt = calendar.toZonedDateTime();
ZoneId normalizedZoneId = calendar.getTimeZone().toZoneId().normalized();
return zdt.withZoneSameInstant(normalizedZoneId);
}
final Calendar dateTimeValue = createDateTime(value, false);
return convertToInstant(value).atZone(ZULU);
}
StringBuilder result = new StringBuilder();
final int year = dateTimeValue.get(Calendar.YEAR);
appendTwoDigits(result, year / 100);
appendTwoDigits(result, year % 100);
result.append('-');
appendTwoDigits(result, dateTimeValue.get(Calendar.MONTH) + 1); // month is zero-based
result.append('-');
appendTwoDigits(result, dateTimeValue.get(Calendar.DAY_OF_MONTH));
result.append('T');
appendTwoDigits(result, dateTimeValue.get(Calendar.HOUR_OF_DAY));
result.append(':');
appendTwoDigits(result, dateTimeValue.get(Calendar.MINUTE));
result.append(':');
appendTwoDigits(result, dateTimeValue.get(Calendar.SECOND));
private static String format(LocalDateTime dateTime, ZoneOffset offset, int nanos) {
String str = dateTime.toString();
if (nanos > 0) {
str = removeTrailingZeros(str);
}
str = str + offset.toString();
final int fractionalSecs = value instanceof Timestamp ?
((Timestamp) value).getNanos() :
dateTimeValue.get(Calendar.MILLISECOND);
try {
appendFractionalSeconds(result, fractionalSecs, value instanceof Timestamp, precision);
} catch (final IllegalArgumentException e) {
throw new EdmPrimitiveTypeException("The value '" + value + "' does not match the facets' constraints.", e);
}
return str;
}
final int offsetInMinutes = (dateTimeValue.get(Calendar.ZONE_OFFSET)
+ dateTimeValue.get(Calendar.DST_OFFSET)) / 60 / 1000;
final int offsetHours = offsetInMinutes / 60;
final int offsetMinutes = Math.abs(offsetInMinutes % 60);
final String offsetString = offsetInMinutes == 0 ? "Z" : String.format("%+03d:%02d", offsetHours, offsetMinutes);
result.append(offsetString);
private static String removeTrailingZeros(String str) {
char[] chars = str.toCharArray();
int trailingZeros = 0;
for (int i = chars.length - 1; i >= 0 && chars[i] == '0'; i--) {
trailingZeros++;
}
return str.substring(0, chars.length - trailingZeros);
}
return result.toString();
}
/**
* Creates a date/time value from the given value.
*
* @param value the value as {@link Calendar}, {@link Date}, or {@link Long}
* @param isLocal whether the value is to be in the default time zone (or in GMT)
* @return the value as {@link Calendar} in the desired time zone
* @throws EdmPrimitiveTypeException if the type of the value is not supported
*/
protected static <T> Calendar createDateTime(final T value, final boolean isLocal) throws EdmPrimitiveTypeException {
Calendar dateTimeValue;
if (value instanceof Date) {
dateTimeValue = Calendar.getInstance(isLocal ? TimeZone.getDefault() : TimeZone.getTimeZone("GMT"));
dateTimeValue.setTime((Date) value);
} else if (value instanceof Calendar) {
dateTimeValue = (Calendar) ((Calendar) value).clone();
} else if (value instanceof Long) {
dateTimeValue = Calendar.getInstance(isLocal ? TimeZone.getDefault() : TimeZone.getTimeZone("GMT"));
dateTimeValue.setTimeInMillis((Long) value);
} else {
throw new EdmPrimitiveTypeException("The value type " + value.getClass() + " is not supported.");
}
return dateTimeValue;
}
/**
* Appends the given number to the given string builder, assuming that the number has at most two digits,
* performance-optimized.
*
* @param result a {@link StringBuilder}
* @param number an integer that must satisfy <code>0 <= number <= 99</code>
*/
protected static void appendTwoDigits(final StringBuilder result, final int number) {
result.append((char) ('0' + number / 10));
result.append((char) ('0' + number % 10));
}
/**
* Appends the given milli- or nanoseconds to the given string builder, performance-optimized.
* @param result a {@link StringBuilder}
* @param fractionalSeconds fractional seconds (nonnegative and assumed to be in the valid range)
* @param isNano whether the value is to be interpreted as nanoseconds (milliseconds if false)
* @param precision the upper limit for decimal digits (optional, defaults to zero)
* @throws IllegalArgumentException if precision is not met
*/
protected static void appendFractionalSeconds(StringBuilder result, final int fractionalSeconds,
final boolean isNano, final Integer precision) throws IllegalArgumentException {
if (fractionalSeconds > 0) {
// Determine the number of trailing zeroes.
int nonSignificant = 0;
int output = fractionalSeconds;
while (output % 10 == 0) {
output /= 10;
nonSignificant++;
}
if (precision != null && precision < (isNano ? 9 : 3) - nonSignificant) {
throw new IllegalArgumentException();
}
result.append('.');
for (int d = 100 * (isNano ? 1000 * 1000 : 1); d > 0; d /= 10) {
final byte digit = (byte) (fractionalSeconds % (d * 10) / d);
if (digit > 0 || fractionalSeconds % d > 0) {
result.append((char) ('0' + digit));
}
}
}
}
/**
* Creates an {@link Instant} from the given value.
*
* @param value the value as {@link Instant}, {@link java.util.Date},
* {@link java.sql.Timestamp}, {@link Long} or
* {@link GregorianCalendar}
* @return the value as {@link Instant}
* @throws EdmPrimitiveTypeException if the type of the value is not supported
*/
private static <T> Instant convertToInstant(final T value) throws EdmPrimitiveTypeException {
if (value instanceof java.sql.Time || value instanceof java.sql.Date) {
throw new EdmPrimitiveTypeException("The value type " + value.getClass() + " is not supported.");
} else if (value instanceof java.util.Date) {
return ((java.util.Date) value).toInstant();
} else if (value instanceof Timestamp) {
return ((Timestamp) value).toInstant();
} else if (value instanceof Long) {
return Instant.ofEpochMilli((Long) value);
} else {
throw new EdmPrimitiveTypeException("The value type " + value.getClass() + " is not supported.");
}
}
}

View File

@ -19,103 +19,115 @@
package org.apache.olingo.commons.core.edm.primitivetype;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeParseException;
import java.util.Calendar;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.GregorianCalendar;
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,}?)0*)?)?");
private static final LocalDate EPOCH = LocalDate.ofEpochDay(0l);
private static final EdmTimeOfDay INSTANCE = new EdmTimeOfDay();
private static final EdmTimeOfDay INSTANCE = new EdmTimeOfDay();
public static EdmTimeOfDay getInstance() {
return INSTANCE;
}
public static EdmTimeOfDay getInstance() {
return INSTANCE;
}
@Override
public Class<?> getDefaultType() {
return Calendar.class;
}
@Override
public Class<?> getDefaultType() {
return Calendar.class;
}
@SuppressWarnings("unchecked")
@Override
protected <T> T internalValueOfString(final String value, final Boolean isNullable, final Integer maxLength,
final Integer precision, final Integer scale, final Boolean isUnicode, final Class<T> returnType)
throws EdmPrimitiveTypeException {
LocalTime time;
try {
time = LocalTime.parse(value);
} catch (DateTimeParseException ex) {
throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.");
}
@Override
protected <T> T internalValueOfString(final String value,
final Boolean isNullable, final Integer maxLength, final Integer precision,
final Integer scale, final Boolean isUnicode, final Class<T> returnType) throws EdmPrimitiveTypeException {
// appropriate types
if (returnType.isAssignableFrom(LocalTime.class)) {
return (T) time;
} else if (returnType.isAssignableFrom(java.sql.Time.class)) {
return (T) java.sql.Time.valueOf(time);
}
final Matcher matcher = PATTERN.matcher(value);
if (!matcher.matches()) {
throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.");
}
// inappropriate types, which need to be supported for backward compatibility
ZonedDateTime zdt = LocalDateTime.of(EPOCH, time).atZone(ZoneId.systemDefault());
if (returnType.isAssignableFrom(Calendar.class)) {
return (T) GregorianCalendar.from(zdt);
} else if (returnType.isAssignableFrom(Long.class)) {
return (T) Long.valueOf(zdt.toInstant().toEpochMilli());
} else if (returnType.isAssignableFrom(java.sql.Date.class)) {
throw new EdmPrimitiveTypeException("The value type " + returnType + " is not supported.");
} else if (returnType.isAssignableFrom(Timestamp.class)) {
return (T) Timestamp.from(zdt.toInstant());
} else if (returnType.isAssignableFrom(java.util.Date.class)) {
return (T) java.util.Date.from(zdt.toInstant());
} else {
throw new EdmPrimitiveTypeException("The value type " + returnType + " is not supported.");
}
}
final Calendar dateTimeValue = Calendar.getInstance();
dateTimeValue.clear();
dateTimeValue.set(Calendar.HOUR_OF_DAY, Byte.parseByte(matcher.group(1)));
dateTimeValue.set(Calendar.MINUTE, Byte.parseByte(matcher.group(2)));
dateTimeValue.set(Calendar.SECOND, matcher.group(3) == null ? 0 : Byte.parseByte(matcher.group(3)));
@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 {
// appropriate types
if (value instanceof LocalTime) {
return value.toString();
} else if(value instanceof java.sql.Time) {
return value.toString();
}
// inappropriate types, which need to be supported for backward compatibility
if (value instanceof GregorianCalendar) {
GregorianCalendar calendar = (GregorianCalendar) value;
return calendar.toZonedDateTime().toLocalTime().toString();
}
long millis;
if (value instanceof Long) {
millis = (Long)value;
} else if (value instanceof java.util.Date) {
millis = ((java.util.Date)value).getTime();
} else {
throw new EdmPrimitiveTypeException("The value type " + value.getClass() + " is not supported.");
}
ZonedDateTime zdt = Instant.ofEpochMilli(millis).atZone(ZoneId.systemDefault());
return zdt.toLocalTime().toString();
int nanoSeconds = 0;
if (matcher.group(4) != null) {
if (matcher.group(4).length() == 1 || matcher.group(4).length() > 13) {
throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.");
}
final String decimals = matcher.group(5);
if (decimals.length() > (precision == null ? 0 : precision)) {
throw new EdmPrimitiveTypeException("The literal '" + value + "' does not match the facets' constraints.");
}
if (returnType.isAssignableFrom(Timestamp.class)) {
if (decimals.length() <= 9) {
nanoSeconds = Integer.parseInt(decimals + "000000000".substring(decimals.length()));
} else {
throw new EdmPrimitiveTypeException("The literal '" + value
+ "' cannot be converted to value type " + returnType + ".");
}
} else {
if (decimals.length() <= 3) {
final String milliSeconds = decimals + "000".substring(decimals.length());
dateTimeValue.set(Calendar.MILLISECOND, Short.parseShort(milliSeconds));
} else {
throw new EdmPrimitiveTypeException("The literal '" + value
+ "' cannot be converted to value type " + returnType + ".");
}
}
}
try {
return EdmDateTimeOffset.convertDateTime(dateTimeValue, nanoSeconds, returnType);
} catch (final IllegalArgumentException e) {
throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.", e);
} catch (final ClassCastException e) {
throw new EdmPrimitiveTypeException("The value type " + returnType + " is not supported.", e);
}
}
@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 Calendar dateTimeValue = EdmDateTimeOffset.createDateTime(value, true);
StringBuilder result = new StringBuilder();
EdmDateTimeOffset.appendTwoDigits(result, dateTimeValue.get(Calendar.HOUR_OF_DAY));
result.append(':');
EdmDateTimeOffset.appendTwoDigits(result, dateTimeValue.get(Calendar.MINUTE));
result.append(':');
EdmDateTimeOffset.appendTwoDigits(result, dateTimeValue.get(Calendar.SECOND));
final int fractionalSecs = value instanceof Timestamp ?
((Timestamp) value).getNanos() :
dateTimeValue.get(Calendar.MILLISECOND);
try {
EdmDateTimeOffset.appendFractionalSeconds(result, fractionalSecs, value instanceof Timestamp, precision);
} catch (final IllegalArgumentException e) {
throw new EdmPrimitiveTypeException("The value '" + value + "' does not match the facets' constraints.", e);
}
return result.toString();
}
//
// final Calendar dateTimeValue = EdmDateTimeOffset.createDateTime(value, true);
//
// StringBuilder result = new StringBuilder();
// EdmDateTimeOffset.appendTwoDigits(result, dateTimeValue.get(Calendar.HOUR_OF_DAY));
// result.append(':');
// EdmDateTimeOffset.appendTwoDigits(result, dateTimeValue.get(Calendar.MINUTE));
// result.append(':');
// EdmDateTimeOffset.appendTwoDigits(result, dateTimeValue.get(Calendar.SECOND));
//
// final int fractionalSecs = value instanceof Timestamp ? ((Timestamp) value).getNanos()
// : dateTimeValue.get(Calendar.MILLISECOND);
// try {
// EdmDateTimeOffset.appendFractionalSeconds(result, fractionalSecs, value instanceof Timestamp, precision);
// } catch (final IllegalArgumentException e) {
// throw new EdmPrimitiveTypeException("The value '" + value + "' does not match the facets' constraints.", e);
// }
//
// return result.toString();
}
}

View File

@ -20,8 +20,8 @@ package org.apache.olingo.commons.core.edm.primitivetype;
import static org.junit.Assert.assertEquals;
import java.time.LocalDate;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
@ -30,64 +30,79 @@ import org.junit.Test;
public class EdmDateTest extends PrimitiveTypeBaseTest {
private final EdmPrimitiveType instance = EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Date);
private final EdmPrimitiveType instance = EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Date);
@Test
public void toUriLiteral() throws Exception {
assertEquals("2009-12-26", instance.toUriLiteral("2009-12-26"));
assertEquals("-2009-12-26", instance.toUriLiteral("-2009-12-26"));
}
@Test
public void toUriLiteral() throws Exception {
assertEquals("2009-12-26", instance.toUriLiteral("2009-12-26"));
assertEquals("-2009-12-26", instance.toUriLiteral("-2009-12-26"));
}
@Test
public void fromUriLiteral() throws Exception {
assertEquals("2009-12-26", instance.fromUriLiteral("2009-12-26"));
assertEquals("-2009-12-26", instance.fromUriLiteral("-2009-12-26"));
}
@Test
public void fromUriLiteral() throws Exception {
assertEquals("2009-12-26", instance.fromUriLiteral("2009-12-26"));
assertEquals("-2009-12-26", instance.fromUriLiteral("-2009-12-26"));
}
@Test
public void valueToString() throws Exception {
Calendar dateTime = Calendar.getInstance();
dateTime.clear();
dateTime.setTimeZone(TimeZone.getTimeZone("GMT-11:30"));
dateTime.set(2012, 1, 29, 13, 0, 0);
assertEquals("2012-02-29", instance.valueToString(dateTime, null, null, null, null, null));
@Test
public void valueToString() throws Exception {
Calendar dateTime = Calendar.getInstance();
dateTime.clear();
setTimeZone(dateTime, "GMT-11:30");
dateTime.set(2012, 1, 29, 13, 0, 0);
assertEquals("2012-02-29", instance.valueToString(dateTime, null, null, null, null, null));
Long millis = 1330558323007L;
millis -= TimeZone.getDefault().getOffset(millis);
assertEquals("2012-02-29", instance.valueToString(millis, null, null, null, null, null));
Long millis = 1330558323007L;
millis -= TimeZone.getDefault().getOffset(millis);
assertEquals("2012-02-29", instance.valueToString(millis, null, null, null, null, null));
assertEquals("1969-12-31", instance.valueToString(new Date(-43200000), null, null, null, null, null));
assertEquals("1969-12-31", instance.valueToString(new java.util.Date(-43200000), null, null, null, null, null));
assertEquals("1969-12-31",
instance.valueToString(java.sql.Date.valueOf("1969-12-31"), null, null, null, null, null));
assertEquals("1969-12-31",
instance.valueToString(LocalDate.parse("1969-12-31"), null, null, null, null, null));
dateTime.set(Calendar.YEAR, 12344);
assertEquals("12344-02-29", instance.valueToString(dateTime, null, null, null, null, null));
// TODO support for years beyond 9999
// dateTime.set(Calendar.YEAR, 12344);
// assertEquals("12344-02-29", instance.valueToString(dateTime, null, null, null, null, null));
expectTypeErrorInValueToString(instance, 0);
}
expectTypeErrorInValueToString(instance, 0);
}
@Test
public void valueOfString() throws Exception {
Calendar dateTime = Calendar.getInstance();
dateTime.clear();
dateTime.set(2012, 1, 29);
assertEquals(dateTime, instance.valueOfString("2012-02-29", null, null, null, null, null, Calendar.class));
assertEquals(Long.valueOf(dateTime.getTimeInMillis()), instance.valueOfString("2012-02-29", null, null, null, null,
null, Long.class));
assertEquals(dateTime.getTime(), instance.valueOfString("2012-02-29", null, null, null, null, null, Date.class));
@Test
public void valueOfString() throws Exception {
Calendar dateTime = Calendar.getInstance();
dateTime.clear();
dateTime.set(2012, 1, 29);
assertEqualCalendar(dateTime,
instance.valueOfString("2012-02-29", null, null, null, null, null, Calendar.class));
assertEquals(Long.valueOf(dateTime.getTimeInMillis()),
instance.valueOfString("2012-02-29", null, null, null, null, null, Long.class));
assertEquals(dateTime.getTime(),
instance.valueOfString("2012-02-29", null, null, null, null, null, java.util.Date.class));
assertEquals(java.sql.Date.valueOf("2012-02-29"),
instance.valueOfString("2012-02-29", null, null, null, null, null, java.sql.Date.class));
assertEquals(LocalDate.parse("2012-02-29"),
instance.valueOfString("2012-02-29", null, null, null, null, null, LocalDate.class));
dateTime.set(Calendar.YEAR, 12344);
assertEquals(dateTime, instance.valueOfString("12344-02-29", null, null, null, null, null, Calendar.class));
// TODO support for years beyond 9999
// dateTime.set(Calendar.YEAR, 12344);
// Calendar result = instance.valueOfString("12344-02-29", null, null, null,
// null, null, Calendar.class);
// this.assertEqualCalendar(dateTime, result);
// TODO: Clarify whether negative years are really needed.
// dateTime.set(-1, 1, 28);
// assertEquals(dateTime, instance.valueOfString("-0001-02-28", null, Calendar.class));
// TODO: Clarify whether negative years are really needed.
// dateTime.set(-1, 1, 28);
// assertEquals(dateTime, instance.valueOfString("-0001-02-28", null,
// Calendar.class));
expectContentErrorInValueOfString(instance, "2012-02-29T23:32:02");
expectContentErrorInValueOfString(instance, "2012-02-30");
expectContentErrorInValueOfString(instance, "20120229");
expectContentErrorInValueOfString(instance, "2012-02-1");
expectContentErrorInValueOfString(instance, "2012-2-12");
expectContentErrorInValueOfString(instance, "123-02-03");
expectContentErrorInValueOfString(instance, "2012-02-29T23:32:02");
expectContentErrorInValueOfString(instance, "2012-02-30");
expectContentErrorInValueOfString(instance, "20120229");
expectContentErrorInValueOfString(instance, "2012-02-1");
expectContentErrorInValueOfString(instance, "2012-2-12");
expectContentErrorInValueOfString(instance, "123-02-03");
expectTypeErrorInValueOfString(instance, "2012-02-29");
}
expectTypeErrorInValueOfString(instance, "2012-02-29");
}
}

View File

@ -22,9 +22,12 @@ import static org.junit.Assert.assertEquals;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
@ -32,129 +35,208 @@ import org.junit.Test;
public class EdmDateTimeOffsetTest extends PrimitiveTypeBaseTest {
final EdmPrimitiveType instance = EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.DateTimeOffset);
final EdmPrimitiveType instance = EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.DateTimeOffset);
@Test
public void toUriLiteral() throws Exception {
assertEquals("2009-12-26T21:23:38Z", instance.toUriLiteral("2009-12-26T21:23:38Z"));
assertEquals("2002-10-10T12:00:00-05:00", instance.toUriLiteral("2002-10-10T12:00:00-05:00"));
}
@Test
public void toUriLiteral() throws Exception {
assertEquals("2009-12-26T21:23:38Z", instance.toUriLiteral("2009-12-26T21:23:38Z"));
assertEquals("2002-10-10T12:00:00-05:00", instance.toUriLiteral("2002-10-10T12:00:00-05:00"));
}
@Test
public void fromUriLiteral() throws Exception {
assertEquals("2009-12-26T21:23:38Z", instance.fromUriLiteral("2009-12-26T21:23:38Z"));
assertEquals("2002-10-10T12:00:00-05:00", instance.fromUriLiteral("2002-10-10T12:00:00-05:00"));
}
@Test
public void fromUriLiteral() throws Exception {
assertEquals("2009-12-26T21:23:38Z", instance.fromUriLiteral("2009-12-26T21:23:38Z"));
assertEquals("2002-10-10T12:00:00-05:00", instance.fromUriLiteral("2002-10-10T12:00:00-05:00"));
}
@Test
public void valueToString() throws Exception {
Calendar dateTime = Calendar.getInstance();
dateTime.clear();
dateTime.setTimeZone(TimeZone.getTimeZone("GMT"));
dateTime.set(2012, 1, 29, 1, 2, 3);
assertEquals("2012-02-29T01:02:03Z", instance.valueToString(dateTime, null, null, null, null, null));
assertEquals("2012-02-29T01:02:03Z", instance.valueToString(dateTime, null, null, 0, null, null));
assertEquals("2012-02-29T01:02:03Z", instance.valueToString(dateTime, null, null, 5, null, null));
@Test
public void valueToStringFromInstant() throws Exception {
Instant instant = Instant.parse("2012-02-29T01:02:03Z");
assertEquals("2012-02-29T01:02:03Z", instance.valueToString(instant, null, null, null, null, null));
assertEquals("2012-02-29T01:02:03Z", instance.valueToString(instant, null, null, 0, null, null));
assertEquals("2012-02-29T01:02:03Z", instance.valueToString(instant, null, null, 5, null, null));
}
dateTime.setTimeZone(TimeZone.getTimeZone("GMT-1:30"));
assertEquals("2012-02-29T01:02:03-01:30", instance.valueToString(dateTime, null, null, null, null, null));
@Test
public void valueToStringFromZonedDateTime() throws Exception {
ZonedDateTime zdt = ZonedDateTime.parse("2012-02-28T23:32:03-01:30");
dateTime.setTimeZone(TimeZone.getTimeZone("GMT+11:00"));
assertEquals("2012-02-29T01:02:03+11:00", instance.valueToString(dateTime, null, null, null, null, null));
assertEquals("2012-02-28T23:32:03-01:30", instance.valueToString(zdt, null, null, null, null, null));
dateTime.set(Calendar.MILLISECOND, 503);
assertEquals("2012-02-29T01:02:03.503+11:00", instance.valueToString(dateTime, null, null, null, null, null));
assertEquals("2012-02-29T01:02:03.503+11:00", instance.valueToString(dateTime, null, null, 3, null, null));
zdt = zdt.withZoneSameInstant(ZoneId.of("GMT+11:00"));
assertEquals("2012-02-29T12:02:03+11:00", instance.valueToString(zdt, null, null, null, null, null));
dateTime.set(Calendar.MILLISECOND, 530);
assertEquals("2012-02-29T01:02:03.53+11:00", instance.valueToString(dateTime, null, null, null, null, null));
assertEquals("2012-02-29T01:02:03.53+11:00", instance.valueToString(dateTime, null, null, 3, null, null));
zdt = zdt.plus(123, ChronoUnit.MILLIS);
dateTime.set(Calendar.MILLISECOND, 53);
assertEquals("2012-02-29T01:02:03.053+11:00", instance.valueToString(dateTime, null, null, null, null, null));
assertEquals("2012-02-29T01:02:03.053+11:00", instance.valueToString(dateTime, null, null, 3, null, null));
assertEquals("2012-02-29T12:02:03.123+11:00", instance.valueToString(zdt, null, null, null, null, null));
assertEquals("2012-02-29T12:02:03.123+11:00", instance.valueToString(zdt, null, null, 3, null, null));
zdt = zdt.plus(456789, ChronoUnit.NANOS);
assertEquals("2012-02-29T12:02:03.123456789+11:00", instance.valueToString(zdt, null, null, 9, null, null));
}
final Long millis = 1330558323007L;
assertEquals("2012-02-29T23:32:03.007Z", instance.valueToString(millis, null, null, null, null, null));
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));
@Test
public void valueToStringFromCalendar() throws Exception {
Calendar dateTime = Calendar.getInstance();
dateTime.clear();
setTimeZone(dateTime, "GMT");
dateTime.set(2012, 1, 29, 1, 2, 3);
assertEquals("2012-02-29T01:02:03Z", instance.valueToString(dateTime, null, null, null, null, null));
assertEquals("2012-02-29T01:02:03Z", instance.valueToString(dateTime, null, null, 0, null, null));
assertEquals("2012-02-29T01:02:03Z", instance.valueToString(dateTime, null, null, 5, 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));
setTimeZone(dateTime, "GMT-1:30");
assertEquals("2012-02-28T23:32:03-01:30", instance.valueToString(dateTime, null, null, null, null, null));
final Date date = new Date(millis);
assertEquals("2012-02-29T23:32:03.007Z", instance.valueToString(date, null, null, null, null, null));
assertEquals("2012-02-29T23:32:03.007Z", instance.valueToString(date, null, null, 3, null, null));
setTimeZone(dateTime, "GMT+11:00");
assertEquals("2012-02-29T12:02:03+11:00", instance.valueToString(dateTime, null, null, null, null, null));
Timestamp timestamp = new Timestamp(0);
timestamp.setNanos(120);
assertEquals("1970-01-01T00:00:00.00000012Z", instance.valueToString(timestamp, null, null, null, null, null));
assertEquals("1970-01-01T00:00:00.00000012Z", instance.valueToString(timestamp, null, null, 8, null, null));
dateTime.set(Calendar.MILLISECOND, 503);
assertEquals("2012-02-29T12:02:03.503+11:00", instance.valueToString(dateTime, null, null, null, null, null));
assertEquals("2012-02-29T12:02:03.503+11:00", instance.valueToString(dateTime, null, null, 3, null, null));
expectFacetsErrorInValueToString(instance, 3L, null, null, 2, null, null);
expectFacetsErrorInValueToString(instance, timestamp, null, null, 7, null, null);
dateTime.set(Calendar.MILLISECOND, 530);
assertEquals("2012-02-29T12:02:03.53+11:00", instance.valueToString(dateTime, null, null, null, null, null));
assertEquals("2012-02-29T12:02:03.53+11:00", instance.valueToString(dateTime, null, null, 3, null, null));
expectTypeErrorInValueToString(instance, 0);
}
dateTime.set(Calendar.MILLISECOND, 53);
assertEquals("2012-02-29T12:02:03.053+11:00", instance.valueToString(dateTime, null, null, null, null, null));
assertEquals("2012-02-29T12:02:03.053+11:00", instance.valueToString(dateTime, null, null, 3, null, null));
}
@Test
public void valueOfString() throws Exception {
Calendar dateTime = Calendar.getInstance();
dateTime.clear();
dateTime.setTimeZone(TimeZone.getTimeZone("GMT"));
dateTime.set(2012, 1, 29, 1, 2, 3);
assertEquals(dateTime, instance.valueOfString("2012-02-29T01:02:03Z", null, null, null, null, null,
Calendar.class));
assertEquals(Long.valueOf(dateTime.getTimeInMillis()), instance.valueOfString("2012-02-29T01:02:03+00:00", null,
null, null, null, null, Long.class));
assertEquals(dateTime, instance.valueOfString("2012-02-29T01:02:03", null, null, null, null, null,
Calendar.class));
@Test
public void valueToStringFromLong() throws Exception {
Long millis = 1330558323000L;
assertEquals("2012-02-29T23:32:03Z", instance.valueToString(millis, null, null, null, null, null));
millis = 1330558323007L;
assertEquals("2012-02-29T23:32:03.007Z", instance.valueToString(millis, null, null, null, null, null));
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));
}
dateTime.clear();
dateTime.setTimeZone(TimeZone.getTimeZone("GMT-01:30"));
dateTime.set(2012, 1, 29, 1, 2, 3);
assertEquals(dateTime.getTime(), instance.valueOfString("2012-02-29T01:02:03-01:30", null, null, null, null, null,
Date.class));
@Test
public void valueToStringFromJavaUtilDate() throws Exception {
final Long millis = 1330558323007L;
final Date date = new Date(millis);
assertEquals("2012-02-29T23:32:03.007Z", instance.valueToString(date, null, null, null, null, null));
assertEquals("2012-02-29T23:32:03.007Z", instance.valueToString(date, null, null, 3, null, null));
}
dateTime.clear();
dateTime.setTimeZone(TimeZone.getTimeZone("GMT+11:00"));
dateTime.set(2012, 1, 29, 1, 2, 3);
assertEquals(dateTime, instance.valueOfString("2012-02-29T01:02:03+11:00", null, null, null, null, null,
Calendar.class));
@Test
public void valueToStringFromTimestamp() throws Exception {
Timestamp timestamp = new Timestamp(0);
timestamp.setNanos(120);
assertEquals("1970-01-01T00:00:00.00000012Z", instance.valueToString(timestamp, null, null, null, null, null));
assertEquals("1970-01-01T00:00:00.00000012Z", instance.valueToString(timestamp, null, null, 8, null, null));
dateTime.add(Calendar.MILLISECOND, 7);
assertEquals(dateTime, instance.valueOfString("2012-02-29T01:02:03.007+11:00", null, null, 3, null, null,
Calendar.class));
assertEquals(530000001, instance.valueOfString("2012-02-29T01:02:03.530000001+11:00", null, null, 9, null, null,
Timestamp.class).getNanos());
}
assertEquals(Long.valueOf(120000L), instance.valueOfString("1970-01-01T00:02", null, null, null, null, null,
Long.class));
assertEquals(Long.valueOf(12L), instance.valueOfString("1970-01-01T00:00:00.012", null, null, 3, null, null,
Long.class));
assertEquals(Long.valueOf(120L), instance.valueOfString("1970-01-01T00:00:00.12", null, null, 2, null, null,
Long.class));
@Test
public void valueToStringFromInvalidTypes() throws Exception {
expectTypeErrorInValueToString(instance, Integer.valueOf(0));
expectTypeErrorInValueToString(instance, Time.valueOf("12:13:14"));
expectTypeErrorInValueToString(instance, java.sql.Date.valueOf("2019-10-25"));
}
assertEquals(new Time(120000L), instance.valueOfString("1970-01-01T00:02", null, null, null, null, null,
Time.class));
// java.sql.Time does not keep track of milliseconds.
assertEquals(new Time(0), instance.valueOfString("1970-01-01T00:00:00.012", null, null, 3, null, null,
Time.class));
assertEquals(new Time(0), instance.valueOfString("1970-01-01T00:00:00.12", null, null, 2, null, null, Time.class));
@Test
public void valueOfStringToInstant() throws Exception {
Instant instant = Instant.parse("2012-02-29T01:02:03Z");
assertEquals(instant,
instance.valueOfString("2012-02-29T01:02:03Z", null, null, null, null, null, Instant.class));
assertEquals(instant,
instance.valueOfString("2012-02-29T01:02:03", null, null, null, null, null, Instant.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");
expectContentErrorInValueOfString(instance, "2012-02-29T23:32:02+24:00");
expectContentErrorInValueOfString(instance, "2012-02-30T01:02:03");
expectContentErrorInValueOfString(instance, "2012-02-29T23:32:02.");
expectContentErrorInValueOfString(instance, "2012-02-29T23:32:02.0000000000000");
@Test
public void valueOfStringToZonedDateTime() throws Exception {
ZonedDateTime zdt = ZonedDateTime.parse("2012-02-29T01:02:03-01:30");
assertEquals(zdt,
instance.valueOfString("2012-02-29T01:02:03-01:30", null, null, null, null, null, ZonedDateTime.class));
}
expectUnconvertibleErrorInValueOfString(instance, "2012-02-29T23:32:02.1234", Calendar.class);
expectUnconvertibleErrorInValueOfString(instance, "2012-02-29T23:32:02.0123456789", Timestamp.class);
@Test
public void valueOfStringToCalendar() throws Exception {
Calendar dateTime = Calendar.getInstance();
dateTime.clear();
setTimeZone(dateTime, "GMT");
dateTime.set(2012, 1, 29, 1, 2, 3);
assertEqualCalendar(dateTime,
instance.valueOfString("2012-02-29T01:02:03Z", null, null, null, null, null, Calendar.class));
assertEqualCalendar(dateTime,
instance.valueOfString("2012-02-29T01:02:03", null, null, null, null, null, Calendar.class));
dateTime.clear();
setTimeZone(dateTime, "GMT-01:30");
dateTime.set(2012, 1, 29, 1, 2, 3);
assertEquals(dateTime.getTime(),
instance.valueOfString("2012-02-29T01:02:03-01:30", null, null, null, null, null, Date.class));
dateTime.clear();
setTimeZone(dateTime, "GMT+11:00");
dateTime.set(2012, 1, 29, 1, 2, 3);
assertEqualCalendar(dateTime,
instance.valueOfString("2012-02-29T01:02:03+11:00", null, null, null, null, null, Calendar.class));
dateTime.add(Calendar.MILLISECOND, 7);
assertEqualCalendar(dateTime,
instance.valueOfString("2012-02-29T01:02:03.007+11:00", null, null, 3, null, null, Calendar.class));
}
@Test
public void valueOfStringToTimestamp() throws Exception {
assertEquals(530000001, instance
.valueOfString("2012-02-29T01:02:03.530000001+11:00", null, null, 9, null, null, Timestamp.class)
.getNanos());
}
@Test
public void valueOfStringToLong() throws Exception {
Calendar dateTime = Calendar.getInstance();
dateTime.clear();
setTimeZone(dateTime, "GMT");
dateTime.set(2012, 1, 29, 1, 2, 3);
assertEquals(Long.valueOf(dateTime.getTimeInMillis()),
instance.valueOfString("2012-02-29T01:02:03+00:00", null, null, null, null, null, Long.class));
assertEquals(Long.valueOf(120000L),
instance.valueOfString("1970-01-01T00:02Z", null, null, null, null, null, Long.class));
assertEquals(Long.valueOf(120000L),
instance.valueOfString("1970-01-01T00:02", null, null, null, null, null, Long.class));
assertEquals(Long.valueOf(12L),
instance.valueOfString("1970-01-01T00:00:00.012", null, null, 3, null, null, Long.class));
assertEquals(Long.valueOf(120L),
instance.valueOfString("1970-01-01T00:00:00.12", null, null, 2, null, null, Long.class));
}
@Test
public void valueOfStringToJavaSqlTime() throws Exception {
assertEquals(new Time(120000L),
instance.valueOfString("1970-01-01T00:02", null, null, null, null, null, Time.class));
// java.sql.Time does not keep track of milliseconds.
assertEquals(new Time(0),
instance.valueOfString("1970-01-01T00:00:00.012", null, null, 3, null, null, Time.class));
assertEquals(new Time(0),
instance.valueOfString("1970-01-01T00:00:00.12", null, null, 2, null, null, Time.class));
}
@Test
public void valueOfStringToJavaSqlDate() throws Exception {
assertEquals(new java.sql.Date(120000L),
instance.valueOfString("1970-01-01T00:02", null, null, null, null, null, java.sql.Date.class));
// java.sql.Time does not keep track of milliseconds.
assertEquals(new java.sql.Date(0),
instance.valueOfString("1970-01-01T00:00:00.012", null, null, 3, null, null, java.sql.Date.class));
assertEquals(new java.sql.Date(0),
instance.valueOfString("1970-01-01T00:00:00.12", null, null, 2, null, null, java.sql.Date.class));
}
@Test
public void valueOfStringInvalidData() throws Exception {
expectContentErrorInValueOfString(instance, "2012-02-29T23:32:02X");
expectContentErrorInValueOfString(instance, "2012-02-29T23:32:02+24:00");
expectContentErrorInValueOfString(instance, "2012-02-30T01:02:03");
expectContentErrorInValueOfString(instance, "2012-02-29T23:32:02.0000000000000");
expectTypeErrorInValueOfString(instance, "2012-02-29T01:02:03Z");
}
expectTypeErrorInValueOfString(instance, "2012-02-29T01:02:03Z");
}
}

View File

@ -22,6 +22,12 @@ import static org.junit.Assert.assertEquals;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.TimeZone;
@ -31,105 +37,154 @@ import org.junit.Test;
public class EdmTimeOfDayTest extends PrimitiveTypeBaseTest {
private final EdmPrimitiveType instance = EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.TimeOfDay);
private final EdmPrimitiveType instance = EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.TimeOfDay);
@Test
public void toUriLiteral() throws Exception {
assertEquals("11:12", instance.toUriLiteral("11:12"));
assertEquals("11:12:13.012", instance.toUriLiteral("11:12:13.012"));
}
@Test
public void toUriLiteral() throws Exception {
assertEquals("11:12", instance.toUriLiteral("11:12"));
assertEquals("11:12:13.012", instance.toUriLiteral("11:12:13.012"));
}
@Test
public void fromUriLiteral() throws Exception {
assertEquals("11:12", instance.fromUriLiteral("11:12"));
assertEquals("11:12:13.012", instance.fromUriLiteral("11:12:13.012"));
}
@Test
public void fromUriLiteral() throws Exception {
assertEquals("11:12", instance.fromUriLiteral("11:12"));
assertEquals("11:12:13.012", instance.fromUriLiteral("11:12:13.012"));
}
@Test
public void valueToString() throws Exception {
Calendar dateTime = Calendar.getInstance();
dateTime.clear();
dateTime.setTimeZone(TimeZone.getTimeZone("GMT+11:30"));
dateTime.set(1, 2, 3, 4, 5, 6);
assertEquals("04:05:06", instance.valueToString(dateTime, null, null, null, null, null));
@Test
public void valueToString() throws Exception {
Calendar dateTime = Calendar.getInstance();
dateTime.clear();
setTimeZone(dateTime, "GMT+11:30");
dateTime.set(1, 2, 3, 4, 5, 6);
assertEquals("04:05:06", instance.valueToString(dateTime, null, null, null, null, null));
dateTime.add(Calendar.MILLISECOND, 42);
assertEquals("04:05:06.042", instance.valueToString(dateTime, null, null, null, null, null));
assertEquals("04:05:06.042", instance.valueToString(dateTime, null, null, 3, null, null));
assertEquals("04:05:06.042", instance.valueToString(dateTime, null, null, 4, null, null));
dateTime.add(Calendar.MILLISECOND, 42);
assertEquals("04:05:06.042", instance.valueToString(dateTime, null, null, null, null, null));
assertEquals("04:05:06.042", instance.valueToString(dateTime, null, null, 3, null, null));
assertEquals("04:05:06.042", instance.valueToString(dateTime, null, null, 4, null, null));
Calendar dateTime2 = Calendar.getInstance();
dateTime2.clear();
dateTime2.setTimeZone(TimeZone.getDefault());
dateTime2.set(Calendar.HOUR, 5);
dateTime2.set(Calendar.MINUTE, 59);
dateTime2.set(Calendar.SECOND, 23);
final Time time = new Time(dateTime2.getTimeInMillis());
assertEquals("05:59:23", instance.valueToString(time, null, null, null, null, null));
Calendar dateTime2 = Calendar.getInstance();
dateTime2.clear();
setTimeZone(dateTime, TimeZone.getDefault());
dateTime2.set(Calendar.HOUR, 5);
dateTime2.set(Calendar.MINUTE, 59);
dateTime2.set(Calendar.SECOND, 23);
final java.sql.Time time = new java.sql.Time(dateTime2.getTimeInMillis());
assertEquals("05:59:23", instance.valueToString(time, null, null, null, null, null));
assertEquals("05:59:23", instance.valueToString(dateTime2.getTimeInMillis(), null, null, null, null, null));
assertEquals("05:59:23", instance.valueToString(dateTime2.getTimeInMillis(), null, null, null, null, null));
expectFacetsErrorInValueToString(instance, dateTime, null, null, 2, null, null);
Timestamp timestamp = new Timestamp(0);
timestamp.setNanos(42);
expectFacetsErrorInValueToString(instance, timestamp, null, null, 8, null, null);
// Timestamp timestamp = new Timestamp(0);
// timestamp.setNanos(42);
expectTypeErrorInValueToString(instance, 0);
}
expectTypeErrorInValueToString(instance, 0);
}
@Test
public void valueOfString() throws Exception {
Calendar dateTime = Calendar.getInstance();
dateTime.clear();
@Test
public void valueToStringFromJavaUtilDate() throws Exception {
LocalTime time = LocalTime.parse("04:05:06");
ZonedDateTime zdt = ZonedDateTime.of(LocalDate.ofEpochDay(0), time, ZoneId.systemDefault());
long millis = zdt.toInstant().toEpochMilli();
java.util.Date javaUtilDate = new java.util.Date(millis);
assertEquals("04:05:06", instance.valueToString(javaUtilDate, null, null, null, null, null));
java.sql.Timestamp javaSqlTimestamp = new java.sql.Timestamp(millis);
assertEquals("04:05:06", instance.valueToString(javaSqlTimestamp, null, null, null, null, null));
}
assertEquals(dateTime, instance.valueOfString("00:00", null, null, null, null, null, Calendar.class));
assertEquals(dateTime, instance.valueOfString("00:00:00", null, null, null, null, null, Calendar.class));
assertEquals(dateTime, instance.valueOfString("00:00:00.000000000000", null, null, null, null, null,
Calendar.class));
@Test
public void valueToStringFromLocalTime() throws Exception {
LocalTime time = LocalTime.parse("04:05:06");
assertEquals("04:05:06", instance.valueToString(time, null, null, null, null, null));
}
@Test
public void valueToStringFromJavaSqlTime() throws Exception {
java.sql.Time time = java.sql.Time.valueOf("04:05:06");
assertEquals("04:05:06", instance.valueToString(time, null, null, null, null, null));
}
@Test
public void valueOfString() throws Exception {
Calendar dateTime = Calendar.getInstance();
dateTime.clear();
final Time timeValue = instance.valueOfString("00:00:00.999", null, null, 3, null, null, Time.class);
assertEquals(dateTime.getTimeInMillis(), timeValue.getTime());
assertEqualCalendar(dateTime, instance.valueOfString("00:00", null, null, null, null, null, Calendar.class));
assertEqualCalendar(dateTime, instance.valueOfString("00:00:00", null, null, null, null, null, Calendar.class));
assertEqualCalendar(dateTime,
instance.valueOfString("00:00:00.000000000", null, null, null, null, null, Calendar.class));
dateTime.set(Calendar.MILLISECOND, 999);
assertEquals(dateTime, instance.valueOfString("00:00:00.999", null, null, 3, null, null, Calendar.class));
assertEquals(dateTime, instance.valueOfString("00:00:00.999", null, null, 3, null, null, Calendar.class));
assertEquals(Long.valueOf(dateTime.getTimeInMillis()),
instance.valueOfString("00:00:00.999", null, null, 3, null, null, Long.class));
final Time timeValue = instance.valueOfString("00:00:00.999", null, null, 3, null, null, Time.class);
assertEquals(dateTime.getTimeInMillis(), timeValue.getTime());
final Timestamp timestamp = instance.valueOfString("00:00:00.999888777", null, null, 9, null, null,
Timestamp.class);
assertEquals(dateTime.getTimeInMillis(), timestamp.getTime());
assertEquals(999888777, timestamp.getNanos());
dateTime.set(Calendar.MILLISECOND, 999);
assertEqualCalendar(dateTime,
instance.valueOfString("00:00:00.999", null, null, 3, null, null, Calendar.class));
assertEqualCalendar(dateTime,
instance.valueOfString("00:00:00.999", null, null, 3, null, null, Calendar.class));
assertEquals(Long.valueOf(dateTime.getTimeInMillis()),
instance.valueOfString("00:00:00.999", null, null, 3, null, null, Long.class));
expectFacetsErrorInValueOfString(instance, "11:12:13.123", null, null, null, null, null);
expectFacetsErrorInValueOfString(instance, "11:12:13.123", null, null, 2, null, null);
final Timestamp timestamp = instance.valueOfString("00:00:00.999888777", null, null, 9, null, null,
Timestamp.class);
assertEquals(dateTime.getTimeInMillis(), timestamp.getTime());
assertEquals(999888777, timestamp.getNanos());
expectUnconvertibleErrorInValueOfString(instance, "11:12:13.1234", Calendar.class);
expectUnconvertibleErrorInValueOfString(instance, "11:12:13.0123456789", Timestamp.class);
// expectUnconvertibleErrorInValueOfString(instance, "11:12:13.1234", Calendar.class);
// expectUnconvertibleErrorInValueOfString(instance, "11:12:13.0123456789", Timestamp.class);
expectContentErrorInValueOfString(instance, "24:32:02");
expectContentErrorInValueOfString(instance, "011:12:13");
expectContentErrorInValueOfString(instance, "11:12:13:14");
expectContentErrorInValueOfString(instance, "111213");
expectContentErrorInValueOfString(instance, "1:2:3");
expectContentErrorInValueOfString(instance, "11:12:13.0.1");
expectContentErrorInValueOfString(instance, "11:12:13.");
expectContentErrorInValueOfString(instance, "11:12:13.0000000000000");
expectContentErrorInValueOfString(instance, "24:32:02");
expectContentErrorInValueOfString(instance, "011:12:13");
expectContentErrorInValueOfString(instance, "11:12:13:14");
expectContentErrorInValueOfString(instance, "111213");
expectContentErrorInValueOfString(instance, "1:2:3");
expectContentErrorInValueOfString(instance, "11:12:13.0.1");
// expectContentErrorInValueOfString(instance, "11:12:13.");
expectContentErrorInValueOfString(instance, "11:12:13.0000000000000");
expectTypeErrorInValueOfString(instance, "11:12:13");
}
expectTypeErrorInValueOfString(instance, "11:12:13");
}
@Test
public void valueOfStringToLocalTime() throws Exception {
LocalTime time = LocalTime.parse("04:05:06");
assertEquals(time, instance.valueOfString("04:05:06", null, null, null, null, null, LocalTime.class));
time = time.plus(123, ChronoUnit.MILLIS);
assertEquals(time, instance.valueOfString("04:05:06.123", null, null, null, null, null, LocalTime.class));
time = time.plus(456789, ChronoUnit.NANOS);
assertEquals(time, instance.valueOfString("04:05:06.123456789", null, null, null, null, null, LocalTime.class));
}
@Test
public void valueOfStringToJavaSqlTime() throws Exception {
java.sql.Time time = java.sql.Time.valueOf("04:05:06");
assertEquals(time, instance.valueOfString("04:05:06", null, null, null, null, null, java.sql.Time.class));
}
@Test
public void valueOfStringToJavaUtilDateTime() throws Exception {
LocalTime time = LocalTime.parse("04:05:06");
ZonedDateTime zdt = ZonedDateTime.of(LocalDate.ofEpochDay(0), time, ZoneId.systemDefault());
long millis = zdt.toInstant().toEpochMilli();
java.util.Date javaUtilDate = new java.util.Date(millis);
assertEquals(javaUtilDate, instance.valueOfString("04:05:06", null, null, null, null, null, java.util.Date.class));
}
@Test
public void testRoundTripTime() throws Exception {
java.sql.Time time = instance.valueOfString("04:05:06.002", true, 4000, 3, 0, true, java.sql.Time.class);
String val = instance.valueToString(time, true, 4000, 3, 0, true);
assertEquals("04:05:06", val);
}
@Test
public void testRoundTripTime() throws Exception {
java.sql.Time time = instance.valueOfString("04:05:06.002", true,
4000, 3, 0, true, java.sql.Time.class);
String val = instance.valueToString(time, true, 4000, 3, 0, true);
assertEquals("04:05:06", val);
}
@Test
public void tests() throws Exception {
instance.validate("12:34:55", null, null, null, null, null);
}
@Test
public void tests() throws Exception {
instance.validate("12:34:55", null, null, null, null, null);
}
}

View File

@ -19,16 +19,23 @@
package org.apache.olingo.commons.core.edm.primitivetype;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
public abstract class PrimitiveTypeBaseTest {
private void expectErrorInValueToString(final EdmPrimitiveType instance,
private void expectErrorInValueToString(final EdmPrimitiveType instance,
final Object value, final Boolean isNullable, final Integer maxLength,
final Integer precision, final Integer scale, final Boolean isUnicode,
final String message) {
@ -115,4 +122,26 @@ public abstract class PrimitiveTypeBaseTest {
assertThat(e.getLocalizedMessage(), containsString("' has illegal content."));
}
}
protected void setTimeZone(Calendar dateTime, String ID) {
TimeZone timeZone = TimeZone.getTimeZone(ID);
setTimeZone(dateTime, timeZone);
}
protected void setTimeZone(Calendar dateTime, TimeZone timeZone) {
dateTime.setTimeZone(timeZone);
// ensure that the internal fields are recomputed so that the calendar can be correctly cloned
dateTime.get(Calendar.YEAR);
}
protected void assertEqualCalendar(Calendar expected, Calendar actual) {
assertEquals(normalize(expected), normalize(actual));
}
private ZonedDateTime normalize(Calendar cal) {
GregorianCalendar calendar = (GregorianCalendar) cal;
ZonedDateTime zdt = calendar.toZonedDateTime();
ZoneId normalizedZoneId = calendar.getTimeZone().toZoneId().normalized();
return zdt.withZoneSameInstant(normalizedZoneId);
}
}

View File

@ -25,6 +25,9 @@ import java.io.InputStream;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.channels.WritableByteChannel;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
@ -144,6 +147,41 @@ public class ODataJsonSerializerTest {
Assert.assertEquals(expectedResult, resultString);
}
@Test
public void entitySimpleNewDateTimeAPI() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
entity.getProperty("PropertyDate").setValue(ValueType.PRIMITIVE, LocalDate.parse("2012-12-03"));
entity.getProperty("PropertyDateTimeOffset").setValue(ValueType.PRIMITIVE, Instant.parse("2012-12-03T07:16:23Z"));
entity.getProperty("PropertyTimeOfDay").setValue(ValueType.PRIMITIVE, LocalTime.parse("03:26:05"));
InputStream result = serializer.entity(metadata, edmEntitySet.getEntityType(), entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build())
.build()).getContent();
final String resultString = IOUtils.toString(result);
final String expectedResult = "{"
+ "\"@odata.context\":\"$metadata#ESAllPrim/$entity\","
+ "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+ "\"PropertyInt16\":32767,"
+ "\"PropertyString\":\"First Resource - positive values\","
+ "\"PropertyBoolean\":true,"
+ "\"PropertyByte\":255,"
+ "\"PropertySByte\":127,"
+ "\"PropertyInt32\":2147483647,"
+ "\"PropertyInt64\":9223372036854775807,"
+ "\"PropertySingle\":1.79E20,"
+ "\"PropertyDouble\":-1.79E19,"
+ "\"PropertyDecimal\":34,"
+ "\"PropertyBinary\":\"ASNFZ4mrze8=\","
+ "\"PropertyDate\":\"2012-12-03\","
+ "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\","
+ "\"PropertyDuration\":\"PT6S\","
+ "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\","
+ "\"PropertyTimeOfDay\":\"03:26:05\""
+ "}";
Assert.assertEquals(expectedResult, resultString);
}
@Test
public void entitySimpleMetadataFull() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");