public UriInfo parseUri()

in lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java [94:291]


  public UriInfo parseUri(final String path, final String query, final String fragment, String baseUri)
      throws UriParserException, UriValidationException {

    UriInfoImpl contextUriInfo = new UriInfoImpl();
   
    // Read the query options (system and custom options).
    // This is done before parsing the resource path because the aliases have to be available there.
    // System query options that can only be parsed with context from the resource path will be post-processed later.
    final List<QueryOption> options =
        query == null ? Collections.<QueryOption> emptyList() : UriDecoder.splitAndDecodeOptions(query);
    for (final QueryOption option : options) {
      final String optionName = option.getName();
      String value = option.getText();
      if(UriDecoder.isFormEncoding()){
        value = getFormEncodedValue(value);
      }
      // Parse the untyped option and retrieve a system-option or alias-option instance (or null for a custom option).
      final QueryOption parsedOption = parseOption(optionName, value);
      try {
        contextUriInfo.setQueryOption(parsedOption == null ? option : parsedOption);
      } catch (final ODataRuntimeException e) {
        throw new UriParserSyntaxException(
            parsedOption instanceof SystemQueryOption ?
                "Double system query option!" :
                "Alias already specified! Name: " + optionName,
            e,
            parsedOption instanceof SystemQueryOption ?
                UriParserSyntaxException.MessageKeys.DOUBLE_SYSTEM_QUERY_OPTION :
                UriParserSyntaxException.MessageKeys.DUPLICATED_ALIAS,
            optionName);
      }
    }

    // Read the decoded path segments.
    EdmType contextType = null;
    boolean contextIsCollection = false;

    List<String> pathSegmentsDecoded = UriDecoder.splitAndDecodePath(path);
    int numberOfSegments = pathSegmentsDecoded.size();
    // Remove an initial empty segment resulting from the expected '/' at the beginning of the path.
    if (numberOfSegments > 1 && pathSegmentsDecoded.get(0).isEmpty()) {
      pathSegmentsDecoded.remove(0);
      numberOfSegments--;
    }

    final String firstSegment = pathSegmentsDecoded.get(0);

    if (firstSegment.isEmpty()) {
      ensureLastSegment(firstSegment, 1, numberOfSegments);
      contextUriInfo.setKind(UriInfoKind.service);

    } else if ("$batch".equals(firstSegment)) {
      ensureLastSegment(firstSegment, 1, numberOfSegments);
      contextUriInfo.setKind(UriInfoKind.batch);

    } else if ("$metadata".equals(firstSegment)) {
      ensureLastSegment(firstSegment, 1, numberOfSegments);
      contextUriInfo.setKind(UriInfoKind.metadata);
      contextUriInfo.setFragment(fragment);

    } else if ("$all".equals(firstSegment)) {
      ensureLastSegment(firstSegment, 1, numberOfSegments);
      contextUriInfo.setKind(UriInfoKind.all);
      contextIsCollection = true;

    } else if ("$entity".equals(firstSegment)) {
      if (null != contextUriInfo.getIdOption()) {
        String idOptionText = contextUriInfo.getIdOption().getText();
        if (idOptionText.startsWith(HTTP)) {
          baseUri = UriDecoder.decode(baseUri);
          if (idOptionText.contains(baseUri)) {
            idOptionText = idOptionText.substring(baseUri.length() + 1);
          } else {
            throw new UriParserSemanticException("$id cannot have an absolute path",
                UriParserSemanticException.MessageKeys.NOT_IMPLEMENTED_SYSTEM_QUERY_OPTION);
          }
        }
        if (numberOfSegments > 1) {
          /**
           * If url is of the form 
           * http://localhost:8080/odata-server-tecsvc/odata.svc/$entity/
           * olingo.odata.test1.ETAllPrim?$id=ESAllPrim(32767)
           */
          final ResourcePathParser resourcePathParser = new ResourcePathParser
            (edm, contextUriInfo.getAliasMap());
          String typeCastSegment = pathSegmentsDecoded.get(1);
          ensureLastSegment(typeCastSegment, 2, numberOfSegments);
          contextType = resourcePathParser.parseDollarEntityTypeCast(typeCastSegment);
          contextUriInfo = (UriInfoImpl) new Parser(edm, odata).
              parseUri("/" + idOptionText, query, fragment, baseUri);
          contextUriInfo.setEntityTypeCast((EdmEntityType) contextType);
        } else if (numberOfSegments == 1) {
          /**
           * If url is of the form 
           * http://localhost:8080/odata-server-tecsvc/odata.svc/$entity?$id=ESAllPrim(32527)
           */
          contextUriInfo = (UriInfoImpl) new Parser(edm, odata).
                  parseUri("/" + idOptionText, query, fragment, baseUri);
        }
        contextType = contextUriInfo.getEntityTypeCast();
        contextUriInfo.setKind(UriInfoKind.entityId);
        contextIsCollection = false;
      } else {
        /**
         * If url is of the form 
         * http://localhost:8080/odata-server-tecsvc/odata.svc/$entity/olingo.odata.test1.ETKeyNav/$ref
         */
        ensureLastSegment(firstSegment, 2, numberOfSegments);
        /**
         * If url is of the form 
         * http://localhost:8080/odata-server-tecsvc/odata.svc/$entity/olingo.odata.test1.ETKeyNav
         */
        throw new UriParserSyntaxException("The entity-id MUST be specified using the system query option $id",
                  UriParserSyntaxException.MessageKeys.ENTITYID_MISSING_SYSTEM_QUERY_OPTION_ID);
      }
    } else if (firstSegment.startsWith("$crossjoin")) {
      ensureLastSegment(firstSegment, 1, numberOfSegments);
      contextUriInfo.setKind(UriInfoKind.crossjoin);
      final List<String> entitySetNames = new ResourcePathParser(edm, contextUriInfo.getAliasMap())
          .parseCrossjoinSegment(firstSegment);
      for (final String name : entitySetNames) {
        contextUriInfo.addEntitySetName(name);
      }
      contextIsCollection = true;

    } else {
      contextUriInfo.setKind(UriInfoKind.resource);
      final ResourcePathParser resourcePathParser = new ResourcePathParser(edm, contextUriInfo.getAliasMap());
      int count = 0;
      UriResource lastSegment = null;
      for (final String pathSegment : pathSegmentsDecoded) {
        count++;
        if (pathSegment.startsWith(ENTITY)) {
          /**
           * If url is of the form 
           * http://localhost:8080/odata-server-tecsvc/odata.svc/ESAllPrim/$entity
           */
          throw new UriParserSyntaxException("The entity-id MUST be specified using the system query option $id",
                    UriParserSyntaxException.MessageKeys.ENTITYID_MISSING_SYSTEM_QUERY_OPTION_ID);
        } else {
          final UriResource segment = resourcePathParser.parsePathSegment(pathSegment, lastSegment);
          if (segment != null) {
            if (segment instanceof UriResourceCount
                || segment instanceof UriResourceRef
                || segment instanceof UriResourceValue) {
              ensureLastSegment(pathSegment, count, numberOfSegments);
            } else if (segment instanceof UriResourceAction
                || segment instanceof UriResourceFunction
                && !((UriResourceFunction) segment).getFunction().isComposable()) {
              if (count < numberOfSegments) {
                throw new UriValidationException(
                    "The segment of an action or of a non-composable function must be the last resource-path segment.",
                    UriValidationException.MessageKeys.UNALLOWED_RESOURCE_PATH,
                    pathSegmentsDecoded.get(count));
              }
              lastSegment = segment;
            } else if (segment instanceof UriResourceStartingTypeFilterImpl) {
              throw new UriParserSemanticException("First resource-path segment must not be namespace-qualified.",
                  UriParserSemanticException.MessageKeys.NAMESPACE_NOT_ALLOWED_AT_FIRST_ELEMENT);
            } else {
              lastSegment = segment;
            }
            contextUriInfo.addResourcePart(segment);
          }
        }
      }

      if (lastSegment instanceof UriResourcePartTyped) {
        final UriResourcePartTyped typed = (UriResourcePartTyped) lastSegment;
        contextType = ParserHelper.getTypeInformation(typed);
        if (contextType != null && ((lastSegment instanceof UriResourceEntitySet &&
            (((UriResourceEntitySet) lastSegment).getTypeFilterOnCollection() != null
                || ((UriResourceEntitySet) lastSegment).getTypeFilterOnEntry() != null))
            || contextUriInfo.getIdOption() != null) && contextType instanceof EdmEntityType) {
          contextUriInfo.setEntityTypeCast((EdmEntityType) contextType);
        }
        contextIsCollection = typed.isCollection();
      }
    }

    // Post-process system query options that need context information from the resource path.
    if (contextType instanceof EdmStructuredType && contextUriInfo.getApplyOption() != null) {
      // Data aggregation may change the structure of the result.
      contextType = new DynamicStructuredType((EdmStructuredType) contextType);
    }
    parseApplyOption(contextUriInfo.getApplyOption(), contextType,
        contextUriInfo.getEntitySetNames(), contextUriInfo.getAliasMap());
    parseFilterOption(contextUriInfo.getFilterOption(), contextType,
        contextUriInfo.getEntitySetNames(), contextUriInfo.getAliasMap());
    parseOrderByOption(contextUriInfo.getOrderByOption(), contextType,
        contextUriInfo.getEntitySetNames(), contextUriInfo.getAliasMap());
    parseExpandOption(contextUriInfo.getExpandOption(), contextType,
        contextUriInfo.getKind() == UriInfoKind.all, contextUriInfo.getEntitySetNames(),
        contextUriInfo.getAliasMap());
    parseSelectOption(contextUriInfo.getSelectOption(), contextType, contextIsCollection);

    return contextUriInfo;
  }