Repository: camel Updated Branches: refs/heads/master b77de5f41 -> fc447e8ba
CAMEL-8396 Update Salesforce component to support new REST APIs in Salesforce API V33.0 This commit adds support for the Organization Limits Salesforce API[1]. New operation `limit` was added and can be used like: ...to("salesforce:limit") .choice() .when( simple("${body.dailyApiRequests.remaining} > 0") )... .endChoice(); Supports all usage limits currently returned with v38.0 Salesforce API. Adding of new usage limits is performed by adding enum constant to Limits.Operation and corresponding getter to Limits class. [1] https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_limits.htm Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/af150675 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/af150675 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/af150675 Branch: refs/heads/master Commit: af150675aa2f436c57c30cc1c5373fbef240e8b1 Parents: b77de5f Author: Zoran Regvart <zo...@regvart.com> Authored: Thu Nov 10 17:57:11 2016 +0100 Committer: Claus Ibsen <davscl...@apache.org> Committed: Tue Nov 22 10:07:49 2016 +0100 ---------------------------------------------------------------------- .../component/salesforce/api/dto/Limits.java | 276 +++++++++++++++++++ .../salesforce/internal/OperationName.java | 5 +- .../internal/client/DefaultRestClient.java | 10 + .../salesforce/internal/client/RestClient.java | 7 + .../processor/AbstractRestProcessor.java | 7 + .../internal/processor/JsonRestProcessor.java | 6 + .../salesforce/LimitsIntegrationTest.java | 97 +++++++ .../salesforce/api/dto/LimitsTest.java | 87 ++++++ .../component/salesforce/api/dto/limits.json | 94 +++++++ 9 files changed, 588 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/af150675/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/Limits.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/Limits.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/Limits.java new file mode 100644 index 0000000..20f7c15 --- /dev/null +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/dto/Limits.java @@ -0,0 +1,276 @@ +/** + * 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.camel.component.salesforce.api.dto; + +import java.io.IOException; +import java.io.Serializable; +import java.util.Map; +import java.util.stream.Collectors; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +import org.apache.camel.component.salesforce.api.dto.Limits.LimitsDeserializer; + +/** + * Data given by the `Limits` resource on Salesforce. + * + * @see <a href= "https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_limits.htm"> + * https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_limits.htm</a> + */ +@JsonDeserialize(using = LimitsDeserializer.class) +public final class Limits implements Serializable { + + public static final class LimitsDeserializer extends JsonDeserializer { + + private static final TypeReference<Map<Operation, Usage>> USAGES_TYPE = new TypeReference<Map<Operation, Usage>>() { + }; + + @Override + public Object deserialize(final JsonParser parser, final DeserializationContext context) + throws IOException, JsonProcessingException { + + final Map<Operation, Usage> usages = parser.readValueAs(USAGES_TYPE); + + return new Limits(usages); + } + + } + + public enum Operation { + ConcurrentAsyncGetReportInstances, + ConcurrentSyncReportRuns, + DailyApiRequests, + DailyAsyncApexExecutions, + DailyBulkApiRequests, + DailyDurableGenericStreamingApiEvents, + DailyDurableStreamingApiEvents, + DailyGenericStreamingApiEvents, + DailyStreamingApiEvents, + DailyWorkflowEmails, + DataStorageMB, + DurableStreamingApiConcurrentClients, + FileStorageMB, + HourlyAsyncReportRuns, + HourlyDashboardRefreshes, + HourlyDashboardResults, + HourlyDashboardStatuses, + HourlyODataCallout, + HourlySyncReportRuns, + HourlyTimeBasedWorkflow, + MassEmail, + SingleEmail, + StreamingApiConcurrentClients + } + + /** + * Encapsulates usage limits for single operation. + */ + public static final class Usage implements Serializable { + + private static final long serialVersionUID = 1L; + + private static final int UNKNOWN_VAL = Integer.MIN_VALUE; + + public static final Usage UNKNOWN = new Usage(UNKNOWN_VAL, UNKNOWN_VAL); + + private final int max; + + private final int remaining; + + @JsonCreator + Usage(@JsonProperty("Max") final int max, @JsonProperty("Remaining") final int remaining) { + this.max = max; + this.remaining = remaining; + } + + /** Maximum allowed by the limit */ + public int getMax() { + return max; + } + + /** Remaining invocations allowed */ + public int getRemaining() { + return remaining; + } + + public boolean isUnknown() { + return max == UNKNOWN_VAL && remaining == UNKNOWN_VAL; + } + + @Override + public String toString() { + if (max == UNKNOWN_VAL && remaining == UNKNOWN_VAL) { + return "Undefined"; + } + + return "Max: " + max + ", Remaining: " + remaining; + } + } + + private static final long serialVersionUID = 1L; + + private static final Usage UNDEFINED = new Usage(Usage.UNKNOWN_VAL, Usage.UNKNOWN_VAL); + + private final Map<Operation, Usage> usages; + + public Limits(final Map<Operation, Usage> usages) { + this.usages = usages; + } + + public Usage forOperation(final Operation operation) { + return usages.getOrDefault(operation, UNDEFINED); + } + + /** Concurrent REST API requests for results of asynchronous report runs */ + public Usage getConcurrentAsyncGetReportInstances() { + return forOperation(Operation.ConcurrentAsyncGetReportInstances); + } + + /** Concurrent synchronous report runs via REST API */ + public Usage getConcurrentSyncReportRuns() { + return forOperation(Operation.ConcurrentSyncReportRuns); + } + + /** Daily API calls */ + public Usage getDailyApiRequests() { + return forOperation(Operation.DailyApiRequests); + } + + /** Daily Batch Apex and future method executions */ + public Usage getDailyAsyncApexExecutions() { + return forOperation(Operation.DailyAsyncApexExecutions); + } + + /** Daily Bulk API calls */ + public Usage getDailyBulkApiRequests() { + return forOperation(Operation.DailyBulkApiRequests); + } + + /** + * Daily durable generic streaming events (if generic streaming is enabled for your organization) + */ + public Usage getDailyDurableGenericStreamingApiEvents() { + return forOperation(Operation.DailyDurableGenericStreamingApiEvents); + } + + /** + * Daily durable streaming events (if generic streaming is enabled for your organization) + */ + public Usage getDailyDurableStreamingApiEvents() { + return forOperation(Operation.DailyDurableStreamingApiEvents); + } + + /** + * Daily generic streaming events (if generic streaming is enabled for your organization) + */ + public Usage getDailyGenericStreamingApiEvents() { + return forOperation(Operation.DailyGenericStreamingApiEvents); + } + + /** Daily Streaming API events */ + public Usage getDailyStreamingApiEvents() { + return forOperation(Operation.DailyStreamingApiEvents); + } + + /** Daily workflow emails */ + public Usage getDailyWorkflowEmails() { + return forOperation(Operation.DailyWorkflowEmails); + } + + /** Data storage (MB) */ + public Usage getDataStorageMB() { + return forOperation(Operation.DataStorageMB); + } + + /** Streaming API concurrent clients */ + public Usage getDurableStreamingApiConcurrentClients() { + return forOperation(Operation.DurableStreamingApiConcurrentClients); + } + + /** File storage (MB) */ + public Usage getFileStorageMB() { + return forOperation(Operation.FileStorageMB); + } + + /** Hourly asynchronous report runs via REST API */ + public Usage getHourlyAsyncReportRuns() { + return forOperation(Operation.HourlyAsyncReportRuns); + } + + /** Hourly dashboard refreshes via REST API */ + public Usage getHourlyDashboardRefreshes() { + return forOperation(Operation.HourlyDashboardRefreshes); + } + + /** Hourly REST API requests for dashboard results */ + public Usage getHourlyDashboardResults() { + return forOperation(Operation.HourlyDashboardResults); + } + + /** Hourly dashboard status requests via REST API */ + public Usage getHourlyDashboardStatuses() { + return forOperation(Operation.HourlyDashboardStatuses); + } + + /** Hourly OData callouts */ + public Usage getHourlyODataCallout() { + return forOperation(Operation.HourlyODataCallout); + } + + /** Hourly synchronous report runs via REST API */ + public Usage getHourlySyncReportRuns() { + return forOperation(Operation.HourlySyncReportRuns); + } + + /** Hourly workflow time triggers */ + public Usage getHourlyTimeBasedWorkflow() { + return forOperation(Operation.HourlyTimeBasedWorkflow); + } + + /** + * Daily number of mass emails that are sent to external email addresses by using Apex or Force.com APIs + */ + public Usage getMassEmail() { + return forOperation(Operation.MassEmail); + } + + /** + * Daily number of single emails that are sent to external email addresses by using Apex or Force.com APIs + */ + public Usage getSingleEmail() { + return forOperation(Operation.SingleEmail); + } + + /** Durable streaming API concurrent clients */ + public Usage getStreamingApiConcurrentClients() { + return forOperation(Operation.StreamingApiConcurrentClients); + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return "Limits: " + usages.entrySet().stream().map(e -> e.getKey() + ": " + e.getValue()) + .collect(Collectors.joining(", ")); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/af150675/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/OperationName.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/OperationName.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/OperationName.java index 6107750..15fdf0b 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/OperationName.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/OperationName.java @@ -58,7 +58,10 @@ public enum OperationName { EXECUTE_SYNCREPORT("executeSyncReport"), EXECUTE_ASYNCREPORT("executeAsyncReport"), GET_REPORT_INSTANCES("getReportInstances"), - GET_REPORT_RESULTS("getReportResults"); + GET_REPORT_RESULTS("getReportResults"), + + // limits API + LIMITS("limits"); private final String value; http://git-wip-us.apache.org/repos/asf/camel/blob/af150675/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultRestClient.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultRestClient.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultRestClient.java index f39673b..076b3fd 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultRestClient.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultRestClient.java @@ -405,6 +405,16 @@ public class DefaultRestClient extends AbstractClientBase implements RestClient return instanceUrl + SERVICES_APEXREST + apexUrl; } + @Override + public void limits(final ResponseCallback responseCallback) { + final Request get = getRequest(HttpMethod.GET, versionUrl() + "limits/"); + + // requires authorization token + setAccessToken(get); + + doHttpRequest(get, new DelegatingClientCallback(responseCallback)); + } + private String servicesDataUrl() { return instanceUrl + SERVICES_DATA; } http://git-wip-us.apache.org/repos/asf/camel/blob/af150675/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/RestClient.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/RestClient.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/RestClient.java index af0a2a7..470aa33 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/RestClient.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/RestClient.java @@ -193,4 +193,11 @@ public interface RestClient { */ void apexCall(String httpMethod, String apexUrl, Map<String, Object> queryParams, InputStream requestDto, ResponseCallback callback); + + /** + * Fetches Organization Limits. + * + * @param responseCallback {@link ResponseCallback} to handle response or exception + */ + void limits(ResponseCallback responseCallback); } http://git-wip-us.apache.org/repos/asf/camel/blob/af150675/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java index d487235..35e0aff 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java @@ -152,6 +152,9 @@ public abstract class AbstractRestProcessor extends AbstractSalesforceProcessor case APEX_CALL: processApexCall(exchange, callback); break; + case LIMITS: + processLimits(exchange, callback); + break; default: throw new SalesforceException("Unknown operation name: " + operationName.value(), null); } @@ -561,6 +564,10 @@ public abstract class AbstractRestProcessor extends AbstractSalesforceProcessor return apexUrl; } + private void processLimits(Exchange exchange, AsyncCallback callback) { + restClient.limits((response, exception) -> processResponse(exchange, response, exception, callback)); + } + @SuppressWarnings("unchecked") private Map<String, Object> getQueryParams(Exchange exchange) { http://git-wip-us.apache.org/repos/asf/camel/blob/af150675/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/JsonRestProcessor.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/JsonRestProcessor.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/JsonRestProcessor.java index 4f97a83..7d26b8f 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/JsonRestProcessor.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/JsonRestProcessor.java @@ -33,6 +33,7 @@ import org.apache.camel.component.salesforce.api.SalesforceException; import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase; import org.apache.camel.component.salesforce.api.dto.CreateSObjectResult; import org.apache.camel.component.salesforce.api.dto.GlobalObjects; +import org.apache.camel.component.salesforce.api.dto.Limits; import org.apache.camel.component.salesforce.api.dto.RestResources; import org.apache.camel.component.salesforce.api.dto.SObjectBasicInfo; import org.apache.camel.component.salesforce.api.dto.SObjectDescription; @@ -104,6 +105,11 @@ public class JsonRestProcessor extends AbstractRestProcessor { }); break; + case LIMITS: + // handle known response type + exchange.setProperty(RESPONSE_CLASS, Limits.class); + break; + default: // ignore, some operations do not require response class or type } http://git-wip-us.apache.org/repos/asf/camel/blob/af150675/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/LimitsIntegrationTest.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/LimitsIntegrationTest.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/LimitsIntegrationTest.java new file mode 100644 index 0000000..ed99818 --- /dev/null +++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/LimitsIntegrationTest.java @@ -0,0 +1,97 @@ +/** + * 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.camel.component.salesforce; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.salesforce.api.dto.Limits; +import org.apache.camel.component.salesforce.api.dto.Limits.Usage; +import org.junit.Test; + +public class LimitsIntegrationTest extends AbstractSalesforceTestBase { + + private static final Object NOT_USED = null; + + @Test + public void shouldFetchLimitsForOrganization() { + final Limits limits = template.requestBody("direct:test-limits", NOT_USED, Limits.class); + + assertNotNull("Should fetch limits from Salesforce REST API", limits); + + assertLimitIsFetched("ConcurrentAsyncGetReportInstances", limits.getConcurrentAsyncGetReportInstances()); + + assertLimitIsFetched("ConcurrentSyncReportRuns", limits.getConcurrentSyncReportRuns()); + + assertLimitIsFetched("DailyApiRequests", limits.getDailyApiRequests()); + + assertLimitIsFetched("DailyAsyncApexExecutions", limits.getDailyAsyncApexExecutions()); + + assertLimitIsFetched("DailyBulkApiRequests", limits.getDailyBulkApiRequests()); + + assertLimitIsFetched("DailyDurableGenericStreamingApiEvents", + limits.getDailyDurableGenericStreamingApiEvents()); + + assertLimitIsFetched("DailyDurableStreamingApiEvents", limits.getDailyDurableStreamingApiEvents()); + + assertLimitIsFetched("DailyGenericStreamingApiEvents", limits.getDailyGenericStreamingApiEvents()); + + assertLimitIsFetched("DailyStreamingApiEvents", limits.getDailyStreamingApiEvents()); + + assertLimitIsFetched("DailyWorkflowEmails", limits.getDailyWorkflowEmails()); + + assertLimitIsFetched("DataStorageMB", limits.getDataStorageMB()); + + assertLimitIsFetched("DurableStreamingApiConcurrentClients", limits.getDurableStreamingApiConcurrentClients()); + + assertLimitIsFetched("FileStorageMB", limits.getFileStorageMB()); + + assertLimitIsFetched("HourlyAsyncReportRuns", limits.getHourlyAsyncReportRuns()); + + assertLimitIsFetched("HourlyDashboardRefreshes", limits.getHourlyDashboardRefreshes()); + + assertLimitIsFetched("HourlyDashboardResults", limits.getHourlyDashboardResults()); + + assertLimitIsFetched("HourlyDashboardStatuses", limits.getHourlyDashboardStatuses()); + + assertLimitIsFetched("HourlyODataCallout", limits.getHourlyODataCallout()); + + assertLimitIsFetched("HourlySyncReportRuns", limits.getHourlySyncReportRuns()); + + assertLimitIsFetched("HourlyTimeBasedWorkflow", limits.getHourlyTimeBasedWorkflow()); + + assertLimitIsFetched("MassEmail", limits.getMassEmail()); + + assertLimitIsFetched("SingleEmail", limits.getSingleEmail()); + + assertLimitIsFetched("StreamingApiConcurrentClients", limits.getStreamingApiConcurrentClients()); + } + + private static void assertLimitIsFetched(String property, Usage usage) { + assertNotNull("Usage for `" + property + "` should be defined", usage); + assertNotEquals("Max usage for `" + property + "` should be defined", 0, usage.getMax()); + assertNotEquals("Remaining usage for `" + property + "` should be defined", 0, usage.getRemaining()); + } + + @Override + protected RouteBuilder doCreateRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:test-limits").to("salesforce:limits"); + } + }; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/af150675/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/api/dto/LimitsTest.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/api/dto/LimitsTest.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/api/dto/LimitsTest.java new file mode 100644 index 0000000..6b7b0d3 --- /dev/null +++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/api/dto/LimitsTest.java @@ -0,0 +1,87 @@ +/** + * 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.camel.component.salesforce.api.dto; + +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.apache.camel.component.salesforce.api.dto.Limits.Usage; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.core.IsInstanceOf.instanceOf; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +public class LimitsTest { + + @Test + public void shouldBeKnownIfDefined() { + assertFalse("Known usage must not declare itself as unknown", new Usage(1, 2).isUnknown()); + } + + @Test + public void shouldDeserializeFromSalesforceGeneratedJSON() throws JsonProcessingException, IOException { + final ObjectMapper mapper = new ObjectMapper(); + + final Object read = mapper.readerFor(Limits.class) + .readValue(LimitsTest.class.getResource("/org/apache/camel/component/salesforce/api/dto/limits.json")); + + assertThat("Limits should be parsed from JSON", read, instanceOf(Limits.class)); + + final Limits limits = (Limits) read; + + assertFalse("Should have some usage present", limits.getDailyApiRequests().isUnknown()); + } + + @Test + public void usageShouldBeUnknownIfUnknown() { + assertTrue("Unknown usage must declare itself as such", Usage.UNKNOWN.isUnknown()); + } + + @Test + public void shouldSupportGettingAllDefinedUsages() throws IntrospectionException { + BeanInfo beanInfo = Introspector.getBeanInfo(Limits.class); + + PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); + + Set<String> found = new HashSet<>(); + for (PropertyDescriptor descriptor : propertyDescriptors) { + found.add(descriptor.getName()); + } + + Set<String> defined = Arrays.stream(Limits.Operation.values()).map(Limits.Operation::name) + .map(Introspector::decapitalize).collect(Collectors.toSet()); + + defined.removeAll(found); + + assertThat("All operations declared in Operation enum should have it's corresponding getter", defined, + is(Collections.emptySet())); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/af150675/components/camel-salesforce/camel-salesforce-component/src/test/resources/org/apache/camel/component/salesforce/api/dto/limits.json ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/resources/org/apache/camel/component/salesforce/api/dto/limits.json b/components/camel-salesforce/camel-salesforce-component/src/test/resources/org/apache/camel/component/salesforce/api/dto/limits.json new file mode 100644 index 0000000..c355c74 --- /dev/null +++ b/components/camel-salesforce/camel-salesforce-component/src/test/resources/org/apache/camel/component/salesforce/api/dto/limits.json @@ -0,0 +1,94 @@ +{ + "ConcurrentAsyncGetReportInstances" : { + "Max" : 200, + "Remaining" : 200 + }, + "ConcurrentSyncReportRuns" : { + "Max" : 20, + "Remaining" : 20 + }, + "DailyApiRequests" : { + "Max" : 15000, + "Remaining" : 14998 + }, + "DailyAsyncApexExecutions" : { + "Max" : 250000, + "Remaining" : 250000 + }, + "DailyBulkApiRequests" : { + "Max" : 5000, + "Remaining" : 5000 + }, + "DailyDurableGenericStreamingApiEvents" : { + "Max" : 10000, + "Remaining" : 10000 + }, + "DailyDurableStreamingApiEvents" : { + "Max" : 10000, + "Remaining" : 10000 + }, + "DailyGenericStreamingApiEvents" : { + "Max" : 10000, + "Remaining" : 10000 + }, + "DailyStreamingApiEvents" : { + "Max" : 10000, + "Remaining" : 10000 + }, + "DailyWorkflowEmails" : { + "Max" : 390, + "Remaining" : 390 + }, + "DataStorageMB" : { + "Max" : 5, + "Remaining" : 5 + }, + "DurableStreamingApiConcurrentClients" : { + "Max" : 20, + "Remaining" : 20 + }, + "FileStorageMB" : { + "Max" : 20, + "Remaining" : 20 + }, + "HourlyAsyncReportRuns" : { + "Max" : 1200, + "Remaining" : 1200 + }, + "HourlyDashboardRefreshes" : { + "Max" : 200, + "Remaining" : 200 + }, + "HourlyDashboardResults" : { + "Max" : 5000, + "Remaining" : 5000 + }, + "HourlyDashboardStatuses" : { + "Max" : 999999999, + "Remaining" : 999999999 + }, + "HourlyODataCallout" : { + "Remaining" : 9999, + "Max" : 10000 + }, + "HourlySyncReportRuns" : { + "Max" : 500, + "Remaining" : 500 + }, + "HourlyTimeBasedWorkflow" : { + "Max" : 50, + "Remaining" : 50 + }, + "MassEmail" : { + "Max" : 10, + "Remaining" : 10 + }, + "SingleEmail" : { + "Max" : 15, + "Remaining" : 15 + }, + "StreamingApiConcurrentClients" : { + "Max" : 20, + "Remaining" : 20 + } +} \ No newline at end of file