embulk-input-zendesk 0.3.4 → 0.3.5

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.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +3 -0
  3. data/README.md +32 -2
  4. data/build.gradle +1 -1
  5. data/src/main/java/org/embulk/input/zendesk/RecordImporter.java +134 -0
  6. data/src/main/java/org/embulk/input/zendesk/ZendeskInputPlugin.java +182 -202
  7. data/src/main/java/org/embulk/input/zendesk/clients/ZendeskRestClient.java +54 -52
  8. data/src/main/java/org/embulk/input/zendesk/models/Target.java +3 -3
  9. data/src/main/java/org/embulk/input/zendesk/models/ZendeskException.java +1 -1
  10. data/src/main/java/org/embulk/input/zendesk/services/ZendeskCustomObjectService.java +110 -0
  11. data/src/main/java/org/embulk/input/zendesk/services/ZendeskNPSService.java +30 -0
  12. data/src/main/java/org/embulk/input/zendesk/services/ZendeskNormalServices.java +239 -0
  13. data/src/main/java/org/embulk/input/zendesk/services/ZendeskService.java +14 -0
  14. data/src/main/java/org/embulk/input/zendesk/services/ZendeskSupportAPIService.java +25 -83
  15. data/src/main/java/org/embulk/input/zendesk/services/ZendeskUserEventService.java +158 -0
  16. data/src/main/java/org/embulk/input/zendesk/stream/PagingSpliterator.java +40 -0
  17. data/src/main/java/org/embulk/input/zendesk/stream/paginator/sunshine/CustomObjectSpliterator.java +42 -0
  18. data/src/main/java/org/embulk/input/zendesk/stream/paginator/sunshine/SunshineSpliterator.java +66 -0
  19. data/src/main/java/org/embulk/input/zendesk/stream/paginator/sunshine/UserEventSpliterator.java +35 -0
  20. data/src/main/java/org/embulk/input/zendesk/stream/paginator/support/OrganizationSpliterator.java +13 -0
  21. data/src/main/java/org/embulk/input/zendesk/stream/paginator/support/SupportSpliterator.java +44 -0
  22. data/src/main/java/org/embulk/input/zendesk/stream/paginator/support/UserSpliterator.java +13 -0
  23. data/src/main/java/org/embulk/input/zendesk/utils/ZendeskConstants.java +13 -1
  24. data/src/main/java/org/embulk/input/zendesk/utils/ZendeskDateUtils.java +22 -11
  25. data/src/main/java/org/embulk/input/zendesk/utils/ZendeskUtils.java +52 -114
  26. data/src/test/java/org/embulk/input/zendesk/TestRecordImporter.java +114 -0
  27. data/src/test/java/org/embulk/input/zendesk/TestZendeskInputPlugin.java +184 -99
  28. data/src/test/java/org/embulk/input/zendesk/clients/TestZendeskRestClient.java +6 -20
  29. data/src/test/java/org/embulk/input/zendesk/services/TestZendeskCustomObjectService.java +161 -0
  30. data/src/test/java/org/embulk/input/zendesk/services/TestZendeskNPSService.java +56 -0
  31. data/src/test/java/org/embulk/input/zendesk/services/TestZendeskNormalService.java +189 -0
  32. data/src/test/java/org/embulk/input/zendesk/services/TestZendeskSupportAPIService.java +18 -60
  33. data/src/test/java/org/embulk/input/zendesk/services/TestZendeskUserEventService.java +158 -0
  34. data/src/test/java/org/embulk/input/zendesk/utils/TestZendeskDateUtils.java +50 -2
  35. data/src/test/java/org/embulk/input/zendesk/utils/TestZendeskUtil.java +0 -138
  36. data/src/test/java/org/embulk/input/zendesk/utils/ZendeskTestHelper.java +16 -0
  37. data/src/test/resources/config/nps.yml +29 -0
  38. data/src/test/resources/config/object_records.yml +24 -0
  39. data/src/test/resources/config/relationship_records.yml +23 -0
  40. data/src/test/resources/config/user_events.yml +29 -0
  41. data/src/test/resources/data/duplicate_user.json +0 -0
  42. data/src/test/resources/data/empty_result.json +7 -0
  43. data/src/test/resources/data/expected/user_events_column.json +40 -0
  44. data/src/test/resources/data/object_records.json +30 -0
  45. data/src/test/resources/data/organization.json +39 -0
  46. data/src/test/resources/data/relationship_records.json +57 -0
  47. data/src/test/resources/data/scores.json +21 -0
  48. data/src/test/resources/data/scores_share_same_time_with_next_page.json +35 -0
  49. data/src/test/resources/data/scores_share_same_time_without_next_page.json +35 -0
  50. data/src/test/resources/data/simple_organization.json +23 -0
  51. data/src/test/resources/data/simple_user.json +50 -0
  52. data/src/test/resources/data/simple_user_event.json +19 -0
  53. data/src/test/resources/data/ticket_events_share_same_time_with_next_page.json +279 -0
  54. data/src/test/resources/data/ticket_events_share_same_time_without_next_page.json +279 -0
  55. data/src/test/resources/data/ticket_events_updated_by_system_records.json +279 -0
  56. data/src/test/resources/data/ticket_share_same_time_with_next_page.json +232 -0
  57. data/src/test/resources/data/ticket_share_same_time_without_next_page.json +232 -0
  58. data/src/test/resources/data/ticket_with_updated_by_system_records.json +187 -0
  59. data/src/test/resources/data/user_event.json +19 -0
  60. data/src/test/resources/data/user_event_contain_latter_create_at.json +19 -0
  61. data/src/test/resources/data/user_event_multiple.json +33 -0
  62. metadata +46 -5
  63. data/src/main/java/org/embulk/input/zendesk/utils/ZendeskValidatorUtils.java +0 -79
  64. data/src/test/java/org/embulk/input/zendesk/utils/TestZendeskValidatorUtils.java +0 -130
