protected T internalValueOfString()

in odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmDateTime.java [54:156]


  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets,
      final Class<T> returnType) throws EdmSimpleTypeException {
    // In JSON, we allow also the XML literal form, so there is on purpose
    // no exception if the JSON pattern does not match.
    if (literalKind == EdmLiteralKind.JSON) {
      final Matcher matcher = JSON_PATTERN.matcher(value);
      if (matcher.matches()) {
        long millis;
        try {
          millis = Long.parseLong(matcher.group(1));
        } catch (final NumberFormatException e) {
          throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value), e);
        }
        if (returnType.isAssignableFrom(Long.class)) {
          return returnType.cast(millis);
        } else if (returnType.isAssignableFrom(Date.class)) {
          return returnType.cast(new Date(millis));
        } else if (returnType.isAssignableFrom(Calendar.class)) {
          Calendar dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
          dateTimeValue.clear();
          dateTimeValue.setTimeInMillis(millis);
          return returnType.cast(dateTimeValue);
        } else {
          throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
        }
      }
    }

    Calendar dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
    dateTimeValue.clear();

    String valueString;
    if (literalKind == EdmLiteralKind.URI) {
      //OLINGO-883 prefix is case insensitve so we need to check with lower case if we want to use startsWith()
      if (value.length() > 10 && value.toLowerCase().startsWith("datetime'") && value.endsWith("'")) {
        valueString = value.substring(9, value.length() - 1);
      } else {
        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
      }
    } else {
      valueString = value;
    }

    final Matcher matcher = PATTERN.matcher(valueString);
    if (!matcher.matches()) {
      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
    }

    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)));

    int nanoSeconds = 0;
    if (matcher.group(7) != null) {
      if (matcher.group(7).length() == 1 || matcher.group(7).length() > 10) {
        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
      }
      final String decimals = matcher.group(8);
      if (facets != null && facets.getPrecision() != null && facets.getPrecision() < decimals.length()) {
        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED.addContent(value, facets));
      }
      nanoSeconds = Integer.parseInt(decimals + "000000000".substring(decimals.length()));
      if (!(returnType.isAssignableFrom(Timestamp.class))) {
        if (nanoSeconds % (1000 * 1000) == 0) {
          dateTimeValue.set(Calendar.MILLISECOND, nanoSeconds / (1000 * 1000));
        } else {
          throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
        }
      }
    }

    // The Calendar class does not check any values until a get method is called,
    // so we do just that to validate the fields set above, not because we want
    // to return something else. For strict checks, the lenient mode is switched
    // off temporarily.
    dateTimeValue.setLenient(false);
    try {
      dateTimeValue.get(Calendar.MILLISECOND);
    } catch (final IllegalArgumentException e) {
      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value), e);
    }
    dateTimeValue.setLenient(true);

    if (returnType.isAssignableFrom(Calendar.class)) {
      return returnType.cast(dateTimeValue);
    } else if (returnType.isAssignableFrom(Long.class)) {
      return returnType.cast(dateTimeValue.getTimeInMillis());
    } else if (returnType.isAssignableFrom(Date.class)) {
      return returnType.cast(dateTimeValue.getTime());
    } else if (returnType.isAssignableFrom(Timestamp.class)) {
        Timestamp timestamp = new Timestamp(dateTimeValue.getTimeInMillis());
        if (literalKind != EdmLiteralKind.JSON) {
          timestamp.setNanos(nanoSeconds);
        }
        return returnType.cast(timestamp);
    } else {
      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
    }
  }