- > {
private final Class
org.zendesk.client.v2.Zendesk Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of zendesk-java-client Show documentation
Show all versions of zendesk-java-client Show documentation
Java client for the Zendesk API
The newest version!
package org.zendesk.client.v2;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.util.StdDateFormat;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import org.asynchttpclient.AsyncCompletionHandler;
import org.asynchttpclient.AsyncHttpClient;
import org.asynchttpclient.DefaultAsyncHttpClient;
import org.asynchttpclient.DefaultAsyncHttpClientConfig;
import org.asynchttpclient.ListenableFuture;
import org.asynchttpclient.Realm;
import org.asynchttpclient.Request;
import org.asynchttpclient.RequestBuilder;
import org.asynchttpclient.Response;
import org.asynchttpclient.request.body.multipart.FilePart;
import org.asynchttpclient.request.body.multipart.StringPart;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zendesk.client.v2.model.AgentRole;
import org.zendesk.client.v2.model.Attachment;
import org.zendesk.client.v2.model.Audit;
import org.zendesk.client.v2.model.Automation;
import org.zendesk.client.v2.model.Brand;
import org.zendesk.client.v2.model.Comment;
import org.zendesk.client.v2.model.ComplianceDeletionStatus;
import org.zendesk.client.v2.model.CustomTicketStatus;
import org.zendesk.client.v2.model.DeletedTicket;
import org.zendesk.client.v2.model.Field;
import org.zendesk.client.v2.model.Forum;
import org.zendesk.client.v2.model.Group;
import org.zendesk.client.v2.model.GroupMembership;
import org.zendesk.client.v2.model.Identity;
import org.zendesk.client.v2.model.JiraLink;
import org.zendesk.client.v2.model.JobStatus;
import org.zendesk.client.v2.model.Locale;
import org.zendesk.client.v2.model.Macro;
import org.zendesk.client.v2.model.Metric;
import org.zendesk.client.v2.model.Organization;
import org.zendesk.client.v2.model.OrganizationField;
import org.zendesk.client.v2.model.OrganizationMembership;
import org.zendesk.client.v2.model.SatisfactionRating;
import org.zendesk.client.v2.model.SearchResultEntity;
import org.zendesk.client.v2.model.SortOrder;
import org.zendesk.client.v2.model.Status;
import org.zendesk.client.v2.model.SuspendedTicket;
import org.zendesk.client.v2.model.Ticket;
import org.zendesk.client.v2.model.TicketCount;
import org.zendesk.client.v2.model.TicketForm;
import org.zendesk.client.v2.model.TicketImport;
import org.zendesk.client.v2.model.TicketPage;
import org.zendesk.client.v2.model.TicketResult;
import org.zendesk.client.v2.model.TimeZone;
import org.zendesk.client.v2.model.Topic;
import org.zendesk.client.v2.model.Trigger;
import org.zendesk.client.v2.model.TwitterMonitor;
import org.zendesk.client.v2.model.User;
import org.zendesk.client.v2.model.UserField;
import org.zendesk.client.v2.model.UserRelatedInfo;
import org.zendesk.client.v2.model.View;
import org.zendesk.client.v2.model.dynamic.DynamicContentItem;
import org.zendesk.client.v2.model.dynamic.DynamicContentItemVariant;
import org.zendesk.client.v2.model.hc.Article;
import org.zendesk.client.v2.model.hc.ArticleAttachments;
import org.zendesk.client.v2.model.hc.Category;
import org.zendesk.client.v2.model.hc.ContentTag;
import org.zendesk.client.v2.model.hc.Locales;
import org.zendesk.client.v2.model.hc.PermissionGroup;
import org.zendesk.client.v2.model.hc.Section;
import org.zendesk.client.v2.model.hc.Subscription;
import org.zendesk.client.v2.model.hc.Translation;
import org.zendesk.client.v2.model.hc.UserSegment;
import org.zendesk.client.v2.model.schedules.Holiday;
import org.zendesk.client.v2.model.schedules.Schedule;
import org.zendesk.client.v2.model.targets.BasecampTarget;
import org.zendesk.client.v2.model.targets.CampfireTarget;
import org.zendesk.client.v2.model.targets.EmailTarget;
import org.zendesk.client.v2.model.targets.PivotalTarget;
import org.zendesk.client.v2.model.targets.Target;
import org.zendesk.client.v2.model.targets.TwitterTarget;
import org.zendesk.client.v2.model.targets.UrlTarget;
/**
* @author stephenc
* @since 04/04/2013 13:08
*/
public class Zendesk implements Closeable {
private static final String JSON = "application/json; charset=UTF-8";
private static final String USER_AGENT_HEADER = "User-Agent";
private static final DefaultAsyncHttpClientConfig DEFAULT_ASYNC_HTTP_CLIENT_CONFIG =
new DefaultAsyncHttpClientConfig.Builder().setFollowRedirect(true).build();
private final boolean closeClient;
private final AsyncHttpClient client;
private final Realm realm;
private final String url;
private final String oauthToken;
private final Map headers;
private final int cbpPageSize;
private final ObjectMapper mapper;
private final Logger logger;
private boolean closed = false;
private static final Map> searchResultTypes =
searchResultTypes();
private static final Map> targetTypes = targetTypes();
private static Map> searchResultTypes() {
Map> result = new HashMap<>();
result.put("ticket", Ticket.class);
result.put("user", User.class);
result.put("group", Group.class);
result.put("organization", Organization.class);
result.put("topic", Topic.class);
result.put("article", Article.class);
return Collections.unmodifiableMap(result);
}
private static Map> targetTypes() {
Map> result = new HashMap<>();
result.put("url_target", UrlTarget.class);
result.put("email_target", EmailTarget.class);
result.put("basecamp_target", BasecampTarget.class);
result.put("campfire_target", CampfireTarget.class);
result.put("pivotal_target", PivotalTarget.class);
result.put("twitter_target", TwitterTarget.class);
// TODO: Implement other Target types
// result.put("clickatell_target", ClickatellTarget.class);
// result.put("flowdock_target", FlowdockTarget.class);
// result.put("get_satisfaction_target", GetSatisfactionTarget.class);
// result.put("yammer_target", YammerTarget.class);
return Collections.unmodifiableMap(result);
}
private Zendesk(
AsyncHttpClient client,
String url,
String username,
String password,
Map headers,
int cbpPageSize) {
this.logger = LoggerFactory.getLogger(Zendesk.class);
this.closeClient = client == null;
this.oauthToken = null;
this.client =
client == null ? new DefaultAsyncHttpClient(DEFAULT_ASYNC_HTTP_CLIENT_CONFIG) : client;
this.url = url.endsWith("/") ? url + "api/v2" : url + "/api/v2";
if (username != null) {
this.realm =
new Realm.Builder(username, password)
.setScheme(Realm.AuthScheme.BASIC)
.setUsePreemptiveAuth(true)
.build();
} else {
if (password != null) {
throw new IllegalStateException(
"Cannot specify token or password without specifying username");
}
this.realm = null;
}
headers.putIfAbsent(USER_AGENT_HEADER, new DefaultUserAgent().toString());
this.headers = Collections.unmodifiableMap(headers);
this.cbpPageSize = cbpPageSize;
this.mapper = createMapper();
}
private Zendesk(
AsyncHttpClient client,
String url,
String oauthToken,
Map headers,
int cbpPageSize) {
this.logger = LoggerFactory.getLogger(Zendesk.class);
this.closeClient = client == null;
this.realm = null;
this.client =
client == null ? new DefaultAsyncHttpClient(DEFAULT_ASYNC_HTTP_CLIENT_CONFIG) : client;
this.url = url.endsWith("/") ? url + "api/v2" : url + "/api/v2";
if (oauthToken != null) {
this.oauthToken = oauthToken;
} else {
throw new IllegalStateException(
"Cannot specify token or password without specifying username");
}
headers.putIfAbsent(USER_AGENT_HEADER, new DefaultUserAgent().toString());
this.headers = Collections.unmodifiableMap(headers);
this.cbpPageSize = cbpPageSize;
this.mapper = createMapper();
}
//////////////////////////////////////////////////////////////////////
// Closeable interface methods
//////////////////////////////////////////////////////////////////////
public boolean isClosed() {
return closed || client.isClosed();
}
public void close() {
if (closeClient && !client.isClosed()) {
try {
client.close();
} catch (IOException e) {
logger.warn("Unexpected error on client close", e);
}
}
closed = true;
}
//////////////////////////////////////////////////////////////////////
// Action methods
//////////////////////////////////////////////////////////////////////
public JobStatus getJobStatus(JobStatus status) {
return complete(getJobStatusAsync(status));
}
public ListenableFuture getJobStatusAsync(JobStatus status) {
return submit(
req("GET", tmpl("/job_statuses/{id}.json").set("id", status.getId())), handleJobStatus());
}
public List getJobStatuses(List statuses) {
return complete(getJobStatusesAsync(statuses));
}
public ListenableFuture> getJobStatusesAsync(List statuses) {
List ids = new ArrayList<>(statuses.size());
for (JobStatus status : statuses) {
ids.add(status.getId());
}
Class clazz = (Class) (Object) JobStatus.class;
return submit(
req("GET", tmpl("/job_statuses/show_many.json{?ids}").set("ids", ids)),
handleList(clazz, "job_statuses"));
}
public Iterable getBrands() {
return new PagedIterable<>(cbp("/brands.json"), handleList(Brand.class, "brands"));
}
public TicketForm getTicketForm(long id) {
return complete(
submit(
req("GET", tmpl("/ticket_forms/{id}.json").set("id", id)),
handle(TicketForm.class, "ticket_form")));
}
public List getTicketForms() {
return complete(
submit(
req("GET", cnst("/ticket_forms.json")), handleList(TicketForm.class, "ticket_forms")));
}
public TicketForm createTicketForm(TicketForm ticketForm) {
return complete(
submit(
req(
"POST",
cnst("/ticket_forms.json"),
JSON,
json(Collections.singletonMap("ticket_form", ticketForm))),
handle(TicketForm.class, "ticket_form")));
}
public TicketForm updateTicketForm(TicketForm ticketForm) {
checkHasId(ticketForm);
return complete(
submit(
req(
"PUT",
tmpl("/ticket_forms/{id}.json").set("id", ticketForm.getId()),
JSON,
json(Collections.singletonMap("ticket_form", ticketForm))),
handle(TicketForm.class, "ticket_form")));
}
public void deleteTicketForm(TicketForm ticketForm) {
checkHasId(ticketForm);
deleteTicketForm(ticketForm.getId());
}
public void deleteTicketForm(long id) {
complete(submit(req("DELETE", tmpl("/ticket_forms/{id}.json").set("id", id)), handleStatus()));
}
public Ticket importTicket(TicketImport ticketImport) {
return complete(
submit(
req(
"POST",
cnst("/imports/tickets.json"),
JSON,
json(Collections.singletonMap("ticket", ticketImport))),
handle(Ticket.class, "ticket")));
}
public JobStatus importTickets(TicketImport... ticketImports) {
return importTickets(Arrays.asList(ticketImports));
}
public JobStatus importTickets(List ticketImports) {
return complete(importTicketsAsync(ticketImports));
}
public ListenableFuture importTicketsAsync(List ticketImports) {
return submit(
req(
"POST",
cnst("/imports/tickets/create_many.json"),
JSON,
json(Collections.singletonMap("tickets", ticketImports))),
handleJobStatus());
}
public TicketCount getTicketsCount() {
return complete(
submit(req("GET", cnst("/tickets/count.json")), handle(TicketCount.class, "count")));
}
public TicketCount getTicketsCountForOrganization(long id) {
return complete(
submit(
req("GET", tmpl("/organizations/{id}/tickets/count.json").set("id", id)),
handle(TicketCount.class, "count")));
}
public TicketCount getCcdTicketsCountForUser(long id) {
return complete(
submit(
req("GET", tmpl("/users/{id}/tickets/ccd/count.json").set("id", id)),
handle(TicketCount.class, "count")));
}
public TicketCount getAssignedTicketsCountForUser(long id) {
return complete(
submit(
req("GET", tmpl("/users/{id}/tickets/assigned/count.json").set("id", id)),
handle(TicketCount.class, "count")));
}
public Ticket getTicket(long id) {
return complete(
submit(
req("GET", tmpl("/tickets/{id}.json").set("id", id)), handle(Ticket.class, "ticket")));
}
public Iterable getTicketIncidents(long id) {
return new PagedIterable<>(
cbp("/tickets/{id}/incidents.json").set("id", id), handleList(Ticket.class, "tickets"));
}
public List getTicketCollaborators(long id) {
return complete(
submit(
req("GET", tmpl("/tickets/{id}/collaborators.json").set("id", id)),
handleList(User.class, "users")));
}
/** https://developer.zendesk.com/rest_api/docs/support/tickets#list-deleted-tickets */
public Iterable getDeletedTickets() {
return new PagedIterable<>(
cbp("/deleted_tickets.json"), handleList(DeletedTicket.class, "deleted_tickets"));
}
/** https://developer.zendesk.com/rest_api/docs/support/tickets#list-deleted-tickets */
public Iterable getDeletedTickets(String sortBy, SortOrder sortOrder) {
return new PagedIterable<>(
tmpl("/deleted_tickets.json?sort_by={sortBy}&sort_order={sortOrder}")
.set("sortBy", sortBy)
.set("sortOrder", sortOrder.getQueryParameter()),
handleList(DeletedTicket.class, "deleted_tickets"));
}
public void deleteTicket(Ticket ticket) {
checkHasId(ticket);
deleteTicket(ticket.getId());
}
public void deleteTicket(long id) {
complete(submit(req("DELETE", tmpl("/tickets/{id}.json").set("id", id)), handleStatus()));
}
public JobStatus permanentlyDeleteTicket(Ticket ticket) {
checkHasId(ticket);
return permanentlyDeleteTicket(ticket.getId());
}
public JobStatus permanentlyDeleteTicket(long id) {
return complete(
submit(req("DELETE", tmpl("/deleted_tickets/{id}.json").set("id", id)), handleJobStatus()));
}
public ListenableFuture queueCreateTicketAsync(Ticket ticket) {
return submit(
req(
"POST",
cnst("/tickets.json?async=true"),
JSON,
json(Collections.singletonMap("ticket", ticket))),
handleJobStatus());
}
public ListenableFuture createTicketAsync(Ticket ticket) {
return submit(
req("POST", cnst("/tickets.json"), JSON, json(Collections.singletonMap("ticket", ticket))),
handle(Ticket.class, "ticket"));
}
public Ticket createTicket(Ticket ticket) {
return complete(createTicketAsync(ticket));
}
public JobStatus createTickets(Ticket... tickets) {
return createTickets(Arrays.asList(tickets));
}
public JobStatus createTickets(List tickets) {
return complete(createTicketsAsync(tickets));
}
public ListenableFuture createTicketsAsync(List tickets) {
return submit(
req(
"POST",
cnst("/tickets/create_many.json"),
JSON,
json(Collections.singletonMap("tickets", tickets))),
handleJobStatus());
}
public Ticket updateTicket(Ticket ticket) {
checkHasId(ticket);
return complete(
submit(
req(
"PUT",
tmpl("/tickets/{id}.json").set("id", ticket.getId()),
JSON,
json(Collections.singletonMap("ticket", ticket))),
handle(Ticket.class, "ticket")));
}
public JobStatus updateTickets(Ticket... tickets) {
return updateTickets(Arrays.asList(tickets));
}
public JobStatus updateTickets(List tickets) {
return complete(updateTicketsAsync(tickets));
}
public ListenableFuture updateTicketsAsync(List tickets) {
return submit(
req(
"PUT",
cnst("/tickets/update_many.json"),
JSON,
json(Collections.singletonMap("tickets", tickets))),
handleJobStatus());
}
public void markTicketAsSpam(Ticket ticket) {
checkHasId(ticket);
markTicketAsSpam(ticket.getId());
}
public void markTicketAsSpam(long id) {
complete(
submit(req("PUT", tmpl("/tickets/{id}/mark_as_spam.json").set("id", id)), handleStatus()));
}
public JobStatus deleteTickets(long id, long... ids) {
return complete(
submit(
req("DELETE", tmpl("/tickets/destroy_many.json{?ids}").set("ids", idArray(id, ids))),
handleJobStatus()));
}
public JobStatus permanentlyDeleteTickets(long id, long... ids) {
return complete(
submit(
req(
"DELETE",
tmpl("/deleted_tickets/destroy_many.json{?ids}").set("ids", idArray(id, ids))),
handleJobStatus()));
}
public Iterable getTickets() {
return new PagedIterable<>(cbp("/tickets.json"), handleList(Ticket.class, "tickets"));
}
/**
* @deprecated This API is no longer available from the vendor. Use the {@link
* #getTicketsFromSearch(String)} method instead
* @param ticketStatus
* @return
*/
@Deprecated
public Iterable getTicketsByStatus(Status... ticketStatus) {
return new PagedIterable<>(
tmpl("/tickets.json{?status}").set("status", statusArray(ticketStatus)),
handleList(Ticket.class, "tickets"));
}
public Iterable getTicketsByExternalId(String externalId, boolean includeArchived) {
Iterable results =
new PagedIterable<>(
tmpl("/tickets.json{?external_id}").set("external_id", externalId),
handleList(Ticket.class, "tickets"));
if (!includeArchived || results.iterator().hasNext()) {
return results;
}
return new PagedIterable<>(
tmpl("/search.json{?query}{&type}")
.set("query", "external_id:" + externalId)
.set("type", "ticket"),
handleList(Ticket.class, "results"));
}
public Iterable getTicketsByExternalId(String externalId) {
return getTicketsByExternalId(externalId, false);
}
public Iterable getTicketsFromSearch(String searchTerm) {
return new PagedIterable<>(
tmpl("/search.json{?query}").set("query", searchTerm + " type:ticket"),
handleList(Ticket.class, "results"));
}
public Iterable getArticleFromSearch(String searchTerm) {
return new PagedIterable<>(
tmpl("/help_center/articles/search.json{?query}").set("query", searchTerm),
handleList(Article.class, "results"));
}
public Iterable getArticleFromSearch(String searchTerm, Long sectionId) {
return new PagedIterable<>(
tmpl("/help_center/articles/search.json{?section,query}")
.set("query", searchTerm)
.set("section", sectionId),
handleList(Article.class, "results"));
}
public Iterable getArticlesFromAnyLabels(List labels) {
return new PagedIterable<>(
tmpl("/help_center/articles/search.json{?label_names}").set("label_names", labels),
handleList(Article.class, "results"));
}
public Iterable getArticlesFromAllLabels(List labels) {
return new PagedIterable<>(
tmpl("/help_center/en-us/articles.json{?label_names}").set("label_names", labels),
handleList(Article.class, "articles"));
}
public List getAttachmentsFromArticle(Long articleID) {
return complete(
submit(
req("GET", tmpl("/help_center/articles/{id}/attachments.json").set("id", articleID)),
handleArticleAttachmentsList("article_attachments")));
}
public List getTickets(long id, long... ids) {
return complete(
submit(
req("GET", tmpl("/tickets/show_many.json{?ids}").set("ids", idArray(id, ids))),
handleList(Ticket.class, "tickets")));
}
public Iterable getRecentTickets() {
return new PagedIterable<>(cnst("/tickets/recent.json"), handleList(Ticket.class, "tickets"));
}
/** https://developer.zendesk.com/rest_api/docs/support/incremental_export */
public Iterable getTicketsIncrementally(Date startTime) {
return new PagedIterable<>(
tmpl("/incremental/tickets.json{?start_time}")
.set("start_time", msToSeconds(startTime.getTime())),
handleIncrementalList(Ticket.class, "tickets"));
}
/**
* https://developer.zendesk.com/rest_api/docs/support/incremental_export
*
* @deprecated incremental export does not support an end_time parameter
*/
@Deprecated
public Iterable getTicketsIncrementally(Date startTime, Date endTime) {
return new PagedIterable<>(
tmpl("/incremental/tickets.json{?start_time,end_time}")
.set("start_time", msToSeconds(startTime.getTime()))
.set("end_time", msToSeconds(endTime.getTime())),
handleIncrementalList(Ticket.class, "tickets"));
}
public Iterable getOrganizationTickets(long organizationId) {
return new PagedIterable<>(
tmpl("/organizations/{organizationId}/tickets.json").set("organizationId", organizationId),
handleList(Ticket.class, "tickets"));
}
public Iterable getOrganizationRequests(
long organizationId) {
return new PagedIterable<>(
tmpl("/organizations/{organizationId}/requests.json").set("organizationId", organizationId),
handleList(org.zendesk.client.v2.model.Request.class, "requests"));
}
public Iterable getUserRequestedTickets(long userId) {
return new PagedIterable<>(
tmpl("/users/{userId}/tickets/requested.json").set("userId", userId),
handleList(Ticket.class, "tickets"));
}
public Iterable getComplianceDeletionStatuses(long userId) {
return new PagedIterable<>(
tmpl("/users/{userId}/compliance_deletion_statuses.json").set("userId", userId),
handleList(ComplianceDeletionStatus.class, "compliance_deletion_statuses"));
}
public Iterable getCustomTicketStatuses() {
return new PagedIterable<>(
tmpl("/custom_statuses.json"), handleList(CustomTicketStatus.class, "custom_statuses"));
}
public Iterable getUserCCDTickets(long userId) {
return new PagedIterable<>(
tmpl("/users/{userId}/tickets/ccd.json").set("userId", userId),
handleList(Ticket.class, "tickets"));
}
public UserRelatedInfo getUserRelatedInfo(long userId) {
return complete(
submit(
req("GET", tmpl("/users/{userId}/related.json").set("userId", userId)),
handle(UserRelatedInfo.class, "user_related")));
}
public Iterable getTicketMetrics() {
return new PagedIterable<>(
cbp("/ticket_metrics.json"), handleList(Metric.class, "ticket_metrics"));
}
public Metric getTicketMetricByTicket(long id) {
return complete(
submit(
req("GET", tmpl("/tickets/{ticketId}/metrics.json").set("ticketId", id)),
handle(Metric.class, "ticket_metric")));
}
public Metric getTicketMetric(long id) {
return complete(
submit(
req("GET", tmpl("/ticket_metrics/{ticketMetricId}.json").set("ticketMetricId", id)),
handle(Metric.class, "ticket_metric")));
}
public Iterable getTicketAudits(Ticket ticket) {
checkHasId(ticket);
return getTicketAudits(ticket.getId());
}
public Iterable getTicketAudits(Long id) {
return new PagedIterable<>(
cbp("/tickets/{ticketId}/audits.json").set("ticketId", id),
handleList(Audit.class, "audits"));
}
public Audit getTicketAudit(Ticket ticket, Audit audit) {
checkHasId(audit);
return getTicketAudit(ticket, audit.getId());
}
public Audit getTicketAudit(Ticket ticket, long id) {
checkHasId(ticket);
return getTicketAudit(ticket.getId(), id);
}
public Audit getTicketAudit(long ticketId, long auditId) {
return complete(
submit(
req(
"GET",
tmpl("/tickets/{ticketId}/audits/{auditId}.json")
.set("ticketId", ticketId)
.set("auditId", auditId)),
handle(Audit.class, "audit")));
}
public void trustTicketAudit(Ticket ticket, Audit audit) {
checkHasId(audit);
trustTicketAudit(ticket, audit.getId());
}
public void trustTicketAudit(Ticket ticket, long id) {
checkHasId(ticket);
trustTicketAudit(ticket.getId(), id);
}
public void trustTicketAudit(long ticketId, long auditId) {
complete(
submit(
req(
"PUT",
tmpl("/tickets/{ticketId}/audits/{auditId}/trust.json")
.set("ticketId", ticketId)
.set("auditId", auditId)),
handleStatus()));
}
public void makePrivateTicketAudit(Ticket ticket, Audit audit) {
checkHasId(audit);
makePrivateTicketAudit(ticket, audit.getId());
}
public void makePrivateTicketAudit(Ticket ticket, long id) {
checkHasId(ticket);
makePrivateTicketAudit(ticket.getId(), id);
}
public void makePrivateTicketAudit(long ticketId, long auditId) {
complete(
submit(
req(
"PUT",
tmpl("/tickets/{ticketId}/audits/{auditId}/make_private.json")
.set("ticketId", ticketId)
.set("auditId", auditId)),
handleStatus()));
}
public Iterable getTicketFields() {
return new PagedIterable<>(
cbp("/ticket_fields.json"), handleList(Field.class, "ticket_fields"));
}
public Field getTicketField(long id) {
return complete(
submit(
req("GET", tmpl("/ticket_fields/{id}.json").set("id", id)),
handle(Field.class, "ticket_field")));
}
public Field createTicketField(Field field) {
return complete(
submit(
req(
"POST",
cnst("/ticket_fields.json"),
JSON,
json(Collections.singletonMap("ticket_field", field))),
handle(Field.class, "ticket_field")));
}
public Field updateTicketField(Field field) {
checkHasId(field);
return complete(
submit(
req(
"PUT",
tmpl("/ticket_fields/{id}.json").set("id", field.getId()),
JSON,
json(Collections.singletonMap("ticket_field", field))),
handle(Field.class, "ticket_field")));
}
public void deleteTicketField(Field field) {
checkHasId(field);
deleteTicket(field.getId());
}
public void deleteTicketField(long id) {
complete(submit(req("DELETE", tmpl("/ticket_fields/{id}.json").set("id", id)), handleStatus()));
}
public Iterable getSuspendedTickets() {
return new PagedIterable<>(
cbp("/suspended_tickets.json"), handleList(SuspendedTicket.class, "suspended_tickets"));
}
/**
* Recover Multiple Suspended Tickets. Accepts
* up to 100 ticket ids.
*
* @throws IllegalArgumentException when the number of tickets exceeds 100
* @param tickets tickets to be recovered
* @return recovered tickets
*/
public Iterable recoverSuspendedTickets(List tickets) {
if (100 < tickets.size()) {
throw new IllegalArgumentException(
"This endpoint accepts up to 100 tickets. Provided "
+ tickets.size()
+ " tickets.\n"
+ "https://developer.zendesk.com/rest_api/docs/support/suspended_tickets#recover-multiple-suspended-tickets");
}
List ids = new ArrayList<>();
for (SuspendedTicket ticket : tickets) {
ids.add(ticket.getId());
}
return complete(
submit(
req("PUT", tmpl("/suspended_tickets/recover_many.json{?ids}").set("ids", ids)),
handleList(Ticket.class, "tickets")));
}
public void deleteSuspendedTicket(SuspendedTicket ticket) {
checkHasId(ticket);
deleteSuspendedTicket(ticket.getId());
}
public void deleteSuspendedTicket(long id) {
complete(
submit(req("DELETE", tmpl("/suspended_tickets/{id}.json").set("id", id)), handleStatus()));
}
public Attachment.Upload createUpload(String fileName, byte[] content) {
return createUpload(null, fileName, "application/binary", content);
}
public Attachment.Upload createUpload(String fileName, String contentType, byte[] content) {
return createUpload(null, fileName, contentType, content);
}
public Attachment.Upload createUpload(
String token, String fileName, String contentType, byte[] content) {
TemplateUri uri = tmpl("/uploads.json{?filename,token}").set("filename", fileName);
if (token != null) {
uri.set("token", token);
}
return complete(
submit(req("POST", uri, contentType, content), handle(Attachment.Upload.class, "upload")));
}
public void associateAttachmentsToArticle(String idArticle, List attachments) {
TemplateUri uri =
tmpl("/help_center/articles/{article_id}/bulk_attachments.json")
.set("article_id", idArticle);
List attachmentsIds = new ArrayList<>();
for (Attachment item : attachments) {
attachmentsIds.add(item.getId());
}
complete(
submit(
req(
"POST",
uri,
JSON,
json(Collections.singletonMap("attachment_ids", attachmentsIds))),
handleStatus()));
}
/** Create upload article with inline false */
public ArticleAttachments createUploadArticle(long articleId, File file) throws IOException {
return createUploadArticle(articleId, file, false);
}
public ArticleAttachments createUploadArticle(long articleId, File file, boolean inline)
throws IOException {
RequestBuilder builder =
reqBuilder(
"POST",
tmpl("/help_center/articles/{id}/attachments.json").set("id", articleId).toString());
builder.setHeader("Content-Type", "multipart/form-data");
if (inline) builder.addBodyPart(new StringPart("inline", "true"));
builder.addBodyPart(
new FilePart(
"file", file, "application/octet-stream", StandardCharsets.UTF_8, file.getName()));
final Request req = builder.build();
return complete(submit(req, handle(ArticleAttachments.class, "article_attachment")));
}
public void deleteUpload(Attachment.Upload upload) {
checkHasToken(upload);
deleteUpload(upload.getToken());
}
public void deleteUpload(String token) {
complete(
submit(req("DELETE", tmpl("/uploads/{token}.json").set("token", token)), handleStatus()));
}
public Attachment getAttachment(Attachment attachment) {
checkHasId(attachment);
return getAttachment(attachment.getId());
}
public Attachment getAttachment(long id) {
return complete(
submit(
req("GET", tmpl("/attachments/{id}.json").set("id", id)),
handle(Attachment.class, "attachment")));
}
public void deleteAttachment(Attachment attachment) {
checkHasId(attachment);
deleteAttachment(attachment.getId());
}
public void deleteAttachment(long id) {
complete(submit(req("DELETE", tmpl("/attachments/{id}.json").set("id", id)), handleStatus()));
}
public Iterable getTargets() {
return new PagedIterable<>(cnst("/targets.json"), handleTargetList("targets"));
}
public Target getTarget(long id) {
return complete(
submit(
req("GET", tmpl("/targets/{id}.json").set("id", id)), handle(Target.class, "target")));
}
public Target createTarget(Target target) {
return complete(
submit(
req(
"POST",
cnst("/targets.json"),
JSON,
json(Collections.singletonMap("target", target))),
handle(Target.class, "target")));
}
public void deleteTarget(long targetId) {
complete(submit(req("DELETE", tmpl("/targets/{id}.json").set("id", targetId)), handleStatus()));
}
public Iterable getTriggers() {
return new PagedIterable<>(cbp("/triggers.json"), handleList(Trigger.class, "triggers"));
}
public Iterable getTriggers(
String categoryId, boolean active, String sortBy, SortOrder sortOrder) {
return new PagedIterable<>(
tmpl("/triggers.json{?category_id,active,sort_by,sort_order}")
.set("category_id", categoryId)
.set("active", active)
.set("sort_by", sortBy)
.set("sort_order", sortOrder.getQueryParameter()),
handleList(Trigger.class, "triggers"));
}
public Iterable getActiveTriggers() {
return new PagedIterable<>(cbp("/triggers/active.json"), handleList(Trigger.class, "triggers"));
}
public Iterable searchTriggers(String query) {
return new PagedIterable<>(
tmpl("/triggers/search.json{?query}").set("query", query),
handleList(Trigger.class, "triggers"));
}
public Iterable searchTriggers(
String query, boolean active, String sortBy, SortOrder sortOrder) {
return new PagedIterable<>(
tmpl("/triggers/search.json{?query,active,sort_by,sort_order}")
.set("query", query)
.set("active", active)
.set("sort_by", sortBy)
.set("sort_order", sortOrder.getQueryParameter()),
handleList(Trigger.class, "triggers"));
}
public Trigger getTrigger(long id) {
return complete(
submit(
req("GET", tmpl("/triggers/{id}.json").set("id", id)),
handle(Trigger.class, "trigger")));
}
public Trigger createTrigger(Trigger trigger) {
return complete(
submit(
req(
"POST",
cnst("/triggers.json"),
JSON,
json(Collections.singletonMap("trigger", trigger))),
handle(Trigger.class, "trigger")));
}
public Trigger updateTrigger(Long triggerId, Trigger trigger) {
return complete(
submit(
req(
"PUT",
tmpl("/triggers/{id}.json").set("id", triggerId),
JSON,
json(Collections.singletonMap("trigger", trigger))),
handle(Trigger.class, "trigger")));
}
public void deleteTrigger(long triggerId) {
complete(
submit(req("DELETE", tmpl("/triggers/{id}.json").set("id", triggerId)), handleStatus()));
}
public Iterable getViews() {
return new PagedIterable<>(cbp("/views.json"), handleList(View.class, "views"));
}
public Iterable getView(long id) {
return new PagedIterable<>(
tmpl("/views/{id}/tickets.json").set("id", id), handleList(Ticket.class, "tickets"));
}
// Automations
public Iterable getAutomations() {
return new PagedIterable<>(
cbp("/automations.json"), handleList(Automation.class, "automations"));
}
public Automation getAutomation(long id) {
return complete(
submit(
req("GET", tmpl("/automations/{id}.json").set("id", id)),
handle(Automation.class, "automation")));
}
public Automation createAutomation(Automation automation) {
return complete(
submit(
req(
"POST",
cnst("/automations.json"),
JSON,
json(Collections.singletonMap("automation", automation))),
handle(Automation.class, "automation")));
}
public Automation updateAutomation(Long automationId, Automation automation) {
return complete(
submit(
req(
"PUT",
tmpl("/automations/{id}.json").set("id", automationId),
JSON,
json(Collections.singletonMap("automation", automation))),
handle(Automation.class, "automation")));
}
public void deleteAutomation(long automationId) {
complete(
submit(
req("DELETE", tmpl("/automations/{id}.json").set("id", automationId)), handleStatus()));
}
public Iterable getTwitterMonitors() {
return new PagedIterable<>(
cnst("/channels/twitter/monitored_twitter_handles.json"),
handleList(TwitterMonitor.class, "monitored_twitter_handles"));
}
public Iterable getUsers() {
return new PagedIterable<>(cbp("/users.json"), handleList(User.class, "users"));
}
public Iterable getUsersByRole(String role, String... roles) {
// Going to have to build this URI manually, because the RFC6570 template spec doesn't support
// variables like ?role[]=...role[]=..., which is what Zendesk requires.
// See https://developer.zendesk.com/rest_api/docs/core/users#filters
final StringBuilder uriBuilder =
new StringBuilder("/users.json?page[size]=").append(cbpPageSize);
if (roles.length == 0) {
uriBuilder.append("&role=").append(encodeUrl(role));
} else {
uriBuilder.append("&role[]=").append(encodeUrl(role));
}
for (final String curRole : roles) {
uriBuilder.append("&role[]=").append(encodeUrl(curRole));
}
return new PagedIterable<>(cnst(uriBuilder.toString()), handleList(User.class, "users"));
}
public List getUsers(long id, long... ids) {
return complete(
submit(
req("GET", tmpl("/users/show_many.json{?ids}").set("ids", idArray(id, ids))),
handleList(User.class, "users")));
}
/**
* @deprecated - User externalIds are Strings in Zendesk API, not longs. Use {@link
* #getUsersByExternalIds(String, String...)} instead
*/
@Deprecated
public List getUsersByExternalIds(long externalId, long... externalIds) {
return complete(
submit(
req(
"GET",
tmpl("/users/show_many.json{?external_ids}")
.set("external_ids", idArray(externalId, externalIds))),
handleList(User.class, "users")));
}
public List getUsersByExternalIds(String externalId, String... externalIds) {
return complete(
submit(
req(
"GET",
tmpl("/users/show_many.json{?external_ids}")
.set("external_ids", idArray(externalId, externalIds))),
handleList(User.class, "users")));
}
public Iterable getUsersIncrementally(Date startTime) {
return new PagedIterable<>(
tmpl("/incremental/users.json{?start_time}")
.set("start_time", msToSeconds(startTime.getTime())),
handleIncrementalList(User.class, "users"));
}
public Iterable getGroupUsers(long id) {
return new PagedIterable<>(
cbp("/groups/{id}/users.json").set("id", id), handleList(User.class, "users"));
}
public Iterable getOrganizationUsers(long id) {
return new PagedIterable<>(
cbp("/organizations/{id}/users.json").set("id", id), handleList(User.class, "users"));
}
public User getUser(long id) {
return complete(
submit(req("GET", tmpl("/users/{id}.json").set("id", id)), handle(User.class, "user")));
}
public User getAuthenticatedUser() {
return complete(submit(req("GET", cnst("/users/me.json")), handle(User.class, "user")));
}
public Iterable getUserFields() {
return complete(
submit(req("GET", cnst("/user_fields.json")), handleList(UserField.class, "user_fields")));
}
public User createUser(User user) {
return complete(
submit(
req("POST", cnst("/users.json"), JSON, json(Collections.singletonMap("user", user))),
handle(User.class, "user")));
}
public User mergeUsers(long userIdThatWillRemain, long userIdThatWillBeMerged) {
return complete(
submit(
req(
"PUT",
tmpl("/users/{id}/merge.json").set("id", userIdThatWillBeMerged),
JSON,
json(
Collections.singletonMap(
"user", Collections.singletonMap("id", userIdThatWillRemain)))),
handle(User.class, "user")));
}
public JobStatus createUsers(User... users) {
return createUsers(Arrays.asList(users));
}
public JobStatus createUsers(List users) {
return complete(createUsersAsync(users));
}
public ListenableFuture createUsersAsync(List users) {
return submit(
req(
"POST",
cnst("/users/create_many.json"),
JSON,
json(Collections.singletonMap("users", users))),
handleJobStatus());
}
public User createOrUpdateUser(User user) {
return complete(
submit(
req(
"POST",
cnst("/users/create_or_update.json"),
JSON,
json(Collections.singletonMap("user", user))),
handle(User.class, "user")));
}
public JobStatus createOrUpdateUsers(User... users) {
return createOrUpdateUsers(Arrays.asList(users));
}
public JobStatus createOrUpdateUsers(List users) {
return complete(createOrUpdateUsersAsync(users));
}
public ListenableFuture createOrUpdateUsersAsync(List users) {
return submit(
req(
"POST",
cnst("/users/create_or_update_many.json"),
JSON,
json(Collections.singletonMap("users", users))),
handleJobStatus());
}
public User updateUser(User user) {
checkHasId(user);
return complete(
submit(
req(
"PUT",
tmpl("/users/{id}.json").set("id", user.getId()),
JSON,
json(Collections.singletonMap("user", user))),
handle(User.class, "user")));
}
public JobStatus updateUsers(User... users) {
return updateUsers(Arrays.asList(users));
}
public JobStatus updateUsers(List users) {
return complete(updateUsersAsync(users));
}
public ListenableFuture updateUsersAsync(List users) {
return submit(
req(
"PUT",
cnst("/users/update_many.json"),
JSON,
json(Collections.singletonMap("users", users))),
handleJobStatus());
}
public void deleteUser(User user) {
checkHasId(user);
deleteUser(user.getId());
}
public void deleteUser(long id) {
complete(submit(req("DELETE", tmpl("/users/{id}.json").set("id", id)), handleStatus()));
}
public JobStatus deleteUsers(long... ids) {
return complete(
submit(
req("DELETE", tmpl("/users/destroy_many.json{?ids}").set("ids", ids)),
handleJobStatus()));
}
public User permanentlyDeleteUser(User user) {
checkHasId(user);
return permanentlyDeleteUser(user.getId());
}
public User permanentlyDeleteUser(long id) {
deleteUser(id);
return complete(
submit(req("DELETE", tmpl("/deleted_users/{id}.json").set("id", id)), handle(User.class)));
}
public User suspendUser(long id) {
User user = new User();
user.setId(id);
user.setSuspended(true);
return updateUser(user);
}
public User unsuspendUser(long id) {
User user = new User();
user.setId(id);
user.setSuspended(false);
return updateUser(user);
}
public Iterable lookupUserByEmail(String email) {
return new PagedIterable<>(
tmpl("/users/search.json{?query}").set("query", email), handleList(User.class, "users"));
}
public Iterable lookupUserByExternalId(String externalId) {
return new PagedIterable<>(
tmpl("/users/search.json{?external_id}").set("external_id", externalId),
handleList(User.class, "users"));
}
public User getCurrentUser() {
return complete(submit(req("GET", cnst("/users/me.json")), handle(User.class, "user")));
}
public void resetUserPassword(User user, String password) {
checkHasId(user);
resetUserPassword(user.getId(), password);
}
public void resetUserPassword(long id, String password) {
complete(
submit(
req(
"POST",
tmpl("/users/{id}/password.json").set("id", id),
JSON,
json(Collections.singletonMap("password", password))),
handleStatus()));
}
public void changeUserPassword(User user, String oldPassword, String newPassword) {
checkHasId(user);
Map req = new HashMap<>();
req.put("previous_password", oldPassword);
req.put("password", newPassword);
complete(
submit(
req("PUT", tmpl("/users/{id}/password.json").set("id", user.getId()), JSON, json(req)),
handleStatus()));
}
public List getUserIdentities(User user) {
checkHasId(user);
return getUserIdentities(user.getId());
}
public List getUserIdentities(long userId) {
return complete(
submit(
req("GET", tmpl("/users/{id}/identities.json").set("id", userId)),
handleList(Identity.class, "identities")));
}
public Identity getUserIdentity(User user, Identity identity) {
checkHasId(identity);
return getUserIdentity(user, identity.getId());
}
public Identity getUserIdentity(User user, long identityId) {
checkHasId(user);
return getUserIdentity(user.getId(), identityId);
}
public Identity getUserIdentity(long userId, long identityId) {
return complete(
submit(
req(
"GET",
tmpl("/users/{userId}/identities/{identityId}.json")
.set("userId", userId)
.set("identityId", identityId)),
handle(Identity.class, "identity")));
}
public List setUserPrimaryIdentity(User user, Identity identity) {
checkHasId(identity);
return setUserPrimaryIdentity(user, identity.getId());
}
public List setUserPrimaryIdentity(User user, long identityId) {
checkHasId(user);
return setUserPrimaryIdentity(user.getId(), identityId);
}
public List setUserPrimaryIdentity(long userId, long identityId) {
return complete(
submit(
req(
"PUT",
tmpl("/users/{userId}/identities/{identityId}/make_primary.json")
.set("userId", userId)
.set("identityId", identityId),
JSON,
null),
handleList(Identity.class, "identities")));
}
public Identity verifyUserIdentity(User user, Identity identity) {
checkHasId(identity);
return verifyUserIdentity(user, identity.getId());
}
public Identity verifyUserIdentity(User user, long identityId) {
checkHasId(user);
return verifyUserIdentity(user.getId(), identityId);
}
public Identity verifyUserIdentity(long userId, long identityId) {
return complete(
submit(
req(
"PUT",
tmpl("/users/{userId}/identities/{identityId}/verify.json")
.set("userId", userId)
.set("identityId", identityId),
JSON,
null),
handle(Identity.class, "identity")));
}
public Identity requestVerifyUserIdentity(User user, Identity identity) {
checkHasId(identity);
return requestVerifyUserIdentity(user, identity.getId());
}
public Identity requestVerifyUserIdentity(User user, long identityId) {
checkHasId(user);
return requestVerifyUserIdentity(user.getId(), identityId);
}
public Identity requestVerifyUserIdentity(long userId, long identityId) {
return complete(
submit(
req(
"PUT",
tmpl("/users/{userId}/identities/{identityId}/request_verification.json")
.set("userId", userId)
.set("identityId", identityId),
JSON,
null),
handle(Identity.class, "identity")));
}
public Identity updateUserIdentity(long userId, Identity identity) {
checkHasId(identity);
return complete(
submit(
req(
"PUT",
tmpl("/users/{userId}/identities/{identityId}.json")
.set("userId", userId)
.set("identityId", identity.getId()),
JSON,
json(Collections.singletonMap("identity", identity))),
handle(Identity.class, "identity")));
}
public Identity updateUserIdentity(User user, Identity identity) {
checkHasId(user);
return updateUserIdentity(user.getId(), identity);
}
public void deleteUserIdentity(User user, Identity identity) {
checkHasId(identity);
deleteUserIdentity(user, identity.getId());
}
public void deleteUserIdentity(User user, long identityId) {
checkHasId(user);
deleteUserIdentity(user.getId(), identityId);
}
public void deleteUserIdentity(long userId, long identityId) {
complete(
submit(
req(
"DELETE",
tmpl("/users/{userId}/identities/{identityId}.json")
.set("userId", userId)
.set("identityId", identityId)),
handleStatus()));
}
public Identity createUserIdentity(long userId, Identity identity) {
return complete(
submit(
req(
"POST",
tmpl("/users/{userId}/identities.json").set("userId", userId),
JSON,
json(Collections.singletonMap("identity", identity))),
handle(Identity.class, "identity")));
}
public Identity createUserIdentity(User user, Identity identity) {
return complete(
submit(
req(
"POST",
tmpl("/users/{userId}/identities.json").set("userId", user.getId()),
JSON,
json(Collections.singletonMap("identity", identity))),
handle(Identity.class, "identity")));
}
public Iterable getCustomAgentRoles() {
return new PagedIterable<>(
cnst("/custom_roles.json"), handleList(AgentRole.class, "custom_roles"));
}
public Iterable getRequests() {
return new PagedIterable<>(
cbp("/requests.json"), handleList(org.zendesk.client.v2.model.Request.class, "requests"));
}
public Iterable getOpenRequests() {
return new PagedIterable<>(
cbp("/requests/open.json"),
handleList(org.zendesk.client.v2.model.Request.class, "requests"));
}
public Iterable getSolvedRequests() {
return new PagedIterable<>(
cbp("/requests/solved.json"),
handleList(org.zendesk.client.v2.model.Request.class, "requests"));
}
public Iterable getCCRequests() {
return new PagedIterable<>(
cnst("/requests/ccd.json"),
handleList(org.zendesk.client.v2.model.Request.class, "requests"));
}
public Iterable getUserRequests(User user) {
checkHasId(user);
return getUserRequests(user.getId());
}
public Iterable getUserRequests(long id) {
return new PagedIterable<>(
tmpl("/users/{id}/requests.json").set("id", id),
handleList(org.zendesk.client.v2.model.Request.class, "requests"));
}
public org.zendesk.client.v2.model.Request getRequest(long id) {
return complete(
submit(
req("GET", tmpl("/requests/{id}.json").set("id", id)),
handle(org.zendesk.client.v2.model.Request.class, "request")));
}
public org.zendesk.client.v2.model.Request createRequest(
org.zendesk.client.v2.model.Request request) {
return complete(
submit(
req(
"POST",
cnst("/requests.json"),
JSON,
json(Collections.singletonMap("request", request))),
handle(org.zendesk.client.v2.model.Request.class, "request")));
}
public org.zendesk.client.v2.model.Request updateRequest(
org.zendesk.client.v2.model.Request request) {
checkHasId(request);
return complete(
submit(
req(
"PUT",
tmpl("/requests/{id}.json").set("id", request.getId()),
JSON,
json(Collections.singletonMap("request", request))),
handle(org.zendesk.client.v2.model.Request.class, "request")));
}
public Iterable getRequestComments(org.zendesk.client.v2.model.Request request) {
checkHasId(request);
return getRequestComments(request.getId());
}
public Iterable getRequestComments(long id) {
return new PagedIterable<>(
cbp("/requests/{id}/comments.json").set("id", id), handleList(Comment.class, "comments"));
}
public Iterable getTicketComments(long id) {
return getTicketComments(id, SortOrder.ASCENDING);
}
public Iterable getTicketComments(long id, SortOrder order) {
return new PagedIterable<>(
tmpl("/tickets/{id}/comments.json?sort_order={order}")
.set("id", id)
.set("order", order.getQueryParameter()),
handleList(Comment.class, "comments"));
}
public Comment getRequestComment(org.zendesk.client.v2.model.Request request, Comment comment) {
checkHasId(comment);
return getRequestComment(request, comment.getId());
}
public Comment getRequestComment(org.zendesk.client.v2.model.Request request, long commentId) {
checkHasId(request);
return getRequestComment(request.getId(), commentId);
}
public Comment getRequestComment(long requestId, long commentId) {
return complete(
submit(
req(
"GET",
tmpl("/requests/{requestId}/comments/{commentId}.json")
.set("requestId", requestId)
.set("commentId", commentId)),
handle(Comment.class, "comment")));
}
public Ticket createComment(long ticketId, Comment comment) {
Ticket ticket = new Ticket();
ticket.setComment(comment);
return complete(
submit(
req(
"PUT",
tmpl("/tickets/{id}.json").set("id", ticketId),
JSON,
json(Collections.singletonMap("ticket", ticket))),
handle(Ticket.class, "ticket")));
}
public Ticket createTicketFromTweet(long tweetId, long monitorId) {
Map map = new HashMap<>();
map.put("twitter_status_message_id", tweetId);
map.put("monitored_twitter_handle_id", monitorId);
return complete(
submit(
req(
"POST",
cnst("/channels/twitter/tickets.json"),
JSON,
json(Collections.singletonMap("ticket", map))),
handle(Ticket.class, "ticket")));
}
public Iterable getOrganizations() {
return new PagedIterable<>(
cbp("/organizations.json"), handleList(Organization.class, "organizations"));
}
public List getOrganizations(long id, long... ids) {
return complete(
submit(
req("GET", tmpl("/organizations/show_many.json{?ids}").set("ids", idArray(id, ids))),
handleList(Organization.class, "organizations")));
}
public Iterable getOrganizationsIncrementally(Date startTime) {
return new PagedIterable<>(
tmpl("/incremental/organizations.json{?start_time}")
.set("start_time", msToSeconds(startTime.getTime())),
handleIncrementalList(Organization.class, "organizations"));
}
public Iterable getOrganizationFields() {
// The organization_fields api doesn't seem to support paging
return complete(
submit(
req("GET", cnst("/organization_fields.json")),
handleList(OrganizationField.class, "organization_fields")));
}
public Iterable getAutoCompleteOrganizations(String name) {
if (name == null || name.length() < 2) {
throw new IllegalArgumentException("Name must be at least 2 characters long");
}
return new PagedIterable<>(
tmpl("/organizations/autocomplete.json{?name}").set("name", name),
handleList(Organization.class, "organizations"));
}
// TODO getOrganizationRelatedInformation
public Organization getOrganization(long id) {
return complete(
submit(
req("GET", tmpl("/organizations/{id}.json").set("id", id)),
handle(Organization.class, "organization")));
}
public Organization createOrganization(Organization organization) {
return complete(
submit(
req(
"POST",
cnst("/organizations.json"),
JSON,
json(Collections.singletonMap("organization", organization))),
handle(Organization.class, "organization")));
}
public JobStatus createOrganizations(Organization... organizations) {
return createOrganizations(Arrays.asList(organizations));
}
public JobStatus createOrganizations(List organizations) {
return complete(createOrganizationsAsync(organizations));
}
public ListenableFuture createOrganizationsAsync(List organizations) {
return submit(
req(
"POST",
cnst("/organizations/create_many.json"),
JSON,
json(Collections.singletonMap("organizations", organizations))),
handleJobStatus());
}
public Organization createOrUpdateOrganization(Organization organization) {
return complete(
submit(
req(
"POST",
cnst("/organizations/create_or_update.json"),
JSON,
json(Collections.singletonMap("organization", organization))),
handle(Organization.class, "organization")));
}
public Organization updateOrganization(Organization organization) {
checkHasId(organization);
return complete(
submit(
req(
"PUT",
tmpl("/organizations/{id}.json").set("id", organization.getId()),
JSON,
json(Collections.singletonMap("organization", organization))),
handle(Organization.class, "organization")));
}
public JobStatus updateOrganizations(Organization... organizations) {
return updateOrganizations(Arrays.asList(organizations));
}
public JobStatus updateOrganizations(List organizations) {
return complete(updateOrganizationsAsync(organizations));
}
public ListenableFuture updateOrganizationsAsync(List organizations) {
return submit(
req(
"PUT",
cnst("/organizations/update_many.json"),
JSON,
json(Collections.singletonMap("organizations", organizations))),
handleJobStatus());
}
public void deleteOrganization(Organization organization) {
checkHasId(organization);
deleteOrganization(organization.getId());
}
public void deleteOrganization(long id) {
complete(submit(req("DELETE", tmpl("/organizations/{id}.json").set("id", id)), handleStatus()));
}
public JobStatus deleteOrganizations(long... ids) {
return complete(
submit(
req("DELETE", tmpl("/organizations/destroy_many.json{?ids}").set("ids", ids)),
handleJobStatus()));
}
public Iterable lookupOrganizationsByExternalId(String externalId) {
if (externalId == null || externalId.length() == 0) {
throw new IllegalArgumentException("External ID must not be null or length 0");
}
return new PagedIterable<>(
tmpl("/organizations/search.json{?external_id}").set("external_id", externalId),
handleList(Organization.class, "organizations"));
}
public Iterable getOrganizationMemberships() {
return new PagedIterable<>(
cbp("/organization_memberships.json"),
handleList(OrganizationMembership.class, "organization_memberships"));
}
public Iterable getOrganizationMembershipsForOrg(long organization_id) {
return new PagedIterable<>(
cbp("/organizations/{organization_id}/organization_memberships.json")
.set("organization_id", organization_id),
handleList(OrganizationMembership.class, "organization_memberships"));
}
public Iterable getOrganizationMembershipsForUser(long user_id) {
return new PagedIterable<>(
cbp("/users/{user_id}/organization_memberships.json").set("user_id", user_id),
handleList(OrganizationMembership.class, "organization_memberships"));
}
public OrganizationMembership getOrganizationMembershipForUser(long user_id, long id) {
return complete(
submit(
req(
"GET",
tmpl("/users/{user_id}/organization_memberships/{id}.json")
.set("user_id", user_id)
.set("id", id)),
handle(OrganizationMembership.class, "organization_membership")));
}
public OrganizationMembership getOrganizationMembership(long id) {
return complete(
submit(
req("GET", tmpl("/organization_memberships/{id}.json").set("id", id)),
handle(OrganizationMembership.class, "organization_membership")));
}
public OrganizationMembership createOrganizationMembership(
OrganizationMembership organizationMembership) {
return complete(
submit(
req(
"POST",
cnst("/organization_memberships.json"),
JSON,
json(Collections.singletonMap("organization_membership", organizationMembership))),
handle(OrganizationMembership.class, "organization_membership")));
}
/**
* https://developer.zendesk.com/rest_api/docs/support/organization_memberships#create-many-memberships
*/
public JobStatus createOrganizationMemberships(
OrganizationMembership... organizationMemberships) {
return createOrganizationMemberships(Arrays.asList(organizationMemberships));
}
/**
* https://developer.zendesk.com/rest_api/docs/support/organization_memberships#create-many-memberships
*/
public JobStatus createOrganizationMemberships(
List organizationMemberships) {
return complete(createOrganizationMembershipsAsync(organizationMemberships));
}
/**
* https://developer.zendesk.com/rest_api/docs/support/organization_memberships#create-many-memberships
*/
public ListenableFuture createOrganizationMembershipsAsync(
List organizationMemberships) {
return submit(
req(
"POST",
cnst("/organization_memberships/create_many.json"),
JSON,
json(Collections.singletonMap("organization_memberships", organizationMemberships))),
handleJobStatus());
}
public void deleteOrganizationMembership(long id) {
complete(
submit(
req("DELETE", tmpl("/organization_memberships/{id}.json").set("id", id)),
handleStatus()));
}
/**
* https://developer.zendesk.com/rest_api/docs/support/organization_memberships#bulk-delete-memberships
*/
public void deleteOrganizationMemberships(long id, long... ids) {
complete(
submit(
req(
"DELETE",
tmpl("/organization_memberships/destroy_many.json{?ids}")
.set("ids", idArray(id, ids))),
handleStatus()));
}
public Iterable getGroups() {
return new PagedIterable<>(cbp("/groups.json"), handleList(Group.class, "groups"));
}
public Iterable getAssignableGroups() {
return new PagedIterable<>(cbp("/groups/assignable.json"), handleList(Group.class, "groups"));
}
public Group getGroup(long id) {
return complete(
submit(req("GET", tmpl("/groups/{id}.json").set("id", id)), handle(Group.class, "group")));
}
public Group createGroup(Group group) {
return complete(
submit(
req("POST", cnst("/groups.json"), JSON, json(Collections.singletonMap("group", group))),
handle(Group.class, "group")));
}
/**
* This API will be removed in a future release. The API endpoint does not exist. Instead, the
* {@link #createGroup(Group) createGroup} method should be called for each Group
*
* @see Zendesk Java Client
* Issue #111
*/
@Deprecated
public List createGroups(Group... groups) {
return createGroups(Arrays.asList(groups));
}
/**
* This API will be removed in a future release. The API endpoint does not exist. Instead, the
* {@link #createGroup(Group) createGroup} method should be called for each Group
*
* @see Zendesk Java Client
* Issue #111
*/
@Deprecated
public List createGroups(List groups) {
throw new ZendeskException("API Endpoint for createGroups does not exist.");
}
public Group updateGroup(Group group) {
checkHasId(group);
return complete(
submit(
req(
"PUT",
tmpl("/groups/{id}.json").set("id", group.getId()),
JSON,
json(Collections.singletonMap("group", group))),
handle(Group.class, "group")));
}
public void deleteGroup(Group group) {
checkHasId(group);
deleteGroup(group.getId());
}
public void deleteGroup(long id) {
complete(submit(req("DELETE", tmpl("/groups/{id}.json").set("id", id)), handleStatus()));
}
public Iterable getMacros() {
return new PagedIterable<>(cbp("/macros.json"), handleList(Macro.class, "macros"));
}
public Macro getMacro(long macroId) {
return complete(
submit(
req("GET", tmpl("/macros/{id}.json").set("id", macroId)),
handle(Macro.class, "macro")));
}
public Macro createMacro(Macro macro) {
return complete(
submit(
req("POST", cnst("/macros.json"), JSON, json(Collections.singletonMap("macro", macro))),
handle(Macro.class, "macro")));
}
public Macro updateMacro(Long macroId, Macro macro) {
return complete(
submit(
req(
"PUT",
tmpl("/macros/{id}.json").set("id", macroId),
JSON,
json(Collections.singletonMap("macro", macro))),
handle(Macro.class, "macro")));
}
public Ticket macrosShowChangesToTicket(long macroId) {
return complete(
submit(
req("GET", tmpl("/macros/{id}/apply.json").set("id", macroId)),
handle(TicketResult.class, "result")))
.getTicket();
}
public Ticket macrosShowTicketAfterChanges(long ticketId, long macroId) {
return complete(
submit(
req(
"GET",
tmpl("/tickets/{ticket_id}/macros/{id}/apply.json")
.set("ticket_id", ticketId)
.set("id", macroId)),
handle(TicketResult.class, "result")))
.getTicket();
}
public List addTagToTicket(long id, String... tags) {
return complete(
submit(
req(
"PUT",
tmpl("/tickets/{id}/tags.json").set("id", id),
JSON,
json(Collections.singletonMap("tags", tags))),
handle(List.class, "tags")));
}
public List addTagToTopics(long id, String... tags) {
return complete(
submit(
req(
"PUT",
tmpl("/topics/{id}/tags.json").set("id", id),
JSON,
json(Collections.singletonMap("tags", tags))),
handle(List.class, "tags")));
}
public List addTagToOrganisations(long id, String... tags) {
return complete(
submit(
req(
"PUT",
tmpl("/organizations/{id}/tags.json").set("id", id),
JSON,
json(Collections.singletonMap("tags", tags))),
handle(List.class, "tags")));
}
public List setTagOnTicket(long id, String... tags) {
return complete(
submit(
req(
"POST",
tmpl("/tickets/{id}/tags.json").set("id", id),
JSON,
json(Collections.singletonMap("tags", tags))),
handle(List.class, "tags")));
}
public List setTagOnTopics(long id, String... tags) {
return complete(
submit(
req(
"POST",
tmpl("/topics/{id}/tags.json").set("id", id),
JSON,
json(Collections.singletonMap("tags", tags))),
handle(List.class, "tags")));
}
public List setTagOnOrganisations(long id, String... tags) {
return complete(
submit(
req(
"POST",
tmpl("/organizations/{id}/tags.json").set("id", id),
JSON,
json(Collections.singletonMap("tags", tags))),
handle(List.class, "tags")));
}
public List removeTagFromTicket(long id, String... tags) {
return complete(
submit(
req(
"DELETE",
tmpl("/tickets/{id}/tags.json").set("id", id),
JSON,
json(Collections.singletonMap("tags", tags))),
handle(List.class, "tags")));
}
public List removeTagFromTopics(long id, String... tags) {
return complete(
submit(
req(
"DELETE",
tmpl("/topics/{id}/tags.json").set("id", id),
JSON,
json(Collections.singletonMap("tags", tags))),
handle(List.class, "tags")));
}
public List removeTagFromOrganisations(long id, String... tags) {
return complete(
submit(
req(
"DELETE",
tmpl("/organizations/{id}/tags.json").set("id", id),
JSON,
json(Collections.singletonMap("tags", tags))),
handle(List.class, "tags")));
}
public Map getIncrementalTicketsResult(long unixEpochTime) {
return complete(
submit(
req("GET", tmpl("/exports/tickets.json?start_time={time}").set("time", unixEpochTime)),
handle(Map.class)));
}
public Iterable getGroupMemberships() {
return new PagedIterable<>(
cbp("/group_memberships.json"), handleList(GroupMembership.class, "group_memberships"));
}
public Iterable getGroupMembershipByUser(long user_id) {
return new PagedIterable<>(
cbp("/users/{user_id}/group_memberships.json").set("user_id", user_id),
handleList(GroupMembership.class, "group_memberships"));
}
public Iterable getGroupMemberships(long group_id) {
return new PagedIterable<>(
cbp("/groups/{group_id}/memberships.json").set("group_id", group_id),
handleList(GroupMembership.class, "group_memberships"));
}
public Iterable getAssignableGroupMemberships() {
return new PagedIterable<>(
cbp("/group_memberships/assignable.json"),
handleList(GroupMembership.class, "group_memberships"));
}
public Iterable getAssignableGroupMemberships(long group_id) {
return new PagedIterable<>(
cbp("/groups/{group_id}/memberships/assignable.json").set("group_id", group_id),
handleList(GroupMembership.class, "group_memberships"));
}
public GroupMembership getGroupMembership(long id) {
return complete(
submit(
req("GET", tmpl("/group_memberships/{id}.json").set("id", id)),
handle(GroupMembership.class, "group_membership")));
}
public GroupMembership getGroupMembership(long user_id, long group_membership_id) {
return complete(
submit(
req(
"GET",
tmpl("/users/{uid}/group_memberships/{gmid}.json")
.set("uid", user_id)
.set("gmid", group_membership_id)),
handle(GroupMembership.class, "group_membership")));
}
public GroupMembership createGroupMembership(GroupMembership groupMembership) {
return complete(
submit(
req(
"POST",
cnst("/group_memberships.json"),
JSON,
json(Collections.singletonMap("group_membership", groupMembership))),
handle(GroupMembership.class, "group_membership")));
}
public GroupMembership createGroupMembership(long user_id, GroupMembership groupMembership) {
return complete(
submit(
req(
"POST",
tmpl("/users/{id}/group_memberships.json").set("id", user_id),
JSON,
json(Collections.singletonMap("group_membership", groupMembership))),
handle(GroupMembership.class, "group_membership")));
}
public void deleteGroupMembership(GroupMembership groupMembership) {
checkHasId(groupMembership);
deleteGroupMembership(groupMembership.getId());
}
public void deleteGroupMembership(long id) {
complete(
submit(req("DELETE", tmpl("/group_memberships/{id}.json").set("id", id)), handleStatus()));
}
public void deleteGroupMembership(long user_id, GroupMembership groupMembership) {
checkHasId(groupMembership);
deleteGroupMembership(user_id, groupMembership.getId());
}
public void deleteGroupMembership(long user_id, long group_membership_id) {
complete(
submit(
req(
"DELETE",
tmpl("/users/{uid}/group_memberships/{gmid}.json")
.set("uid", user_id)
.set("gmid", group_membership_id)),
handleStatus()));
}
public List setGroupMembershipAsDefault(
long user_id, GroupMembership groupMembership) {
checkHasId(groupMembership);
return complete(
submit(
req(
"PUT",
tmpl("/users/{uid}/group_memberships/{gmid}/make_default.json")
.set("uid", user_id)
.set("gmid", groupMembership.getId()),
JSON,
json(Collections.singletonMap("group_memberships", groupMembership))),
handleList(GroupMembership.class, "results")));
}
public Iterable getForums() {
return new PagedIterable<>(cnst("/forums.json"), handleList(Forum.class, "forums"));
}
public List getForums(long category_id) {
return complete(
submit(
req("GET", tmpl("/categories/{id}/forums.json").set("id", category_id)),
handleList(Forum.class, "forums")));
}
public Forum getForum(long id) {
return complete(
submit(req("GET", tmpl("/forums/{id}.json").set("id", id)), handle(Forum.class, "forum")));
}
public Forum createForum(Forum forum) {
return complete(
submit(
req("POST", cnst("/forums.json"), JSON, json(Collections.singletonMap("forum", forum))),
handle(Forum.class, "forum")));
}
public Forum updateForum(Forum forum) {
checkHasId(forum);
return complete(
submit(
req(
"PUT",
tmpl("/forums/{id}.json").set("id", forum.getId()),
JSON,
json(Collections.singletonMap("forum", forum))),
handle(Forum.class, "forum")));
}
public void deleteForum(Forum forum) {
checkHasId(forum);
complete(
submit(req("DELETE", tmpl("/forums/{id}.json").set("id", forum.getId())), handleStatus()));
}
public Iterable getTopics() {
return new PagedIterable<>(cnst("/topics.json"), handleList(Topic.class, "topics"));
}
public List getTopics(long forum_id) {
return complete(
submit(
req("GET", tmpl("/forums/{id}/topics.json").set("id", forum_id)),
handleList(Topic.class, "topics")));
}
public List getTopicsByUser(long user_id) {
return complete(
submit(
req("GET", tmpl("/users/{id}/topics.json").set("id", user_id)),
handleList(Topic.class, "topics")));
}
public Topic getTopic(long id) {
return complete(
submit(req("GET", tmpl("/topics/{id}.json").set("id", id)), handle(Topic.class, "topic")));
}
public Topic createTopic(Topic topic) {
checkHasId(topic);
return complete(
submit(
req("POST", cnst("/topics.json"), JSON, json(Collections.singletonMap("topic", topic))),
handle(Topic.class, "topic")));
}
public Topic importTopic(Topic topic) {
checkHasId(topic);
return complete(
submit(
req(
"POST",
cnst("/import/topics.json"),
JSON,
json(Collections.singletonMap("topic", topic))),
handle(Topic.class, "topic")));
}
public List getTopics(long id, long... ids) {
return complete(
submit(
req("POST", tmpl("/topics/show_many.json{?ids}").set("ids", idArray(id, ids))),
handleList(Topic.class, "topics")));
}
public Topic updateTopic(Topic topic) {
checkHasId(topic);
return complete(
submit(
req(
"PUT",
tmpl("/topics/{id}.json").set("id", topic.getId()),
JSON,
json(Collections.singletonMap("topic", topic))),
handle(Topic.class, "topic")));
}
public void deleteTopic(Topic topic) {
checkHasId(topic);
complete(
submit(req("DELETE", tmpl("/topics/{id}.json").set("id", topic.getId())), handleStatus()));
}
// https://support.zendesk.com/hc/communities/public/posts/203464106-Managing-Organization-Memberships-via-the-Zendesk-API
public Iterable getOrganizationMembershipByUser(long user_id) {
return getOrganizationMembershipsForUser(user_id);
}
public OrganizationMembership getGroupOrganization(
long user_id, long organization_membership_id) {
return complete(
submit(
req(
"GET",
tmpl("/users/{uid}/organization_memberships/{oid}.json")
.set("uid", user_id)
.set("oid", organization_membership_id)),
handle(OrganizationMembership.class, "organization_membership")));
}
public OrganizationMembership createOrganizationMembership(
long user_id, OrganizationMembership organizationMembership) {
return complete(
submit(
req(
"POST",
tmpl("/users/{id}/organization_memberships.json").set("id", user_id),
JSON,
json(Collections.singletonMap("organization_membership", organizationMembership))),
handle(OrganizationMembership.class, "organization_membership")));
}
public void deleteOrganizationMembership(
long user_id, OrganizationMembership organizationMembership) {
checkHasId(organizationMembership);
deleteOrganizationMembership(user_id, organizationMembership.getId());
}
public void deleteOrganizationMembership(long user_id, long organization_membership_id) {
complete(
submit(
req(
"DELETE",
tmpl("/users/{uid}/organization_memberships/{oid}.json")
.set("uid", user_id)
.set("oid", organization_membership_id)),
handleStatus()));
}
public List setOrganizationMembershipAsDefault(
long user_id, OrganizationMembership organizationMembership) {
checkHasId(organizationMembership);
return complete(
submit(
req(
"PUT",
tmpl("/users/{uid}/organization_memberships/{omid}/make_default.json")
.set("uid", user_id)
.set("omid", organizationMembership.getId()),
JSON,
json(Collections.singletonMap("organization_memberships", organizationMembership))),
handleList(OrganizationMembership.class, "results")));
}
// -- END BETA
public Iterable getSearchResults(String query) {
return new PagedIterable<>(
tmpl("/search.json{?query}").set("query", query), handleSearchList("results"));
}
public Iterable getSearchResults(Class type, String query) {
return getSearchResults(type, query, Collections.emptyMap());
}
/**
* @deprecated Use {@link #getSearchResults(Class, String, Map)} instead.
*/
@Deprecated
public Iterable getSearchResults(
Class type, String query, String params) {
/*
preserving backwards compatabile logic, this method will continue to do what it did before, which is "wrong"
in that you can't really specify things like sort order via this method
*/
Map paramsMap = new HashMap<>(1);
paramsMap.put("params", params);
return getSearchResults(type, query, paramsMap);
}
public Iterable getSearchResults(
Class type, String query, String sortBy, SortOrder sortOrder) {
Map paramsMap = new HashMap<>(2);
paramsMap.put("sort_by", sortBy);
paramsMap.put("sort_order", sortOrder.getQueryParameter());
return getSearchResults(type, query, paramsMap);
}
public Iterable getSearchResults(
Class type, String query, Map params) {
String typeName = getTypeName(type);
if (typeName == null) {
return Collections.emptyList();
}
TemplateUri templateUri = getSearchUri(params, query, typeName);
return new PagedIterable<>(templateUri, handleList(type, "results"));
}
/**
* Search API implementation with pagination support.
*
* @param searchType type of search entity like Ticket, User etc
* @param pageType page return type to which the search result will be deserialized
* @param query string used filter a type given by searchType
* @param queryParams additional parameters other than filter string like per_page, page etc
* @param sortBy name of any field of the searchType
* @param sortOrder sort order
*/
public Optional getSearchResults(
final Class> searchType,
final Class pageType,
final String query,
final Map queryParams,
final String sortBy,
final SortOrder sortOrder) {
String typeName = getTypeName(searchType);
if (typeName == null) {
return Optional.empty();
}
final Map paramsMap = new HashMap<>();
if (queryParams != null) {
paramsMap.putAll(queryParams);
}
if (sortBy != null && sortOrder != null) {
paramsMap.put("sort_by", sortBy);
paramsMap.put("sort_order", sortOrder.getQueryParameter());
}
final TemplateUri templateUri = getSearchUri(paramsMap, query, typeName);
return Optional.of(complete(submit(req("GET", templateUri.toString()), handle(pageType))));
}
/**
* Ticket Search API implementation with pagination support.
*
* @param query string used filter a type given by searchType
* @param queryParams additional parameters other than filter string like per_page, page etc
* @param sortBy name of any field of the searchType
* @param sortOrder sort order
*/
public Optional getSearchTicketResults(
final String query,
final Map queryParams,
final String sortBy,
final SortOrder sortOrder) {
return getSearchResults(Ticket.class, TicketPage.class, query, queryParams, sortBy, sortOrder);
}
public void notifyApp(String json) {
complete(submit(req("POST", cnst("/apps/notify.json"), JSON, json.getBytes()), handleStatus()));
}
public void updateInstallation(int id, String json) {
complete(
submit(
req("PUT", tmpl("/apps/installations/{id}.json").set("id", id), JSON, json.getBytes()),
handleStatus()));
}
public Iterable getSatisfactionRatings() {
return new PagedIterable<>(
cbp("/satisfaction_ratings.json"),
handleList(SatisfactionRating.class, "satisfaction_ratings"));
}
public SatisfactionRating getSatisfactionRating(long id) {
return complete(
submit(
req("GET", tmpl("/satisfaction_ratings/{id}.json").set("id", id)),
handle(SatisfactionRating.class, "satisfaction_rating")));
}
public SatisfactionRating createSatisfactionRating(
long ticketId, SatisfactionRating satisfactionRating) {
return complete(
submit(
req(
"POST",
tmpl("/tickets/{ticketId}/satisfaction_rating.json").set("ticketId", ticketId),
JSON,
json(Collections.singletonMap("satisfaction_rating", satisfactionRating))),
handle(SatisfactionRating.class, "satisfaction_rating")));
}
public SatisfactionRating createSatisfactionRating(
Ticket ticket, SatisfactionRating satisfactionRating) {
return createSatisfactionRating(ticket.getId(), satisfactionRating);
}
//////////////////////////////////////////////////////////////////////
// Action methods for Dynamic Content - Items and Variants
//////////////////////////////////////////////////////////////////////
public Iterable getDynamicContentItems() {
return new PagedIterable<>(
cbp("/dynamic_content/items.json"), handleList(DynamicContentItem.class, "items"));
}
public DynamicContentItem getDynamicContentItem(long id) {
return complete(
submit(
req("GET", tmpl("/dynamic_content/items/{id}.json").set("id", id)),
handle(DynamicContentItem.class, "item")));
}
public DynamicContentItem createDynamicContentItem(DynamicContentItem item) {
return complete(
submit(
req(
"POST",
cnst("/dynamic_content/items.json"),
JSON,
json(Collections.singletonMap("item", item))),
handle(DynamicContentItem.class, "item")));
}
public DynamicContentItem updateDynamicContentItem(DynamicContentItem item) {
checkHasId(item);
return complete(
submit(
req(
"PUT",
tmpl("/dynamic_content/items/{id}.json").set("id", item.getId()),
JSON,
json(Collections.singletonMap("item", item))),
handle(DynamicContentItem.class, "item")));
}
public void deleteDynamicContentItem(DynamicContentItem item) {
checkHasId(item);
complete(
submit(
req("DELETE", tmpl("/dynamic_content/items/{id}.json").set("id", item.getId())),
handleStatus()));
}
/** VARIANTS */
public Iterable getDynamicContentItemVariants(
DynamicContentItem item) {
checkHasId(item);
return new PagedIterable<>(
cbp("/dynamic_content/items/{id}/variants.json").set("id", item.getId()),
handleList(DynamicContentItemVariant.class, "variants"));
}
public DynamicContentItemVariant getDynamicContentItemVariant(Long itemId, long id) {
return complete(
submit(
req(
"GET",
tmpl("/dynamic_content/items/{itemId}/variants/{id}.json")
.set("itemId", itemId)
.set("id", id)),
handle(DynamicContentItemVariant.class, "variant")));
}
public DynamicContentItemVariant createDynamicContentItemVariant(
Long itemId, DynamicContentItemVariant variant) {
checkHasItemId(itemId);
return complete(
submit(
req(
"POST",
tmpl("/dynamic_content/items/{id}/variants.json").set("id", itemId),
JSON,
json(Collections.singletonMap("variant", variant))),
handle(DynamicContentItemVariant.class, "variant")));
}
public DynamicContentItemVariant updateDynamicContentItemVariant(
Long itemId, DynamicContentItemVariant variant) {
checkHasItemId(itemId);
checkHasId(variant);
return complete(
submit(
req(
"PUT",
tmpl("/dynamic_content/items/{itemId}/variants/{id}.json")
.set("itemId", itemId)
.set("id", variant.getId()),
JSON,
json(Collections.singletonMap("variant", variant))),
handle(DynamicContentItemVariant.class, "variant")));
}
public void deleteDynamicContentItemVariant(Long itemId, DynamicContentItemVariant variant) {
checkHasItemId(itemId);
checkHasId(variant);
complete(
submit(
req(
"DELETE",
tmpl("/dynamic_content/items/{itemId}/variants/{id}.json")
.set("itemId", itemId)
.set("id", variant.getId())),
handleStatus()));
}
//////////////////////////////////////////////////////////////////////
// Action methods for Locales
//////////////////////////////////////////////////////////////////////
/**
* https://developer.zendesk.com/api-reference/ticketing/account-configuration/locales/#list-locales
*
* @return the translation locales available for the account.
* @since FIXME
*/
public Iterable getLocales() {
return new PagedIterable<>(cnst("/locales.json"), handleList(Locale.class, "locales"));
}
// TODO search with query building API
//////////////////////////////////////////////////////////////////////
// Action methods for Help Center
//////////////////////////////////////////////////////////////////////
/**
* Get all permission groups
*
* @return List of Permission Groups
*/
public Iterable getPermissionGroups() {
return new PagedIterable<>(
cnst("/guide/permission_groups.json"),
handleList(PermissionGroup.class, "permission_groups"));
}
/**
* Get permission group by id
*
* @param id
*/
public PermissionGroup getPermissionGroup(long id) {
return complete(
submit(
req("GET", tmpl("/guide/permission_groups/{id}.json").set("id", id)),
handle(PermissionGroup.class, "permission_group")));
}
/**
* Create permission group
*
* @param permissionGroup
*/
public PermissionGroup createPermissionGroup(PermissionGroup permissionGroup) {
return complete(
submit(
req(
"POST",
tmpl("/guide/permission_groups.json"),
JSON,
json(Collections.singletonMap("permission_group", permissionGroup))),
handle(PermissionGroup.class, "permission_group")));
}
/**
* Update permission group
*
* @param permissionGroup
*/
public PermissionGroup updatePermissionGroup(PermissionGroup permissionGroup) {
checkHasId(permissionGroup);
return complete(
submit(
req(
"PUT",
tmpl("/guide/permission_groups/{id}.json").set("id", permissionGroup.getId()),
JSON,
json(Collections.singletonMap("permission_group", permissionGroup))),
handle(PermissionGroup.class, "permission_group")));
}
/**
* Delete permission group
*
* @param permissionGroup
*/
public void deletePermissionGroup(PermissionGroup permissionGroup) {
checkHasId(permissionGroup);
deletePermissionGroup(permissionGroup.getId());
}
/**
* Delete permission group
*
* @param id
*/
public void deletePermissionGroup(long id) {
complete(
submit(
req("DELETE", tmpl("/guide/permission_groups/{id}.json").set("id", id)),
handleStatus()));
}
/**
* Get user segments
*
* @return List of User Segments
*/
public Iterable getUserSegments() {
return new PagedIterable<>(
cnst("/help_center/user_segments.json"), handleList(UserSegment.class, "user_segments"));
}
/**
* Returns the list of user segments that a particular user belongs to
*
* @return List of User Segments
*/
public Iterable getUserSegments(long id) {
return new PagedIterable<>(
tmpl("/help_center/users/{id}/user_segments.json").set("id", id),
handleList(UserSegment.class, "user_segments"));
}
/**
* Request only user segments applicable on the account's current Guide plan
*
* @return List of User Segments
*/
public Iterable getUserSegmentsApplicable() {
return new PagedIterable<>(
cnst("/help_center/user_segments/applicable.json"),
handleList(UserSegment.class, "user_segments"));
}
/**
* Get user segment by id
*
* @param id
*/
public UserSegment getUserSegment(long id) {
return complete(
submit(
req("GET", tmpl("/help_center/user_segments/{id}.json").set("id", id)),
handle(UserSegment.class, "user_segment")));
}
/**
* List Sections using a User Segment
*
* @param userSegment
* @return List of Sections
*/
public Iterable getSections(UserSegment userSegment) {
checkHasId(userSegment);
return new PagedIterable<>(
tmpl("/help_center/user_segments/{id}/sections.json").set("id", userSegment.getId()),
handleList(Section.class, "sections"));
}
/**
* List Topics using a User Segment
*
* @param userSegment
* @return List of Topics
*/
public Iterable getTopics(UserSegment userSegment) {
checkHasId(userSegment);
return new PagedIterable<>(
tmpl("/help_center/user_segments/{id}/topics.json").set("id", userSegment.getId()),
handleList(Topic.class, "topics"));
}
/**
* Create User Segment
*
* @param userSegment
*/
public UserSegment createUserSegment(UserSegment userSegment) {
return complete(
submit(
req(
"POST",
tmpl("/help_center/user_segments.json"),
JSON,
json(Collections.singletonMap("user_segment", userSegment))),
handle(UserSegment.class, "user_segment")));
}
/**
* Update User Segment
*
* @param userSegment
*/
public UserSegment updateUserSegment(UserSegment userSegment) {
checkHasId(userSegment);
return complete(
submit(
req(
"PUT",
tmpl("/help_center/user_segments/{id}.json").set("id", userSegment.getId()),
JSON,
json(Collections.singletonMap("user_segment", userSegment))),
handle(UserSegment.class, "user_segment")));
}
/**
* Delete User Segment
*
* @param userSegment
*/
public void deleteUserSegment(UserSegment userSegment) {
checkHasId(userSegment);
deleteUserSegment(userSegment.getId());
}
/**
* Delete User Segment
*
* @param id
*/
public void deleteUserSegment(long id) {
complete(
submit(
req("DELETE", tmpl("/help_center/user_segments/{id}.json").set("id", id)),
handleStatus()));
}
public Locales listHelpCenterLocales() {
return complete(submit(req("GET", cnst("/help_center/locales.json")), handle(Locales.class)));
}
/**
* @deprecated Use {@link Zendesk#listHelpCenterLocales()} instead
*/
@Deprecated
public List getHelpCenterLocales() {
return listHelpCenterLocales().getLocales();
}
/**
* Get all articles from help center.
*
* @return List of Articles.
*/
public Iterable getArticles() {
return new PagedIterable<>(
cnst("/help_center/articles.json"), handleList(Article.class, "articles"));
}
public Iterable getArticles(String locale) {
return new PagedIterable<>(
tmpl("/help_center/{locale}/articles.json").set("locale", locale),
handleList(Article.class, "articles"));
}
public Iterable getArticles(Category category) {
checkHasId(category);
return new PagedIterable<>(
tmpl("/help_center/categories/{id}/articles.json").set("id", category.getId()),
handleList(Article.class, "articles"));
}
public Iterable getArticles(Category category, String locale) {
checkHasId(category);
return new PagedIterable<>(
tmpl("/help_center/{locale}/categories/{id}/articles.json")
.set("id", category.getId())
.set("locale", locale),
handleList(Article.class, "articles"));
}
public Iterable getArticles(Section section) {
checkHasId(section);
return new PagedIterable<>(
tmpl("/help_center/sections/{id}/articles.json").set("id", section.getId()),
handleList(Article.class, "articles"));
}
public Iterable getArticles(Section section, String locale) {
checkHasId(section);
return new PagedIterable<>(
tmpl("/help_center/{locale}/sections/{id}/articles.json")
.set("id", section.getId())
.set("locale", locale),
handleList(Article.class, "articles"));
}
public Iterable getArticlesIncrementally(Date startTime) {
return new PagedIterable<>(
tmpl("/help_center/incremental/articles.json{?start_time}")
.set("start_time", msToSeconds(startTime.getTime())),
handleIncrementalList(Article.class, "articles"));
}
public List getArticlesFromPage(int page) {
return complete(
submit(
req("GET", tmpl("/help_center/articles.json?page={page}").set("page", page)),
handleList(Article.class, "articles")));
}
public Article getArticle(long id) {
return complete(
submit(
req("GET", tmpl("/help_center/articles/{id}.json").set("id", id)),
handle(Article.class, "article")));
}
public Iterable getArticleTranslations(Long articleId) {
return new PagedIterable<>(
tmpl("/help_center/articles/{articleId}/translations.json").set("articleId", articleId),
handleList(Translation.class, "translations"));
}
public Translation showArticleTranslation(long articleId, String locale) {
return complete(
submit(
req(
"GET",
tmpl("/help_center/articles/{articleId}/translations/{locale}.json")
.set("articleId", articleId)
.set("locale", locale)),
handle(Translation.class, "translation")));
}
public Article createArticle(Article article) {
checkHasSectionId(article);
return complete(
submit(
req(
"POST",
tmpl("/help_center/sections/{id}/articles.json").set("id", article.getSectionId()),
JSON,
json(Collections.singletonMap("article", article))),
handle(Article.class, "article")));
}
public Article createArticle(Article article, boolean notifySubscribers) {
checkHasSectionId(article);
Map map = new HashMap();
map.put("article", article);
map.put(
"notify_subscribers", notifySubscribers ? String.valueOf("true") : String.valueOf("false"));
return complete(
submit(
req(
"POST",
tmpl("/help_center/sections/{id}/articles.json").set("id", article.getSectionId()),
JSON,
json(Collections.unmodifiableMap(map))),
handle(Article.class, "article")));
}
public Article updateArticle(Article article) {
checkHasId(article);
return complete(
submit(
req(
"PUT",
tmpl("/help_center/articles/{id}.json").set("id", article.getId()),
JSON,
json(Collections.singletonMap("article", article))),
handle(Article.class, "article")));
}
public Translation createArticleTranslation(Long articleId, Translation translation) {
checkHasArticleId(articleId);
return complete(
submit(
req(
"POST",
tmpl("/help_center/articles/{id}/translations.json").set("id", articleId),
JSON,
json(Collections.singletonMap("translation", translation))),
handle(Translation.class, "translation")));
}
public Translation updateArticleTranslation(
Long articleId, String locale, Translation translation) {
checkHasId(translation);
return complete(
submit(
req(
"PUT",
tmpl("/help_center/articles/{id}/translations/{locale}.json")
.set("id", articleId)
.set("locale", locale),
JSON,
json(Collections.singletonMap("translation", translation))),
handle(Translation.class, "translation")));
}
public void deleteArticle(Article article) {
checkHasId(article);
complete(
submit(
req("DELETE", tmpl("/help_center/articles/{id}.json").set("id", article.getId())),
handleStatus()));
}
/**
* Delete translation.
*
* @param translation
*/
public void deleteTranslation(Translation translation) {
checkHasId(translation);
deleteTranslation(translation.getId());
}
/**
* Delete translation.
*
* @param translationId
*/
public void deleteTranslation(Long translationId) {
complete(
submit(
req("DELETE", tmpl("/help_center/translations/{id}.json").set("id", translationId)),
handleStatus()));
}
/**
* Delete attachment from article.
*
* @param attachment
*/
public void deleteArticleAttachment(ArticleAttachments attachment) {
checkHasId(attachment);
deleteArticleAttachment(attachment.getId());
}
/**
* Delete attachment from article.
*
* @param id attachment identifier.
*/
public void deleteArticleAttachment(long id) {
complete(
submit(
req("DELETE", tmpl("/help_center/articles/attachments/{id}.json").set("id", id)),
handleStatus()));
}
public Iterable getCategories() {
return new PagedIterable<>(
cnst("/help_center/categories.json"), handleList(Category.class, "categories"));
}
public Category getCategory(long id) {
return complete(
submit(
req("GET", tmpl("/help_center/categories/{id}.json").set("id", id)),
handle(Category.class, "category")));
}
public Iterable getCategoryTranslations(Long categoryId) {
return new PagedIterable<>(
tmpl("/help_center/categories/{categoryId}/translations.json")
.set("categoryId", categoryId),
handleList(Translation.class, "translations"));
}
public Translation showCategoryTranslation(long categoryId, String locale) {
return complete(
submit(
req(
"GET",
tmpl("/help_center/categories/{categoryId}/translations/{locale}.json")
.set("categoryId", categoryId)
.set("locale", locale)),
handle(Translation.class, "translation")));
}
public Category createCategory(Category category) {
return complete(
submit(
req(
"POST",
cnst("/help_center/categories.json"),
JSON,
json(Collections.singletonMap("category", category))),
handle(Category.class, "category")));
}
public Category updateCategory(Category category) {
checkHasId(category);
return complete(
submit(
req(
"PUT",
tmpl("/help_center/categories/{id}.json").set("id", category.getId()),
JSON,
json(Collections.singletonMap("category", category))),
handle(Category.class, "category")));
}
public Translation createCategoryTranslation(Long categoryId, Translation translation) {
checkHasCategoryId(categoryId);
return complete(
submit(
req(
"POST",
tmpl("/help_center/categories/{id}/translations.json").set("id", categoryId),
JSON,
json(Collections.singletonMap("translation", translation))),
handle(Translation.class, "translation")));
}
public Translation updateCategoryTranslation(
Long categoryId, String locale, Translation translation) {
checkHasId(translation);
return complete(
submit(
req(
"PUT",
tmpl("/help_center/categories/{id}/translations/{locale}.json")
.set("id", categoryId)
.set("locale", locale),
JSON,
json(Collections.singletonMap("translation", translation))),
handle(Translation.class, "translation")));
}
public void deleteCategory(Category category) {
checkHasId(category);
complete(
submit(
req("DELETE", tmpl("/help_center/categories/{id}.json").set("id", category.getId())),
handleStatus()));
}
public Iterable getSections() {
return new PagedIterable<>(
cnst("/help_center/sections.json"), handleList(Section.class, "sections"));
}
public Iterable getSections(Category category) {
checkHasId(category);
return new PagedIterable<>(
tmpl("/help_center/categories/{id}/sections.json").set("id", category.getId()),
handleList(Section.class, "sections"));
}
public Section getSection(long id) {
return complete(
submit(
req("GET", tmpl("/help_center/sections/{id}.json").set("id", id)),
handle(Section.class, "section")));
}
public Iterable getSectionTranslations(Long sectionId) {
return new PagedIterable<>(
tmpl("/help_center/sections/{sectionId}/translations.json").set("sectionId", sectionId),
handleList(Translation.class, "translations"));
}
public Translation showSectionTranslation(long sectionId, String locale) {
return complete(
submit(
req(
"GET",
tmpl("/help_center/sections/{sectionId}/translations/{locale}.json")
.set("sectionId", sectionId)
.set("locale", locale)),
handle(Translation.class, "translation")));
}
public Section createSection(Section section) {
checkHasCategoryId(section);
return complete(
submit(
req(
"POST",
tmpl("/help_center/categories/{id}/sections.json")
.set("id", section.getCategoryId()),
JSON,
json(Collections.singletonMap("section", section))),
handle(Section.class, "section")));
}
public Section updateSection(Section section) {
checkHasId(section);
return complete(
submit(
req(
"PUT",
tmpl("/help_center/sections/{id}.json").set("id", section.getId()),
JSON,
json(Collections.singletonMap("section", section))),
handle(Section.class, "section")));
}
public Translation createSectionTranslation(Long sectionId, Translation translation) {
checkHasSectionId(sectionId);
return complete(
submit(
req(
"POST",
tmpl("/help_center/sections/{id}/translations.json").set("id", sectionId),
JSON,
json(Collections.singletonMap("translation", translation))),
handle(Translation.class, "translation")));
}
public Translation updateSectionTranslation(
Long sectionId, String locale, Translation translation) {
checkHasId(translation);
return complete(
submit(
req(
"PUT",
tmpl("/help_center/sections/{id}/translations/{locale}.json")
.set("id", sectionId)
.set("locale", locale),
JSON,
json(Collections.singletonMap("translation", translation))),
handle(Translation.class, "translation")));
}
public void deleteSection(Section section) {
checkHasId(section);
complete(
submit(
req("DELETE", tmpl("/help_center/sections/{id}.json").set("id", section.getId())),
handleStatus()));
}
public Iterable getUserSubscriptions(User user) {
checkHasId(user);
return getUserSubscriptions(user.getId());
}
public Iterable getUserSubscriptions(Long userId) {
return new PagedIterable<>(
tmpl("/help_center/users/{userId}/subscriptions.json").set("userId", userId),
handleList(Subscription.class, "subscriptions"));
}
public Iterable getArticleSubscriptions(Long articleId) {
return getArticleSubscriptions(articleId, null);
}
public Iterable getArticleSubscriptions(Long articleId, String locale) {
return new PagedIterable<>(
tmpl("/help_center{/locale}/articles/{articleId}/subscriptions.json")
.set("locale", locale)
.set("articleId", articleId),
handleList(Subscription.class, "subscriptions"));
}
public Iterable getSectionSubscriptions(Long sectionId) {
return getSectionSubscriptions(sectionId, null);
}
public Iterable getSectionSubscriptions(Long sectionId, String locale) {
return new PagedIterable<>(
tmpl("/help_center{/locale}/sections/{sectionId}/subscriptions.json")
.set("locale", locale)
.set("sectionId", sectionId),
handleList(Subscription.class, "subscriptions"));
}
/**
* Get a list of the current business hours schedules
*
* @return A List of Schedules
*/
public Iterable getSchedules() {
return complete(
submit(
req("GET", cnst("/business_hours/schedules.json")),
handleList(Schedule.class, "schedules")));
}
public Schedule getSchedule(Schedule schedule) {
checkHasId(schedule);
return getSchedule(schedule.getId());
}
public Schedule getSchedule(Long scheduleId) {
return complete(
submit(
req("GET", tmpl("/business_hours/schedules/{id}.json").set("id", scheduleId)),
handle(Schedule.class, "schedule")));
}
public Iterable getHolidaysForSchedule(Schedule schedule) {
checkHasId(schedule);
return getHolidaysForSchedule(schedule.getId());
}
public Iterable getHolidaysForSchedule(Long scheduleId) {
return complete(
submit(
req("GET", tmpl("/business_hours/schedules/{id}/holidays.json").set("id", scheduleId)),
handleList(Holiday.class, "holidays")));
}
public ContentTag getContentTag(String contentTagId) {
return complete(
submit(
req("GET", tmpl("/guide/content_tags/{id}").set("id", contentTagId)),
handle(ContentTag.class, "content_tag")));
}
public ContentTag createContentTag(ContentTag contentTag) {
checkHasName(contentTag);
return complete(
submit(
req(
"POST",
cnst("/guide/content_tags"),
JSON,
json(Collections.singletonMap("content_tag", contentTag))),
handle(ContentTag.class, "content_tag")));
}
public ContentTag updateContentTag(ContentTag contentTag) {
checkHasId(contentTag);
checkHasName(contentTag);
return complete(
submit(
req(
"PUT",
tmpl("/guide/content_tags/{id}").set("id", contentTag.getId()),
JSON,
json(Collections.singletonMap("content_tag", contentTag))),
handle(ContentTag.class, "content_tag")));
}
public void deleteContentTag(ContentTag contentTag) {
checkHasId(contentTag);
complete(
submit(
req("DELETE", tmpl("/guide/content_tags/{id}").set("id", contentTag.getId())),
handleStatus()));
}
public Iterable getContentTags() {
int defaultPageSize = 10;
return getContentTags(defaultPageSize, null);
}
public Iterable getContentTags(int pageSize) {
return getContentTags(pageSize, null);
}
public Iterable getContentTags(int pageSize, String namePrefix) {
Function afterCursorUriBuilder =
(String afterCursor) -> buildContentTagsSearchUrl(pageSize, namePrefix, afterCursor);
return new PagedIterable<>(
afterCursorUriBuilder.apply(null),
handleListWithAfterCursorButNoLinks(ContentTag.class, afterCursorUriBuilder, "records"));
}
public Iterable getJiraLinks() {
return new PagedIterable<>(cnst("/jira/links"), handleList(JiraLink.class, "links"));
}
private Uri buildContentTagsSearchUrl(int pageSize, String namePrefixFilter, String afterCursor) {
final StringBuilder uriBuilder =
new StringBuilder("/guide/content_tags?page[size]=").append(pageSize);
if (namePrefixFilter != null) {
uriBuilder.append("&filter[name_prefix]=").append(encodeUrl(namePrefixFilter));
}
if (afterCursor != null) {
uriBuilder.append("&page[after]=").append(encodeUrl(afterCursor));
}
return cnst(uriBuilder.toString());
}
public List getTimeZones() {
return complete(
submit(req("GET", cnst("/time_zones.json")), handleList(TimeZone.class, "time_zones")));
}
//////////////////////////////////////////////////////////////////////
// Helper methods
//////////////////////////////////////////////////////////////////////
private byte[] json(Object object) {
try {
return mapper.writeValueAsBytes(object);
} catch (JsonProcessingException e) {
throw new ZendeskException(e.getMessage(), e);
}
}
private ListenableFuture submit(
Request request, ZendeskAsyncCompletionHandler handler) {
if (logger.isDebugEnabled()) {
if (request.getStringData() != null) {
logger.debug(
"Request {} {}\n{}", request.getMethod(), request.getUrl(), request.getStringData());
} else if (request.getByteData() != null) {
logger.debug(
"Request {} {} {} {} bytes",
request.getMethod(),
request.getUrl(),
request.getHeaders().get("Content-type"),
request.getByteData().length);
} else {
logger.debug("Request {} {}", request.getMethod(), request.getUrl());
}
}
return client.executeRequest(request, handler);
}
private abstract static class ZendeskAsyncCompletionHandler extends AsyncCompletionHandler {
@Override
public void onThrowable(Throwable t) {
if (t instanceof IOException) {
throw new ZendeskException(t);
} else {
super.onThrowable(t);
}
}
}
private Request req(String method, Uri template) {
return req(method, template.toString());
}
private Request req(String method, String url) {
return reqBuilder(method, url).build();
}
private Request req(String method, Uri template, String contentType, byte[] body) {
RequestBuilder builder = reqBuilder(method, template.toString());
builder.addHeader("Content-type", contentType);
builder.setBody(body);
return builder.build();
}
private RequestBuilder reqBuilder(String method, String url) {
RequestBuilder builder = new RequestBuilder(method);
if (realm != null) {
builder.setRealm(realm);
} else {
builder.addHeader("Authorization", "Bearer " + oauthToken);
}
headers.forEach(builder::setHeader);
return builder.setUrl(url);
}
protected ZendeskAsyncCompletionHandler handleStatus() {
return new ZendeskAsyncCompletionHandler() {
@Override
public Void onCompleted(Response response) throws Exception {
logResponse(response);
if (isStatus2xx(response)) {
return null;
} else if (isRateLimitResponse(response)) {
throw new ZendeskResponseRateLimitException(response);
}
throw new ZendeskResponseException(response);
}
};
}
@SuppressWarnings("unchecked")
protected ZendeskAsyncCompletionHandler handle(final Class clazz) {
return new ZendeskAsyncCompletionHandler() {
@Override
public T onCompleted(Response response) throws Exception {
logResponse(response);
if (isStatus2xx(response)) {
return (T) mapper.readerFor(clazz).readValue(response.getResponseBodyAsStream());
} else if (isRateLimitResponse(response)) {
throw new ZendeskResponseRateLimitException(response);
}
if (response.getStatusCode() == 404) {
return null;
}
throw new ZendeskResponseException(response);
}
};
}
private class BasicAsyncCompletionHandler extends ZendeskAsyncCompletionHandler {
private final Class clazz;
private final String name;
private final Class[] typeParams;
public BasicAsyncCompletionHandler(Class clazz, String name, Class... typeParams) {
this.clazz = clazz;
this.name = name;
this.typeParams = typeParams;
}
@Override
public T onCompleted(Response response) throws Exception {
logResponse(response);
if (isStatus2xx(response)) {
if (typeParams.length > 0) {
JavaType type = mapper.getTypeFactory().constructParametricType(clazz, typeParams);
return mapper.convertValue(
mapper.readTree(response.getResponseBodyAsStream()).get(name), type);
}
return mapper.convertValue(
mapper.readTree(response.getResponseBodyAsStream()).get(name), clazz);
} else if (isRateLimitResponse(response)) {
throw new ZendeskResponseRateLimitException(response);
}
if (response.getStatusCode() == 404) {
return null;
}
throw new ZendeskResponseException(response);
}
}
protected ZendeskAsyncCompletionHandler handle(
final Class clazz, final String name, final Class... typeParams) {
return new BasicAsyncCompletionHandler<>(clazz, name, typeParams);
}
protected ZendeskAsyncCompletionHandler handleJobStatus() {
return new BasicAsyncCompletionHandler(JobStatus.class, "job_status") {
@Override
public JobStatus onCompleted(Response response) throws Exception {
JobStatus result = super.onCompleted(response);
if (result == null) {
// null is when we receive a 404 response.
// For an async job we trigger an error
throw new ZendeskResponseException(response);
}
return result;
}
};
}
private static final String CURSOR_LINKS = "links";
private static final String CURSOR_NEXT_PAGE = "next";
private static final String NEXT_PAGE = "next_page";
private static final String END_TIME = "end_time";
private static final String COUNT = "count";
private static final int INCREMENTAL_EXPORT_MAX_COUNT_BY_REQUEST = 1000;
private abstract class PagedAsyncCompletionHandler extends ZendeskAsyncCompletionHandler {
private String nextPage;
public void setPagedProperties(JsonNode responseNode, Class> clazz) {
JsonNode node = responseNode.get(CURSOR_LINKS);
// Attempt to use cursor pagination if possible
if (node != null) {
node = node.get(CURSOR_NEXT_PAGE);
} else {
node = responseNode.get(NEXT_PAGE);
}
if (node == null) {
this.nextPage = null;
if (logger.isDebugEnabled()) {
logger.debug(
NEXT_PAGE
+ " property not found, pagination not supported"
+ (clazz != null ? " for " + clazz.getName() : ""));
}
} else {
this.nextPage = node.asText();
}
}
public String getNextPage() {
return nextPage;
}
public void setNextPage(String nextPage) {
this.nextPage = nextPage;
}
}
private class PagedAsyncListCompletionHandler extends PagedAsyncCompletionHandler