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 <[email protected]>
Authored: Thu Nov 10 17:57:11 2016 +0100
Committer: Claus Ibsen <[email protected]>
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