Repository: olingo-odata4
Updated Branches:
  refs/heads/master a3a84c9e8 -> 1ce51fd4e


[OLINGO-1202]Bound function scenarios, samples and tests


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

Branch: refs/heads/master
Commit: 1ce51fd4ec59ef46091d32459c69e8e9eec671af
Parents: a3a84c9
Author: Archana Rai <archana....@sap.com>
Authored: Mon Nov 13 16:07:34 2017 +0530
Committer: Archana Rai <archana....@sap.com>
Committed: Mon Nov 13 16:07:34 2017 +0530

----------------------------------------------------------------------
 .../tecsvc/http/BasicBoundFunctionITCase.java   | 372 +++++++++++++++++++
 .../commons/core/edm/EdmProviderImpl.java       |   8 +-
 .../EdmProviderImplOverloadingTest.java         |   6 +-
 .../olingo/server/tecsvc/data/FunctionData.java |  87 ++++-
 .../TechnicalPrimitiveComplexProcessor.java     |  32 +-
 .../tecsvc/provider/FunctionProvider.java       |  17 +
 .../server/tecsvc/provider/SchemaProvider.java  |   1 +
 samples/tutorials/p9_action/pom.xml             |   2 +-
 .../myservice/mynamespace/data/Storage.java     |  24 ++
 .../mynamespace/service/DemoEdmProvider.java    |  70 ++++
 .../service/DemoEntityCollectionProcessor.java  |  21 ++
 .../service/DemoEntityProcessor.java            |  30 +-
 12 files changed, 659 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1ce51fd4/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicBoundFunctionITCase.java
----------------------------------------------------------------------
diff --git 
a/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicBoundFunctionITCase.java
 
