[OLINGO-904] Allow expand on crossjoin with entity set level

Future changes still needed to support navigation/options afterwards


Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/e5d1e823
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/e5d1e823
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/e5d1e823

Branch: refs/heads/master
Commit: e5d1e823c5c8a8113c17db5dfcfd3073b9d82da4
Parents: 8406c58
Author: Christian Amend <[email protected]>
Authored: Fri Mar 18 14:35:06 2016 +0100
Committer: Christian Amend <[email protected]>
Committed: Mon Mar 21 10:09:17 2016 +0100

----------------------------------------------------------------------
 .../server/core/uri/parser/ExpandParser.java    | 49 +++++++++++++++++---
 .../olingo/server/core/uri/parser/Parser.java   | 34 +++++++-------
 .../core/uri/parser/TestFullResourcePath.java   | 21 +++++++++
 3 files changed, 82 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e5d1e823/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java
index 03750a5..2fc0faf 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/ExpandParser.java
@@ -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);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e5d1e823/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
index e1313c1..b4469d8 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
@@ -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()) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e5d1e823/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/TestFullResourcePath.java
----------------------------------------------------------------------
diff --git 
a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/TestFullResourcePath.java
 
b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/TestFullResourcePath.java
index 32c56b4..64cf757 100644
--- 
a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/TestFullResourcePath.java
+++ 
b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/parser/TestFullResourcePath.java
@@ -947,6 +947,27 @@ public class TestFullResourcePath {
   }
 
   @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);
     
testUri.runEx("$crossjoin/error").isExSyntax(UriParserSyntaxException.MessageKeys.MUST_BE_LAST_SEGMENT);

Reply via email to