[OLINGO-450]: implementing support for execution of Functions and Actions Signed-off-by: mibo <[email protected]>
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 <[email protected]> Authored: Thu Oct 2 15:11:13 2014 -0500 Committer: mibo <[email protected]> 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\":[" + + "\"[email protected]\",\"[email protected]\",\"[email protected]\"]," + + "\"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)); + } +}