@@ -0,0 +1,14 @@
1
+ package org.embulk.input.zendesk.services;
2
+
3
+ import com.fasterxml.jackson.databind.JsonNode;
4
+ import org.embulk.config.TaskReport;
5
+ import org.embulk.input.zendesk.RecordImporter;
6
+
7
+ public interface ZendeskService
8
+ {
9
+ boolean isSupportIncremental();
10
+
11
+ TaskReport addRecordToImporter(int taskIndex, RecordImporter recordImporter);
12
+
13
+ JsonNode getDataFromPath(String path, int page, boolean isPreview, long startTime);
14
+ }
@@ -1,110 +1,52 @@
1
1
  package org.embulk.input.zendesk.services;
2
2
 
3
- import com.fasterxml.jackson.databind.DeserializationFeature;
4
- import com.fasterxml.jackson.databind.JsonNode;
5
- import com.fasterxml.jackson.databind.ObjectMapper;
6
- import com.fasterxml.jackson.databind.node.ObjectNode;
7
- import com.google.common.annotations.VisibleForTesting;
8
- import com.google.common.base.Throwables;
3
+ import org.apache.http.client.utils.URIBuilder;
9
4
  import org.embulk.input.zendesk.ZendeskInputPlugin.PluginTask;
10
- import org.embulk.input.zendesk.clients.ZendeskRestClient;
11
5
  import org.embulk.input.zendesk.models.Target;
12
6
  import org.embulk.input.zendesk.utils.ZendeskConstants;
13
7
  import org.embulk.input.zendesk.utils.ZendeskUtils;
14
- import org.embulk.spi.DataException;
15
8
 
16
- import java.io.IOException;
17
-
18
- public class ZendeskSupportAPIService
9
+ public class ZendeskSupportAPIService extends ZendeskNormalServices
19
10
  {
20
- private ZendeskRestClient zendeskRestClient;
21
-
22
- private PluginTask task;
23
-
24
- private static ObjectMapper mapper = new ObjectMapper();
25
-
26
- static {
27
- mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
28
- mapper.configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, false);
29
- }
30
-
31
11
  public ZendeskSupportAPIService(final PluginTask task)
