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