b/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicBoundFunctionITCase.java
new file mode 100644
index 0000000..efeca67
--- /dev/null
+++ 
b/fit/src/test/java/org/apache/olingo/fit/tecsvc/http/BasicBoundFunctionITCase.java
@@ -0,0 +1,372 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * 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
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.fit.tecsvc.http;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.olingo.client.api.ODataClient;
+import org.apache.olingo.commons.api.http.HttpHeader;
+import org.apache.olingo.commons.api.http.HttpMethod;
+import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.fit.AbstractBaseTestITCase;
+import org.apache.olingo.fit.tecsvc.TecSvcConst;
+import org.junit.Test;
+
+public class BasicBoundFunctionITCase extends AbstractBaseTestITCase {
+
+  private static final String SERVICE_URI = TecSvcConst.BASE_URI + "/";
+
+  @Test
+  public void boundFunctionReturningDerievedType() throws Exception {
+    URL url = new URL(SERVICE_URI + "ESBase(111)/olingo.odata.test1.ETTwoBase/"
+        + "olingo.odata.test1.BFESBaseRTESTwoBase()");
+
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    connection.setRequestMethod(HttpMethod.GET.name());
+    connection.setRequestProperty(HttpHeader.ACCEPT, "application/json");
+    connection.connect();
+
+    assertEquals(HttpStatusCode.OK.getStatusCode(), 
connection.getResponseCode());
+    final String expected =  "\"PropertyInt16\":111,"
+        +  "\"PropertyString\":\"TEST A\","
+        +  "\"AdditionalPropertyString_5\":\"TEST A 0815\","
+        +  "\"AdditionalPropertyString_6\":\"TEST B 0815\"";
+    String content = IOUtils.toString(connection.getInputStream());
+    assertTrue(content.contains(expected));
+    connection.disconnect();
+  }
+  
+  @Test
+  public void boundFunctionReturningNavigationType() throws Exception {
+    URL url = new URL(SERVICE_URI + 
"ESTwoKeyNav(PropertyInt16=1,PropertyString='1')"
+        + 
"/NavPropertyETTwoKeyNavMany/olingo.odata.test1.BFC_RTESTwoKeyNav_()");
+
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    connection.setRequestMethod(HttpMethod.GET.name());
+    connection.setRequestProperty(HttpHeader.ACCEPT, "application/json");
+    connection.connect();
+
+    assertEquals(HttpStatusCode.OK.getStatusCode(), 
connection.getResponseCode());
+    final String expected =    "\"PropertyCompNav\":{"
+        +             "\"PropertyInt16\":1,"
+        +             "\"PropertyComp\":{"
+        +             "\"PropertyString\":\"First Resource - positive 
values\","
+        +             "\"PropertyBinary\":\"ASNFZ4mrze8=\","
+        +             "\"PropertyBoolean\":true,"
+        +             "\"PropertyByte\":255,"
+        +             "\"PropertyDate\":\"2012-12-03\","
+        +             "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\","
+        +             "\"PropertyDecimal\":34,"
+        +             "\"PropertySingle\":1.79E20,"
+        +             "\"PropertyDouble\":-1.79E20,"
+        +             "\"PropertyDuration\":\"PT6S\","
+        +             
"\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\","
+        +             "\"PropertyInt16\":32767,"
+        +             "\"PropertyInt32\":2147483647,"
+        +             "\"PropertyInt64\":9223372036854775807,"
+        +             "\"PropertySByte\":127,"
+        +             "\"PropertyTimeOfDay\":\"21:05:59\"";
+    String content = IOUtils.toString(connection.getInputStream());
+    assertTrue(content.contains(expected));
+    connection.disconnect();
+  }
+  
+  @Test
+  public void boundFunctionCETReturningCT() throws Exception {
+    URL url = new URL(SERVICE_URI + 
"ESAllPrim/olingo.odata.test1.BFNESAllPrimRTCTAllPrim()");
+
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    connection.setRequestMethod(HttpMethod.GET.name());
+    connection.setRequestProperty(HttpHeader.ACCEPT, "application/json");
+    connection.connect();
+
+    assertEquals(HttpStatusCode.OK.getStatusCode(), 
connection.getResponseCode());
+    String content = IOUtils.toString(connection.getInputStream());
+    assertNotNull(content);
+    connection.disconnect();
+  }
+  
+  
+  @Test
+  public void boundFunctionCETReturningET() throws Exception {
+    URL url = new URL(SERVICE_URI + 
"ESTwoKeyNav/olingo.odata.test1.BFCESTwoKeyNavRTTwoKeyNav()");
+
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    connection.setRequestMethod(HttpMethod.GET.name());
+    connection.setRequestProperty(HttpHeader.ACCEPT, "application/json");
+    connection.connect();
+
+    assertEquals(HttpStatusCode.OK.getStatusCode(), 
connection.getResponseCode());
+    String content = IOUtils.toString(connection.getInputStream());
+    assertNotNull(content);
+    connection.disconnect();
+  }
+  
+  @Test
+  public void boundFunctionCETWithParamReturningET() throws Exception {
+    URL url = new URL(SERVICE_URI + 
"ESKeyNav/olingo.odata.test1.BFCESKeyNavRTETKeyNavParam(ParameterString='qw')");
+
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    connection.setRequestMethod(HttpMethod.GET.name());
+    connection.setRequestProperty(HttpHeader.ACCEPT, "application/json");
+    connection.connect();
+
+    assertEquals(HttpStatusCode.OK.getStatusCode(), 
connection.getResponseCode());
+    String content = IOUtils.toString(connection.getInputStream());
+    assertNotNull(content);
+    connection.disconnect();
+  }
+  
+  
+  @Test
+  public void boundFunctionCETParamReturningET() throws Exception {
+    URL url = new URL(SERVICE_URI + 
"ESKeyNav/olingo.odata.test1.BFCESKeyNavRTETKeyNavParam"
+        + "(ParameterString=@p1)?@p1=%27qw%27");
+
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    connection.setRequestMethod(HttpMethod.GET.name());
+    connection.setRequestProperty(HttpHeader.ACCEPT, "application/json");
+    connection.connect();
+
+    assertEquals(HttpStatusCode.OK.getStatusCode(), 
connection.getResponseCode());
+    String content = IOUtils.toString(connection.getInputStream());
+    assertNotNull(content);
+    connection.disconnect();
+  }
+  
+  
+  @Test
+  public void boundFunctionCETParamReturningCET() throws Exception {
+    URL url = new URL(SERVICE_URI + 
"ESBaseTwoKeyNav/olingo.odata.test1.BFCESBaseTwoKeyNavRTESBaseTwoKey()");
+
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    connection.setRequestMethod(HttpMethod.GET.name());
+    connection.setRequestProperty(HttpHeader.ACCEPT, "application/json");
+    connection.connect();
+
+    assertEquals(HttpStatusCode.OK.getStatusCode(), 
connection.getResponseCode());
+    String content = IOUtils.toString(connection.getInputStream());
+    assertNotNull(content);
+    connection.disconnect();
+  }
+  
+  
+  @Test
+  public void boundFunctionCETReturningPT() throws Exception {
+    URL url = new URL(SERVICE_URI + 
"ESTwoKeyNav/olingo.odata.test1.BFNESTwoKeyNavRTString()");
+
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    connection.setRequestMethod(HttpMethod.GET.name());
+    connection.setRequestProperty(HttpHeader.ACCEPT, "application/json");
+    connection.connect();
+
+    assertEquals(HttpStatusCode.OK.getStatusCode(), 
connection.getResponseCode());
+    String content = IOUtils.toString(connection.getInputStream());
+    assertNotNull(content);
+    connection.disconnect();
+  }
+  
+  
+  @Test
+  public void boundFunctionCETReturningCCT() throws Exception {
+    URL url = new URL(SERVICE_URI + 
"ESTwoKeyNav/olingo.odata.test1.BFCESTwoKeyNavRTCollCTNavFiveProp()");
+
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    connection.setRequestMethod(HttpMethod.GET.name());
+    connection.setRequestProperty(HttpHeader.ACCEPT, "application/json");
+    connection.connect();
+
+    assertEquals(HttpStatusCode.OK.getStatusCode(), 
connection.getResponseCode());
+    String content = IOUtils.toString(connection.getInputStream());
+    assertNotNull(content);
+    connection.disconnect();
+  }
+  
+  
+  @Test
+  public void boundFunctionCETReturningCPT() throws Exception {
+    URL url = new URL(SERVICE_URI + 
"ESTwoKeyNav/olingo.odata.test1.BFCESTwoKeyNavRTCollDecimal()");
+
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    connection.setRequestMethod(HttpMethod.GET.name());
+    connection.setRequestProperty(HttpHeader.ACCEPT, "application/json");
+    connection.connect();
+
+    assertEquals(HttpStatusCode.OK.getStatusCode(), 
connection.getResponseCode());
+    String content = IOUtils.toString(connection.getInputStream());
+    assertNotNull(content);
+    connection.disconnect();
+  }
+  
+  @Test
+  public void boundFunctionETReturningCT() throws Exception {
+    URL url = new URL(SERVICE_URI + 
"ESTwoKeyNav(PropertyInt16=1,PropertyString='1')/"
+        + "olingo.odata.test1.BFCETTwoKeyNavRTCTTwoPrim()");
+
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    connection.setRequestMethod(HttpMethod.GET.name());
+    connection.setRequestProperty(HttpHeader.ACCEPT, "application/json");
+    connection.connect();
+
+    assertEquals(HttpStatusCode.OK.getStatusCode(), 
connection.getResponseCode());
+    String content = IOUtils.toString(connection.getInputStream());
+    assertNotNull(content);
+    connection.disconnect();
+  }
+  
+  @Test
+  public void boundFunctionETReturningET() throws Exception {
+    URL url = new URL(SERVICE_URI + 
"ESKeyNav(1)/olingo.odata.test1.BFCETKeyNavRTETKeyNav()");
+
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    connection.setRequestMethod(HttpMethod.GET.name());
+    connection.setRequestProperty(HttpHeader.ACCEPT, "application/json");
+    connection.connect();
+
+    assertEquals(HttpStatusCode.OK.getStatusCode(), 
connection.getResponseCode());
+    String content = IOUtils.toString(connection.getInputStream());
+    assertNotNull(content);
+    connection.disconnect();
+  }
+  
+  @Test
+  public void boundFunctionETReturningCET() throws Exception {
+    URL url = new URL(SERVICE_URI + 
"ESTwoKeyNav(PropertyInt16=1,PropertyString='1')/"
+        + "olingo.odata.test1.BFCSINavRTESTwoKeyNav()");
+
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    connection.setRequestMethod(HttpMethod.GET.name());
+    connection.setRequestProperty(HttpHeader.ACCEPT, "application/json");
+    connection.connect();
+
+    assertEquals(HttpStatusCode.OK.getStatusCode(), 
connection.getResponseCode());
+    String content = IOUtils.toString(connection.getInputStream());
+    assertNotNull(content);
+    connection.disconnect();
+  }
+  
+  
+  @Test
+  public void boundFunctionETSetPath() throws Exception {
+    URL url = new URL(SERVICE_URI + 
"ESTwoKeyNav(PropertyInt16=1,PropertyString='1')/"
+        + 
"NavPropertyETTwoKeyNavMany/olingo.odata.test1.BFC_RTESTwoKeyNav_()");
+
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    connection.setRequestMethod(HttpMethod.GET.name());
+    connection.setRequestProperty(HttpHeader.ACCEPT, "application/json");
+    connection.connect();
+
+    assertEquals(HttpStatusCode.OK.getStatusCode(), 
connection.getResponseCode());
+    String content = IOUtils.toString(connection.getInputStream());
+    assertNotNull(content);
+    connection.disconnect();
+  }
+  
+  @Test
+  public void boundFunctionETIsComposible() throws Exception {
+    URL url = new URL(SERVICE_URI + 
"ESTwoKeyNav/olingo.odata.test1.BFESTwoKeyNavRTESTwoKeyNav()"
+        + "?$top=1&$skip=1&$select=PropertyString");
+
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    connection.setRequestMethod(HttpMethod.GET.name());
+    connection.setRequestProperty(HttpHeader.ACCEPT, "application/json");
+    connection.connect();
+
+    assertEquals(HttpStatusCode.OK.getStatusCode(), 
connection.getResponseCode());
+    String content = IOUtils.toString(connection.getInputStream());
+    assertNotNull(content);
+    connection.disconnect();
+  }
+  
+  @Test
+  public void boundFunctionETIsComposibleFilter() throws Exception {
+    URL url = new URL(SERVICE_URI + 
"ESTwoKeyNav/olingo.odata.test1.BFESTwoKeyNavRTESTwoKeyNav()?"
+        + "$filter=PropertyString%20eq%20%272%27");
+
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    connection.setRequestMethod(HttpMethod.GET.name());
+    connection.setRequestProperty(HttpHeader.ACCEPT, "application/json");
+    connection.connect();
+
+    assertEquals(HttpStatusCode.OK.getStatusCode(), 
connection.getResponseCode());
+    String content = IOUtils.toString(connection.getInputStream());
+    assertNotNull(content);
+    connection.disconnect();
+  }
+  
+  @Test
+  public void boundFunctionETIsComposibleOrderBy() throws Exception {
+    URL url = new URL(SERVICE_URI + 
"ESTwoKeyNav/olingo.odata.test1.BFESTwoKeyNavRTESTwoKeyNav()?"
+        + "$orderby=PropertyInt16%20desc");
+
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    connection.setRequestMethod(HttpMethod.GET.name());
+    connection.setRequestProperty(HttpHeader.ACCEPT, "application/json");
+    connection.connect();
+
+    assertEquals(HttpStatusCode.OK.getStatusCode(), 
connection.getResponseCode());
+    String content = IOUtils.toString(connection.getInputStream());
+    assertNotNull(content);
+    connection.disconnect();
+  }
+  
+  @Test
+  public void boundFunctionOverload() throws Exception {
+    URL url = new URL(SERVICE_URI + 
"ESTwoKeyNav/olingo.odata.test1.BFC_RTESTwoKeyNav_()");
+
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    connection.setRequestMethod(HttpMethod.GET.name());
+    connection.setRequestProperty(HttpHeader.ACCEPT, "application/json");
+    connection.connect();
+
+    assertEquals(HttpStatusCode.OK.getStatusCode(), 
connection.getResponseCode());
+    String content = IOUtils.toString(connection.getInputStream());
+    assertNotNull(content);
+    connection.disconnect();
+  }
+  
+  @Test
+  public void boundFunctionOverloadParam() throws Exception {
+    URL url = new URL(SERVICE_URI + 
"ESTwoKeyNav/olingo.odata.test1.BFC_RTESTwoKeyNav_(ParameterString='abc')");
+
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    connection.setRequestMethod(HttpMethod.GET.name());
+    connection.setRequestProperty(HttpHeader.ACCEPT, "application/json");
+    connection.connect();
+
+    assertEquals(HttpStatusCode.OK.getStatusCode(), 
connection.getResponseCode());
+    String content = IOUtils.toString(connection.getInputStream());
+    assertNotNull(content);
+    connection.disconnect();
+  }
+  
+  
+  
+  @Override
+  protected ODataClient getClient() {
+    return null;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1ce51fd4/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmProviderImpl.java
----------------------------------------------------------------------
diff --git 
a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmProviderImpl.java
 
b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmProviderImpl.java
index 6f5ea64..6f8e7f4 100644
--- 
a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmProviderImpl.java
+++ 
b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmProviderImpl.java
@@ -184,6 +184,9 @@ public class EdmProviderImpl extends AbstractEdm {
       Boolean isBindingParameterCollection)
       throws ODataException {
     CsdlComplexType complexType = 
provider.getComplexType(bindingParameterTypeName);
+    if(provider.getEntityType(parameter.getTypeFQN()) == null){
+      return false;
+    }
     List<CsdlProperty> properties = 
provider.getEntityType(parameter.getTypeFQN()).getProperties();
     for (CsdlProperty property : properties) {
       String paramPropertyTypeName = 
property.getTypeAsFQNObject().getFullQualifiedNameAsString();
@@ -234,7 +237,10 @@ public class EdmProviderImpl extends AbstractEdm {
             throw new EdmException("No parameter specified for bound function: 
" + functionName);
           }
           final CsdlParameter bindingParameter = providerParameters.get(0);
-          if (bindingParameterTypeName.equals(bindingParameter.getTypeFQN())
+          if ((bindingParameterTypeName.equals(bindingParameter.getTypeFQN())
+              
||isEntityPreviousTypeCompatibleToBindingParam(bindingParameterTypeName, 
bindingParameter) ||
+              
isComplexPreviousTypeCompatibleToBindingParam(bindingParameterTypeName, 
bindingParameter, 
+                  isBindingParameterCollection))
               && isBindingParameterCollection.booleanValue() == 
bindingParameter.isCollection()
               && parameterNamesCopy.size() == providerParameters.size() - 1) {
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1ce51fd4/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmProviderImplOverloadingTest.java
----------------------------------------------------------------------
diff --git 
a/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmProviderImplOverloadingTest.java
 
b/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmProviderImplOverloadingTest.java
index 45d3d2b..916ca22 100644
--- 
a/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmProviderImplOverloadingTest.java
+++ 
b/lib/commons-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmProviderImplOverloadingTest.java
@@ -37,8 +37,10 @@ import org.apache.olingo.commons.api.edm.EdmFunction;
 import org.apache.olingo.commons.api.edm.FullQualifiedName;
 import org.apache.olingo.commons.api.edm.provider.CsdlAction;
 import org.apache.olingo.commons.api.edm.provider.CsdlEdmProvider;
+import org.apache.olingo.commons.api.edm.provider.CsdlEntityType;
 import org.apache.olingo.commons.api.edm.provider.CsdlFunction;
 import org.apache.olingo.commons.api.edm.provider.CsdlParameter;
+import org.apache.olingo.commons.api.edm.provider.CsdlProperty;
 import org.apache.olingo.commons.core.edm.EdmProviderImpl;
 import org.junit.Before;
 import org.junit.Test;
@@ -70,7 +72,9 @@ public class EdmProviderImplOverloadingTest {
         new 
CsdlAction().setName(operationName1.getName()).setBound(true).setParameters(action2Parameters);
     actions.add(action);
     when(provider.getActions(operationName1)).thenReturn(actions);
-
+    CsdlEntityType type = new CsdlEntityType().setProperties(new 
ArrayList<CsdlProperty>());
+    when(provider.getEntityType(operationType1)).thenReturn(type);
+    when(provider.getEntityType(operationType2)).thenReturn(type);
     List<CsdlFunction> functions = new ArrayList<CsdlFunction>();
     CsdlFunction function = new 
CsdlFunction().setName(operationName1.getName());
     functions.add(function);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1ce51fd4/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/FunctionData.java
----------------------------------------------------------------------
diff --git 
a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/FunctionData.java
 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/FunctionData.java
index ef1fa70..42c9f2e 100644
--- 
a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/FunctionData.java
+++ 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/FunctionData.java
@@ -18,10 +18,15 @@
  */
 package org.apache.olingo.server.tecsvc.data;
 
+import java.math.BigDecimal;
+import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Calendar;
 import java.util.List;
 import java.util.Map;
+import java.util.TimeZone;
+import java.util.UUID;
 
 import org.apache.olingo.commons.api.data.ComplexValue;
 import org.apache.olingo.commons.api.data.Entity;
@@ -35,6 +40,8 @@ import 
org.apache.olingo.server.tecsvc.provider.ComplexTypeProvider;
 
 public class FunctionData {
 
+  private static final UUID GUID = 
UUID.fromString("01234567-89ab-cdef-0123-456789abcdef");;
+
   protected static EntityCollection entityCollectionFunction(final String name,
       final Map<String, Parameter> parameters, final Map<String, 
EntityCollection> data)
       throws DataProviderException {
@@ -97,6 +104,8 @@ public class FunctionData {
       return DataCreator.createPrimitive(name, (short) 12345);
     } else if (name.equals("UFCRTString")) {
       return DataCreator.createPrimitive(name, "UFCRTString string value");
+    }else if ( name.equals("BFNESTwoKeyNavRTString") ) {
+      return DataCreator.createPrimitive(name, "BFNESTwoKeyNavRTString string 
value");
     } else if (name.equals("UFCRTCollString")) {
       return 
data.get("ESCollAllPrim").getEntities().get(0).getProperty("CollPropertyString");
     } else if (name.equals("UFCRTCTTwoPrim")) {
@@ -173,7 +182,42 @@ public class FunctionData {
         }
       }
       return DataCreator.createPrimitive(null, count);
-    } else {
+    } else if (name.equals("_FC_RTTimeOfDay_")) {
+      return DataCreator.createPrimitive(name,  
getParameterTimeOfDay(parameters));
+    } else if (name.equals("BFNESAllPrimRTCTAllPrim")) {
+      return DataCreator.createComplex(name,
+          ComplexTypeProvider.nameCTAllPrim.getFullQualifiedNameAsString(),
+          DataCreator.createPrimitive("PropertyString", "First Resource - 
first"),
+          DataCreator.createPrimitive("PropertyBinary",
+              new byte[] { 0x01, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xAB, 
(byte) 0xCD, (byte) 0xEF }),
+          DataCreator.createPrimitive("PropertyBoolean", true),
+          DataCreator.createPrimitive("PropertyByte", (short) 255),
+          DataCreator.createPrimitive("PropertyDate", getDate(2012, 10, 3)),
+          DataCreator.createPrimitive("PropertyDateTimeOffset", 
getTimestamp(2012, 10, 3, 7, 16, 23, 123456700)),
+          DataCreator.createPrimitive("PropertyDecimal", 
BigDecimal.valueOf(34.27)),
+          DataCreator.createPrimitive("PropertySingle", (float) 
1.79000000E+20),
+          DataCreator.createPrimitive("PropertyDouble", 
-1.7900000000000000E+19),
+          DataCreator.createPrimitive("PropertyDuration", 
BigDecimal.valueOf(6)),
+          DataCreator.createPrimitive("PropertyGuid", GUID),
+          DataCreator.createPrimitive("PropertyInt16", Short.MAX_VALUE),
+          DataCreator.createPrimitive("PropertyInt32", Integer.MAX_VALUE),
+          DataCreator.createPrimitive("PropertyInt64", Long.MAX_VALUE),
+          DataCreator.createPrimitive("PropertySByte", Byte.MAX_VALUE),
+          DataCreator.createPrimitive("PropertyTimeOfDay", getTime(1, 0, 1)));
+    } else if (name.equals("BFCESTwoKeyNavRTCollCTNavFiveProp")) {
+      return DataCreator.createComplexCollection(name,
+          ComplexTypeProvider.nameCTNavFiveProp.getFullQualifiedNameAsString(),
+          Arrays.asList(
+              DataCreator.createPrimitive("PropertyInt16", (short) 1)));
+    } else if (name.equals("BFCESTwoKeyNavRTCollDecimal")) {
+      return DataCreator.createPrimitiveCollection(name,
+         1d);
+    } else if (name.equals("BFCETTwoKeyNavRTCTTwoPrim")) {
+      return DataCreator.createComplex(name,
+          ComplexTypeProvider.nameCTTwoPrim.getFullQualifiedNameAsString(),
+          DataCreator.createPrimitive("PropertyInt16", (short) 16),
+          DataCreator.createPrimitive("PropertyString", 
"BFCETTwoKeyNavRTCTTwoPrim string value"));
+    }  else {
       throw new DataProviderException("Function " + name + " is not yet 
implemented.",
           HttpStatusCode.NOT_IMPLEMENTED);
     }
@@ -186,4 +230,45 @@ public class FunctionData {
   private static String getParameterString(final Map<String, Parameter> 
parameters) {
     return parameters.containsKey("ParameterString") ? (String) 
parameters.get("ParameterString").getValue() : null;
   }
+  
+  private static Calendar getParameterTimeOfDay(final Map<String, Parameter> 
parameters) {
+    return parameters.containsKey("ParameterTimeOfDay") ? (Calendar) 
parameters.get("ParameterTimeOfDay")
+        .getValue() : null;
+  }
+  
+  private static Calendar getDate(final int year, final int month, final int 
day) {
+    // Date values are always in the local timezone.
+    Calendar date = Calendar.getInstance();
+    date.clear();
+    date.set(year, month - 1, day, 0, 0, 0);
+    date.set(Calendar.MILLISECOND, 0);
+    return date;
+  }
+
+  private static Calendar getTime(final int hour, final int minute, final int 
second) {
+    // Time values are always in the local timezone.
+    Calendar time = Calendar.getInstance();
+    time.clear();
+    time.set(1970, Calendar.JANUARY, 1, hour, minute, second);
+    time.set(Calendar.MILLISECOND, 0);
+    return time;
+  }
+
+  private static Timestamp getTimestamp(final int year, final int month, final 
int day,
+      final int hour, final int minute, final int second, final int 
nanosecond) {
+    Timestamp timestamp = new Timestamp(getDateTime(year, month, day, hour, 
minute, second).getTimeInMillis());
+    timestamp.setNanos(nanosecond);
+    return timestamp;
+  }
+
+
+  private static Calendar getDateTime(final int year, final int month, final 
int day,
+      final int hour, final int minute, final int second) {
+    // Date/Time values are serialized with a timezone offset, so we choose a 
predictable timezone.
+    Calendar dateTime = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+    dateTime.clear();
+    dateTime.set(year, month - 1, day, hour, minute, second);
+    dateTime.set(Calendar.MILLISECOND, 0);
+    return dateTime;
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1ce51fd4/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java
----------------------------------------------------------------------
diff --git 
a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java
 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java
index 2a99ea9..d3983a3 100644
--- 
a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java
+++ 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java
@@ -76,6 +76,7 @@ import org.apache.olingo.server.api.uri.UriResourceProperty;
 import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
 import org.apache.olingo.server.api.uri.queryoption.SelectOption;
 import org.apache.olingo.server.tecsvc.data.DataProvider;
+import org.apache.olingo.server.tecsvc.data.DataProvider.DataProviderException;
 
 /**
  * Technical Processor which provides functionality related to primitive and 
complex types and collections thereof.
@@ -228,7 +229,7 @@ public class TechnicalPrimitiveComplexProcessor extends 
TechnicalProcessor
         getPropertyData(
             dataProvider.readFunctionPrimitiveComplex(((UriResourceFunction) 
resourceParts.get(0)).getFunction(),
             ((UriResourceFunction) resourceParts.get(0)).getParameters(), 
resource), path) :
-        getPropertyData(entity, path);
+        getData(entity, path, resourceParts, resource);
 
     // TODO: implement filter on collection properties (on a shallow copy of 
the values)
     // FilterHandler.applyFilterSystemQuery(uriInfo.getFilterOption(), 
property, uriInfo, serviceMetadata.getEdm());
@@ -257,13 +258,21 @@ public class TechnicalPrimitiveComplexProcessor extends 
TechnicalProcessor
               getComplexTypeFilter() != null) {
             type = 
((UriResourceComplexProperty)resourceParts.get(resourceParts.size() - trailing 
- 1)).
                 getComplexTypeFilter();
-          } else {
+          }else if(resourceParts.get(resourceParts.size() - trailing - 1) 
+             instanceof UriResourceFunction &&
+              ((UriResourceFunction)resourceParts.get(resourceParts.size() - 
trailing - 1)).
+              getFunction() != null){ 
+            type = 
((UriResourceFunction)resourceParts.get(resourceParts.size() - trailing - 1)).
+                getType();
+          }else {
             type = edmProperty == null ?
                 ((UriResourceFunction) resourceParts.get(0)).getType() :
                 edmProperty.getType();
           }
           final EdmReturnType returnType = resourceParts.get(0) instanceof 
UriResourceFunction ?
-              ((UriResourceFunction) 
resourceParts.get(0)).getFunction().getReturnType() : null;
+              ((UriResourceFunction) 
resourceParts.get(0)).getFunction().getReturnType() : 
+                resourceParts.get(1) instanceof UriResourceFunction ? 
+                    ((UriResourceFunction) 
resourceParts.get(1)).getFunction().getReturnType():null ;
 
           if (representationType == RepresentationType.VALUE) {
             response.setContent(serializePrimitiveValue(property, edmProperty, 
(EdmPrimitiveType) type, returnType));
@@ -291,6 +300,20 @@ public class TechnicalPrimitiveComplexProcessor extends 
TechnicalProcessor
     }
   }
 
+  private Property getData(Entity entity, List<String> path, List<UriResource> 
resourceParts, UriInfoResource resource) 
+      throws DataProviderException {
+    if(resourceParts.size()>1 && resourceParts.get(1) instanceof 
UriResourceFunction){
+      return dataProvider.readFunctionPrimitiveComplex(((UriResourceFunction) 
resourceParts.get(1)).getFunction(),
+          ((UriResourceFunction) resourceParts.get(1)).getParameters(), 
resource);
+    }
+    return getPropertyData(entity, path);
+  }
+
+  private Property getFunctionData(UriResource uriResource) {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
   private void updateProperty(final ODataRequest request, ODataResponse 
response, final UriInfo uriInfo,
       final ContentType requestFormat, final ContentType responseFormat, final 
RepresentationType representationType)
       throws ODataApplicationException, ODataLibraryException {
@@ -516,7 +539,8 @@ public class TechnicalPrimitiveComplexProcessor extends 
TechnicalProcessor
           && kind != UriResourceKind.primitiveProperty
           && kind != UriResourceKind.complexProperty
           && kind != UriResourceKind.count
-          && kind != UriResourceKind.value) {
+          && kind != UriResourceKind.value
+          && kind != UriResourceKind.function) {
         throw new ODataApplicationException("Invalid resource type.",
             HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
       }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1ce51fd4/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java
----------------------------------------------------------------------
diff --git 
a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java
 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java
index 2776d2d..182469d 100644
--- 
a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java
+++ 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java
@@ -120,6 +120,9 @@ public class FunctionProvider {
 
   public static final FullQualifiedName nameBFESTwoKeyNavRTESTwoKeyNav =
       new FullQualifiedName(SchemaProvider.NAMESPACE, 
"BFESTwoKeyNavRTESTwoKeyNav");
+  
+  public static final FullQualifiedName nameBFESBaseRTESTwoBase =
+      new FullQualifiedName(SchemaProvider.NAMESPACE, "BFESBaseRTESTwoBase");
 
   public static final FullQualifiedName nameBFCESTwoKeyNavRTCTNavFiveProp = 
new FullQualifiedName(
       SchemaProvider.NAMESPACE, "BFCESTwoKeyNavRTCTNavFiveProp");
@@ -984,6 +987,20 @@ public class FunctionProvider {
                   new 
CsdlReturnType().setType(EntityTypeProvider.nameETTwoKeyNav).setCollection(true)
                       .setNullable(false)));
 
+    } else if (functionName.equals(nameBFESBaseRTESTwoBase)) {
+      return Collections.singletonList(
+          new CsdlFunction()
+              .setName("BFESBaseRTESTwoBase")
+              .setBound(true)
+              .setParameters(Collections.singletonList(
+                  new 
CsdlParameter().setName("BindingParam").setType(EntityTypeProvider.nameETBase)
+                  .setNullable(false)))
+              .setComposable(true)
+              .setEntitySetPath("BindingParam/olingo.odata.test1.ETTwoBase")
+              .setReturnType(
+                  new 
CsdlReturnType().setType(EntityTypeProvider.nameETTwoBase)
+                      .setNullable(false)));
+
     } else if (functionName.equals(nameBFCESKeyNavRTESTwoKeyNav)) {
       return Collections.singletonList(
           new CsdlFunction()

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1ce51fd4/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java
----------------------------------------------------------------------
diff --git 
a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java
 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java
index 6d39976..074870e 100644
--- 
a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java
+++ 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java
@@ -211,6 +211,7 @@ public class SchemaProvider {
     
functions.addAll(prov.getFunctions(FunctionProvider.nameBFCESKeyNavRTESTwoKeyNav));
     
functions.addAll(prov.getFunctions(FunctionProvider.nameBFNESTwoKeyNavRTString));
 
     
functions.addAll(prov.getFunctions(FunctionProvider.nameBFCESTwoKeyNavRTCollDecimal));
+    
functions.addAll(prov.getFunctions(FunctionProvider.nameBFESBaseRTESTwoBase));
 
     // 
functions.addAll(prov.getFunctions(FunctionProvider.nameBFCCTPrimCompRTESTwoKeyNavParam));
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1ce51fd4/samples/tutorials/p9_action/pom.xml
----------------------------------------------------------------------
diff --git a/samples/tutorials/p9_action/pom.xml 
b/samples/tutorials/p9_action/pom.xml
index 7afaeee..cb5232f 100644
--- a/samples/tutorials/p9_action/pom.xml
+++ b/samples/tutorials/p9_action/pom.xml
@@ -30,7 +30,7 @@
        <name>${project.artifactId}-Webapp</name>
 
        <build>
-               <finalName>DemoService</finalName>
+               <finalName>DemoService-Action</finalName>
        </build>
 
        <properties>

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1ce51fd4/samples/tutorials/p9_action/src/main/java/myservice/mynamespace/data/Storage.java
----------------------------------------------------------------------
diff --git 
a/samples/tutorials/p9_action/src/main/java/myservice/mynamespace/data/Storage.java
 
b/samples/tutorials/p9_action/src/main/java/myservice/mynamespace/data/Storage.java
index 243dd8c..87598fc 100644
--- 
a/samples/tutorials/p9_action/src/main/java/myservice/mynamespace/data/Storage.java
+++ 
b/samples/tutorials/p9_action/src/main/java/myservice/mynamespace/data/Storage.java
@@ -144,6 +144,30 @@ public class Storage {
 
     return null;
   }
+  
+  public EntityCollection readEntitySetData(String edmEntityTypeName) throws 
ODataApplicationException {
+
+    if (edmEntityTypeName.equals(DemoEdmProvider.ET_PRODUCT_NAME)) {
+      return getEntityCollection(productList);
+    } else if(edmEntityTypeName.equals(DemoEdmProvider.ET_CATEGORY_NAME)) {
+      return getEntityCollection(categoryList);
+    }
+
+    return null;
+  }
+  
+
+  public Entity readEntityData(String entityTypeName) {
+
+    if (entityTypeName.equals(DemoEdmProvider.ET_PRODUCT_NAME)) {
+      return  getEntityCollection(productList).getEntities().get(0);
+    } else if(entityTypeName.equals(DemoEdmProvider.ET_CATEGORY_NAME)) {
+      return getEntityCollection(categoryList).getEntities().get(0);
+    }
+
+    return null;
+  
+  }
 
   public Entity readEntityData(EdmEntitySet edmEntitySet, List<UriParameter> 
keyParams)
       throws ODataApplicationException {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1ce51fd4/samples/tutorials/p9_action/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java
----------------------------------------------------------------------
diff --git 
a/samples/tutorials/p9_action/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java
 
b/samples/tutorials/p9_action/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java
index 3f2f538..6e4ace6 100644
--- 
a/samples/tutorials/p9_action/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java
+++ 
b/samples/tutorials/p9_action/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java
@@ -82,6 +82,12 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider 
{
   public static final String FUNCTION_COUNT_CATEGORIES = "CountCategories";
   public static final FullQualifiedName FUNCTION_COUNT_CATEGORIES_FQN 
                                                 = new 
FullQualifiedName(NAMESPACE, FUNCTION_COUNT_CATEGORIES);
+  //Bound Function
+  public static final String FUNCTION_PROVIDE_DISCOUNT = "GetDiscountProducts";
+  public static final FullQualifiedName FUNCTION_PROVIDE_DISCOUNT_FQN = new 
FullQualifiedName(NAMESPACE, FUNCTION_PROVIDE_DISCOUNT);
+  
+  public static final String FUNCTION_PROVIDE_DISCOUNT_FOR_PRODUCT = 
"GetDiscountProduct";
+  public static final FullQualifiedName 
FUNCTION_PROVIDE_DISCOUNT_FOR_PRODUCT_FQN = new FullQualifiedName(NAMESPACE, 
FUNCTION_PROVIDE_DISCOUNT_FOR_PRODUCT);
   
   // Function/Action Parameters
   public static final String PARAMETER_AMOUNT = "Amount";
@@ -89,6 +95,9 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider {
   //Bound Action Binding Parameter
   public static final String PARAMETER_CATEGORY = "ParamCategory";
   
+  //Bound Function Binding Parameter
+  public static final String PARAMETER_BIND = "BindingParameter";
+  
   @Override
   public List<CsdlAction> getActions(final FullQualifiedName actionName) {
  // It is allowed to overload actions, so we have to provide a list of Actions 
for each action name
@@ -196,6 +205,65 @@ public class DemoEdmProvider extends 
CsdlAbstractEdmProvider {
       functions.add(function);
 
       return functions;
+    } else if (functionName.equals(FUNCTION_PROVIDE_DISCOUNT_FQN)) {
+
+      final List<CsdlFunction> functions = new ArrayList<CsdlFunction>();
+
+      // Create the parameter for the function
+      final List<CsdlParameter> parameters = new ArrayList<CsdlParameter>();
+      CsdlParameter parameter = new CsdlParameter();
+      parameter.setName(PARAMETER_BIND);
+      parameter.setNullable(false);
+      parameter.setType(ET_CATEGORY_FQN);
+      parameter.setCollection(true);
+      parameters.add(parameter);
+      parameter = new CsdlParameter();
+      parameter.setName(PARAMETER_AMOUNT);
+      parameter.setType(EdmPrimitiveTypeKind.Int32.getFullQualifiedName());
+      parameters.add(parameter);
+
+      // Create the return type of the function
+      final CsdlReturnType returnType = new CsdlReturnType();
+      returnType.setCollection(true).setType(ET_PRODUCT_FQN);
+
+      // Create the function
+      final CsdlFunction function = new CsdlFunction();
+      function.setName(FUNCTION_PROVIDE_DISCOUNT_FQN.getName())
+          .setParameters(parameters)
+          .setBound(true).setReturnType(returnType);
+      functions.add(function);
+
+      return functions;
+
+    } else if (functionName.equals(FUNCTION_PROVIDE_DISCOUNT_FOR_PRODUCT_FQN)) 
{
+
+      final List<CsdlFunction> functions = new ArrayList<CsdlFunction>();
+
+      // Create the parameter for the function
+      final List<CsdlParameter> parameters = new ArrayList<CsdlParameter>();
+      CsdlParameter parameter = new CsdlParameter();
+      parameter.setName(PARAMETER_BIND);
+      parameter.setNullable(false);
+      parameter.setType(ET_CATEGORY_FQN);
+      parameters.add(parameter);
+      parameter = new CsdlParameter();
+      parameter.setName(PARAMETER_AMOUNT);
+      parameter.setType(EdmPrimitiveTypeKind.Int32.getFullQualifiedName());
+      parameters.add(parameter);
+
+      // Create the return type of the function
+      final CsdlReturnType returnType = new CsdlReturnType();
+      returnType.setType(ET_PRODUCT_FQN);
+
+      // Create the function
+      final CsdlFunction function = new CsdlFunction();
+      function.setName(FUNCTION_PROVIDE_DISCOUNT_FOR_PRODUCT_FQN.getName())
+          .setParameters(parameters)
+          .setBound(true).setReturnType(returnType);
+      functions.add(function);
+
+      return functions;
+
     }
 
     return null;
@@ -343,6 +411,8 @@ public class DemoEdmProvider extends 
CsdlAbstractEdmProvider {
     // add functions
     List<CsdlFunction> functions = new ArrayList<CsdlFunction>();
     functions.addAll(getFunctions(FUNCTION_COUNT_CATEGORIES_FQN));
+    functions.addAll(getFunctions(FUNCTION_PROVIDE_DISCOUNT_FQN));
+    functions.addAll(getFunctions(FUNCTION_PROVIDE_DISCOUNT_FOR_PRODUCT_FQN));
     schema.setFunctions(functions);
     
     // add EntityContainer

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1ce51fd4/samples/tutorials/p9_action/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java
----------------------------------------------------------------------
diff --git 
a/samples/tutorials/p9_action/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java
 
b/samples/tutorials/p9_action/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java
index 471f2d1..c058296 100644
--- 
a/samples/tutorials/p9_action/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java
+++ 
b/samples/tutorials/p9_action/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java
@@ -170,6 +170,27 @@ public class DemoEntityCollectionProcessor implements 
EntityCollectionProcessor
         // note: we don't need to check uriResourceNavigation.isCollection(),
         // because we are the EntityCollectionProcessor
         responseEntityCollection = 
storage.getRelatedEntityCollection(sourceEntity, targetEntityType);
+      } else if (lastSegment instanceof UriResourceFunction) {// For bound 
function
+        UriResourceFunction uriResourceFunction = (UriResourceFunction) 
lastSegment;
+        // 2nd: fetch the data from backend
+        // first fetch the target entity type 
+        String targetEntityType = 
uriResourceFunction.getFunction().getReturnType().getType().getName();
+        // contextURL displays the last segment
+        for(EdmEntitySet entitySet : 
serviceMetadata.getEdm().getEntityContainer().getEntitySets()){
+          if(targetEntityType.equals(entitySet.getEntityType().getName())){
+            responseEdmEntitySet = entitySet;
+            break;
+          }
+        }
+        
+        // error handling for null entities
+        if (targetEntityType == null || responseEdmEntitySet == null) {
+          throw new ODataApplicationException("Entity not found.",
+              HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT);
+        }
+
+        // then fetch the entity collection for the target type
+        responseEntityCollection = storage.readEntitySetData(targetEntityType);
       }
     } else { // this would be the case for e.g. Products(1)/Category/Products
       throw new ODataApplicationException("Not supported",

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1ce51fd4/samples/tutorials/p9_action/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java
----------------------------------------------------------------------
diff --git 
a/samples/tutorials/p9_action/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java
 
b/samples/tutorials/p9_action/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java
index ffdee3f..54af258 100644
--- 
a/samples/tutorials/p9_action/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java
+++ 
b/samples/tutorials/p9_action/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java
@@ -156,9 +156,9 @@ public class DemoEntityProcessor implements EntityProcessor 
{
       List<UriParameter> keyPredicates = 
uriResourceEntitySet.getKeyPredicates();
       responseEntity = storage.readEntityData(startEdmEntitySet, 
keyPredicates);
     } else if (segmentCount == 2) { // navigation
-      UriResource navSegment = resourceParts.get(1); // in our example we 
don't support more complex URIs
-      if (navSegment instanceof UriResourceNavigation) {
-        UriResourceNavigation uriResourceNavigation = (UriResourceNavigation) 
navSegment;
+      UriResource segment = resourceParts.get(1); // in our example we don't 
support more complex URIs
+      if (segment instanceof UriResourceNavigation) {
+        UriResourceNavigation uriResourceNavigation = (UriResourceNavigation) 
segment;
         EdmNavigationProperty edmNavigationProperty = 
uriResourceNavigation.getProperty();
         responseEdmEntityType = edmNavigationProperty.getType();
         // contextURL displays the last segment
@@ -181,6 +181,30 @@ public class DemoEntityProcessor implements 
EntityProcessor {
         } else { // e.g. DemoService.svc/Categories(3)/Products(5)
           responseEntity = storage.getRelatedEntity(sourceEntity, 
responseEdmEntityType, navKeyPredicates);
         }
+      }else if (segment instanceof UriResourceFunction) {
+        UriResourceFunction uriResourceFunction = (UriResourceFunction) 
segment;
+
+        // 2nd: fetch the data from backend.
+        // first fetch the target entity type 
+        String targetEntityType = 
uriResourceFunction.getFunction().getReturnType().getType().getName();
+       
+        // contextURL displays the last segment
+        for(EdmEntitySet entitySet : 
serviceMetadata.getEdm().getEntityContainer().getEntitySets()){
+          if(targetEntityType.equals(entitySet.getEntityType().getName())){
+            responseEdmEntityType = entitySet.getEntityType();
+            responseEdmEntitySet = entitySet;
+            break;
+          }
+        }
+        
+        // error handling for null entities
+        if (targetEntityType == null || responseEdmEntitySet == null) {
+          throw new ODataApplicationException("Entity not found.",
+              HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT);
+        }
+
+        // then fetch the entity collection for the target type
+        responseEntity = storage.readEntityData(targetEntityType);
       }
     } else {
       // this would be the case for e.g. 
Products(1)/Category/Products(1)/Category

Reply via email to