You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by mi...@apache.org on 2014/10/20 15:16:05 UTC
[2/2] git commit: [OLINGO-450]: implementing support for execution of
Functions and Actions
[OLINGO-450]: implementing support for execution of Functions and Actions
Signed-off-by: mibo <mi...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/9c621763
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/9c621763
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/9c621763
Branch: refs/heads/OLINGO-450_FunctionActionExecution
Commit: 9c621763216d93bfb61bfcd277fad4572ec9c09d
Parents: 35f24e9
Author: Ramesh Reddy <ra...@jboss.org>
Authored: Thu Oct 2 15:11:13 2014 -0500
Committer: mibo <mi...@apache.org>
Committed: Mon Oct 20 15:06:43 2014 +0200
----------------------------------------------------------------------
.../fit/tecsvc/client/ProcedureITCase.java | 295 +++++++++++++++++++
.../olingo/commons/api/edm/EdmOperation.java | 5 +
.../commons/core/edm/AbstractEdmOperation.java | 5 +
.../api/processor/ProcedureProcessor.java | 48 +++
.../api/serializer/BoundProcedureOption.java | 98 ++++++
.../server/api/serializer/ODataSerializer.java | 10 +
.../api/serializer/ODataSerializerOptions.java | 15 +-
.../server/api/uri/UriResourceAction.java | 7 +
.../apache/olingo/server/core/ODataHandler.java | 27 ++
.../core/serializer/ODataXmlSerializerImpl.java | 9 +
.../serializer/json/ODataJsonSerializer.java | 197 +++++++++++--
.../xml/MetadataDocumentXmlSerializer.java | 5 +-
.../server/core/uri/UriResourceActionImpl.java | 23 +-
.../core/uri/parser/UriParseTreeVisitor.java | 27 +-
lib/server-tecsvc/pom.xml | 1 -
.../olingo/server/tecsvc/data/DataProvider.java | 107 +++++++
.../tecsvc/processor/TechnicalProcessor.java | 174 ++++++++++-
.../tecsvc/provider/ContainerProvider.java | 8 +
.../tecsvc/provider/FunctionProvider.java | 64 +++-
.../server/tecsvc/provider/SchemaProvider.java | 4 +
.../olingo/server/core/ODataHandlerTest.java | 61 +++-
.../server/core/uri/UriResourceImplTest.java | 3 +-
22 files changed, 1160 insertions(+), 33 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ProcedureITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ProcedureITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ProcedureITCase.java
new file mode 100644
index 0000000..45c3e10
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ProcedureITCase.java
@@ -0,0 +1,295 @@
+/*
+ * 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.client;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.*;
+
+import java.util.Collections;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.olingo.client.api.CommonODataClient;
+import org.apache.olingo.client.api.communication.request.invoke.ODataInvokeRequest;
+import org.apache.olingo.client.api.communication.request.invoke.ODataNoContent;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataPropertyRequest;
+import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
+import org.apache.olingo.client.api.v4.ODataClient;
+import org.apache.olingo.client.core.ODataClientFactory;
+import org.apache.olingo.commons.api.domain.CommonODataProperty;
+import org.apache.olingo.commons.api.domain.ODataPrimitiveValue;
+import org.apache.olingo.commons.api.domain.ODataValue;
+import org.apache.olingo.commons.api.domain.v4.ODataProperty;
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.commons.api.format.ODataFormat;
+import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.fit.AbstractBaseTestITCase;
+import org.apache.olingo.fit.tecsvc.TecSvcConst;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class ProcedureITCase extends AbstractBaseTestITCase {
+
+ private static final String SERVICE_URI = TecSvcConst.BASE_URI;
+
+ @Override
+ protected CommonODataClient<?> getClient() {
+ ODataClient odata = ODataClientFactory.getV4();
+ odata.getConfiguration().setDefaultPubFormat(ODataFormat.JSON);
+ return odata;
+ }
+
+ @Test // primitive return
+ public void executeFINRTInt16() {
+ final ODataPropertyRequest<CommonODataProperty> request = getClient().getRetrieveRequestFactory()
+ .getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
+ .appendOperationCallSegment("FINRTInt16")
+ .build());
+
+ assertNotNull(request);
+
+ final ODataRetrieveResponse<CommonODataProperty> response = request.execute();
+ assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+ assertThat(response.getContentType(), containsString(ContentType.APPLICATION_JSON.toContentTypeString()));
+
+ final CommonODataProperty property = response.getBody();
+ assertNotNull(property);
+ assertEquals(5, property.getPrimitiveValue().toValue());
+ }
+
+ @Test
+ public void executeFINRTInt16Raw() throws Exception {
+ final ODataPropertyRequest<CommonODataProperty> request = getClient().getRetrieveRequestFactory()
+ .getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
+ .appendOperationCallSegment("FINRTInt16")
+ .build());
+
+ assertNotNull(request);
+
+ final ODataRetrieveResponse<CommonODataProperty> response = request.execute();
+ assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+ assertThat(response.getContentType(), containsString(ContentType.APPLICATION_JSON.toContentTypeString()));
+
+ assertEquals("{\"@odata.context\":\"$metadata#Edm.Int16\",\"value\":5}",
+ IOUtils.toString(response.getRawResponse(), "UTF-8"));
+ }
+
+ @Test // collection return
+ public void executeUFCRTCollString() throws Exception {
+ final ODataPropertyRequest<CommonODataProperty> request = getClient().getRetrieveRequestFactory()
+ .getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
+ .appendOperationCallSegment("FICRTCollString")
+ .build());
+
+ assertNotNull(request);
+
+ final ODataRetrieveResponse<CommonODataProperty> response = request.execute();
+ assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+ assertThat(response.getContentType(), containsString(ContentType.APPLICATION_JSON.toContentTypeString()));
+
+ assertEquals("{\"@odata.context\":\"$metadata#Collection(Edm.String)\",\"value\":[\"dummy1\",\"dummy2\"]}",
+ IOUtils.toString(response.getRawResponse(), "UTF-8"));
+ }
+
+ @Test // complex return
+ public void executeUFCRTCTTwoPrimParam() throws Exception {
+ final ODataPropertyRequest<CommonODataProperty> request = getClient().getRetrieveRequestFactory()
+ .getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
+ .appendOperationCallSegment("FICRTCTTwoPrimParam(ParameterString='param1',ParameterInt16=2)")
+ .build());
+
+ assertNotNull(request);
+
+ final ODataRetrieveResponse<CommonODataProperty> response = request.execute();
+ assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+ assertThat(response.getContentType(), containsString(ContentType.APPLICATION_JSON.toContentTypeString()));
+ String expected =
+ "{\"@odata.context\":\"$metadata#olingo.odata.test1.CTTwoPrim\","+
+ "\"PropertyInt16\":2,"+
+ "\"PropertyString\":\"param1\""+
+ "}";
+ assertEquals(expected, IOUtils.toString(response.getRawResponse(), "UTF-8"));
+ }
+
+ @Test // complex collection
+ public void executeUFCRTCollCTTwoPrimParam() throws Exception {
+ final ODataPropertyRequest<CommonODataProperty> request = getClient().getRetrieveRequestFactory()
+ .getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
+ .appendOperationCallSegment("FICRTCollCTTwoPrimParam(ParameterString='param1',ParameterInt16=2)")
+ .build());
+
+ assertNotNull(request);
+
+ final ODataRetrieveResponse<CommonODataProperty> response = request.execute();
+ assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+ assertThat(response.getContentType(), containsString(ContentType.APPLICATION_JSON.toContentTypeString()));
+ String expected =
+ "{\"@odata.context\":\"$metadata#Collection(olingo.odata.test1.CTTwoPrim)\","+
+ "\"value\":[{" +
+ "\"PropertyInt16\":2,"+
+ "\"PropertyString\":\"param1\"}"+
+ ",{" +
+ "\"PropertyInt16\":2,"+
+ "\"PropertyString\":\"param1\"}"+
+ "]}";
+ assertEquals(expected, IOUtils.toString(response.getRawResponse(), "UTF-8"));
+ }
+
+ @Test // Entity type return
+ public void executeUFCRTETAllPrimTwoParam() throws Exception {
+ final ODataPropertyRequest<CommonODataProperty> request = getClient().getRetrieveRequestFactory()
+ .getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
+ .appendOperationCallSegment("FICRTETAllPrimTwoParam(ParameterString='param1',ParameterInt16=2)")
+ .build());
+
+ assertNotNull(request);
+
+ final ODataRetrieveResponse<CommonODataProperty> response = request.execute();
+ assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+ assertThat(response.getContentType(), containsString(ContentType.APPLICATION_JSON.toContentTypeString()));
+ String expected =
+ "{\"@odata.context\":\"$metadata#ESAllPrim/$entity\","
+ + "\"PropertyInt16\":32767,"
+ + "\"PropertyString\":\"First Resource - positive values\","
+ + "\"PropertyBoolean\":true,"
+ + "\"PropertyByte\":255,"
+ + "\"PropertySByte\":127,"
+ + "\"PropertyInt32\":2147483647,"
+ + "\"PropertyInt64\":9223372036854775807,"
+ + "\"PropertySingle\":1.79E20,"
+ + "\"PropertyDouble\":-1.79E19,"
+ + "\"PropertyDecimal\":34,"
+ + "\"PropertyBinary\":\"ASNFZ4mrze8=\","
+ + "\"PropertyDate\":\"2012-12-03\","
+ + "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\","
+ + "\"PropertyDuration\":\"PT6S\","
+ + "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\""
+ + ",\"PropertyTimeOfDay\":\"03:26:05\""
+ + "}";
+ assertEquals(expected, IOUtils.toString(response.getRawResponse(), "UTF-8"));
+ }
+
+ @Test // Entity Set return
+ public void executeUFFICRTESMixPrimCollCompTwoParam() throws Exception {
+ final ODataPropertyRequest<CommonODataProperty> request = getClient().getRetrieveRequestFactory()
+ .getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
+ .appendOperationCallSegment("FICRTESMixPrimCollCompTwoParam(ParameterString='param1',ParameterInt16=2)")
+ .build());
+
+ assertNotNull(request);
+
+ final ODataRetrieveResponse<CommonODataProperty> response = request.execute();
+ assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+ assertThat(response.getContentType(), containsString(ContentType.APPLICATION_JSON.toContentTypeString()));
+ String expected =
+ "{\"@odata.context\":\"$metadata#ESMixPrimCollComp\","
+ + "\"value\":["
+ + "{\"PropertyInt16\":32767,"
+ + "\"CollPropertyString\":["
+ + "\"Employee1@company.example\",\"Employee2@company.example\",\"Employee3@company.example\"],"
+ + "\"PropertyComp\":{\"PropertyInt16\":111,\"PropertyString\":\"TEST A\"},"
+ + "\"CollPropertyComp\":["
+ + "{\"PropertyInt16\":123,\"PropertyString\":\"TEST 1\"},"
+ + "{\"PropertyInt16\":456,\"PropertyString\":\"TEST 2\"},"
+ + "{\"PropertyInt16\":789,\"PropertyString\":\"TEST 3\"}"
+ + "]"
+ + "},";
+ assertTrue(IOUtils.toString(response.getRawResponse(), "UTF-8").startsWith(expected));
+ }
+
+ //Bounded - binding param enitityset return string
+ @Test
+ public void executeBFESTwoPrimRTString() throws Exception {
+ final ODataPropertyRequest<CommonODataProperty> request = getClient().getRetrieveRequestFactory()
+ .getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
+ .appendEntitySetSegment("ESTwoPrim")
+ .appendNavigationSegment("olingo.odata.test1")
+ .appendOperationCallSegment("BFESTwoPrimRTString")
+ .build());
+
+ assertNotNull(request);
+
+ final ODataRetrieveResponse<CommonODataProperty> response = request.execute();
+ assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+ String expected = "{\"@odata.context\":\"$metadata#Edm.String\","
+ + "\"#olingo.odata.test1.BFESTwoPrimRTString(BindingParam)\":{},"
+ + "\"value\":\"TEST-A\"}";
+ assertEquals(expected, IOUtils.toString(response.getRawResponse(), "UTF-8"));
+ }
+
+ //Bounded - binding param enitity return string[]
+ @Test
+ public void executeBFESTwoPrimRTCollString() throws Exception {
+ final ODataPropertyRequest<CommonODataProperty> request = getClient().getRetrieveRequestFactory()
+ .getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
+ .appendEntitySetSegment("ESTwoPrim")
+ .appendKeySegment(1)
+ .appendNavigationSegment("olingo.odata.test1")
+ .appendOperationCallSegment("BFESTwoPrimRTCollString")
+ .build());
+
+ assertNotNull(request);
+
+ final ODataRetrieveResponse<CommonODataProperty> response = request.execute();
+ assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+ String expected = "{\"@odata.context\":\"$metadata#Collection(Edm.String)\","
+ + "\"#olingo.odata.test1.BFESTwoPrimRTCollString(BindingParam)\":{},"
+ + "\"value\":[\"dummy1\",\"dummy2\"]}";
+ assertEquals(expected, IOUtils.toString(response.getRawResponse(), "UTF-8"));
+ }
+
+ //Bounded - binding param enitityset return entity
+ @Test
+ @Ignore
+ public void executenameBFESTwoPrimRTETTwoPrim() throws Exception {
+ final ODataPropertyRequest<CommonODataProperty> request = getClient().getRetrieveRequestFactory()
+ .getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
+ .appendEntitySetSegment("ESTwoPrim")
+ .appendNavigationSegment("olingo.odata.test1")
+ .appendOperationCallSegment("BFESTwoPrimRTETTwoPrim(ParameterString='param1')")
+ .build());
+
+ assertNotNull(request);
+
+ final ODataRetrieveResponse<CommonODataProperty> response = request.execute();
+ assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+ String expected = "";
+ assertEquals(expected, IOUtils.toString(response.getRawResponse(), "UTF-8"));
+ }
+
+ /*
+ * Actions test cases
+ */
+
+ @Test // primitive return
+ public void executeAIRTPrimParam() throws Exception {
+ final ODataPrimitiveValue param = getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short)22);
+ final ODataInvokeRequest<ODataProperty> request = getClient().getInvokeRequestFactory().
+ getActionInvokeRequest(getClient().newURIBuilder(SERVICE_URI).
+ appendOperationCallSegment("AIRTPrimParam").build(), ODataProperty.class,
+ Collections.<String, ODataValue> singletonMap("ParameterInt16", param));
+ final ODataProperty response = request.execute().getBody();
+
+ assertEquals("return-string", response.getValue().asPrimitive().toValue());
+ }
+
+ @Test // enrity return
+ public void executeActionEnrity() throws Exception {
+ //TODO: needs the EntitySetPath fix
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmOperation.java
----------------------------------------------------------------------
diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmOperation.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmOperation.java
index d1bc3de..eff49d6 100644
--- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmOperation.java
+++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmOperation.java
@@ -64,4 +64,9 @@ public interface EdmOperation extends EdmType, EdmAnnotatable {
*/
Boolean isBindingParameterTypeCollection();
+ /**
+ * @return EntitySetPath if one available
+ * @return
+ */
+ String getEntitySetPath();
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmOperation.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmOperation.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmOperation.java
index dd7ae81..9264d42 100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmOperation.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmOperation.java
@@ -114,4 +114,9 @@ public abstract class AbstractEdmOperation extends EdmTypeImpl implements EdmOpe
public boolean isBound() {
return isBound;
}
+
+ @Override
+ public String getEntitySetPath() {
+ return this.entitySetPath;
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ProcedureProcessor.java
----------------------------------------------------------------------
diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ProcedureProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ProcedureProcessor.java
new file mode 100644
index 0000000..8bcb025
--- /dev/null
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ProcedureProcessor.java
@@ -0,0 +1,48 @@
+/*
+ * 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.server.api.processor;
+
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.server.api.ODataApplicationException;
+import org.apache.olingo.server.api.ODataRequest;
+import org.apache.olingo.server.api.ODataResponse;
+import org.apache.olingo.server.api.serializer.SerializerException;
+import org.apache.olingo.server.api.uri.UriInfo;
+
+public interface ProcedureProcessor extends Processor {
+ /**
+ * Execute/Invokes the FunctionImport and returns the result
+ * @param request OData request object containing raw HTTP information
+ * @param response OData response object for collecting response data
+ * @param uriInfo Information about the request URI
+ * @param requestedContentType content-type of the response requested
+ */
+ void executeFunction(ODataRequest request, ODataResponse response,
+ UriInfo uriInfo, ContentType requestedContentType) throws ODataApplicationException, SerializerException;
+
+ /**
+ * Execute/Invokes the ActionImport and returns the result if one exists.
+ * @param request OData request object containing raw HTTP information
+ * @param response OData response object for collecting response data
+ * @param uriInfo Information about the request URI
+ * @param requestedContentType content-type of the response requested
+ */
+ void executeAction(ODataRequest request, ODataResponse response,
+ UriInfo uriInfo, ContentType requestedContentType) throws ODataApplicationException, SerializerException;
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/BoundProcedureOption.java
----------------------------------------------------------------------
diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/BoundProcedureOption.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/BoundProcedureOption.java
new file mode 100644
index 0000000..cb90484
--- /dev/null
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/BoundProcedureOption.java
@@ -0,0 +1,98 @@
+/*
+ * 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.server.api.serializer;
+
+import org.apache.olingo.commons.api.edm.EdmAction;
+import org.apache.olingo.commons.api.edm.EdmFunction;
+
+public class BoundProcedureOption {
+ private String procedureName;
+ private String title;
+ private String target;
+
+ public String getProcedureName() {
+ return procedureName;
+ }
+ public String getTitle() {
+ return title;
+ }
+ public String getTarget() {
+ return target;
+ }
+
+ public static Builder with() {
+ return new Builder();
+ }
+
+ public static final class Builder {
+ private BoundProcedureOption procedure = new BoundProcedureOption();
+ private EdmFunction function;
+ private EdmAction action;
+
+ public Builder setFunction(EdmFunction function) {
+ this.function = function;
+ return this;
+ }
+ public Builder setAction(EdmAction action) {
+ this.action = action;
+ return this;
+ }
+ public Builder setTitle(String title) {
+ procedure.title = title;
+ return this;
+ }
+ public Builder setTarget(String target) {
+ procedure.target = target;
+ return this;
+ }
+ public BoundProcedureOption build() {
+ if (this.function != null && this.function.isBound()) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(this.function.getFullQualifiedName().getFullQualifiedNameAsString());
+ if (!this.function.getParameterNames().isEmpty()) {
+ sb.append("(");
+ for (int i = 0; i < this.function.getParameterNames().size(); i++) {
+ if (i > 0) {
+ sb.append(",");
+ }
+ sb.append(this.function.getParameterNames().get(i));
+ }
+ sb.append(")");
+ }
+ this.procedure.procedureName = sb.toString();
+ } else if (this.action != null && this.action.isBound()) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(this.action.getFullQualifiedName().getFullQualifiedNameAsString());
+ if (!this.action.getParameterNames().isEmpty()) {
+ sb.append("(");
+ for (int i = 0; i < this.action.getParameterNames().size(); i++) {
+ if (i > 0) {
+ sb.append(",");
+ }
+ sb.append(this.action.getParameterNames().get(i));
+ }
+ sb.append(")");
+ }
+ this.procedure.procedureName = sb.toString();
+
+ }
+ return this.procedure;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
----------------------------------------------------------------------
diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
index 1331247..0d8acaa 100644
--- a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
@@ -26,6 +26,7 @@ import org.apache.olingo.commons.api.data.Property;
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmReturnType;
import org.apache.olingo.server.api.ODataServerError;
import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
@@ -67,6 +68,15 @@ public interface ODataSerializer {
*/
InputStream entityProperty(EdmProperty edmProperty, Property property, ODataSerializerOptions options)
throws SerializerException;
+
+ /**
+ * Writes the Function/Action procedure return values.
+ * @param returnType return type definition
+ * @param property property value
+ * @param options options for the serializer
+ */
+ InputStream procedureReturn(EdmReturnType returnType, Property property,
+ ODataSerializerOptions options) throws SerializerException;
/**
* Writes entity-set data into an InputStream.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializerOptions.java
----------------------------------------------------------------------
diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializerOptions.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializerOptions.java
index e4ac767..e019ab7 100644
--- a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializerOptions.java
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializerOptions.java
@@ -30,6 +30,7 @@ public class ODataSerializerOptions {
private CountOption count;
private ExpandOption expand;
private SelectOption select;
+ private BoundProcedureOption boundProcedure;
/** Gets the {@link ContextURL}. */
public ContextURL getContextURL() {
@@ -50,7 +51,12 @@ public class ODataSerializerOptions {
public SelectOption getSelect() {
return select;
}
-
+
+ /** Gets BoundProcedure options */
+ public BoundProcedureOption getBoundProcedure() {
+ return boundProcedure;
+ }
+
private ODataSerializerOptions() {}
/** Initializes the options builder. */
@@ -90,6 +96,13 @@ public class ODataSerializerOptions {
options.select = select;
return this;
}
+ /**
+ * Sets bound procedure (fuction/action) metadata
+ */
+ public Builder boundProcedure(final BoundProcedureOption proc) {
+ options.boundProcedure = proc;
+ return this;
+ }
/** Builds the OData serializer options. */
public ODataSerializerOptions build() {
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/UriResourceAction.java
----------------------------------------------------------------------
diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/UriResourceAction.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/UriResourceAction.java
index 1cdc521..aebc857 100644
--- a/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/UriResourceAction.java
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/UriResourceAction.java
@@ -18,6 +18,8 @@
*/
package org.apache.olingo.server.api.uri;
+import java.util.List;
+
import org.apache.olingo.commons.api.edm.EdmAction;
import org.apache.olingo.commons.api.edm.EdmActionImport;
@@ -38,5 +40,10 @@ public interface UriResourceAction extends UriResourcePartTyped {
* @return
*/
EdmActionImport getActionImport();
+
+ /**
+ * @return List of action parameters
+ */
+ List<UriParameter> getParameters();
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
index 4ac780d..79c1547 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
@@ -38,6 +38,7 @@ import org.apache.olingo.server.api.processor.EntitySetProcessor;
import org.apache.olingo.server.api.processor.EntityProcessor;
import org.apache.olingo.server.api.processor.ExceptionProcessor;
import org.apache.olingo.server.api.processor.MetadataProcessor;
+import org.apache.olingo.server.api.processor.ProcedureProcessor;
import org.apache.olingo.server.api.processor.Processor;
import org.apache.olingo.server.api.processor.PropertyProcessor;
import org.apache.olingo.server.api.processor.ServiceDocumentProcessor;
@@ -272,6 +273,32 @@ public class ODataHandler {
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
}
break;
+ case action:
+ if (request.getMethod().equals(HttpMethod.POST)) {
+ ProcedureProcessor pp = selectProcessor(ProcedureProcessor.class);
+
+ requestedContentType =
+ ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, pp, ProcedureProcessor.class);
+
+ pp.executeAction(request, response, uriInfo, requestedContentType);
+ } else {
+ throw new ODataHandlerException("not implemented",
+ ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
+ }
+ break;
+ case function:
+ if (request.getMethod().equals(HttpMethod.GET)) {
+ ProcedureProcessor pp = selectProcessor(ProcedureProcessor.class);
+
+ requestedContentType =
+ ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, pp, ProcedureProcessor.class);
+
+ pp.executeFunction(request, response, uriInfo, requestedContentType);
+ } else {
+ throw new ODataHandlerException("not implemented",
+ ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
+ }
+ break;
default:
throw new ODataHandlerException("not implemented",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java
index 8956a6d..e991d96 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java
@@ -30,6 +30,7 @@ import org.apache.olingo.commons.api.data.Property;
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmReturnType;
import org.apache.olingo.server.api.ODataServerError;
import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.serializer.ODataSerializer;
@@ -116,4 +117,12 @@ public class ODataXmlSerializerImpl implements ODataSerializer {
throw new SerializerException("error serialization not implemented for XML format",
SerializerException.MessageKeys.NOT_IMPLEMENTED);
}
+
+ @Override
+ public InputStream procedureReturn(EdmReturnType returnType,
+ Property property, ODataSerializerOptions options)
+ throws SerializerException {
+ // rameshTODO Auto-generated method stub
+ return null;
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java
index 324c5aa..3cae645 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java
@@ -39,13 +39,15 @@ import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmReturnType;
import org.apache.olingo.commons.api.format.ODataFormat;
import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
import org.apache.olingo.server.api.ODataServerError;
import org.apache.olingo.server.api.ServiceMetadata;
+import org.apache.olingo.server.api.serializer.BoundProcedureOption;
import org.apache.olingo.server.api.serializer.ODataSerializer;
-import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.serializer.ODataSerializerOptions;
+import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
@@ -141,6 +143,11 @@ public class ODataJsonSerializer implements ODataSerializer {
ContextURLBuilder.create(contextURL).toASCIIString());
}
+ if (options != null) {
+ // write title, target in case of bound function/action
+ writeProcedureMetadata(options.getBoundProcedure(), json);
+ }
+
if (options != null && options.getCount() != null && options.getCount().getValue()
&& entitySet.getCount() != null) {
json.writeNumberField(Constants.JSON_COUNT, entitySet.getCount());
@@ -167,7 +174,8 @@ public class ODataJsonSerializer implements ODataSerializer {
try {
JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream());
writeEntity(edmEntitySet.getEntityType(), entity, contextURL,
- options == null ? null : options.getExpand(), options == null ? null : options.getSelect(), json);
+ options == null ? null : options.getExpand(), options == null ? null : options.getSelect(),
+ options == null ? null : options.getBoundProcedure(), json);
json.close();
} catch (final IOException e) {
throw new SerializerException("An I/O exception occurred.", e,
@@ -194,13 +202,13 @@ public class ODataJsonSerializer implements ODataSerializer {
throws IOException, SerializerException {
json.writeStartArray();
for (final Entity entity : entitySet.getEntities()) {
- writeEntity(entityType, entity, null, expand, select, json);
+ writeEntity(entityType, entity, null, expand, select, null, json);
}
json.writeEndArray();
}
protected void writeEntity(final EdmEntityType entityType, final Entity entity, final ContextURL contextURL,
- final ExpandOption expand, final SelectOption select, final JsonGenerator json)
+ final ExpandOption expand, final SelectOption select, BoundProcedureOption boundOption, final JsonGenerator json)
throws IOException, SerializerException {
json.writeStartObject();
if (format != ODataFormat.JSON_NO_METADATA) {
@@ -219,6 +227,9 @@ public class ODataJsonSerializer implements ODataSerializer {
}
}
}
+ // write title, target in case of bound function/action
+ writeProcedureMetadata(boundOption, json);
+
writeProperties(entityType, entity, select, json);
writeNavigationProperties(entityType, entity, expand, json);
json.writeEndObject();
@@ -280,7 +291,7 @@ public class ODataJsonSerializer implements ODataSerializer {
if (navigationLink == null || navigationLink.getInlineEntity() == null) {
json.writeNull();
} else {
- writeEntity(property.getType(), navigationLink.getInlineEntity(), null, innerExpand, innerSelect, json);
+ writeEntity(property.getType(), navigationLink.getInlineEntity(), null, innerExpand, innerSelect, null, json);
}
}
}
@@ -309,9 +320,10 @@ public class ODataJsonSerializer implements ODataSerializer {
} else if (edmProperty.isPrimitive()) {
writePrimitive(edmProperty, property, json);
} else if (property.isLinkedComplex()) {
- writeComplexValue(edmProperty, property.asLinkedComplex().getValue(), selectedPaths, json);
+ writeComplexValue((EdmComplexType) edmProperty.getType(),
+ property.asLinkedComplex().getValue(), selectedPaths, json);
} else if (property.isComplex()) {
- writeComplexValue(edmProperty, property.asComplex(), selectedPaths, json);
+ writeComplexValue((EdmComplexType)edmProperty.getType(), property.asComplex(), selectedPaths, json);
} else {
throw new SerializerException("Property type not yet supported!",
SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, edmProperty.getName());
@@ -339,10 +351,11 @@ public class ODataJsonSerializer implements ODataSerializer {
json.writeString(value.toString());
break;
case COLLECTION_LINKED_COMPLEX:
- writeComplexValue(edmProperty, ((LinkedComplexValue) value).getValue(), selectedPaths, json);
+ writeComplexValue((EdmComplexType)edmProperty.getType(),
+ ((LinkedComplexValue) value).getValue(), selectedPaths, json);
break;
case COLLECTION_COMPLEX:
- writeComplexValue(edmProperty, property.asComplex(), selectedPaths, json);
+ writeComplexValue((EdmComplexType)edmProperty.getType(), property.asComplex(), selectedPaths, json);
break;
default:
throw new SerializerException("Property type not yet supported!",
@@ -351,6 +364,38 @@ public class ODataJsonSerializer implements ODataSerializer {
}
json.writeEndArray();
}
+
+ private void writeCollection(final EdmReturnType edmProperty, final Property property,
+ final Set<List<String>> selectedPaths, JsonGenerator json)
+ throws IOException, EdmPrimitiveTypeException, SerializerException {
+ json.writeStartArray();
+ for (Object value : property.asCollection()) {
+ switch (property.getValueType()) {
+ case COLLECTION_PRIMITIVE:
+ writePrimitiveValue(edmProperty, value, json);
+ break;
+ case COLLECTION_GEOSPATIAL:
+ throw new SerializerException("Property type not yet supported!",
+ SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE,
+ edmProperty.getType().getFullQualifiedName().toString());
+ case COLLECTION_ENUM:
+ json.writeString(value.toString());
+ break;
+ case COLLECTION_LINKED_COMPLEX:
+ writeComplexValue((EdmComplexType)edmProperty.getType(),
+ ((LinkedComplexValue) value).getValue(), selectedPaths, json);
+ break;
+ case COLLECTION_COMPLEX:
+ writeComplexValue((EdmComplexType)edmProperty.getType(), property.asComplex(), selectedPaths, json);
+ break;
+ default:
+ throw new SerializerException("Property type not yet supported!",
+ SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE,
+ edmProperty.getType().getFullQualifiedName().toString());
+ }
+ }
+ json.writeEndArray();
+ }
private void writePrimitive(EdmProperty edmProperty, Property property, JsonGenerator json)
throws EdmPrimitiveTypeException, IOException, SerializerException {
@@ -366,6 +411,23 @@ public class ODataJsonSerializer implements ODataSerializer {
SerializerException.MessageKeys.INCONSISTENT_PROPERTY_TYPE, edmProperty.getName());
}
}
+
+ private void writePrimitive(EdmReturnType edmReturnType, Property property, JsonGenerator json)
+ throws EdmPrimitiveTypeException, IOException, SerializerException {
+ if (property.isPrimitive()) {
+ writePrimitiveValue(edmReturnType, property.asPrimitive(), json);
+ } else if (property.isGeospatial()) {
+ throw new SerializerException("Property type not yet supported!",
+ SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE,
+ edmReturnType.getType().getFullQualifiedName().toString());
+ } else if (property.isEnum()) {
+ writePrimitiveValue(edmReturnType, property.asEnum(), json);
+ } else {
+ throw new SerializerException("Inconsistent property type!",
+ SerializerException.MessageKeys.INCONSISTENT_PROPERTY_TYPE,
+ edmReturnType.getType().getFullQualifiedName().toString());
+ }
+ }
protected void writePrimitiveValue(final EdmProperty edmProperty, final Object primitiveValue,
final JsonGenerator json) throws EdmPrimitiveTypeException, IOException {
@@ -388,19 +450,40 @@ public class ODataJsonSerializer implements ODataSerializer {
json.writeString(value);
}
}
+
+ protected void writePrimitiveValue(final EdmReturnType edmReturnType, final Object primitiveValue,
+ final JsonGenerator json) throws EdmPrimitiveTypeException, IOException {
+ final EdmPrimitiveType type = (EdmPrimitiveType) edmReturnType.getType();
+ final String value = type.valueToString(primitiveValue,
+ edmReturnType.isNullable(), edmReturnType.getMaxLength(),
+ edmReturnType.getPrecision(), edmReturnType.getScale(), true);
+ if (type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean)) {
+ json.writeBoolean(Boolean.parseBoolean(value));
+ } else if (type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Byte)
+ || type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal)
+ || type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Double)
+ || type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Int16)
+ || type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Int32)
+ || type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Int64)
+ || type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.SByte)
+ || type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Single)) {
+ json.writeNumber(value);
+ } else {
+ json.writeString(value);
+ }
+ }
- protected void writeComplexValue(final EdmProperty edmProperty, final List<Property> properties,
+ protected void writeComplexValue(final EdmComplexType type, final List<Property> properties,
final Set<List<String>> selectedPaths, JsonGenerator json)
- throws IOException, EdmPrimitiveTypeException, SerializerException {
+ throws IOException, SerializerException {
json.writeStartObject();
- writePropertyValues(edmProperty, properties, selectedPaths, json);
+ writeComplexPropertyValues(type, properties, selectedPaths, json);
json.writeEndObject();
}
- private void writePropertyValues(final EdmProperty edmProperty,
+ private void writeComplexPropertyValues(final EdmComplexType type,
final List<Property> properties, final Set<List<String>> selectedPaths,
- JsonGenerator json) throws IOException, SerializerException {
- final EdmComplexType type = (EdmComplexType) edmProperty.getType();
+ JsonGenerator json) throws IOException, SerializerException {
for (final String propertyName : type.getPropertyNames()) {
final Property property = findProperty(propertyName, properties);
if (selectedPaths == null || ExpandSelectHelper.isSelected(selectedPaths, propertyName)) {
@@ -444,9 +527,10 @@ public class ODataJsonSerializer implements ODataSerializer {
throw new SerializerException("Property value can not be null",
SerializerException.MessageKeys.NULL_INPUT);
} else if (property.isComplex() && !property.isNull()) {
- writePropertyValues(edmProperty, property.asComplex(), null, json);
+ writeComplexPropertyValues((EdmComplexType)edmProperty.getType(), property.asComplex(), null, json);
} else if (property.isLinkedComplex() && !property.isNull()) {
- writePropertyValues(edmProperty, property.asLinkedComplex().getValue(), null, json);
+ writeComplexPropertyValues((EdmComplexType)edmProperty.getType(),
+ property.asLinkedComplex().getValue(), null, json);
} else {
json.writeFieldName(Constants.VALUE);
writePropertyValue(edmProperty, property, null, json);
@@ -459,4 +543,83 @@ public class ODataJsonSerializer implements ODataSerializer {
}
return buffer.getInputStream();
}
+
+ @Override
+ public InputStream procedureReturn(EdmReturnType returnType, Property property,
+ ODataSerializerOptions options) throws SerializerException {
+ final ContextURL contextURL = checkContextURL(options);
+ CircleStreamBuffer buffer = new CircleStreamBuffer();
+ try {
+ JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream());
+ json.writeStartObject();
+
+ if (this.format != ODataFormat.JSON_NO_METADATA) {
+ if (contextURL != null) {
+ json.writeStringField(Constants.JSON_CONTEXT, ContextURLBuilder.create(contextURL).toASCIIString());
+ }
+ }
+ // write title, target in case of bound function/action
+ if (options != null) {
+ writeProcedureMetadata(options.getBoundProcedure(), json);
+ }
+
+ if (returnType.isCollection()) {
+ switch (returnType.getType().getKind()) {
+ case PRIMITIVE:
+ case COMPLEX:
+ json.writeFieldName(Constants.VALUE);
+ writeCollection(returnType, property, null, json);
+ break;
+ default:
+ throw new SerializerException("Property type not yet supported!",
+ SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE,
+ returnType.getType().getFullQualifiedName().toString());
+ }
+ } else {
+ switch (returnType.getType().getKind()) {
+ case PRIMITIVE:
+ json.writeFieldName(Constants.VALUE);
+ writePrimitiveValue(returnType, property.getValue(), json);
+ break;
+ case COMPLEX:
+ if (property.isComplex()) {
+ writeComplexPropertyValues((EdmComplexType)returnType.getType(), property.asComplex(), null, json);
+ } else if (property.isLinkedComplex()) {
+ writeComplexPropertyValues((EdmComplexType)returnType.getType(),
+ property.asLinkedComplex().getValue(), null, json);
+ }
+ break;
+ default:
+ throw new SerializerException("Property type not yet supported!",
+ SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE,
+ returnType.getType().getFullQualifiedName().toString());
+ }
+ }
+ json.writeEndObject();
+ json.close();
+ } catch (final IOException e) {
+ throw new SerializerException("An I/O exception occurred.", e,
+ SerializerException.MessageKeys.IO_EXCEPTION);
+ } catch (EdmPrimitiveTypeException e) {
+ throw new SerializerException("An I/O exception occurred.", e,
+ SerializerException.MessageKeys.IO_EXCEPTION);
+ }
+ return buffer.getInputStream();
+ }
+
+ private void writeProcedureMetadata(BoundProcedureOption bpOption, JsonGenerator json) throws IOException {
+ if (bpOption != null) {
+ if (this.format == ODataFormat.JSON) {
+ json.writeFieldName("#"+bpOption.getProcedureName());
+ json.writeStartObject();
+ json.writeEndObject();
+ } else if (this.format == ODataFormat.JSON_FULL_METADATA) {
+ json.writeFieldName("#"+bpOption.getProcedureName());
+ json.writeStartObject();
+ json.writeStringField("title", bpOption.getTitle());
+ json.writeStringField("target", bpOption.getTarget());
+ json.writeEndObject();
+ }
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/MetadataDocumentXmlSerializer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/MetadataDocumentXmlSerializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/MetadataDocumentXmlSerializer.java
index 9f81ef3..e73682f 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/MetadataDocumentXmlSerializer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/MetadataDocumentXmlSerializer.java
@@ -83,6 +83,7 @@ public class MetadataDocumentXmlSerializer {
private static final String XML_PARAMETER = "Parameter";
private static final String XML_IS_COMPOSABLE = "IsComposable";
private static final String XML_IS_BOUND = "IsBound";
+ private static final String XML_ENTITY_SET_PATH = "EntitySetPath";
private static final String XML_ENTITY_TYPE = "EntityType";
private static final String XML_SINGLETON = "Singleton";
private static final String XML_ACTION = "Action";
@@ -293,7 +294,9 @@ public class MetadataDocumentXmlSerializer {
for (EdmFunction function : functions) {
writer.writeStartElement(XML_FUNCTION);
writer.writeAttribute(XML_NAME, function.getName());
- // TODO: EntitySetPath
+ if (function.getEntitySetPath() != null) {
+ writer.writeAttribute(XML_ENTITY_SET_PATH, function.getEntitySetPath());
+ }
writer.writeAttribute(XML_IS_BOUND, "" + function.isBound());
writer.writeAttribute(XML_IS_COMPOSABLE, "" + function.isComposable());
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceActionImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceActionImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceActionImpl.java
index 4ca162c..535413e 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceActionImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceActionImpl.java
@@ -18,9 +18,13 @@
*/
package org.apache.olingo.server.core.uri;
+import java.util.ArrayList;
+import java.util.List;
+
import org.apache.olingo.commons.api.edm.EdmAction;
import org.apache.olingo.commons.api.edm.EdmActionImport;
import org.apache.olingo.commons.api.edm.EdmType;
+import org.apache.olingo.server.api.uri.UriParameter;
import org.apache.olingo.server.api.uri.UriResourceAction;
import org.apache.olingo.server.api.uri.UriResourceKind;
@@ -28,6 +32,7 @@ public class UriResourceActionImpl extends UriResourceTypedImpl implements UriRe
protected EdmAction action;
protected EdmActionImport actionImport;
+ protected List<UriParameterImpl> parameters;
public UriResourceActionImpl() {
super(UriResourceKind.action);
@@ -48,9 +53,11 @@ public class UriResourceActionImpl extends UriResourceTypedImpl implements UriRe
return actionImport;
}
- public UriResourceActionImpl setActionImport(final EdmActionImport actionImport) {
+ public UriResourceActionImpl setActionImport(final EdmActionImport actionImport,
+ final List<UriParameterImpl> parameters) {
this.actionImport = actionImport;
setAction(actionImport.getUnboundAction());
+ setParameters(parameters);
return this;
}
@@ -63,6 +70,20 @@ public class UriResourceActionImpl extends UriResourceTypedImpl implements UriRe
public EdmType getType() {
return action.getReturnType().getType();
}
+
+ @Override
+ public List<UriParameter> getParameters() {
+ List<UriParameter> retList = new ArrayList<UriParameter>();
+ for (UriParameterImpl item : parameters) {
+ retList.add(item);
+ }
+ return retList;
+ }
+
+ public UriResourceActionImpl setParameters(final List<UriParameterImpl> parameters) {
+ this.parameters = parameters;
+ return this;
+ }
@Override
public String toString() {
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
index 63d8fb9..4ab3262 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
@@ -18,6 +18,10 @@
*/
package org.apache.olingo.server.core.uri.parser;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
import org.antlr.v4.runtime.misc.NotNull;
import org.antlr.v4.runtime.misc.ParseCancellationException;
import org.antlr.v4.runtime.tree.ParseTree;
@@ -181,9 +185,6 @@ import org.apache.olingo.server.core.uri.queryoption.expression.MethodImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.TypeLiteralImpl;
import org.apache.olingo.server.core.uri.queryoption.expression.UnaryImpl;
-import java.util.ArrayList;
-import java.util.List;
-
/**
* UriVisitor
*
@@ -312,10 +313,24 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
// check ActionImport
EdmActionImport edmActionImport = edmEntityContainer.getActionImport(odi);
if (edmActionImport != null) {
- UriResourceActionImpl uriResource = new UriResourceActionImpl()
- .setActionImport(edmActionImport);
+
+ // read the URI parameters, since unbound actions can not be overloaded
+ // there can be atmost one with given name
+ List<UriParameterImpl> parameters = Collections.EMPTY_LIST;
+ if (!ctx.vlNVO.isEmpty()) {
+ context.contextReadingFunctionParameters = true;
+ parameters = (List<UriParameterImpl>) ctx.vlNVO.get(0).accept(this);
+ context.contextReadingFunctionParameters = false;
+
+ // mark parameters as consumed
+ ctx.vlNVO.remove(0);
+ }
+
+ UriResourceActionImpl uriResource = new UriResourceActionImpl().setActionImport(edmActionImport, parameters);
+
+ uriResource.setAction(edmActionImport.getUnboundAction());
context.contextUriInfo.addResourcePart(uriResource);
- return null;
+ return null;
}
// check FunctionImport
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-tecsvc/pom.xml
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/pom.xml b/lib/server-tecsvc/pom.xml
index bcf29ec..bfe3298 100644
--- a/lib/server-tecsvc/pom.xml
+++ b/lib/server-tecsvc/pom.xml
@@ -121,7 +121,6 @@
<groupId>org.apache.olingo</groupId>
<artifactId>odata-server-core</artifactId>
<version>${project.version}</version>
- <scope>runtime</scope>
</dependency>
<dependency>
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
index 6010e95..8c6136a 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
@@ -35,8 +35,10 @@ import org.apache.olingo.commons.api.data.Link;
import org.apache.olingo.commons.api.data.LinkedComplexValue;
import org.apache.olingo.commons.api.data.Property;
import org.apache.olingo.commons.api.data.ValueType;
+import org.apache.olingo.commons.api.edm.EdmAction;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmEntityType;
+import org.apache.olingo.commons.api.edm.EdmFunction;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
import org.apache.olingo.commons.api.edm.EdmProperty;
@@ -48,6 +50,10 @@ import org.apache.olingo.commons.core.data.LinkedComplexValueImpl;
import org.apache.olingo.commons.core.data.PropertyImpl;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.uri.UriParameter;
+import org.apache.olingo.server.api.uri.UriResourceAction;
+import org.apache.olingo.server.api.uri.UriResourceFunction;
+import org.apache.olingo.server.tecsvc.provider.ActionProvider;
+import org.apache.olingo.server.tecsvc.provider.FunctionProvider;
public class DataProvider {
@@ -543,4 +549,105 @@ public class DataProvider {
link.setInlineEntitySet(target);
entity.getNavigationLinks().add(link);
}
+
+ public Object invokeFunction(UriResourceFunction uriFunction) {
+ final EdmFunction function = uriFunction.getFunction();
+ final List<UriParameter> keys = uriFunction.getParameters();
+
+ if (function.isBound()) {
+ if (function.getFullQualifiedName().equals(FunctionProvider.nameBFESTwoPrimRTString)) {
+ // bound - return primitive
+ return createPrimitive("any", "TEST-A");
+ } else if (function.getFullQualifiedName().equals(FunctionProvider.nameBFESTwoPrimRTCollString)) {
+ // bound - return Collection(primitive)
+ return createCollection("any", "dummy1", "dummy2");
+ } else if (function.getFullQualifiedName().equals(FunctionProvider.nameBFESTwoPrimRTETTwoPrim)) {
+ // bound- entity
+ return data.get("ESTwoPrim").getEntities().get(0);
+ } else if (function.getFullQualifiedName().equals(FunctionProvider.nameBFESTwoPrimRTString)) {
+ // bound- Collection(entity)
+ List<Entity> rows = data.get("ESTwoPrim").getEntities();
+ } else if (function.getFullQualifiedName().equals(FunctionProvider.nameBFCETTwoKeyNavRTCTTwoPrim)) {
+ // bound- complex
+ LinkedComplexValue complexValue = new LinkedComplexValueImpl();
+ complexValue.getValue().add(createPrimitive("PropertyInt16", 5));
+ complexValue.getValue().add(createPrimitive("PropertyString", "TEST-A"));
+ return new PropertyImpl(null, "PropertyComp", ValueType.LINKED_COMPLEX, complexValue);
+ } else if (function.getFullQualifiedName().equals(FunctionProvider.nameBFCESTwoKeyNavRTCollCTTwoPrim)) {
+ // bound- Collection(complex)
+ List<LinkedComplexValue> complexCollection = new ArrayList<LinkedComplexValue>();
+ LinkedComplexValue complexValue = new LinkedComplexValueImpl();
+ complexValue.getValue().add(createPrimitive("PropertyInt16", 5));
+ complexValue.getValue().add(createPrimitive("PropertyString", "TEST-A"));
+ complexCollection.add(complexValue);
+ complexCollection.add(complexValue);
+ return new PropertyImpl(null, "PropertyComp", ValueType.COLLECTION_LINKED_COMPLEX, complexCollection);
+ }
+ }
+
+ if (function.getFullQualifiedName().equals(FunctionProvider.nameUFNRTInt16)) {
+ // unbound - return primitive
+ return createPrimitive("any", new Short((short)5));
+ } else if (function.getFullQualifiedName().equals(FunctionProvider.nameUFCRTCollString)) {
+ // unbound - return Collection(primitive)
+ return createCollection("any", "dummy1", "dummy2");
+ } else if (function.getFullQualifiedName().equals(FunctionProvider.nameUFCRTETAllPrimTwoParam)) {
+ // unbound- entity
+ String parameterString = getParameter("ParameterString", keys).getText();
+ short parameterInt16 = Short.valueOf(getParameter("ParameterInt16", keys).getText());
+ return data.get("ESAllPrim").getEntities().get(0);
+ } else if (function.getFullQualifiedName().equals(FunctionProvider.nameUFCRTESMixPrimCollCompTwoParam)) {
+ // unbound- Collection(entity)
+ String parameterString = getParameter("ParameterString", keys).getText();
+ short ParameterInt16 = Short.valueOf(getParameter("ParameterInt16", keys).getText());
+ return data.get("ESMixPrimCollComp");
+ } else if (function.getFullQualifiedName().equals(FunctionProvider.nameUFCRTCTTwoPrimParam)) {
+ // unbound- complex
+ String parameterString = unquote(getParameter("ParameterString", keys).getText());
+ short parameterInt16 = Short.valueOf(getParameter("ParameterInt16", keys).getText());
+ LinkedComplexValue complexValue = new LinkedComplexValueImpl();
+ complexValue.getValue().add(createPrimitive("PropertyInt16", parameterInt16));
+ complexValue.getValue().add(createPrimitive("PropertyString", parameterString));
+ return new PropertyImpl(null, "PropertyComp", ValueType.LINKED_COMPLEX, complexValue);
+ } else if (function.getFullQualifiedName().equals(FunctionProvider.nameUFCRTCollCTTwoPrimParam)) {
+ // unbound- Collection(complex)
+ String parameterString = unquote(getParameter("ParameterString", keys).getText());
+ short parameterInt16 = Short.valueOf(getParameter("ParameterInt16", keys).getText());
+ List<LinkedComplexValue> complexCollection = new ArrayList<LinkedComplexValue>();
+ LinkedComplexValue complexValue = new LinkedComplexValueImpl();
+ complexValue.getValue().add(createPrimitive("PropertyInt16", parameterInt16));
+ complexValue.getValue().add(createPrimitive("PropertyString", parameterString));
+ complexCollection.add(complexValue);
+ complexCollection.add(complexValue);
+ return new PropertyImpl(null, "PropertyComp", ValueType.COLLECTION_LINKED_COMPLEX, complexCollection);
+ }
+ return null;
+ }
+
+ public Object invokeAction(UriResourceAction uriAction) {
+ final EdmAction action = uriAction.getAction();
+ final List<UriParameter> keys = uriAction.getParameters();
+
+ if (action.getFullQualifiedName().equals(ActionProvider.nameUARTPrimParam)) {
+ // unbound - return primitive
+ return createPrimitive("any", "return-string");
+ }
+ return null;
+ }
+
+ private UriParameter getParameter(String name, List<UriParameter> keys) {
+ for (UriParameter key:keys) {
+ if (key.getName().equals(name)) {
+ return key;
+ }
+ }
+ return null;
+ }
+
+ private static String unquote(String str) {
+ if (str.startsWith("'") && str.endsWith("'")) {
+ return str.substring(1, str.length()-1);
+ }
+ return str;
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
index ca87c6b..9ff5f47 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
@@ -24,16 +24,22 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.TreeMap;
import org.apache.olingo.commons.api.data.ContextURL;
import org.apache.olingo.commons.api.data.ContextURL.Suffix;
import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.data.EntitySet;
import org.apache.olingo.commons.api.data.Property;
+import org.apache.olingo.commons.api.edm.Edm;
+import org.apache.olingo.commons.api.edm.EdmAction;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
+import org.apache.olingo.commons.api.edm.EdmEntityType;
+import org.apache.olingo.commons.api.edm.EdmFunction;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmReturnType;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.format.ODataFormat;
import org.apache.olingo.commons.api.http.HttpContentType;
@@ -46,7 +52,9 @@ import org.apache.olingo.server.api.ODataResponse;
import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.processor.EntityProcessor;
import org.apache.olingo.server.api.processor.EntitySetProcessor;
+import org.apache.olingo.server.api.processor.ProcedureProcessor;
import org.apache.olingo.server.api.processor.PropertyProcessor;
+import org.apache.olingo.server.api.serializer.BoundProcedureOption;
import org.apache.olingo.server.api.serializer.ODataSerializer;
import org.apache.olingo.server.api.serializer.ODataSerializerOptions;
import org.apache.olingo.server.api.serializer.SerializerException;
@@ -54,7 +62,9 @@ import org.apache.olingo.server.api.uri.UriInfo;
import org.apache.olingo.server.api.uri.UriInfoResource;
import org.apache.olingo.server.api.uri.UriParameter;
import org.apache.olingo.server.api.uri.UriResource;
+import org.apache.olingo.server.api.uri.UriResourceAction;
import org.apache.olingo.server.api.uri.UriResourceEntitySet;
+import org.apache.olingo.server.api.uri.UriResourceFunction;
import org.apache.olingo.server.api.uri.UriResourceKind;
import org.apache.olingo.server.api.uri.UriResourceProperty;
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
@@ -64,18 +74,20 @@ import org.apache.olingo.server.tecsvc.data.DataProvider;
/**
* Technical Processor which provides currently implemented processor functionality.
*/
-public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor, PropertyProcessor {
+public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor, PropertyProcessor, ProcedureProcessor {
private OData odata;
private DataProvider dataProvider;
+ private ServiceMetadata edm;
public TechnicalProcessor(final DataProvider dataProvider) {
- this.dataProvider = dataProvider;
+ this.dataProvider = dataProvider;
}
@Override
public void init(final OData odata, final ServiceMetadata edm) {
this.odata = odata;
+ this.edm = edm;
}
@Override
@@ -297,4 +309,162 @@ public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor,
}
}
}
+
+ @Override
+ public void executeFunction(ODataRequest request, ODataResponse response,
+ UriInfo uriInfo, ContentType requestedContentType) throws ODataApplicationException, SerializerException {
+ final List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
+ Object result = null;
+
+ UriResourceFunction functionURI = null;
+ for (UriResource uriResource:resourcePaths) {
+ if (uriResource instanceof UriResourceFunction) {
+ functionURI = (UriResourceFunction)uriResource;
+ break;
+ }
+ }
+
+ if (functionURI == null) {
+ throw new ODataApplicationException("Function not found",
+ HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
+ }
+
+ ODataSerializerOptions.Builder options = ODataSerializerOptions.with();
+ if (functionURI.getFunction().isBound()) {
+ options.boundProcedure(BoundProcedureOption.with()
+ .setFunction(functionURI.getFunction())
+ .setTarget(request.getRawODataPath())
+ .setTitle(functionURI.getFunction().getName()).build());
+ }
+
+ EdmFunction edmFunction = functionURI.getFunction();
+ result = dataProvider.invokeFunction(functionURI);
+ if (result == null) {
+ response.setStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode());
+ } else {
+ final ODataFormat format = ODataFormat.fromContentType(requestedContentType);
+ ODataSerializer serializer = odata.createSerializer(format);
+ EdmReturnType returnType = edmFunction.getReturnType();
+ switch(returnType.getType().getKind()) {
+ case PRIMITIVE:
+ case COMPLEX:
+ ContextURL.Builder contextURL = ContextURL.with().propertyType(returnType.getType());
+ if (returnType.isCollection()) {
+ contextURL.asCollection();
+ }
+ response.setContent(serializer.procedureReturn(returnType, (Property)result,
+ options.contextURL(format == ODataFormat.JSON_NO_METADATA ? null :
+ contextURL.build()).build()));
+ response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+ response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString());
+ break;
+ case ENTITY:
+ EdmEntitySet edmEntitySet = null;
+ if (edmFunction.isBound()) {
+ //TODO: this needs to be fixed to return correct entitySet
+ edmEntitySet = edmFunction.getReturnedEntitySet(null);
+ } else {
+ edmEntitySet = functionURI.getFunctionImport().getReturnedEntitySet();
+ }
+ if (edmEntitySet == null) {
+ throw new ODataApplicationException("EntitySet type not defined on function",
+ HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
+ }
+ if (returnType.isCollection()) {
+ response.setContent(serializer.entitySet(edmEntitySet, (EntitySet)result,
+ options.contextURL(format == ODataFormat.JSON_NO_METADATA ? null:
+ getContextUrl(serializer, edmEntitySet, false, null, null, null)).build()));
+ } else {
+ response.setContent(serializer.entity(edmEntitySet, (Entity) result,
+ options.contextURL(format == ODataFormat.JSON_NO_METADATA ? null:
+ getContextUrl(serializer, edmEntitySet, true, null, null, null)).build()));
+ }
+ response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+ response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString());
+ break;
+ default:
+ throw new ODataApplicationException("Return type not supported",
+ HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
+ }
+ }
+ }
+
+ @Override
+ public void executeAction(ODataRequest request, ODataResponse response,
+ UriInfo uriInfo, ContentType requestedContentType) throws ODataApplicationException, SerializerException {
+ final List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
+ Object result = null;
+
+ UriResourceAction actionURI = null;
+ for (UriResource uriResource:resourcePaths) {
+ if (uriResource instanceof UriResourceAction) {
+ actionURI = (UriResourceAction)uriResource;
+ break;
+ }
+ }
+
+ if (actionURI == null) {
+ throw new ODataApplicationException("Action not found",
+ HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
+ }
+
+ ODataSerializerOptions.Builder options = ODataSerializerOptions.with();
+ if (actionURI.getAction().isBound()) {
+ options.boundProcedure(BoundProcedureOption.with()
+ .setAction(actionURI.getAction())
+ .setTarget(request.getRawODataPath())
+ .setTitle(actionURI.getAction().getName()).build());
+ }
+
+ EdmAction edmAction = actionURI.getAction();
+ result = dataProvider.invokeAction(actionURI);
+ if (result == null) {
+ response.setStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode());
+ } else {
+ final ODataFormat format = ODataFormat.fromContentType(requestedContentType);
+ ODataSerializer serializer = odata.createSerializer(format);
+ EdmReturnType returnType = edmAction.getReturnType();
+ switch(returnType.getType().getKind()) {
+ case PRIMITIVE:
+ case COMPLEX:
+ ContextURL.Builder contextURL = ContextURL.with().propertyType(returnType.getType());
+ if (returnType.isCollection()) {
+ contextURL.asCollection();
+ }
+ response.setContent(serializer.procedureReturn(returnType, (Property)result,
+ options.contextURL(format == ODataFormat.JSON_NO_METADATA ? null :
+ contextURL.build()).build()));
+ response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+ response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString());
+ break;
+ case ENTITY:
+ EdmEntitySet edmEntitySet = null;
+ if (edmAction.isBound()) {
+ //TODO: this needs to be fixed to return correct entitySet
+ edmEntitySet = edmAction.getReturnedEntitySet(null);
+ } else {
+ edmEntitySet = actionURI.getActionImport().getReturnedEntitySet();
+ }
+ if (edmEntitySet == null) {
+ throw new ODataApplicationException("EntitySet type not defined on function",
+ HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
+ }
+ if (returnType.isCollection()) {
+ response.setContent(serializer.entitySet(edmEntitySet, (EntitySet)result,
+ options.contextURL(format == ODataFormat.JSON_NO_METADATA ? null:
+ getContextUrl(serializer, edmEntitySet, false, null, null, null)).build()));
+ } else {
+ response.setContent(serializer.entity(edmEntitySet, (Entity) result,
+ options.contextURL(format == ODataFormat.JSON_NO_METADATA ? null:
+ getContextUrl(serializer, edmEntitySet, true, null, null, null)).build()));
+ }
+ response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+ response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString());
+ break;
+ default:
+ throw new ODataApplicationException("Return type not supported",
+ HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
+ }
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java
index 813bb87..2386d9d 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java
@@ -349,6 +349,8 @@ public class ContainerProvider {
return new FunctionImport()
.setName("FICRTESMixPrimCollCompTwoParam")
.setFunction(FunctionProvider.nameUFCRTESMixPrimCollCompTwoParam)
+ .setEntitySet(new Target.Builder(entityContainer.getFullQualifiedNameAsString()
+ +"/ESMixPrimCollComp", null).build())
.setIncludeInServiceDocument(true);
} else if (name.equals("FINRTESMixPrimCollCompTwoParam")) {
@@ -405,6 +407,12 @@ public class ContainerProvider {
.setFunction(FunctionProvider.nameUFCRTCollCTTwoPrimParam)
.setIncludeInServiceDocument(true);
+ } else if (name.equals("FICRTETAllPrimTwoParam")) {
+ return new FunctionImport()
+ .setName("FICRTETAllPrimTwoParam")
+ .setFunction(FunctionProvider.nameUFCRTETAllPrimTwoParam)
+ .setEntitySet(new Target.Builder(entityContainer.getFullQualifiedNameAsString()+"/ESAllPrim", null).build())
+ .setIncludeInServiceDocument(true);
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/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 c4ee503..7153f4f 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
@@ -20,6 +20,7 @@ package org.apache.olingo.server.tecsvc.provider;
import org.apache.olingo.commons.api.ODataException;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.server.api.edm.provider.EntitySetPath;
import org.apache.olingo.server.api.edm.provider.Function;
import org.apache.olingo.server.api.edm.provider.Parameter;
import org.apache.olingo.server.api.edm.provider.ReturnType;
@@ -111,6 +112,17 @@ public class FunctionProvider {
public static final FullQualifiedName nameBFESTwoKeyNavRTESTwoKeyNav =
new FullQualifiedName(SchemaProvider.NAMESPACE, "BFESTwoKeyNavRTESTwoKeyNav");
+
+ public static final FullQualifiedName nameBFESTwoPrimRTString =
+ new FullQualifiedName(SchemaProvider.NAMESPACE, "BFESTwoPrimRTString");
+
+ public static final FullQualifiedName nameBFESTwoPrimRTCollString =
+ new FullQualifiedName(SchemaProvider.NAMESPACE, "BFESTwoPrimRTCollString");
+
+ public static final FullQualifiedName nameBFESTwoPrimRTETTwoPrim =
+ new FullQualifiedName(SchemaProvider.NAMESPACE, "BFESTwoPrimRTETTwoPrim");
+
+
// Unbound Functions
public static final FullQualifiedName nameUFCRTCollCTTwoPrim =
@@ -839,13 +851,61 @@ public class FunctionProvider {
new Parameter().setName("BindingParam").setType(ComplexTypeProvider.nameCTPrimComp).setNullable(
false),
new Parameter().setName("ParameterString").setType(PropertyProvider.nameString)
- .setNullable(false)))
+ .setNullable(false)))
.setComposable(true)
.setReturnType(
new ReturnType().setType(EntityTypeProvider.nameETTwoKeyNav).setCollection(true).setNullable(false))
);
+ } else if (functionName.equals(nameBFESTwoPrimRTString)) {
+ return Arrays.asList(
+ new Function()
+ .setName("BFESTwoPrimRTString")
+ .setBound(true)
+ .setParameters(
+ Arrays.asList(
+ new Parameter().setName("BindingParam").setType(EntityTypeProvider.nameETTwoPrim).setNullable(
+ false).setCollection(true)))
+ .setEntitySetPath(new EntitySetPath().
+ setBindingParameter("BindingParam").setPath("ESTwoPrim"))
+ .setComposable(true)
+ .setReturnType(
+ new ReturnType().setType(PropertyProvider.nameString).setCollection(false).setNullable(false))
+ );
+ } else if (functionName.equals(nameBFESTwoPrimRTCollString)) {
+ return Arrays.asList(
+ new Function()
+ .setName("BFESTwoPrimRTCollString")
+ .setBound(true)
+ .setParameters(
+ Arrays.asList(
+ new Parameter().setName("BindingParam").
+ setType(EntityTypeProvider.nameETTwoPrim).setNullable(false)))
+ .setEntitySetPath(new EntitySetPath().setBindingParameter("BindingParam")
+ .setPath("ESTwoPrim"))
+ .setComposable(true)
+ .setReturnType(
+ new ReturnType().setType(PropertyProvider.nameString).setCollection(true).setNullable(false))
+ );
+ } else if (functionName.equals(nameBFESTwoPrimRTETTwoPrim)) {
+ return Arrays.asList(
+ new Function()
+ .setName("BFESTwoPrimRTETTwoPrim")
+ .setBound(true)
+ .setParameters(
+ Arrays.asList(
+ new Parameter().setName("BindingParam")
+ .setType(EntityTypeProvider.nameETTwoPrim).setNullable(false).setCollection(true),
+ new Parameter().setName("ParameterString")
+ .setType(PropertyProvider.nameString).setNullable(false)))
+ .setEntitySetPath(new EntitySetPath().setBindingParameter("BindingParam")
+ .setPath("ESTwoPrim"))
+ .setComposable(true)
+ .setReturnType(
+ new ReturnType().setType(EntityTypeProvider.nameETTwoPrim)
+ .setCollection(false).setNullable(false))
+ );
}
-
+
return null;
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/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 a0a282e..fe22fa1 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
@@ -165,6 +165,10 @@ public class SchemaProvider {
functions.addAll(prov.getFunctions(FunctionProvider.nameBFCESTwoKeyNavRTStringParam));
functions.addAll(prov.getFunctions(FunctionProvider.nameBFCESKeyNavRTETKeyNavParam));
functions.addAll(prov.getFunctions(FunctionProvider.nameBFCCTPrimCompRTETTwoKeyNavParam));
+ functions.addAll(prov.getFunctions(FunctionProvider.nameBFESTwoPrimRTString));
+ functions.addAll(prov.getFunctions(FunctionProvider.nameBFESTwoPrimRTCollString));
+ functions.addAll(prov.getFunctions(FunctionProvider.nameBFESTwoPrimRTETTwoPrim));
+
// functions.addAll(prov.getFunctions(FunctionProvider.nameBFCCTPrimCompRTESTwoKeyNavParam));
// EntityContainer
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
index d99c9ae..ea5cdd7 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
@@ -40,9 +40,11 @@ import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.edmx.EdmxReference;
import org.apache.olingo.server.api.processor.EntitySetProcessor;
import org.apache.olingo.server.api.processor.MetadataProcessor;
+import org.apache.olingo.server.api.processor.ProcedureProcessor;
import org.apache.olingo.server.api.processor.PropertyProcessor;
import org.apache.olingo.server.api.processor.ServiceDocumentProcessor;
import org.apache.olingo.server.api.uri.UriInfo;
+import org.apache.olingo.server.tecsvc.provider.ActionProvider;
import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
import org.junit.Before;
import org.junit.Test;
@@ -341,4 +343,61 @@ public class ODataHandlerTest {
Mockito.any(UriInfo.class),
Mockito.any(ContentType.class));
}
-}
\ No newline at end of file
+
+ @Test
+ public void testInvokeActionImport() throws Exception {
+ ODataRequest request = new ODataRequest();
+
+ request.setMethod(HttpMethod.POST);
+ request.setRawODataPath("AIRTPrimParam(ParameterInt16=1)");
+
+ ProcedureProcessor processor = mock(ProcedureProcessor.class);
+ handler.register(processor);
+
+ ODataResponse response = handler.process(request);
+
+ Mockito.verify(processor).executeAction(
+ Mockito.any(ODataRequest.class),
+ Mockito.any(ODataResponse.class),
+ Mockito.any(UriInfo.class),
+ Mockito.any(ContentType.class));
+ }
+
+ public void testInvokeFunctionImport() throws Exception {
+ ODataRequest request = new ODataRequest();
+
+ request.setMethod(HttpMethod.GET);
+ request.setRawODataPath("FICRTETTwoKeyNavParam(ParameterInt16=1)");
+
+ ProcedureProcessor processor = mock(ProcedureProcessor.class);
+ handler.register(processor);
+
+ ODataResponse response = handler.process(request);
+
+ Mockito.verify(processor).executeFunction(
+ Mockito.any(ODataRequest.class),
+ Mockito.any(ODataResponse.class),
+ Mockito.any(UriInfo.class),
+ Mockito.any(ContentType.class));
+ }
+
+ @Test
+ public void testInvokeBoundAction() throws Exception {
+ ODataRequest request = new ODataRequest();
+
+ request.setMethod(HttpMethod.POST);
+ request.setRawODataPath("ESAllPrim/"
+ + ActionProvider.nameBAESAllPrimRTETAllPrim.getFullQualifiedNameAsString());
+
+ ProcedureProcessor processor = mock(ProcedureProcessor.class);
+ handler.register(processor);
+
+ ODataResponse response = handler.process(request);
+
+ Mockito.verify(processor).executeAction(
+ Mockito.any(ODataRequest.class),
+ Mockito.any(ODataResponse.class),
+ Mockito.any(UriInfo.class),
+ Mockito.any(ContentType.class));
+ }
+}