/** * 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.Collections; import java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import com.fasterxml.jackson.annotation.JsonAnySetter; 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.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import org.apache.camel.component.salesforce.api.TypeReferences; 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 { @Override public Object deserialize(final JsonParser parser, final DeserializationContext context) throws IOException, JsonProcessingException { final Map<Operation, Usage> usages = parser.readValueAs(TypeReferences.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; private final Map<String, Usage> perApplication = new HashMap<>(); @JsonCreator Usage(@JsonProperty("Max") final int max, @JsonProperty("Remaining") final int remaining) { this.max = max; this.remaining = remaining; } /** Returns {@link Usage} for application */ public Optional<Usage> forApplication(final String application) { return Optional.ofNullable(perApplication.get(application)); } /** Further per application usage. */ public Set<String> getApplications() { return perApplication.keySet(); } /** Maximum allowed by the limit */ public int getMax() { return max; } /** Returns usages per application */ public Map<String, Usage> getPerApplicationUsage() { return Collections.unmodifiableMap(perApplication); } /** 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 + ", per application: " + perApplication; } @JsonAnySetter void addApplicationUsage(final String application, final Usage usage) { perApplication.put(application, usage); } } 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(", ")); } }