[OLINGO-904] Allow expand on crossjoin with entity set level
Future changes still needed to support navigation/options afterwards
This commit is contained in:
parent
8406c58b7f
commit
e5d1e823c5
|
@ -6,9 +6,9 @@
|
|||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
package org.apache.olingo.server.core.uri.parser;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.olingo.commons.api.edm.Edm;
|
||||
|
@ -41,6 +42,7 @@ import org.apache.olingo.server.api.uri.queryoption.SystemQueryOptionKind;
|
|||
import org.apache.olingo.server.core.uri.UriInfoImpl;
|
||||
import org.apache.olingo.server.core.uri.UriResourceComplexPropertyImpl;
|
||||
import org.apache.olingo.server.core.uri.UriResourceCountImpl;
|
||||
import org.apache.olingo.server.core.uri.UriResourceEntitySetImpl;
|
||||
import org.apache.olingo.server.core.uri.UriResourceNavigationPropertyImpl;
|
||||
import org.apache.olingo.server.core.uri.UriResourceRefImpl;
|
||||
import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
|
||||
|
@ -57,24 +59,58 @@ public class ExpandParser {
|
|||
private final Edm edm;
|
||||
private final OData odata;
|
||||
private final Map<String, AliasQueryOption> aliases;
|
||||
private final Collection<String> crossjoinEntitySetNames;
|
||||
|
||||
public ExpandParser(final Edm edm, final OData odata, final Map<String, AliasQueryOption> aliases) {
|
||||
public ExpandParser(final Edm edm, final OData odata, final Map<String, AliasQueryOption> aliases,
|
||||
final Collection<String> crossjoinEntitySetNames) {
|
||||
this.edm = edm;
|
||||
this.odata = odata;
|
||||
this.aliases = aliases;
|
||||
this.crossjoinEntitySetNames = crossjoinEntitySetNames;
|
||||
}
|
||||
|
||||
public ExpandOption parse(UriTokenizer tokenizer, final EdmStructuredType referencedType)
|
||||
throws UriParserException, UriValidationException {
|
||||
ExpandOptionImpl expandOption = new ExpandOptionImpl();
|
||||
do {
|
||||
final ExpandItem item = parseItem(tokenizer, referencedType);
|
||||
expandOption.addExpandItem(item);
|
||||
// In the crossjoin case the start has to be an EntitySet name which will dictate the reference type
|
||||
if (crossjoinEntitySetNames != null && !crossjoinEntitySetNames.isEmpty()) {
|
||||
final ExpandItem item = parseCrossJoinItem(tokenizer);
|
||||
expandOption.addExpandItem(item);
|
||||
} else {
|
||||
final ExpandItem item = parseItem(tokenizer, referencedType);
|
||||
expandOption.addExpandItem(item);
|
||||
}
|
||||
} while (tokenizer.next(TokenKind.COMMA));
|
||||
|
||||
return expandOption;
|
||||
}
|
||||
|
||||
private ExpandItem parseCrossJoinItem(UriTokenizer tokenizer) throws UriParserSemanticException {
|
||||
ExpandItemImpl item = new ExpandItemImpl();
|
||||
if (tokenizer.next(TokenKind.STAR)) {
|
||||
item.setIsStar(true);
|
||||
} else if (tokenizer.next(TokenKind.ODataIdentifier)) {
|
||||
String entitySetName = tokenizer.getText();
|
||||
if (crossjoinEntitySetNames.contains(entitySetName)) {
|
||||
UriInfoImpl resource = new UriInfoImpl().setKind(UriInfoKind.resource);
|
||||
final UriResourceEntitySetImpl entitySetResourceSegment =
|
||||
new UriResourceEntitySetImpl(edm.getEntityContainer().getEntitySet(entitySetName));
|
||||
resource.addResourcePart(entitySetResourceSegment);
|
||||
|
||||
item.setResourcePath(resource);
|
||||
} else {
|
||||
throw new UriParserSemanticException("Unknown crossjoin entity set.",
|
||||
UriParserSemanticException.MessageKeys.UNKNOWN_PART, entitySetName);
|
||||
}
|
||||
} else {
|
||||
throw new UriParserSemanticException("If the target resource is a crossjoin an entity set is "
|
||||
+ "needed as the starting point.",
|
||||
UriParserSemanticException.MessageKeys.UNKNOWN_PART);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
private ExpandItem parseItem(UriTokenizer tokenizer, final EdmStructuredType referencedType)
|
||||
throws UriParserException, UriValidationException {
|
||||
ExpandItemImpl item = new ExpandItemImpl();
|
||||
|
@ -167,6 +203,7 @@ public class ExpandParser {
|
|||
|
||||
EdmStructuredType type = referencedType;
|
||||
String name = null;
|
||||
|
||||
while (tokenizer.next(TokenKind.ODataIdentifier)) {
|
||||
name = tokenizer.getText();
|
||||
final EdmProperty property = referencedType.getStructuralProperty(name);
|
||||
|
@ -217,7 +254,7 @@ public class ExpandParser {
|
|||
|
||||
} else if (!forRef && !forCount && tokenizer.next(TokenKind.EXPAND)) {
|
||||
ParserHelper.requireNext(tokenizer, TokenKind.EQ);
|
||||
systemQueryOption = new ExpandParser(edm, odata, aliases).parse(tokenizer, referencedType);
|
||||
systemQueryOption = new ExpandParser(edm, odata, aliases, null).parse(tokenizer, referencedType);
|
||||
|
||||
} else if (tokenizer.next(TokenKind.FILTER)) {
|
||||
ParserHelper.requireNext(tokenizer, TokenKind.EQ);
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
|
@ -98,15 +98,15 @@ public class Parser {
|
|||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,7 @@ public class Parser {
|
|||
parseOrderByOption(contextUriInfo.getOrderByOption(), contextType,
|
||||
contextUriInfo.getEntitySetNames(), contextUriInfo.getAliasMap());
|
||||
parseExpandOption(contextUriInfo.getExpandOption(), contextType,
|
||||
!contextUriInfo.getEntitySetNames().isEmpty() || contextUriInfo.getKind() == UriInfoKind.all,
|
||||
contextUriInfo.getKind() == UriInfoKind.all, contextUriInfo.getEntitySetNames(),
|
||||
contextUriInfo.getAliasMap());
|
||||
parseSelectOption(contextUriInfo.getSelectOption(), contextType, contextIsCollection);
|
||||
|
||||
|
@ -335,16 +335,18 @@ public class Parser {
|
|||
}
|
||||
}
|
||||
|
||||
private void parseExpandOption(ExpandOption expandOption, final EdmType contextType, final boolean isCrossjoinOrAll,
|
||||
final Map<String, AliasQueryOption> aliases) throws UriParserException, UriValidationException {
|
||||
private void parseExpandOption(ExpandOption expandOption, final EdmType contextType, final boolean isAll,
|
||||
final List<String> entitySetNames, final Map<String, AliasQueryOption> aliases) throws UriParserException,
|
||||
UriValidationException {
|
||||
if (expandOption != null) {
|
||||
if (!(contextType instanceof EdmStructuredType || isCrossjoinOrAll)) {
|
||||
if (!(contextType instanceof EdmStructuredType || isAll
|
||||
|| (entitySetNames != null && !entitySetNames.isEmpty()))) {
|
||||
throw new UriValidationException("Expand is only allowed on structured types!",
|
||||
UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED, expandOption.getName());
|
||||
}
|
||||
final String optionValue = expandOption.getText();
|
||||
UriTokenizer expandTokenizer = new UriTokenizer(optionValue);
|
||||
final ExpandOption option = new ExpandParser(edm, odata, aliases).parse(expandTokenizer,
|
||||
final ExpandOption option = new ExpandParser(edm, odata, aliases, entitySetNames).parse(expandTokenizer,
|
||||
contextType instanceof EdmStructuredType ? (EdmStructuredType) contextType : null);
|
||||
checkOptionEOF(expandTokenizer, expandOption.getName(), optionValue);
|
||||
for (final ExpandItem item : option.getExpandItems()) {
|
||||
|
|
|
@ -946,6 +946,27 @@ public class TestFullResourcePath {
|
|||
.is("<<ESTwoPrim/PropertyString> eq <ESMixPrimCollComp/PropertyComp/PropertyString>>");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void crossjoinExpand() throws Exception {
|
||||
testUri.run("$crossjoin(ESTwoPrim,ESAllPrim)",
|
||||
"$expand=ESTwoPrim")
|
||||
.goExpand()
|
||||
.first().goPath().first().isEntitySet("ESTwoPrim");
|
||||
|
||||
testUri.run("$crossjoin(ESTwoPrim,ESAllPrim)",
|
||||
"$expand=ESTwoPrim,ESAllPrim")
|
||||
.goExpand()
|
||||
.first().goPath().first().isEntitySet("ESTwoPrim")
|
||||
.goUpExpandValidator().next().goPath().first().isEntitySet("ESAllPrim");
|
||||
|
||||
//TODO: Once crossjoin is implemented these tests should no longer result in errors
|
||||
// testUri.run("$crossjoin(ESTwoPrim,ESAllPrim)",
|
||||
// "$expand=ESAllPrim/NavPropertyETTwoPrimOne")
|
||||
// .goExpand()
|
||||
// .first().goPath().at(0).isEntitySet("ESAllPrim")
|
||||
// .at(1).isNavProperty("NavPropertyETTwoPrimOne", new FullQualifiedName("Namespace1_Alias.ETTwoPrim"), false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void crossjoinError() throws Exception {
|
||||
testUri.runEx("$crossjoin").isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX);
|
||||
|
|
Loading…
Reference in New Issue