This is an automated email from the ASF dual-hosted git repository. acosentino pushed a commit to branch camel-2.x in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-2.x by this push: new c4bc060 CAMEL-13185: Add splitResults implementations to Olingo Components c4bc060 is described below commit c4bc06042a1487dd937f2101308a8d72c3f4af76 Author: phantomjinx <p.g.richard...@phantomjinx.co.uk> AuthorDate: Tue Feb 12 14:03:30 2019 +0000 CAMEL-13185: Add splitResults implementations to Olingo Components * Adds splitResults methods to both Olingo 2 & 4 Consumers --- .../camel/component/olingo2/Olingo2Consumer.java | 19 +++++ .../camel/component/olingo2/Olingo2Index.java | 20 ++--- .../component/olingo2/Olingo2ComponentTest.java | 80 +++++++++++++++---- .../camel/component/olingo4/Olingo4Consumer.java | 31 ++++++++ .../camel/component/olingo4/Olingo4Index.java | 17 ++-- .../component/olingo4/Olingo4ComponentTest.java | 90 +++++++++++++++++----- 6 files changed, 207 insertions(+), 50 deletions(-) diff --git a/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Consumer.java b/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Consumer.java index e784cfd..e92d96d 100644 --- a/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Consumer.java +++ b/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Consumer.java @@ -16,7 +16,9 @@ */ package org.apache.camel.component.olingo2; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import org.apache.camel.Exchange; @@ -27,6 +29,7 @@ import org.apache.camel.component.olingo2.internal.Olingo2ApiName; import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.component.AbstractApiConsumer; import org.apache.camel.util.component.ApiConsumerHelper; +import org.apache.olingo.odata2.api.ep.entry.ODataEntry; import org.apache.olingo.odata2.api.ep.feed.ODataFeed; @@ -131,4 +134,20 @@ public class Olingo2Consumer extends AbstractApiConsumer<Olingo2ApiName, Olingo2 resultIndex.index(result); } + + @Override + public Object splitResult(Object result) { + List<Object> splitResult = new ArrayList<>(); + + if (result instanceof ODataFeed) { + ODataFeed odataFeed = (ODataFeed) result; + for (ODataEntry entry : odataFeed.getEntries()) { + splitResult.add(entry); + } + } else if (result instanceof ODataEntry) { + splitResult.add(result); + } + + return splitResult; + } } diff --git a/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Index.java b/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Index.java index 81ac6a2..1198a10 100644 --- a/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Index.java +++ b/components/camel-olingo2/camel-olingo2-component/src/main/java/org/apache/camel/component/olingo2/Olingo2Index.java @@ -1,11 +1,12 @@ -/* - * Copyright (C) 2016 Red Hat, Inc. +/** + * 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 * - * Licensed 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 + * 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, @@ -128,12 +129,11 @@ public class Olingo2Index { } } - @SuppressWarnings( "unchecked" ) + @SuppressWarnings("unchecked") public Object filterResponse(Object response) { if (response instanceof ODataFeed) { response = filter((ODataFeed) response); - } else - if (response instanceof Iterable) { + } else if (response instanceof Iterable) { response = filter((Iterable<Object>) response); } else if (response.getClass().isArray()) { List<Object> result = new ArrayList<>(); diff --git a/components/camel-olingo2/camel-olingo2-component/src/test/java/org/apache/camel/component/olingo2/Olingo2ComponentTest.java b/components/camel-olingo2/camel-olingo2-component/src/test/java/org/apache/camel/component/olingo2/Olingo2ComponentTest.java index 65d26ee..c60a3d9 100644 --- a/components/camel-olingo2/camel-olingo2-component/src/test/java/org/apache/camel/component/olingo2/Olingo2ComponentTest.java +++ b/components/camel-olingo2/camel-olingo2-component/src/test/java/org/apache/camel/component/olingo2/Olingo2ComponentTest.java @@ -252,19 +252,27 @@ public class Olingo2ComponentTest extends AbstractOlingo2TestSupport { * and filter already seen items on subsequent exchanges * Use a delay since the mock endpoint does not always get * the correct number of exchanges before being satisfied. + * + * Note: + * - consumer.splitResults is set to false since this ensures the first returned message + * contains all the results. This is preferred for the purposes of this test. The default + * will mean the first n messages contain the results (where n is the result total) then + * subsequent messages will be empty */ @Test public void testConsumerReadFilterAlreadySeen() throws Exception { final Map<String, Object> headers = new HashMap<>(); - String endpoint = "olingo2://read/Manufacturers?filterAlreadySeen=true&consumer.delay=2&consumer.sendEmptyMessageWhenIdle=true"; - final ODataFeed manufacturers = (ODataFeed)requestBodyAndHeaders(endpoint, null, headers); - assertNotNull(manufacturers); - int expectedManufacturers = manufacturers.getEntries().size(); + String endpoint = "olingo2://read/Manufacturers?filterAlreadySeen=true&consumer.delay=2&consumer.sendEmptyMessageWhenIdle=true&consumer.splitResult=false"; int expectedMsgCount = 3; MockEndpoint mockEndpoint = getMockEndpoint("mock:consumer-alreadyseen"); mockEndpoint.expectedMessageCount(expectedMsgCount); mockEndpoint.setResultWaitTime(60000); + + final ODataFeed manufacturers = (ODataFeed)requestBodyAndHeaders(endpoint, null, headers); + assertNotNull(manufacturers); + int expectedManufacturers = manufacturers.getEntries().size(); + mockEndpoint.assertIsSatisfied(); for (int i = 0; i < expectedMsgCount; ++i) { @@ -277,8 +285,7 @@ public class Olingo2ComponentTest extends AbstractOlingo2TestSupport { assertTrue(body instanceof ODataFeed); ODataFeed set = (ODataFeed) body; assertEquals(expectedManufacturers, set.getEntries().size()); - } - else { + } else { // // Subsequent polling messages should be empty // since the filterAlreadySeen property is true @@ -302,6 +309,9 @@ public class Olingo2ComponentTest extends AbstractOlingo2TestSupport { String endpoint = "direct:read-people-nofilterseen"; int expectedMsgCount = 3; + MockEndpoint mockEndpoint = getMockEndpoint("mock:producer-noalreadyseen"); + mockEndpoint.expectedMessageCount(expectedMsgCount); + int expectedEntities = -1; for (int i = 0; i < expectedMsgCount; ++i) { final ODataFeed manufacturers = (ODataFeed)requestBodyAndHeaders(endpoint, null, headers); @@ -311,8 +321,6 @@ public class Olingo2ComponentTest extends AbstractOlingo2TestSupport { } } - MockEndpoint mockEndpoint = getMockEndpoint("mock:producer-noalreadyseen"); - mockEndpoint.expectedMessageCount(expectedMsgCount); mockEndpoint.assertIsSatisfied(); for (int i = 0; i < expectedMsgCount; ++i) { @@ -337,6 +345,9 @@ public class Olingo2ComponentTest extends AbstractOlingo2TestSupport { String endpoint = "direct:read-people-filterseen"; int expectedMsgCount = 3; + MockEndpoint mockEndpoint = getMockEndpoint("mock:producer-alreadyseen"); + mockEndpoint.expectedMessageCount(expectedMsgCount); + int expectedEntities = -1; for (int i = 0; i < expectedMsgCount; ++i) { final ODataFeed manufacturers = (ODataFeed)requestBodyAndHeaders(endpoint, null, headers); @@ -346,8 +357,6 @@ public class Olingo2ComponentTest extends AbstractOlingo2TestSupport { } } - MockEndpoint mockEndpoint = getMockEndpoint("mock:producer-alreadyseen"); - mockEndpoint.expectedMessageCount(expectedMsgCount); mockEndpoint.assertIsSatisfied(); for (int i = 0; i < expectedMsgCount; ++i) { @@ -360,8 +369,7 @@ public class Olingo2ComponentTest extends AbstractOlingo2TestSupport { // First polled messages contained all the manufacturers // assertEquals(expectedEntities, set.getEntries().size()); - } - else { + } else { // // Subsequent messages should be empty // since the filterAlreadySeen property is true @@ -371,6 +379,49 @@ public class Olingo2ComponentTest extends AbstractOlingo2TestSupport { } } + /** + * Read entity set of the Manufacturers object and split the results + * into individual messages + */ + @Test + public void testConsumerReadSplitResults() throws Exception { + final Map<String, Object> headers = new HashMap<>(); + String endpoint = "olingo2://read/Manufacturers?consumer.splitResult=true"; + + int expectedMsgCount = 2; + MockEndpoint mockEndpoint = getMockEndpoint("mock:consumer-splitresult"); + mockEndpoint.expectedMessageCount(expectedMsgCount); + + final ODataFeed odataFeed = (ODataFeed)requestBodyAndHeaders(endpoint, null, headers); + assertNotNull(odataFeed); + + mockEndpoint.assertIsSatisfied(); + + // + // 2 individual messages in the exchange, + // each containing a different entity. + // + for (int i = 0; i < expectedMsgCount; ++i) { + Object body = mockEndpoint.getExchanges().get(i).getIn().getBody(); + assertTrue(body instanceof ODataEntry); + ODataEntry entry = (ODataEntry)body; + Map<String, Object> properties = entry.getProperties(); + assertNotNull(properties); + + Object name = properties.get("Name"); + assertNotNull(name); + switch(i) { + case 0: + assertEquals("Star Powered Racing", name); + break; + case 1: + assertEquals("Horse Powered Racing", name); + break; + default: + } + } + } + @Override protected RouteBuilder createRouteBuilder() throws Exception { return new RouteBuilder() { @@ -422,8 +473,9 @@ public class Olingo2ComponentTest extends AbstractOlingo2TestSupport { // // Consumer endpoint // - from("olingo2://read/Manufacturers?filterAlreadySeen=true&consumer.delay=2&consumer.sendEmptyMessageWhenIdle=true") - .to("mock:consumer-alreadyseen"); + from("olingo2://read/Manufacturers?filterAlreadySeen=true&consumer.delay=2&consumer.sendEmptyMessageWhenIdle=true&consumer.splitResult=false").to("mock:consumer-alreadyseen"); + + from("olingo2://read/Manufacturers?consumer.splitResult=true").to("mock:consumer-splitresult"); } }; } diff --git a/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Consumer.java b/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Consumer.java index eedc0ed..4cee0a5 100644 --- a/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Consumer.java +++ b/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Consumer.java @@ -16,7 +16,9 @@ */ package org.apache.camel.component.olingo4; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import org.apache.camel.Exchange; @@ -27,7 +29,11 @@ import org.apache.camel.component.olingo4.internal.Olingo4ApiName; import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.component.AbstractApiConsumer; import org.apache.camel.util.component.ApiConsumerHelper; +import org.apache.olingo.client.api.domain.ClientEntity; import org.apache.olingo.client.api.domain.ClientEntitySet; +import org.apache.olingo.client.api.domain.ClientValue; +import org.apache.olingo.client.core.domain.ClientPrimitiveValueImpl; +import org.apache.olingo.client.core.domain.ClientPropertyImpl; /** * The Olingo4 consumer. @@ -131,4 +137,29 @@ public class Olingo4Consumer extends AbstractApiConsumer<Olingo4ApiName, Olingo4 resultIndex.index(result); } + + @Override + public Object splitResult(Object result) { + List<Object> splitResult = new ArrayList<>(); + + if (result instanceof ClientEntitySet) { + ClientEntitySet entitySet = (ClientEntitySet) result; + for (ClientEntity entity : entitySet.getEntities()) { + // + // If $count has been set to true then this value is left behind + // on the ClientEntitySet. Therefore, append it to each result. + // + if (entitySet.getCount() != null) { + ClientValue value = new ClientPrimitiveValueImpl.BuilderImpl() + .buildInt32(entitySet.getCount()); + entity.getProperties().add(new ClientPropertyImpl("ResultCount", value)); + } + splitResult.add(entity); + } + } else if (result instanceof ClientEntity) { + splitResult.add(result); + } + + return splitResult; + } } diff --git a/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Index.java b/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Index.java index a5f7694..c00adbb 100644 --- a/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Index.java +++ b/components/camel-olingo4/camel-olingo4-component/src/main/java/org/apache/camel/component/olingo4/Olingo4Index.java @@ -1,11 +1,12 @@ -/* - * Copyright (C) 2016 Red Hat, Inc. +/** + * 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 * - * Licensed 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 + * 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, @@ -94,7 +95,7 @@ public class Olingo4Index { } } - @SuppressWarnings( "unchecked" ) + @SuppressWarnings("unchecked") public Object filterResponse(Object response) { if (response instanceof ClientEntitySet) { response = filter((ClientEntitySet) response); diff --git a/components/camel-olingo4/camel-olingo4-component/src/test/java/org/apache/camel/component/olingo4/Olingo4ComponentTest.java b/components/camel-olingo4/camel-olingo4-component/src/test/java/org/apache/camel/component/olingo4/Olingo4ComponentTest.java index fd34bdb..dfafcbe 100644 --- a/components/camel-olingo4/camel-olingo4-component/src/test/java/org/apache/camel/component/olingo4/Olingo4ComponentTest.java +++ b/components/camel-olingo4/camel-olingo4-component/src/test/java/org/apache/camel/component/olingo4/Olingo4ComponentTest.java @@ -32,6 +32,7 @@ import org.apache.olingo.client.api.domain.ClientComplexValue; import org.apache.olingo.client.api.domain.ClientEntity; import org.apache.olingo.client.api.domain.ClientEntitySet; import org.apache.olingo.client.api.domain.ClientPrimitiveValue; +import org.apache.olingo.client.api.domain.ClientProperty; import org.apache.olingo.client.api.domain.ClientServiceDocument; import org.apache.olingo.commons.api.Constants; import org.apache.olingo.commons.api.edm.Edm; @@ -301,19 +302,26 @@ public class Olingo4ComponentTest extends AbstractOlingo4TestSupport { * and filter already seen items on subsequent exchanges * Use a delay since the mock endpoint does not always get * the correct number of exchanges before being satisfied. + * + * Note: + * - consumer.splitResults is set to false since this ensures the first returned message + * contains all the results. This is preferred for the purposes of this test. The default + * will mean the first n messages contain the results (where n is the result total) then + * subsequent messages will be empty */ @Test public void testConsumerReadFilterAlreadySeen() throws Exception { final Map<String, Object> headers = new HashMap<>(); - String endpoint = "olingo4://read/People?filterAlreadySeen=true&consumer.delay=2&consumer.sendEmptyMessageWhenIdle=true"; + String endpoint = "olingo4://read/People?filterAlreadySeen=true&consumer.delay=2&consumer.sendEmptyMessageWhenIdle=true&consumer.splitResult=false"; int expectedEntities = 20; + int expectedMsgCount = 3; + MockEndpoint mockEndpoint = getMockEndpoint("mock:consumer-alreadyseen"); + mockEndpoint.expectedMessageCount(expectedMsgCount); + final ClientEntitySet entities = (ClientEntitySet)requestBodyAndHeaders(endpoint, null, headers); assertNotNull(entities); assertEquals(expectedEntities, entities.getEntities().size()); - int expectedMsgCount = 3; - MockEndpoint mockEndpoint = getMockEndpoint("mock:consumer-alreadyseen"); - mockEndpoint.expectedMessageCount(expectedMsgCount); mockEndpoint.assertIsSatisfied(); for (int i = 0; i < expectedMsgCount; ++i) { @@ -326,8 +334,7 @@ public class Olingo4ComponentTest extends AbstractOlingo4TestSupport { assertTrue(body instanceof ClientEntitySet); ClientEntitySet set = (ClientEntitySet) body; assertEquals(expectedEntities, set.getEntities().size()); - } - else { + } else { // // Subsequent polling messages should be empty // since the filterAlreadySeen property is true @@ -352,13 +359,14 @@ public class Olingo4ComponentTest extends AbstractOlingo4TestSupport { int expectedEntities = 20; int expectedMsgCount = 3; + MockEndpoint mockEndpoint = getMockEndpoint("mock:producer-noalreadyseen"); + mockEndpoint.expectedMessageCount(expectedMsgCount); + for (int i = 0; i < expectedMsgCount; ++i) { final ClientEntitySet entities = (ClientEntitySet)requestBodyAndHeaders(endpoint, null, headers); assertNotNull(entities); } - MockEndpoint mockEndpoint = getMockEndpoint("mock:producer-noalreadyseen"); - mockEndpoint.expectedMessageCount(expectedMsgCount); mockEndpoint.assertIsSatisfied(); for (int i = 0; i < expectedMsgCount; ++i) { @@ -384,13 +392,14 @@ public class Olingo4ComponentTest extends AbstractOlingo4TestSupport { int expectedEntities = 20; int expectedMsgCount = 3; + MockEndpoint mockEndpoint = getMockEndpoint("mock:producer-alreadyseen"); + mockEndpoint.expectedMessageCount(expectedMsgCount); + for (int i = 0; i < expectedMsgCount; ++i) { final ClientEntitySet entities = (ClientEntitySet)requestBodyAndHeaders(endpoint, null, headers); assertNotNull(entities); } - MockEndpoint mockEndpoint = getMockEndpoint("mock:producer-alreadyseen"); - mockEndpoint.expectedMessageCount(expectedMsgCount); mockEndpoint.assertIsSatisfied(); for (int i = 0; i < expectedMsgCount; ++i) { @@ -403,8 +412,7 @@ public class Olingo4ComponentTest extends AbstractOlingo4TestSupport { // First polled messages contained all the entities // assertEquals(expectedEntities, set.getEntities().size()); - } - else { + } else { // // Subsequent messages should be empty // since the filterAlreadySeen property is true @@ -414,6 +422,51 @@ public class Olingo4ComponentTest extends AbstractOlingo4TestSupport { } } + /** + * Read entity set of the People object and split the results + * into individual messages + */ + @Test + public void testConsumerReadSplitResults() throws Exception { + final Map<String, Object> headers = new HashMap<>(); + String endpoint = "olingo4://read/People?consumer.splitResult=true"; + int expectedEntities = 20; + + int expectedMsgCount = 3; + MockEndpoint mockEndpoint = getMockEndpoint("mock:consumer-splitresult"); + mockEndpoint.expectedMinimumMessageCount(expectedMsgCount); + + final ClientEntitySet entities = (ClientEntitySet)requestBodyAndHeaders(endpoint, null, headers); + assertNotNull(entities); + assertEquals(expectedEntities, entities.getEntities().size()); + + mockEndpoint.assertIsSatisfied(); + // + // At least 3 individual messages in the exchange, + // each containing a different entity. + // + for (int i = 0; i < expectedMsgCount; ++i) { + Object body = mockEndpoint.getExchanges().get(i).getIn().getBody(); + assertTrue(body instanceof ClientEntity); + ClientEntity entity = (ClientEntity)body; + ClientProperty nameProperty = entity.getProperty("UserName"); + assertNotNull(nameProperty); + + switch(i) { + case 0: + assertEquals("russellwhyte", nameProperty.getValue().toString()); + break; + case 1: + assertEquals("scottketchum", nameProperty.getValue().toString()); + break; + case 2: + assertEquals("ronaldmundy", nameProperty.getValue().toString()); + break; + default: + } + } + } + @Override protected RouteBuilder createRouteBuilder() throws Exception { return new RouteBuilder() { @@ -459,18 +512,19 @@ public class Olingo4ComponentTest extends AbstractOlingo4TestSupport { from("direct:delete-with-etag").to("olingo4://delete/Airlines('AA')"); from("direct:read-people-nofilterseen") - .to("olingo4://read/People") - .to("mock:producer-noalreadyseen"); + .to("olingo4://read/People") + .to("mock:producer-noalreadyseen"); from("direct:read-people-filterseen") - .to("olingo4://read/People?filterAlreadySeen=true") - .to("mock:producer-alreadyseen"); + .to("olingo4://read/People?filterAlreadySeen=true") + .to("mock:producer-alreadyseen"); // // Consumer endpoint // - from("olingo4://read/People?filterAlreadySeen=true&consumer.delay=2&consumer.sendEmptyMessageWhenIdle=true") - .to("mock:consumer-alreadyseen"); + from("olingo4://read/People?filterAlreadySeen=true&consumer.delay=2&consumer.sendEmptyMessageWhenIdle=true&consumer.splitResult=false").to("mock:consumer-alreadyseen"); + + from("olingo4://read/People?consumer.splitResult=true").to("mock:consumer-splitresult"); } }; }