32
12
  {
33
- this.task = task;
13
+ super(task);
34
14
  }
35
15
 
36
- public void setTask(PluginTask task)
16
+ public boolean isSupportIncremental()
37
17
  {
38
- this.task = task;
18
+ return !(task.getTarget().equals(Target.TICKET_FORMS) || task.getTarget().equals(Target.TICKET_FIELDS));
39
19
  }
40
20
 
41
- public JsonNode getData(String path, final int page, final boolean isPreview, long startTime)
21
+ @Override
22
+ protected String buildURI(final int page, long startTime)
42
23
  {
43
- if (path.isEmpty()) {
44
- path = buildPath(page, startTime);
45
- }
46
- try {
47
- final String response = getZendeskRestClient().doGet(path, task, isPreview);
48
- return parseJsonObject(response);
49
- }
50
- catch (final Exception e) {
51
- throw Throwables.propagate(e);
52
- }
53
- }
24
+ final URIBuilder uriBuilder = ZendeskUtils.getURIBuilder(task.getLoginUrl()).setPath(buildPath());
54
25
 
55
- @VisibleForTesting
56
- protected ZendeskRestClient getZendeskRestClient()
57
- {
58
- if (zendeskRestClient == null) {
59
- zendeskRestClient = new ZendeskRestClient();
26
+ if (isSupportIncremental()) {
27
+ uriBuilder.setParameter(ZendeskConstants.Field.START_TIME, String.valueOf(startTime));
28
+ if (Target.TICKET_METRICS.equals(task.getTarget())) {
29
+ uriBuilder.setParameter("include", "metric_sets");
30
+ }
60
31
  }
61
- return zendeskRestClient;
62
- }
63
-
64
- private ObjectNode parseJsonObject(final String jsonText)
65
- {
66
- JsonNode node = parseJsonNode(jsonText);
67
- if (node.isObject()) {
68
- return (ObjectNode) node;
32
+ else {
33
+ uriBuilder.setParameter("sort_by", "id")
34
+ .setParameter("per_page", String.valueOf(100))
35
+ .setParameter("page", String.valueOf(page));
69
36
  }
70
37
 
71
- throw new DataException("Expected object node to parse but doesn't get");
72
- }
73
-
74
- private JsonNode parseJsonNode(final String jsonText)
75
- {
76
- try {
77
- return mapper.readTree(jsonText);
78
- }
79
- catch (final IOException e) {
80
- throw Throwables.propagate(e);
81
- }
38
+ return uriBuilder.toString();
82
39
  }
83
40
 
84
- private String buildPath(final int page, long startTime)
41
+ private String buildPath()
85
42
  {
86
- boolean isSupportIncremental = ZendeskUtils.isSupportAPIIncremental(task.getTarget());
87
-
88
- StringBuilder urlBuilder = new StringBuilder(task.getLoginUrl())
89
- .append("/")
90
- .append(isSupportIncremental
91
- ? ZendeskConstants.Url.API_INCREMENTAL
92
- : ZendeskConstants.Url.API)
93
- .append("/")
94
- .append(Target.TICKET_METRICS.equals(task.getTarget())
43
+ return (isSupportIncremental()
44
+ ? ZendeskConstants.Url.API_INCREMENTAL
45
+ : ZendeskConstants.Url.API) +
46
+ "/" +
47
+ (Target.TICKET_METRICS.equals(task.getTarget())
95
48
  ? Target.TICKETS.toString()
96
49
  : task.getTarget().toString())
97
- .append(".json?");
98
-
99
- urlBuilder
100
- .append(isSupportIncremental
101
- ? "start_time=" + startTime
102
- : "sort_by=id&per_page=100&page=" + page);
103
-
104
- if (Target.TICKET_METRICS.equals(task.getTarget())) {
105
- urlBuilder.append("&include=metric_sets");
106
- }
107
-
108
- return urlBuilder.toString();
50
+ + ".json";
109
51
  }
110
52
  }
@@ -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
+ }
@@ -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
+ }
@@ -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
+ }