embulk-input-zendesk-all 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.travis.yml +5 -0
- data/CHANGELOG.md +126 -0
- data/LICENSE.txt +21 -0
- data/README.md +91 -0
- data/build.gradle +123 -0
- data/config/checkstyle/checkstyle.xml +128 -0
- data/config/checkstyle/default.xml +108 -0
- data/gradle/wrapper/gradle-wrapper.jar +0 -0
- data/gradle/wrapper/gradle-wrapper.properties +5 -0
- data/gradlew +172 -0
- data/gradlew.bat +84 -0
- data/lib/embulk/guess/zendesk.rb +21 -0
- data/lib/embulk/input/zendesk.rb +3 -0
- data/src/main/java/org/embulk/input/zendesk/RecordImporter.java +134 -0
- data/src/main/java/org/embulk/input/zendesk/ZendeskInputPlugin.java +513 -0
- data/src/main/java/org/embulk/input/zendesk/clients/ZendeskRestClient.java +291 -0
- data/src/main/java/org/embulk/input/zendesk/models/AuthenticationMethod.java +23 -0
- data/src/main/java/org/embulk/input/zendesk/models/Target.java +47 -0
- data/src/main/java/org/embulk/input/zendesk/models/ZendeskException.java +25 -0
- data/src/main/java/org/embulk/input/zendesk/services/ZendeskCustomObjectService.java +110 -0
- data/src/main/java/org/embulk/input/zendesk/services/ZendeskNPSService.java +30 -0
- data/src/main/java/org/embulk/input/zendesk/services/ZendeskNormalServices.java +347 -0
- data/src/main/java/org/embulk/input/zendesk/services/ZendeskService.java +14 -0
- data/src/main/java/org/embulk/input/zendesk/services/ZendeskSupportAPIService.java +63 -0
- data/src/main/java/org/embulk/input/zendesk/services/ZendeskUserEventService.java +158 -0
- data/src/main/java/org/embulk/input/zendesk/stream/PagingSpliterator.java +40 -0
- data/src/main/java/org/embulk/input/zendesk/stream/paginator/sunshine/CustomObjectSpliterator.java +42 -0
- data/src/main/java/org/embulk/input/zendesk/stream/paginator/sunshine/SunshineSpliterator.java +66 -0
- data/src/main/java/org/embulk/input/zendesk/stream/paginator/sunshine/UserEventSpliterator.java +35 -0
- data/src/main/java/org/embulk/input/zendesk/stream/paginator/support/OrganizationSpliterator.java +13 -0
- data/src/main/java/org/embulk/input/zendesk/stream/paginator/support/SupportSpliterator.java +44 -0
- data/src/main/java/org/embulk/input/zendesk/stream/paginator/support/UserSpliterator.java +13 -0
- data/src/main/java/org/embulk/input/zendesk/utils/ZendeskConstants.java +72 -0
- data/src/main/java/org/embulk/input/zendesk/utils/ZendeskDateUtils.java +68 -0
- data/src/main/java/org/embulk/input/zendesk/utils/ZendeskUtils.java +92 -0
- data/src/test/java/org/embulk/input/zendesk/TestRecordImporter.java +114 -0
- data/src/test/java/org/embulk/input/zendesk/TestZendeskInputPlugin.java +402 -0
- data/src/test/java/org/embulk/input/zendesk/clients/TestZendeskRestClient.java +337 -0
- data/src/test/java/org/embulk/input/zendesk/services/TestZendeskCustomObjectService.java +161 -0
- data/src/test/java/org/embulk/input/zendesk/services/TestZendeskNPSService.java +56 -0
- data/src/test/java/org/embulk/input/zendesk/services/TestZendeskNormalService.java +261 -0
- data/src/test/java/org/embulk/input/zendesk/services/TestZendeskSupportAPIService.java +130 -0
- data/src/test/java/org/embulk/input/zendesk/services/TestZendeskUserEventService.java +158 -0
- data/src/test/java/org/embulk/input/zendesk/utils/TestZendeskDateUtils.java +87 -0
- data/src/test/java/org/embulk/input/zendesk/utils/TestZendeskUtil.java +22 -0
- data/src/test/java/org/embulk/input/zendesk/utils/ZendeskPluginTestRuntime.java +133 -0
- data/src/test/java/org/embulk/input/zendesk/utils/ZendeskTestHelper.java +92 -0
- data/src/test/resources/config/base.yml +14 -0
- data/src/test/resources/config/base_validator.yml +48 -0
- data/src/test/resources/config/incremental.yml +54 -0
- data/src/test/resources/config/non-incremental.yml +39 -0
- data/src/test/resources/config/nps.yml +31 -0
- data/src/test/resources/config/object_records.yml +24 -0
- data/src/test/resources/config/relationship_records.yml +23 -0
- data/src/test/resources/config/user_events.yml +29 -0
- data/src/test/resources/config/util.yml +18 -0
- data/src/test/resources/data/client.json +293 -0
- data/src/test/resources/data/duplicate_user.json +0 -0
- data/src/test/resources/data/empty_result.json +7 -0
- data/src/test/resources/data/error_data.json +187 -0
- data/src/test/resources/data/expected/ticket_column.json +148 -0
- data/src/test/resources/data/expected/ticket_column_with_related_objects.json +152 -0
- data/src/test/resources/data/expected/ticket_fields_column.json +92 -0
- data/src/test/resources/data/expected/ticket_metrics_column.json +98 -0
- data/src/test/resources/data/expected/user_events_column.json +40 -0
- data/src/test/resources/data/object_records.json +30 -0
- data/src/test/resources/data/organization.json +39 -0
- data/src/test/resources/data/relationship_records.json +57 -0
- data/src/test/resources/data/scores.json +21 -0
- data/src/test/resources/data/scores_share_same_time_with_next_page.json +35 -0
- data/src/test/resources/data/scores_share_same_time_without_next_page.json +35 -0
- data/src/test/resources/data/simple_organization.json +23 -0
- data/src/test/resources/data/simple_user.json +50 -0
- data/src/test/resources/data/simple_user_event.json +19 -0
- data/src/test/resources/data/ticket_events_share_same_time_with_next_page.json +279 -0
- data/src/test/resources/data/ticket_events_share_same_time_without_next_page.json +279 -0
- data/src/test/resources/data/ticket_events_updated_by_system_records.json +279 -0
- data/src/test/resources/data/ticket_fields.json +225 -0
- data/src/test/resources/data/ticket_metrics.json +397 -0
- data/src/test/resources/data/ticket_share_same_time_with_next_page.json +232 -0
- data/src/test/resources/data/ticket_share_same_time_without_next_page.json +232 -0
- data/src/test/resources/data/ticket_with_related_objects.json +67 -0
- data/src/test/resources/data/ticket_with_updated_by_system_records.json +187 -0
- data/src/test/resources/data/tickets.json +232 -0
- data/src/test/resources/data/tickets_continue.json +52 -0
- data/src/test/resources/data/user_event.json +19 -0
- data/src/test/resources/data/user_event_contain_latter_create_at.json +19 -0
- data/src/test/resources/data/user_event_multiple.json +33 -0
- data/src/test/resources/data/util.json +19 -0
- data/src/test/resources/data/util_page.json +227 -0
- metadata +168 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
package org.embulk.input.zendesk.services;
|
|
2
|
+
|
|
3
|
+
import com.fasterxml.jackson.databind.JsonNode;
|
|
4
|
+
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
5
|
+
import com.google.common.annotations.VisibleForTesting;
|
|
6
|
+
import org.apache.http.client.utils.URIBuilder;
|
|
7
|
+
import org.embulk.config.TaskReport;
|
|
8
|
+
import org.embulk.input.zendesk.RecordImporter;
|
|
9
|
+
import org.embulk.input.zendesk.ZendeskInputPlugin;
|
|
10
|
+
import org.embulk.input.zendesk.clients.ZendeskRestClient;
|
|
11
|
+
import org.embulk.input.zendesk.models.Target;
|
|
12
|
+
import org.embulk.input.zendesk.stream.paginator.sunshine.UserEventSpliterator;
|
|
13
|
+
import org.embulk.input.zendesk.stream.paginator.support.OrganizationSpliterator;
|
|
14
|
+
import org.embulk.input.zendesk.stream.paginator.support.UserSpliterator;
|
|
15
|
+
import org.embulk.input.zendesk.utils.ZendeskConstants;
|
|
16
|
+
import org.embulk.input.zendesk.utils.ZendeskDateUtils;
|
|
17
|
+
import org.embulk.input.zendesk.utils.ZendeskUtils;
|
|
18
|
+
import org.embulk.spi.DataException;
|
|
19
|
+
import org.embulk.spi.Exec;
|
|
20
|
+
|
|
21
|
+
import java.io.IOException;
|
|
22
|
+
import java.time.Instant;
|
|
23
|
+
import java.util.List;
|
|
24
|
+
import java.util.Set;
|
|
25
|
+
import java.util.concurrent.ConcurrentHashMap;
|
|
26
|
+
import java.util.stream.Collectors;
|
|
27
|
+
import java.util.stream.Stream;
|
|
28
|
+
import java.util.stream.StreamSupport;
|
|
29
|
+
|
|
30
|
+
public class ZendeskUserEventService implements ZendeskService
|
|
31
|
+
{
|
|
32
|
+
protected ZendeskInputPlugin.PluginTask task;
|
|
33
|
+
|
|
34
|
+
private ZendeskRestClient zendeskRestClient;
|
|
35
|
+
|
|
36
|
+
public ZendeskUserEventService(final ZendeskInputPlugin.PluginTask task)
|
|
37
|
+
{
|
|
38
|
+
this.task = task;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public boolean isSupportIncremental()
|
|
42
|
+
{
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@Override
|
|
47
|
+
public TaskReport addRecordToImporter(final int taskIndex, final RecordImporter recordImporter)
|
|
48
|
+
{
|
|
49
|
+
final TaskReport taskReport = Exec.newTaskReport();
|
|
50
|
+
|
|
51
|
+
if (Exec.isPreview()) {
|
|
52
|
+
JsonNode jsonNode = mockJsonNode();
|
|
53
|
+
recordImporter.addRecord(jsonNode.get(0));
|
|
54
|
+
return taskReport;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
final List<JsonNode> organizations = StreamSupport.stream(new OrganizationSpliterator(buildOrganizationURI(), getZendeskRestClient(), task), false)
|
|
58
|
+
.collect(Collectors.toList());
|
|
59
|
+
final Set<String> knownUserIds = ConcurrentHashMap.newKeySet();
|
|
60
|
+
organizations.parallelStream().forEach(
|
|
61
|
+
organization -> {
|
|
62
|
+
Stream<JsonNode> stream = StreamSupport.stream(new UserSpliterator(buildOrganizationWithUserURI(organization.get("url").asText()),
|
|
63
|
+
getZendeskRestClient(), task, Exec.isPreview()), true);
|
|
64
|
+
|
|
65
|
+
if (task.getDedup()) {
|
|
66
|
+
stream = stream.filter(item -> knownUserIds.add(item.get("id").asText()));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
stream.forEach(s ->
|
|
70
|
+
{
|
|
71
|
+
Stream<JsonNode> userEventStream = StreamSupport.stream(new UserEventSpliterator(s.get("id").asText(), buildUserEventURI(s.get("id").asText()),
|
|
72
|
+
getZendeskRestClient(), task, Exec.isPreview()), true);
|
|
73
|
+
userEventStream.forEach(recordImporter::addRecord);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
return taskReport;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@Override
|
|
81
|
+
public JsonNode getDataFromPath(final String path, final int page, final boolean isPreview, final long startTime)
|
|
82
|
+
{
|
|
83
|
+
return new ObjectMapper().createObjectNode().set(task.getTarget().getJsonName(), mockJsonNode());
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@VisibleForTesting
|
|
87
|
+
protected ZendeskRestClient getZendeskRestClient()
|
|
88
|
+
{
|
|
89
|
+
if (zendeskRestClient == null) {
|
|
90
|
+
zendeskRestClient = new ZendeskRestClient();
|
|
91
|
+
}
|
|
92
|
+
return zendeskRestClient;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private String buildOrganizationURI()
|
|
96
|
+
{
|
|
97
|
+
return ZendeskUtils.getURIBuilder(task.getLoginUrl())
|
|
98
|
+
.setPath(ZendeskConstants.Url.API + "/" + Target.ORGANIZATIONS.getJsonName())
|
|
99
|
+
.setParameter("per_page", "100")
|
|
100
|
+
.setParameter("page", "1")
|
|
101
|
+
.toString();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private String buildOrganizationWithUserURI(final String path)
|
|
105
|
+
{
|
|
106
|
+
return path.replace(".json", "")
|
|
107
|
+
+ "/users.json?per_page=100&page=1";
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
private String buildUserEventURI(final String userID)
|
|
111
|
+
{
|
|
112
|
+
final URIBuilder uriBuilder = ZendeskUtils.getURIBuilder(task.getLoginUrl())
|
|
113
|
+
.setPath(ZendeskConstants.Url.API_USER_EVENT)
|
|
114
|
+
.setParameter("identifier", task.getProfileSource().get() + ":user_id:" + userID);
|
|
115
|
+
|
|
116
|
+
task.getUserEventSource().ifPresent(eventSource -> uriBuilder.setParameter("source", eventSource));
|
|
117
|
+
task.getUserEventType().ifPresent(eventType -> uriBuilder.setParameter("type", eventType));
|
|
118
|
+
task.getStartTime().ifPresent(startTime -> {
|
|
119
|
+
try {
|
|
120
|
+
uriBuilder.setParameter("start_time", ZendeskDateUtils.convertToDateTimeFormat(startTime, ZendeskConstants.Misc.ISO_INSTANT));
|
|
121
|
+
}
|
|
122
|
+
catch (DataException e) {
|
|
123
|
+
uriBuilder.setParameter("start_time", ZendeskDateUtils.convertToDateTimeFormat(Instant.EPOCH.toString(), ZendeskConstants.Misc.ISO_INSTANT));
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
task.getEndTime().ifPresent(endTime -> uriBuilder.setParameter("end_time", ZendeskDateUtils.convertToDateTimeFormat(endTime, ZendeskConstants.Misc.ISO_INSTANT)));
|
|
128
|
+
|
|
129
|
+
return uriBuilder.toString();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
private JsonNode mockJsonNode()
|
|
133
|
+
{
|
|
134
|
+
try {
|
|
135
|
+
String mockData = "[\n" +
|
|
136
|
+
" {\n" +
|
|
137
|
+
" \"id\": \"5c7f31aef8df240001e60bbf\",\n" +
|
|
138
|
+
" \"type\": \"remove_from_cart\",\n" +
|
|
139
|
+
" \"source\": \"shopify\",\n" +
|
|
140
|
+
" \"description\": \"\",\n" +
|
|
141
|
+
" \"authenticated\": true,\n" +
|
|
142
|
+
" \"created_at\": \"2019-03-06T02:34:22Z\",\n" +
|
|
143
|
+
" \"received_at\": \"2019-03-06T02:34:22Z\",\n" +
|
|
144
|
+
" \"properties\": {\n" +
|
|
145
|
+
" \"model\": 221,\n" +
|
|
146
|
+
" \"size\": 6\n" +
|
|
147
|
+
" },\n" +
|
|
148
|
+
" \"user_id\": \"12312354234\"\n" +
|
|
149
|
+
" }\n" +
|
|
150
|
+
"]";
|
|
151
|
+
|
|
152
|
+
return new ObjectMapper().readTree(mockData);
|
|
153
|
+
}
|
|
154
|
+
catch (IOException ex) {
|
|
155
|
+
throw new RuntimeException("Can not create sample data " + ex.getMessage());
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
package org.embulk.input.zendesk.stream;
|
|
2
|
+
|
|
3
|
+
import org.embulk.input.zendesk.ZendeskInputPlugin;
|
|
4
|
+
import org.embulk.input.zendesk.clients.ZendeskRestClient;
|
|
5
|
+
|
|
6
|
+
import java.util.Spliterator;
|
|
7
|
+
|
|
8
|
+
public abstract class PagingSpliterator<E> implements Spliterator<E>
|
|
9
|
+
{
|
|
10
|
+
protected ZendeskRestClient zendeskRestClient;
|
|
11
|
+
protected boolean isPreview;
|
|
12
|
+
protected ZendeskInputPlugin.PluginTask task;
|
|
13
|
+
protected String path;
|
|
14
|
+
|
|
15
|
+
protected PagingSpliterator(final String path, final ZendeskRestClient zendeskRestClient, final ZendeskInputPlugin.PluginTask task, final boolean isPreview)
|
|
16
|
+
{
|
|
17
|
+
this.path = path;
|
|
18
|
+
this.zendeskRestClient = zendeskRestClient;
|
|
19
|
+
this.task = task;
|
|
20
|
+
this.isPreview = isPreview;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@Override
|
|
24
|
+
public Spliterator<E> trySplit()
|
|
25
|
+
{
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@Override
|
|
30
|
+
public int characteristics()
|
|
31
|
+
{
|
|
32
|
+
return DISTINCT | NONNULL | IMMUTABLE;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@Override
|
|
36
|
+
public long estimateSize()
|
|
37
|
+
{
|
|
38
|
+
return Long.MAX_VALUE;
|
|
39
|
+
}
|
|
40
|
+
}
|
data/src/main/java/org/embulk/input/zendesk/stream/paginator/sunshine/CustomObjectSpliterator.java
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
package org.embulk.input.zendesk.stream.paginator.sunshine;
|
|
2
|
+
|
|
3
|
+
import com.fasterxml.jackson.databind.JsonNode;
|
|
4
|
+
import org.embulk.input.zendesk.ZendeskInputPlugin;
|
|
5
|
+
import org.embulk.input.zendesk.clients.ZendeskRestClient;
|
|
6
|
+
import org.embulk.input.zendesk.utils.ZendeskUtils;
|
|
7
|
+
|
|
8
|
+
import java.util.Iterator;
|
|
9
|
+
import java.util.function.Consumer;
|
|
10
|
+
|
|
11
|
+
public class CustomObjectSpliterator extends SunshineSpliterator
|
|
12
|
+
{
|
|
13
|
+
public CustomObjectSpliterator(final String path, final ZendeskRestClient zendeskRestClient, final ZendeskInputPlugin.PluginTask task, final boolean isPreview)
|
|
14
|
+
{
|
|
15
|
+
super(path, zendeskRestClient, task, isPreview);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@Override
|
|
19
|
+
protected boolean isContinue(final JsonNode jsonNode, final Consumer<? super JsonNode> action)
|
|
20
|
+
{
|
|
21
|
+
final Iterator<JsonNode> iterator = ZendeskUtils.getListRecords(jsonNode, task.getTarget().getJsonName());
|
|
22
|
+
|
|
23
|
+
if (isPreview) {
|
|
24
|
+
if (iterator.hasNext()) {
|
|
25
|
+
JsonNode item = iterator.next();
|
|
26
|
+
// we have data for preview, no need to continue
|
|
27
|
+
if (item != null && !item.isNull()) {
|
|
28
|
+
action.accept(item);
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
handleRunIterator(iterator, action);
|
|
34
|
+
|
|
35
|
+
if (jsonNode.has("links") && !ZendeskUtils.isNull(jsonNode.get("links"))
|
|
36
|
+
&& jsonNode.get("links").has("next") && !ZendeskUtils.isNull(jsonNode.get("links").get("next"))) {
|
|
37
|
+
path = task.getLoginUrl() + jsonNode.get("links").get("next");
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
data/src/main/java/org/embulk/input/zendesk/stream/paginator/sunshine/SunshineSpliterator.java
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
package org.embulk.input.zendesk.stream.paginator.sunshine;
|
|
2
|
+
|
|
3
|
+
import com.fasterxml.jackson.databind.JsonNode;
|
|
4
|
+
import org.apache.http.HttpStatus;
|
|
5
|
+
import org.embulk.config.ConfigException;
|
|
6
|
+
import org.embulk.input.zendesk.ZendeskInputPlugin;
|
|
7
|
+
import org.embulk.input.zendesk.clients.ZendeskRestClient;
|
|
8
|
+
import org.embulk.input.zendesk.models.ZendeskException;
|
|
9
|
+
import org.embulk.input.zendesk.stream.PagingSpliterator;
|
|
10
|
+
import org.embulk.input.zendesk.utils.ZendeskUtils;
|
|
11
|
+
|
|
12
|
+
import java.util.Iterator;
|
|
13
|
+
import java.util.function.Consumer;
|
|
14
|
+
|
|
15
|
+
public class SunshineSpliterator extends PagingSpliterator<JsonNode>
|
|
16
|
+
{
|
|
17
|
+
public SunshineSpliterator(final String path, final ZendeskRestClient zendeskRestClient, final ZendeskInputPlugin.PluginTask task, final boolean isPreview)
|
|
18
|
+
{
|
|
19
|
+
super(path, zendeskRestClient, task, isPreview);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@Override
|
|
23
|
+
public boolean tryAdvance(final Consumer<? super JsonNode> action)
|
|
24
|
+
{
|
|
25
|
+
try {
|
|
26
|
+
final String result = zendeskRestClient.doGet(path, task, isPreview);
|
|
27
|
+
|
|
28
|
+
if (result != null && !result.isEmpty()) {
|
|
29
|
+
final JsonNode jsonNode = ZendeskUtils.parseJsonObject(result);
|
|
30
|
+
final JsonNode targetJsonNode = jsonNode.get(task.getTarget().getJsonName());
|
|
31
|
+
if (!ZendeskUtils.isNull(targetJsonNode)) {
|
|
32
|
+
return isContinue(jsonNode, action);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (final ConfigException e) {
|
|
37
|
+
if (!(e.getCause() instanceof ZendeskException && ((ZendeskException) e.getCause()).getStatusCode() == HttpStatus.SC_NOT_FOUND)) {
|
|
38
|
+
throw e;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
protected void handleRunIterator(Iterator<JsonNode> iterator, final Consumer<? super JsonNode> action)
|
|
45
|
+
{
|
|
46
|
+
iterator.forEachRemaining(
|
|
47
|
+
item -> {
|
|
48
|
+
if (item != null && !item.isNull()) {
|
|
49
|
+
action.accept(iterator.next());
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
protected boolean isContinue(final JsonNode jsonNode, final Consumer<? super JsonNode> action)
|
|
55
|
+
{
|
|
56
|
+
final Iterator<JsonNode> iterator = ZendeskUtils.getListRecords(jsonNode, task.getTarget().getJsonName());
|
|
57
|
+
handleRunIterator(iterator, action);
|
|
58
|
+
|
|
59
|
+
if (jsonNode.has("links") && !ZendeskUtils.isNull(jsonNode.get("links"))
|
|
60
|
+
&& jsonNode.get("links").has("next") && !ZendeskUtils.isNull(jsonNode.get("links").get("next"))) {
|
|
61
|
+
path = task.getLoginUrl() + jsonNode.get("links").get("next");
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
}
|
data/src/main/java/org/embulk/input/zendesk/stream/paginator/sunshine/UserEventSpliterator.java
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
package org.embulk.input.zendesk.stream.paginator.sunshine;
|
|
2
|
+
|
|
3
|
+
import com.fasterxml.jackson.databind.JsonNode;
|
|
4
|
+
import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
5
|
+
import org.embulk.input.zendesk.ZendeskInputPlugin;
|
|
6
|
+
import org.embulk.input.zendesk.clients.ZendeskRestClient;
|
|
7
|
+
import org.embulk.input.zendesk.utils.ZendeskUtils;
|
|
8
|
+
|
|
9
|
+
import java.util.Iterator;
|
|
10
|
+
import java.util.function.Consumer;
|
|
11
|
+
|
|
12
|
+
public class UserEventSpliterator extends SunshineSpliterator
|
|
13
|
+
{
|
|
14
|
+
private String userID;
|
|
15
|
+
|
|
16
|
+
public UserEventSpliterator(final String userID, final String path, final ZendeskRestClient zendeskRestClient, final ZendeskInputPlugin.PluginTask task, final boolean isPreview)
|
|
17
|
+
{
|
|
18
|
+
super(path, zendeskRestClient, task, isPreview);
|
|
19
|
+
this.userID = userID;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@Override
|
|
23
|
+
protected void handleRunIterator(final Iterator<JsonNode> iterator, final Consumer<? super JsonNode> action)
|
|
24
|
+
{
|
|
25
|
+
iterator.forEachRemaining(
|
|
26
|
+
item -> {
|
|
27
|
+
if (!ZendeskUtils.isNull(item)) {
|
|
28
|
+
JsonNode temp = iterator.next();
|
|
29
|
+
// Because in the returned json doesn't have user_id, so we try to add to it
|
|
30
|
+
((ObjectNode) temp).put("user_id", this.userID);
|
|
31
|
+
action.accept(temp);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
data/src/main/java/org/embulk/input/zendesk/stream/paginator/support/OrganizationSpliterator.java
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
package org.embulk.input.zendesk.stream.paginator.support;
|
|
2
|
+
|
|
3
|
+
import org.embulk.input.zendesk.ZendeskInputPlugin;
|
|
4
|
+
import org.embulk.input.zendesk.clients.ZendeskRestClient;
|
|
5
|
+
import org.embulk.input.zendesk.models.Target;
|
|
6
|
+
|
|
7
|
+
public class OrganizationSpliterator extends SupportSpliterator
|
|
8
|
+
{
|
|
9
|
+
public OrganizationSpliterator(final String path, final ZendeskRestClient zendeskRestClient, final ZendeskInputPlugin.PluginTask task)
|
|
10
|
+
{
|
|
11
|
+
super(Target.ORGANIZATIONS, path, zendeskRestClient, task, false);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
package org.embulk.input.zendesk.stream.paginator.support;
|
|
2
|
+
|
|
3
|
+
import com.fasterxml.jackson.databind.JsonNode;
|
|
4
|
+
import org.embulk.input.zendesk.ZendeskInputPlugin;
|
|
5
|
+
import org.embulk.input.zendesk.clients.ZendeskRestClient;
|
|
6
|
+
import org.embulk.input.zendesk.models.Target;
|
|
7
|
+
import org.embulk.input.zendesk.stream.PagingSpliterator;
|
|
8
|
+
import org.embulk.input.zendesk.utils.ZendeskUtils;
|
|
9
|
+
|
|
10
|
+
import java.util.Iterator;
|
|
11
|
+
import java.util.function.Consumer;
|
|
12
|
+
|
|
13
|
+
public class SupportSpliterator extends PagingSpliterator<JsonNode>
|
|
14
|
+
{
|
|
15
|
+
Target target;
|
|
16
|
+
|
|
17
|
+
public SupportSpliterator(final Target target, final String path, final ZendeskRestClient zendeskRestClient, final ZendeskInputPlugin.PluginTask task, final boolean isPreview)
|
|
18
|
+
{
|
|
19
|
+
super(path, zendeskRestClient, task, isPreview);
|
|
20
|
+
this.target = target;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@Override
|
|
24
|
+
public boolean tryAdvance(final Consumer<? super JsonNode> action)
|
|
25
|
+
{
|
|
26
|
+
final String result = zendeskRestClient.doGet(path, task, isPreview);
|
|
27
|
+
if (result != null && !result.isEmpty()) {
|
|
28
|
+
final JsonNode jsonNode = ZendeskUtils.parseJsonObject(result);
|
|
29
|
+
final Iterator<JsonNode> iterator = ZendeskUtils.getListRecords(jsonNode, target.getJsonName());
|
|
30
|
+
iterator.forEachRemaining(
|
|
31
|
+
item -> {
|
|
32
|
+
if (!ZendeskUtils.isNull(item)) {
|
|
33
|
+
action.accept(item);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
if (jsonNode.get("next_page") != null && !jsonNode.get("next_page").isNull()) {
|
|
37
|
+
path = jsonNode.get("next_page").asText();
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
package org.embulk.input.zendesk.stream.paginator.support;
|
|
2
|
+
|
|
3
|
+
import org.embulk.input.zendesk.ZendeskInputPlugin;
|
|
4
|
+
import org.embulk.input.zendesk.clients.ZendeskRestClient;
|
|
5
|
+
import org.embulk.input.zendesk.models.Target;
|
|
6
|
+
|
|
7
|
+
public class UserSpliterator extends SupportSpliterator
|
|
8
|
+
{
|
|
9
|
+
public UserSpliterator(final String path, final ZendeskRestClient zendeskRestClient, final ZendeskInputPlugin.PluginTask task, final boolean isPreview)
|
|
10
|
+
{
|
|
11
|
+
super(Target.USERS, path, zendeskRestClient, task, isPreview);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
package org.embulk.input.zendesk.utils;
|
|
2
|
+
|
|
3
|
+
import com.google.common.collect.ImmutableList;
|
|
4
|
+
|
|
5
|
+
import java.util.Arrays;
|
|
6
|
+
import java.util.List;
|
|
7
|
+
|
|
8
|
+
public class ZendeskConstants
|
|
9
|
+
{
|
|
10
|
+
private ZendeskConstants()
|
|
11
|
+
{
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public static class Header
|
|
15
|
+
{
|
|
16
|
+
public static final String APPLICATION_JSON = "application/json";
|
|
17
|
+
|
|
18
|
+
public static final String ZENDESK_MARKETPLACE_NAME = "X-Zendesk-Marketplace-Name";
|
|
19
|
+
public static final String ZENDESK_MARKETPLACE_ORGANIZATION_ID = "X-Zendesk-Marketplace-Organization-Id";
|
|
20
|
+
public static final String ZENDESK_MARKETPLACE_APP_ID = "X-Zendesk-Marketplace-App-Id";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public static class Field
|
|
24
|
+
{
|
|
25
|
+
public static final String START_TIME = "start_time";
|
|
26
|
+
public static final String END_TIME = "end_time";
|
|
27
|
+
public static final String COUNT = "count";
|
|
28
|
+
public static final String GENERATED_TIMESTAMP = "generated_timestamp";
|
|
29
|
+
public static final String UPDATED_AT = "updated_at";
|
|
30
|
+
public static final String ID = "id";
|
|
31
|
+
public static final String NEXT_PAGE="next_page";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public static class Url
|
|
35
|
+
{
|
|
36
|
+
public static final String API = "/api/v2";
|
|
37
|
+
public static final String API_INCREMENTAL = API + "/incremental";
|
|
38
|
+
public static final String API_NPS_INCREMENTAL = API + "/nps/incremental";
|
|
39
|
+
public static final String API_OBJECT_RECORD = "api/sunshine/objects/records";
|
|
40
|
+
public static final String API_RELATIONSHIP_RECORD = "api/sunshine/relationships/records";
|
|
41
|
+
public static final String API_USER_EVENT = "api/sunshine/events";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public static class Misc
|
|
45
|
+
{
|
|
46
|
+
public static final String RUBY_TIMESTAMP_FORMAT = "%Y-%m-%dT%H:%M:%S%z";
|
|
47
|
+
public static final String RUBY_TIMESTAMP_FORMAT_INPUT = "uuuu-MM-dd HH:mm:ss Z";
|
|
48
|
+
public static final String JAVA_TIMESTAMP_FORMAT = "uuuu-MM-dd'T'HH:mm:ss.SSS'Z'";
|
|
49
|
+
public static final String ISO_TIMESTAMP_FORMAT = "uuuu-MM-dd'T'HH:mm:ssXXX";
|
|
50
|
+
public static final String ISO_INSTANT = "uuuu-MM-dd'T'HH:mm:ss'Z'";
|
|
51
|
+
public static final String RUBY_TIMESTAMP_FORMAT_INPUT_NO_SPACE = "uuuu-MM-dd HH:mm:ssZ";
|
|
52
|
+
public static final String TOO_RECENT_START_TIME = "Too recent start_time.";
|
|
53
|
+
public static final int RECORDS_SIZE_PER_PAGE = 100;
|
|
54
|
+
public static final int MAXIMUM_RECORDS_INCREMENTAL = 1000;
|
|
55
|
+
|
|
56
|
+
// 1 MB
|
|
57
|
+
public static final int GUESS_BUFFER_SIZE = 1024 * 1024;
|
|
58
|
+
public static final List<String> SUPPORT_DATE_TIME_FORMAT = ImmutableList.copyOf(Arrays.asList(ZendeskConstants.Misc.ISO_INSTANT, ZendeskConstants.Misc.RUBY_TIMESTAMP_FORMAT_INPUT,
|
|
59
|
+
ZendeskConstants.Misc.JAVA_TIMESTAMP_FORMAT, ZendeskConstants.Misc.ISO_TIMESTAMP_FORMAT,
|
|
60
|
+
ZendeskConstants.Misc.RUBY_TIMESTAMP_FORMAT_INPUT_NO_SPACE));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public static class Regex
|
|
64
|
+
{
|
|
65
|
+
public static final String ID = "_id$";
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
public static class HttpStatus
|
|
69
|
+
{
|
|
70
|
+
public static final int TOO_MANY_REQUEST = 429;
|
|
71
|
+
}
|
|
72
|
+
}
|