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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/README.md +32 -2
- data/build.gradle +1 -1
- data/src/main/java/org/embulk/input/zendesk/RecordImporter.java +134 -0
- data/src/main/java/org/embulk/input/zendesk/ZendeskInputPlugin.java +182 -202
- data/src/main/java/org/embulk/input/zendesk/clients/ZendeskRestClient.java +54 -52
- data/src/main/java/org/embulk/input/zendesk/models/Target.java +3 -3
- data/src/main/java/org/embulk/input/zendesk/models/ZendeskException.java +1 -1
- 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 +239 -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 +25 -83
- 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 +13 -1
- data/src/main/java/org/embulk/input/zendesk/utils/ZendeskDateUtils.java +22 -11
- data/src/main/java/org/embulk/input/zendesk/utils/ZendeskUtils.java +52 -114
- data/src/test/java/org/embulk/input/zendesk/TestRecordImporter.java +114 -0
- data/src/test/java/org/embulk/input/zendesk/TestZendeskInputPlugin.java +184 -99
- data/src/test/java/org/embulk/input/zendesk/clients/TestZendeskRestClient.java +6 -20
- 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 +189 -0
- data/src/test/java/org/embulk/input/zendesk/services/TestZendeskSupportAPIService.java +18 -60
- data/src/test/java/org/embulk/input/zendesk/services/TestZendeskUserEventService.java +158 -0
- data/src/test/java/org/embulk/input/zendesk/utils/TestZendeskDateUtils.java +50 -2
- data/src/test/java/org/embulk/input/zendesk/utils/TestZendeskUtil.java +0 -138
- data/src/test/java/org/embulk/input/zendesk/utils/ZendeskTestHelper.java +16 -0
- data/src/test/resources/config/nps.yml +29 -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/data/duplicate_user.json +0 -0
- data/src/test/resources/data/empty_result.json +7 -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_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_updated_by_system_records.json +187 -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
- metadata +46 -5
- data/src/main/java/org/embulk/input/zendesk/utils/ZendeskValidatorUtils.java +0 -79
- data/src/test/java/org/embulk/input/zendesk/utils/TestZendeskValidatorUtils.java +0 -130
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
|
+
}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
package org.embulk.input.zendesk.utils;
|
|
2
2
|
|
|
3
|
+
import com.google.common.collect.ImmutableList;
|
|
4
|
+
|
|
5
|
+
import java.util.Arrays;
|
|
6
|
+
import java.util.List;
|
|
7
|
+
|
|
3
8
|
public class ZendeskConstants
|
|
4
9
|
{
|
|
5
10
|
private ZendeskConstants()
|
|
@@ -27,8 +32,12 @@ public class ZendeskConstants
|
|
|
27
32
|
|
|
28
33
|
public static class Url
|
|
29
34
|
{
|
|
30
|
-
public static final String API = "api/v2";
|
|
35
|
+
public static final String API = "/api/v2";
|
|
31
36
|
public static final String API_INCREMENTAL = API + "/incremental";
|
|
37
|
+
public static final String API_NPS_INCREMENTAL = API + "/nps/incremental";
|
|
38
|
+
public static final String API_OBJECT_RECORD = "api/sunshine/objects/records";
|
|
39
|
+
public static final String API_RELATIONSHIP_RECORD = "api/sunshine/relationships/records";
|
|
40
|
+
public static final String API_USER_EVENT = "api/sunshine/events";
|
|
32
41
|
}
|
|
33
42
|
|
|
34
43
|
public static class Misc
|
|
@@ -45,6 +54,9 @@ public class ZendeskConstants
|
|
|
45
54
|
|
|
46
55
|
// 1 MB
|
|
47
56
|
public static final int GUESS_BUFFER_SIZE = 1024 * 1024;
|
|
57
|
+
public static final List<String> SUPPORT_DATE_TIME_FORMAT = ImmutableList.copyOf(Arrays.asList(ZendeskConstants.Misc.ISO_INSTANT, ZendeskConstants.Misc.RUBY_TIMESTAMP_FORMAT_INPUT,
|
|
58
|
+
ZendeskConstants.Misc.JAVA_TIMESTAMP_FORMAT, ZendeskConstants.Misc.ISO_TIMESTAMP_FORMAT,
|
|
59
|
+
ZendeskConstants.Misc.RUBY_TIMESTAMP_FORMAT_INPUT_NO_SPACE));
|
|
48
60
|
}
|
|
49
61
|
|
|
50
62
|
public static class Regex
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
package org.embulk.input.zendesk.utils;
|
|
2
2
|
|
|
3
|
-
import com.google.common.base.Joiner;
|
|
4
3
|
import org.embulk.spi.DataException;
|
|
5
4
|
|
|
5
|
+
import java.time.Instant;
|
|
6
6
|
import java.time.LocalDateTime;
|
|
7
7
|
import java.time.OffsetDateTime;
|
|
8
8
|
import java.time.ZoneOffset;
|
|
9
9
|
import java.time.format.DateTimeFormatter;
|
|
10
10
|
import java.time.format.DateTimeParseException;
|
|
11
|
-
import java.util.Arrays;
|
|
12
11
|
|
|
13
|
-
import java.util.List;
|
|
14
12
|
import java.util.Optional;
|
|
15
13
|
|
|
16
14
|
public class ZendeskDateUtils
|
|
@@ -19,25 +17,21 @@ public class ZendeskDateUtils
|
|
|
19
17
|
{
|
|
20
18
|
}
|
|
21
19
|
|
|
22
|
-
private static final List<String> supportedFormats = Arrays.asList(ZendeskConstants.Misc.ISO_INSTANT, ZendeskConstants.Misc.RUBY_TIMESTAMP_FORMAT_INPUT,
|
|
23
|
-
ZendeskConstants.Misc.JAVA_TIMESTAMP_FORMAT, ZendeskConstants.Misc.ISO_TIMESTAMP_FORMAT,
|
|
24
|
-
ZendeskConstants.Misc.RUBY_TIMESTAMP_FORMAT_INPUT_NO_SPACE);
|
|
25
|
-
|
|
26
20
|
public static long isoToEpochSecond(final String time)
|
|
27
21
|
{
|
|
28
|
-
Optional<String> pattern = supportedTimeFormat(time
|
|
22
|
+
final Optional<String> pattern = supportedTimeFormat(time);
|
|
29
23
|
if (pattern.isPresent()) {
|
|
30
24
|
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern.get()).withZone(ZoneOffset.UTC);
|
|
31
25
|
final OffsetDateTime offsetDateTime = LocalDateTime.parse(time, formatter).atOffset(ZoneOffset.UTC);
|
|
32
26
|
return offsetDateTime.toInstant().getEpochSecond();
|
|
33
27
|
}
|
|
34
28
|
|
|
35
|
-
throw new DataException("Fail to parse value '" + time + "' follow formats " +
|
|
29
|
+
throw new DataException("Fail to parse value '" + time + "' follow formats " + ZendeskConstants.Misc.SUPPORT_DATE_TIME_FORMAT.toString());
|
|
36
30
|
}
|
|
37
31
|
|
|
38
|
-
|
|
32
|
+
public static Optional<String> supportedTimeFormat(final String value)
|
|
39
33
|
{
|
|
40
|
-
for (final String fmt :
|
|
34
|
+
for (final String fmt : ZendeskConstants.Misc.SUPPORT_DATE_TIME_FORMAT) {
|
|
41
35
|
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(fmt);
|
|
42
36
|
try {
|
|
43
37
|
formatter.parse(value);
|
|
@@ -49,4 +43,21 @@ public class ZendeskDateUtils
|
|
|
49
43
|
}
|
|
50
44
|
return Optional.empty();
|
|
51
45
|
}
|
|
46
|
+
|
|
47
|
+
public static String convertToDateTimeFormat(String datetime, String dateTimeFormat)
|
|
48
|
+
{
|
|
49
|
+
return OffsetDateTime.ofInstant(Instant.ofEpochSecond(ZendeskDateUtils.isoToEpochSecond(datetime)), ZoneOffset.UTC)
|
|
50
|
+
.format(DateTimeFormatter.ofPattern(dateTimeFormat));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// start_time should be start from 0
|
|
54
|
+
public static long getStartTime(final String time)
|
|
55
|
+
{
|
|
56
|
+
try {
|
|
57
|
+
return isoToEpochSecond(time);
|
|
58
|
+
}
|
|
59
|
+
catch (DataException ex) {
|
|
60
|
+
return 0;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
52
63
|
}
|
|
@@ -1,150 +1,88 @@
|
|
|
1
1
|
package org.embulk.input.zendesk.utils;
|
|
2
2
|
|
|
3
|
+
import com.fasterxml.jackson.databind.DeserializationFeature;
|
|
3
4
|
import com.fasterxml.jackson.databind.JsonNode;
|
|
5
|
+
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
6
|
+
import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
4
7
|
import com.google.common.base.Charsets;
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
import org.embulk.
|
|
8
|
-
import org.embulk.spi.
|
|
9
|
-
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import org.embulk.spi.json.JsonParser;
|
|
14
|
-
import org.embulk.spi.time.Timestamp;
|
|
15
|
-
import org.slf4j.Logger;
|
|
16
|
-
|
|
8
|
+
import com.google.common.base.Throwables;
|
|
9
|
+
import org.apache.http.client.utils.URIBuilder;
|
|
10
|
+
import org.embulk.config.ConfigException;
|
|
11
|
+
import org.embulk.spi.DataException;
|
|
12
|
+
|
|
13
|
+
import java.io.IOException;
|
|
14
|
+
import java.net.URI;
|
|
15
|
+
import java.net.URISyntaxException;
|
|
17
16
|
import java.util.Base64;
|
|
18
|
-
import java.util.
|
|
17
|
+
import java.util.Iterator;
|
|
19
18
|
|
|
20
19
|
public class ZendeskUtils
|
|
21
20
|
{
|
|
22
|
-
private static final
|
|
21
|
+
private static final ObjectMapper mapper = new ObjectMapper();
|
|
22
|
+
|
|
23
|
+
static {
|
|
24
|
+
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
|
25
|
+
mapper.configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, false);
|
|
26
|
+
}
|
|
23
27
|
|
|
24
28
|
private ZendeskUtils()
|
|
25
29
|
{}
|
|
26
30
|
|
|
27
|
-
public static boolean isSupportAPIIncremental(final Target target)
|
|
28
|
-
{
|
|
29
|
-
return !Target.TICKET_FORMS.equals(target)
|
|
30
|
-
&& !Target.TICKET_FIELDS.equals(target);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
31
|
public static String convertBase64(final String text)
|
|
34
32
|
{
|
|
35
33
|
return Base64.getEncoder().encodeToString(text.getBytes(Charsets.UTF_8));
|
|
36
34
|
}
|
|
37
35
|
|
|
38
|
-
public static int numberToSplitWithHintingInTask(int count)
|
|
36
|
+
public static int numberToSplitWithHintingInTask(final int count)
|
|
39
37
|
{
|
|
40
38
|
return (int) Math.ceil((double) count / ZendeskConstants.Misc.RECORDS_SIZE_PER_PAGE);
|
|
41
39
|
}
|
|
42
40
|
|
|
43
|
-
public static
|
|
41
|
+
public static ObjectNode parseJsonObject(final String jsonText)
|
|
44
42
|
{
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
JsonNode data = record.get(column.getName());
|
|
50
|
-
|
|
51
|
-
setColumn(column, data, (value) -> {
|
|
52
|
-
pageBuilder.setJson(column, new JsonParser().parse(value.toString()));
|
|
53
|
-
return null;
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
@Override
|
|
58
|
-
public void stringColumn(Column column)
|
|
59
|
-
{
|
|
60
|
-
JsonNode data = record.get(column.getName());
|
|
61
|
-
|
|
62
|
-
setColumn(column, data, (value) -> {
|
|
63
|
-
pageBuilder.setString(column, value.asText());
|
|
64
|
-
return null;
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
@Override
|
|
69
|
-
public void timestampColumn(Column column)
|
|
70
|
-
{
|
|
71
|
-
JsonNode data = record.get(column.getName());
|
|
72
|
-
setColumn(column, data, (value) -> {
|
|
73
|
-
Timestamp timestamp = getTimestampValue(value.asText());
|
|
74
|
-
if (timestamp == null) {
|
|
75
|
-
pageBuilder.setNull(column);
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
pageBuilder.setTimestamp(column, timestamp);
|
|
79
|
-
}
|
|
80
|
-
return null;
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
@Override
|
|
85
|
-
public void booleanColumn(Column column)
|
|
86
|
-
{
|
|
87
|
-
JsonNode data = record.get(column.getName());
|
|
88
|
-
|
|
89
|
-
setColumn(column, data, (value) -> {
|
|
90
|
-
pageBuilder.setBoolean(column, value.asBoolean());
|
|
91
|
-
return null;
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
@Override
|
|
96
|
-
public void longColumn(Column column)
|
|
97
|
-
{
|
|
98
|
-
JsonNode data = record.get(column.getName());
|
|
99
|
-
|
|
100
|
-
setColumn(column, data, (value) -> {
|
|
101
|
-
pageBuilder.setLong(column, value.asLong());
|
|
102
|
-
return null;
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
@Override
|
|
107
|
-
public void doubleColumn(Column column)
|
|
108
|
-
{
|
|
109
|
-
JsonNode data = record.get(column.getName());
|
|
43
|
+
final JsonNode node = ZendeskUtils.parseJsonNode(jsonText);
|
|
44
|
+
if (node.isObject()) {
|
|
45
|
+
return (ObjectNode) node;
|
|
46
|
+
}
|
|
110
47
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return null;
|
|
114
|
-
});
|
|
115
|
-
}
|
|
48
|
+
throw new DataException("Expected object node to parse but doesn't get");
|
|
49
|
+
}
|
|
116
50
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
setter.apply(data);
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
pageBuilder.addRecord();
|
|
51
|
+
public static Iterator<JsonNode> getListRecords(final JsonNode result, final String targetJsonName)
|
|
52
|
+
{
|
|
53
|
+
if (!result.has(targetJsonName) || !result.get(targetJsonName).isArray()) {
|
|
54
|
+
throw new DataException(String.format("Missing '%s' from Zendesk API response", targetJsonName));
|
|
55
|
+
}
|
|
56
|
+
return result.get(targetJsonName).elements();
|
|
127
57
|
}
|
|
128
58
|
|
|
129
|
-
|
|
59
|
+
public static boolean isNull(final JsonNode jsonNode)
|
|
130
60
|
{
|
|
131
61
|
return jsonNode == null || jsonNode.isNull();
|
|
132
62
|
}
|
|
133
63
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
64
|
+
public static URIBuilder getURIBuilder(final String urlString)
|
|
65
|
+
{
|
|
66
|
+
final URI uri;
|
|
67
|
+
try {
|
|
68
|
+
uri = new URI(urlString);
|
|
69
|
+
}
|
|
70
|
+
catch (final URISyntaxException e) {
|
|
71
|
+
throw new ConfigException("URL is invalid format " + urlString);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return new URIBuilder()
|
|
75
|
+
.setScheme(uri.getScheme())
|
|
76
|
+
.setHost(uri.getHost());
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private static JsonNode parseJsonNode(final String jsonText)
|
|
139
80
|
{
|
|
140
|
-
Timestamp result = null;
|
|
141
81
|
try {
|
|
142
|
-
|
|
143
|
-
result = Timestamp.ofEpochSecond(timeStamp);
|
|
82
|
+
return ZendeskUtils.mapper.readTree(jsonText);
|
|
144
83
|
}
|
|
145
|
-
catch (
|
|
146
|
-
|
|
84
|
+
catch (final IOException e) {
|
|
85
|
+
throw Throwables.propagate(e);
|
|
147
86
|
}
|
|
148
|
-
return result;
|
|
149
87
|
}
|
|
150
88
|
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
package org.embulk.input.zendesk;
|
|
2
|
+
|
|
3
|
+
import com.fasterxml.jackson.databind.JsonNode;
|
|
4
|
+
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
|
5
|
+
import org.embulk.EmbulkTestRuntime;
|
|
6
|
+
import org.embulk.input.zendesk.utils.ZendeskTestHelper;
|
|
7
|
+
import org.embulk.spi.Column;
|
|
8
|
+
import org.embulk.spi.PageBuilder;
|
|
9
|
+
import org.embulk.spi.Schema;
|
|
10
|
+
import org.embulk.spi.json.JsonParser;
|
|
11
|
+
import org.embulk.spi.time.Timestamp;
|
|
12
|
+
import org.embulk.spi.time.TimestampParser;
|
|
13
|
+
import org.junit.Before;
|
|
14
|
+
import org.junit.BeforeClass;
|
|
15
|
+
import org.junit.Rule;
|
|
16
|
+
import org.junit.Test;
|
|
17
|
+
import org.mockito.Mockito;
|
|
18
|
+
import org.msgpack.value.Value;
|
|
19
|
+
|
|
20
|
+
import static org.mockito.Mockito.mock;
|
|
21
|
+
import static org.mockito.Mockito.spy;
|
|
22
|
+
import static org.mockito.Mockito.times;
|
|
23
|
+
import static org.mockito.Mockito.verify;
|
|
24
|
+
|
|
25
|
+
public class TestRecordImporter
|
|
26
|
+
{
|
|
27
|
+
@Rule
|
|
28
|
+
@SuppressFBWarnings("URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
|
|
29
|
+
public EmbulkTestRuntime runtime = new EmbulkTestRuntime();
|
|
30
|
+
|
|
31
|
+
public PageBuilder pageBuilder = mock(PageBuilder.class);
|
|
32
|
+
|
|
33
|
+
private static Schema schema;
|
|
34
|
+
private static Column booleanColumn;
|
|
35
|
+
private static Column longColumn;
|
|
36
|
+
private static Column doubleColumn;
|
|
37
|
+
private static Column stringColumn;
|
|
38
|
+
private static Column dateColumn;
|
|
39
|
+
private static Column jsonColumn;
|
|
40
|
+
private static ZendeskInputPlugin.PluginTask pluginTask;
|
|
41
|
+
|
|
42
|
+
private RecordImporter recordImporter;
|
|
43
|
+
|
|
44
|
+
@BeforeClass
|
|
45
|
+
public static void setUp()
|
|
46
|
+
{
|
|
47
|
+
pluginTask = ZendeskTestHelper.getConfigSource("util.yml").loadConfig(ZendeskInputPlugin.PluginTask.class);
|
|
48
|
+
schema = pluginTask.getColumns().toSchema();
|
|
49
|
+
booleanColumn = schema.getColumn(0);
|
|
50
|
+
longColumn = schema.getColumn(1);
|
|
51
|
+
doubleColumn = schema.getColumn(2);
|
|
52
|
+
stringColumn = schema.getColumn(3);
|
|
53
|
+
dateColumn = schema.getColumn(4);
|
|
54
|
+
jsonColumn = schema.getColumn(5);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@Before
|
|
58
|
+
public void prepare()
|
|
59
|
+
{
|
|
60
|
+
recordImporter = spy(new RecordImporter(schema, pageBuilder));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@Test
|
|
64
|
+
public void testAddRecordAllRight()
|
|
65
|
+
{
|
|
66
|
+
String name = "allRight";
|
|
67
|
+
JsonNode dataJson = ZendeskTestHelper.getJsonFromFile("data/util.json").get(name);
|
|
68
|
+
|
|
69
|
+
Boolean boolValue = Boolean.TRUE;
|
|
70
|
+
long longValue = 1;
|
|
71
|
+
double doubleValue = 1;
|
|
72
|
+
String stringValue = "string";
|
|
73
|
+
Timestamp dateValue = TimestampParser.of("%Y-%m-%dT%H:%M:%S%z", "UTC").parse("2019-01-01T00:00:00Z");
|
|
74
|
+
Value jsonValue = new JsonParser().parse("{}");
|
|
75
|
+
|
|
76
|
+
recordImporter.addRecord(dataJson);
|
|
77
|
+
|
|
78
|
+
verify(pageBuilder, times(1)).setBoolean(booleanColumn, boolValue);
|
|
79
|
+
verify(pageBuilder, times(1)).setLong(longColumn, longValue);
|
|
80
|
+
verify(pageBuilder, times(1)).setDouble(doubleColumn, doubleValue);
|
|
81
|
+
verify(pageBuilder, times(1)).setString(stringColumn, stringValue);
|
|
82
|
+
verify(pageBuilder, times(1)).setTimestamp(dateColumn, dateValue);
|
|
83
|
+
verify(pageBuilder, times(1)).setJson(jsonColumn, jsonValue);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@Test
|
|
87
|
+
public void testAddRecordAllWrong()
|
|
88
|
+
{
|
|
89
|
+
String name = "allWrong";
|
|
90
|
+
JsonNode dataJson = ZendeskTestHelper.getJsonFromFile("data/util.json").get(name);
|
|
91
|
+
|
|
92
|
+
Value jsonValue = new JsonParser().parse("{}");
|
|
93
|
+
|
|
94
|
+
recordImporter.addRecord(dataJson);
|
|
95
|
+
|
|
96
|
+
verify(pageBuilder, times(1)).setNull(booleanColumn);
|
|
97
|
+
verify(pageBuilder, times(1)).setNull(longColumn);
|
|
98
|
+
verify(pageBuilder, times(1)).setNull(doubleColumn);
|
|
99
|
+
verify(pageBuilder, times(1)).setNull(stringColumn);
|
|
100
|
+
verify(pageBuilder, times(1)).setNull(dateColumn);
|
|
101
|
+
verify(pageBuilder, times(1)).setJson(jsonColumn, jsonValue);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
@Test
|
|
105
|
+
public void testAddRecordAllMissing()
|
|
106
|
+
{
|
|
107
|
+
String name = "allMissing";
|
|
108
|
+
JsonNode dataJson = ZendeskTestHelper.getJsonFromFile("data/util.json").get(name);
|
|
109
|
+
|
|
110
|
+
recordImporter.addRecord(dataJson);
|
|
111
|
+
|
|
112
|
+
verify(pageBuilder, times(6)).setNull(Mockito.any());
|
|
113
|
+
}
|
|
114
|
+
}
|