embulk-input-marketo_extended 0.6.18
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/.github/PULL_REQUEST_TEMPLATE.md +37 -0
- data/.gitignore +14 -0
- data/.travis.yml +6 -0
- data/CHANGELOG.md +170 -0
- data/LICENSE.txt +21 -0
- data/README.md +213 -0
- data/build.gradle +103 -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 +6 -0
- data/gradlew +169 -0
- data/gradlew.bat +84 -0
- data/lib/embulk/input/marketo.rb +3 -0
- data/settings.gradle +1 -0
- data/src/main/java/org/embulk/input/marketo/CsvTokenizer.java +700 -0
- data/src/main/java/org/embulk/input/marketo/MarketoInputPlugin.java +15 -0
- data/src/main/java/org/embulk/input/marketo/MarketoInputPluginDelegate.java +100 -0
- data/src/main/java/org/embulk/input/marketo/MarketoService.java +38 -0
- data/src/main/java/org/embulk/input/marketo/MarketoServiceImpl.java +245 -0
- data/src/main/java/org/embulk/input/marketo/MarketoUtils.java +212 -0
- data/src/main/java/org/embulk/input/marketo/delegate/ActivityBulkExtractInputPlugin.java +167 -0
- data/src/main/java/org/embulk/input/marketo/delegate/CampaignInputPlugin.java +48 -0
- data/src/main/java/org/embulk/input/marketo/delegate/CustomObjectInputPlugin.java +75 -0
- data/src/main/java/org/embulk/input/marketo/delegate/CustomObjectResponseMapperBuilder.java +81 -0
- data/src/main/java/org/embulk/input/marketo/delegate/LeadBulkExtractInputPlugin.java +66 -0
- data/src/main/java/org/embulk/input/marketo/delegate/LeadServiceResponseMapperBuilder.java +85 -0
- data/src/main/java/org/embulk/input/marketo/delegate/LeadWithListInputPlugin.java +64 -0
- data/src/main/java/org/embulk/input/marketo/delegate/LeadWithProgramInputPlugin.java +60 -0
- data/src/main/java/org/embulk/input/marketo/delegate/MarketoBaseBulkExtractInputPlugin.java +441 -0
- data/src/main/java/org/embulk/input/marketo/delegate/MarketoBaseInputPluginDelegate.java +92 -0
- data/src/main/java/org/embulk/input/marketo/delegate/ProgramInputPlugin.java +228 -0
- data/src/main/java/org/embulk/input/marketo/exception/MarketoAPIException.java +30 -0
- data/src/main/java/org/embulk/input/marketo/model/BulkExtractRangeHeader.java +26 -0
- data/src/main/java/org/embulk/input/marketo/model/MarketoAccessTokenResponse.java +92 -0
- data/src/main/java/org/embulk/input/marketo/model/MarketoBulkExtractRequest.java +68 -0
- data/src/main/java/org/embulk/input/marketo/model/MarketoError.java +40 -0
- data/src/main/java/org/embulk/input/marketo/model/MarketoField.java +126 -0
- data/src/main/java/org/embulk/input/marketo/model/MarketoResponse.java +82 -0
- data/src/main/java/org/embulk/input/marketo/model/filter/DateRangeFilter.java +40 -0
- data/src/main/java/org/embulk/input/marketo/rest/MarketoBaseRestClient.java +306 -0
- data/src/main/java/org/embulk/input/marketo/rest/MarketoInputStreamResponseEntityReader.java +69 -0
- data/src/main/java/org/embulk/input/marketo/rest/MarketoRESTEndpoint.java +47 -0
- data/src/main/java/org/embulk/input/marketo/rest/MarketoResponseJetty92EntityReader.java +89 -0
- data/src/main/java/org/embulk/input/marketo/rest/MarketoRestClient.java +569 -0
- data/src/main/java/org/embulk/input/marketo/rest/RecordPagingIterable.java +180 -0
- data/src/test/java/org/embulk/input/marketo/MarketoServiceImplTest.java +140 -0
- data/src/test/java/org/embulk/input/marketo/MarketoUtilsTest.java +87 -0
- data/src/test/java/org/embulk/input/marketo/delegate/ActivityBulkExtractInputPluginTest.java +128 -0
- data/src/test/java/org/embulk/input/marketo/delegate/CampaignInputPluginTest.java +73 -0
- data/src/test/java/org/embulk/input/marketo/delegate/CustomObjectInputPluginTest.java +102 -0
- data/src/test/java/org/embulk/input/marketo/delegate/LeadBulkExtractInputPluginTest.java +99 -0
- data/src/test/java/org/embulk/input/marketo/delegate/LeadServiceResponseMapperBuilderTest.java +119 -0
- data/src/test/java/org/embulk/input/marketo/delegate/LeadWithListInputPluginTest.java +101 -0
- data/src/test/java/org/embulk/input/marketo/delegate/LeadWithProgramInputPluginTest.java +103 -0
- data/src/test/java/org/embulk/input/marketo/delegate/MarketoBaseBulkExtractInputPluginTest.java +169 -0
- data/src/test/java/org/embulk/input/marketo/delegate/ProgramInputPluginTest.java +343 -0
- data/src/test/java/org/embulk/input/marketo/rest/MarketoBaseRestClientTest.java +368 -0
- data/src/test/java/org/embulk/input/marketo/rest/MarketoRestClientTest.java +584 -0
- data/src/test/resources/config/activity_bulk_extract_config.yaml +7 -0
- data/src/test/resources/config/custom_object_config.yaml +8 -0
- data/src/test/resources/config/lead_bulk_extract_config.yaml +8 -0
- data/src/test/resources/config/rest_config.yaml +3 -0
- data/src/test/resources/fixtures/activity_extract1.csv +35 -0
- data/src/test/resources/fixtures/activity_extract2.csv +22 -0
- data/src/test/resources/fixtures/activity_types.json +22 -0
- data/src/test/resources/fixtures/all_program_full.json +53 -0
- data/src/test/resources/fixtures/campaign_response.json +38 -0
- data/src/test/resources/fixtures/campaign_response_full.json +102 -0
- data/src/test/resources/fixtures/custom_object_describe.json +124 -0
- data/src/test/resources/fixtures/custom_object_describe_marketo_fields_full.json +22 -0
- data/src/test/resources/fixtures/custom_object_expected.json +66 -0
- data/src/test/resources/fixtures/custom_object_response.json +24 -0
- data/src/test/resources/fixtures/custom_object_response_full.json +23 -0
- data/src/test/resources/fixtures/lead_by_list.json +33 -0
- data/src/test/resources/fixtures/lead_by_program_response.json +47 -0
- data/src/test/resources/fixtures/lead_describe.json +221 -0
- data/src/test/resources/fixtures/lead_describe_expected.json +66 -0
- data/src/test/resources/fixtures/lead_describe_marketo_fields_full.json +518 -0
- data/src/test/resources/fixtures/lead_extract1.csv +11 -0
- data/src/test/resources/fixtures/lead_response_full.json +2402 -0
- data/src/test/resources/fixtures/lead_with_program_full.json +17 -0
- data/src/test/resources/fixtures/leads_extract2.csv +10 -0
- data/src/test/resources/fixtures/list_reponse_full.json +191 -0
- data/src/test/resources/fixtures/lists_response.json +31 -0
- data/src/test/resources/fixtures/program_response.json +71 -0
- metadata +171 -0
@@ -0,0 +1,69 @@
|
|
1
|
+
package org.embulk.input.marketo.rest;
|
2
|
+
|
3
|
+
import com.fasterxml.jackson.core.type.TypeReference;
|
4
|
+
import com.fasterxml.jackson.databind.ObjectMapper;
|
5
|
+
import com.fasterxml.jackson.databind.ObjectReader;
|
6
|
+
import com.fasterxml.jackson.databind.node.ObjectNode;
|
7
|
+
import com.google.common.io.CharStreams;
|
8
|
+
import org.eclipse.jetty.client.api.Response;
|
9
|
+
import org.eclipse.jetty.client.util.InputStreamResponseListener;
|
10
|
+
import org.eclipse.jetty.http.HttpHeader;
|
11
|
+
import org.embulk.input.marketo.exception.MarketoAPIException;
|
12
|
+
import org.embulk.input.marketo.model.MarketoResponse;
|
13
|
+
import org.embulk.util.retryhelper.jetty92.Jetty92ResponseReader;
|
14
|
+
|
15
|
+
import java.io.InputStream;
|
16
|
+
import java.io.InputStreamReader;
|
17
|
+
import java.util.concurrent.TimeUnit;
|
18
|
+
|
19
|
+
/**
|
20
|
+
* Created by tai.khuu on 9/5/17.
|
21
|
+
*/
|
22
|
+
public class MarketoInputStreamResponseEntityReader implements Jetty92ResponseReader<InputStream>
|
23
|
+
{
|
24
|
+
private static final ObjectReader OBJECT_READER = new ObjectMapper().readerFor(new TypeReference<MarketoResponse<ObjectNode>>(){ });
|
25
|
+
|
26
|
+
private InputStreamResponseListener listener;
|
27
|
+
|
28
|
+
private long timeout;
|
29
|
+
|
30
|
+
public MarketoInputStreamResponseEntityReader(long timeout)
|
31
|
+
{
|
32
|
+
this.timeout = timeout;
|
33
|
+
}
|
34
|
+
|
35
|
+
@Override
|
36
|
+
public Response.Listener getListener()
|
37
|
+
{
|
38
|
+
this.listener = new InputStreamResponseListener();
|
39
|
+
return this.listener;
|
40
|
+
}
|
41
|
+
|
42
|
+
@Override
|
43
|
+
public Response getResponse() throws Exception
|
44
|
+
{
|
45
|
+
return this.listener.get(timeout, TimeUnit.MILLISECONDS);
|
46
|
+
}
|
47
|
+
|
48
|
+
@Override
|
49
|
+
public InputStream readResponseContent() throws Exception
|
50
|
+
{
|
51
|
+
if (!getResponse().getHeaders().getField(HttpHeader.CONTENT_TYPE).getValue().equals("text/csv")) {
|
52
|
+
String errorString = readResponseContentInString();
|
53
|
+
|
54
|
+
MarketoResponse<ObjectNode> errorResponse = OBJECT_READER.readValue(errorString);
|
55
|
+
if (!errorResponse.isSuccess()) {
|
56
|
+
throw new MarketoAPIException(errorResponse.getErrors());
|
57
|
+
}
|
58
|
+
}
|
59
|
+
return this.listener.getInputStream();
|
60
|
+
}
|
61
|
+
|
62
|
+
@Override
|
63
|
+
public String readResponseContentInString() throws Exception
|
64
|
+
{
|
65
|
+
try (InputStreamReader inputStreamReader = new InputStreamReader(this.listener.getInputStream())) {
|
66
|
+
return CharStreams.toString(inputStreamReader);
|
67
|
+
}
|
68
|
+
}
|
69
|
+
}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
package org.embulk.input.marketo.rest;
|
2
|
+
|
3
|
+
import org.apache.commons.lang3.text.StrSubstitutor;
|
4
|
+
|
5
|
+
import java.util.Map;
|
6
|
+
|
7
|
+
/**
|
8
|
+
* Created by tai.khuu on 9/5/17.
|
9
|
+
*/
|
10
|
+
public enum MarketoRESTEndpoint
|
11
|
+
{
|
12
|
+
ACCESS_TOKEN("/oauth/token"),
|
13
|
+
CREATE_LEAD_EXTRACT("/bulk/v1/leads/export/create.json"),
|
14
|
+
CREATE_ACTIVITY_EXTRACT("/bulk/v1/activities/export/create.json"),
|
15
|
+
DESCRIBE_LEAD("/rest/v1/leads/describe.json"),
|
16
|
+
START_LEAD_EXPORT_JOB("/bulk/v1/leads/export/${export_id}/enqueue.json"),
|
17
|
+
START_ACTIVITY_EXPORT_JOB("/bulk/v1/activities/export/${export_id}/enqueue.json"),
|
18
|
+
GET_ACTIVITY_EXPORT_STATUS("/bulk/v1/activities/export/${export_id}/status.json"),
|
19
|
+
GET_LEAD_EXPORT_STATUS("/bulk/v1/leads/export/${export_id}/status.json"),
|
20
|
+
GET_LEAD_EXPORT_RESULT("/bulk/v1/leads/export/${export_id}/file.json"),
|
21
|
+
GET_ACTIVITY_EXPORT_RESULT("/bulk/v1/activities/export/${export_id}/file.json"),
|
22
|
+
GET_LISTS("/rest/v1/lists.json"),
|
23
|
+
GET_LEADS_BY_LIST("/rest/v1/lists/${list_id}/leads.json"),
|
24
|
+
GET_PROGRAMS("/rest/asset/v1/programs.json"),
|
25
|
+
GET_LEADS_BY_PROGRAM("/rest/v1/leads/programs/${program_id}.json"),
|
26
|
+
GET_CAMPAIGN("/rest/v1/campaigns.json"),
|
27
|
+
GET_PROGRAMS_BY_TAG("/rest/asset/v1/program/byTag.json"),
|
28
|
+
GET_CUSTOM_OBJECT("/rest/v1/customobjects/${api_name}.json"),
|
29
|
+
GET_CUSTOM_OBJECT_DESCRIBE("/rest/v1/customobjects/${api_name}/describe.json"),
|
30
|
+
GET_ACTIVITY_TYPES("/rest/v1/activities/types.json");
|
31
|
+
private String endpoint;
|
32
|
+
|
33
|
+
MarketoRESTEndpoint(String endpoint)
|
34
|
+
{
|
35
|
+
this.endpoint = endpoint;
|
36
|
+
}
|
37
|
+
|
38
|
+
public String getEndpoint()
|
39
|
+
{
|
40
|
+
return endpoint;
|
41
|
+
}
|
42
|
+
|
43
|
+
public String getEndpoint(Map<String, String> pathParams)
|
44
|
+
{
|
45
|
+
return StrSubstitutor.replace(endpoint, pathParams);
|
46
|
+
}
|
47
|
+
}
|
@@ -0,0 +1,89 @@
|
|
1
|
+
package org.embulk.input.marketo.rest;
|
2
|
+
|
3
|
+
import com.fasterxml.jackson.databind.DeserializationFeature;
|
4
|
+
import com.fasterxml.jackson.databind.JavaType;
|
5
|
+
import com.fasterxml.jackson.databind.ObjectMapper;
|
6
|
+
import com.fasterxml.jackson.databind.node.ObjectNode;
|
7
|
+
import com.google.common.io.CharStreams;
|
8
|
+
import org.eclipse.jetty.client.api.Response;
|
9
|
+
import org.eclipse.jetty.client.util.InputStreamResponseListener;
|
10
|
+
import org.embulk.input.marketo.exception.MarketoAPIException;
|
11
|
+
import org.embulk.input.marketo.model.MarketoResponse;
|
12
|
+
import org.embulk.spi.DataException;
|
13
|
+
import org.embulk.spi.Exec;
|
14
|
+
import org.embulk.util.retryhelper.jetty92.Jetty92ResponseReader;
|
15
|
+
import org.slf4j.Logger;
|
16
|
+
|
17
|
+
import java.io.IOException;
|
18
|
+
import java.io.InputStream;
|
19
|
+
import java.io.InputStreamReader;
|
20
|
+
import java.nio.charset.StandardCharsets;
|
21
|
+
import java.util.concurrent.TimeUnit;
|
22
|
+
|
23
|
+
/**
|
24
|
+
* Created by tai.khuu on 9/1/17.
|
25
|
+
*/
|
26
|
+
public class MarketoResponseJetty92EntityReader<T> implements Jetty92ResponseReader<MarketoResponse<T>>
|
27
|
+
{
|
28
|
+
private InputStreamResponseListener listener;
|
29
|
+
|
30
|
+
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
31
|
+
|
32
|
+
private static final Logger LOGGER = Exec.getLogger(MarketoResponseJetty92EntityReader.class);
|
33
|
+
private Long timeout;
|
34
|
+
|
35
|
+
private JavaType javaType;
|
36
|
+
|
37
|
+
public MarketoResponseJetty92EntityReader(long timeout)
|
38
|
+
{
|
39
|
+
this.timeout = timeout;
|
40
|
+
javaType = OBJECT_MAPPER.getTypeFactory().constructParametrizedType(MarketoResponse.class, MarketoResponse.class, ObjectNode.class);
|
41
|
+
}
|
42
|
+
|
43
|
+
public MarketoResponseJetty92EntityReader(long timeout, Class<T> resultClass)
|
44
|
+
{
|
45
|
+
this.listener = new InputStreamResponseListener();
|
46
|
+
this.timeout = timeout;
|
47
|
+
this.javaType = OBJECT_MAPPER.getTypeFactory().constructParametrizedType(MarketoResponse.class, MarketoResponse.class, resultClass);
|
48
|
+
}
|
49
|
+
|
50
|
+
@Override
|
51
|
+
public Response.Listener getListener()
|
52
|
+
{
|
53
|
+
this.listener = new InputStreamResponseListener();
|
54
|
+
return this.listener;
|
55
|
+
}
|
56
|
+
|
57
|
+
@Override
|
58
|
+
public Response getResponse() throws Exception
|
59
|
+
{
|
60
|
+
return this.listener.get(timeout, TimeUnit.MILLISECONDS);
|
61
|
+
}
|
62
|
+
|
63
|
+
@Override
|
64
|
+
public MarketoResponse<T> readResponseContent() throws Exception
|
65
|
+
{
|
66
|
+
String response = readResponseContentInString();
|
67
|
+
try {
|
68
|
+
MarketoResponse<T> marketoResponse = OBJECT_MAPPER.readValue(response, javaType);
|
69
|
+
if (!marketoResponse.isSuccess()) {
|
70
|
+
throw new MarketoAPIException(marketoResponse.getErrors());
|
71
|
+
}
|
72
|
+
return marketoResponse;
|
73
|
+
}
|
74
|
+
catch (IOException ex) {
|
75
|
+
LOGGER.error("Can't parse json content", ex);
|
76
|
+
throw new DataException("Exception when parse json content");
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
@Override
|
81
|
+
public String readResponseContentInString() throws Exception
|
82
|
+
{
|
83
|
+
InputStream inputStream = this.listener.getInputStream();
|
84
|
+
try (InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
|
85
|
+
String reponseContent = CharStreams.toString(inputStreamReader);
|
86
|
+
return reponseContent;
|
87
|
+
}
|
88
|
+
}
|
89
|
+
}
|
@@ -0,0 +1,569 @@
|
|
1
|
+
package org.embulk.input.marketo.rest;
|
2
|
+
|
3
|
+
import com.fasterxml.jackson.core.JsonProcessingException;
|
4
|
+
import com.fasterxml.jackson.databind.JsonNode;
|
5
|
+
import com.fasterxml.jackson.databind.node.ObjectNode;
|
6
|
+
import com.google.common.base.Optional;
|
7
|
+
import com.google.common.collect.ArrayListMultimap;
|
8
|
+
import com.google.common.collect.ImmutableListMultimap;
|
9
|
+
import com.google.common.collect.ImmutableMap;
|
10
|
+
import com.google.common.collect.Multimap;
|
11
|
+
import org.apache.commons.lang3.StringUtils;
|
12
|
+
import org.eclipse.jetty.client.util.FormContentProvider;
|
13
|
+
import org.eclipse.jetty.util.Fields;
|
14
|
+
import org.embulk.config.Config;
|
15
|
+
import org.embulk.config.ConfigDefault;
|
16
|
+
import org.embulk.config.ConfigException;
|
17
|
+
import org.embulk.config.Task;
|
18
|
+
import org.embulk.input.marketo.MarketoUtils;
|
19
|
+
import org.embulk.input.marketo.model.BulkExtractRangeHeader;
|
20
|
+
import org.embulk.input.marketo.model.MarketoBulkExtractRequest;
|
21
|
+
import org.embulk.input.marketo.model.MarketoError;
|
22
|
+
import org.embulk.input.marketo.model.MarketoField;
|
23
|
+
import org.embulk.input.marketo.model.MarketoResponse;
|
24
|
+
import org.embulk.input.marketo.model.filter.DateRangeFilter;
|
25
|
+
import org.embulk.spi.DataException;
|
26
|
+
import org.embulk.spi.Exec;
|
27
|
+
import org.embulk.spi.type.Type;
|
28
|
+
import org.embulk.spi.type.Types;
|
29
|
+
import org.embulk.util.retryhelper.jetty92.DefaultJetty92ClientCreator;
|
30
|
+
import org.embulk.util.retryhelper.jetty92.Jetty92RetryHelper;
|
31
|
+
import org.slf4j.Logger;
|
32
|
+
|
33
|
+
import java.io.InputStream;
|
34
|
+
import java.text.SimpleDateFormat;
|
35
|
+
import java.util.ArrayList;
|
36
|
+
import java.util.Date;
|
37
|
+
import java.util.HashMap;
|
38
|
+
import java.util.List;
|
39
|
+
import java.util.Map;
|
40
|
+
|
41
|
+
/**
|
42
|
+
* Created by tai.khuu on 8/22/17.
|
43
|
+
*/
|
44
|
+
public class MarketoRestClient extends MarketoBaseRestClient
|
45
|
+
{
|
46
|
+
private static final String BATCH_SIZE = "batchSize";
|
47
|
+
|
48
|
+
private static final String NEXT_PAGE_TOKEN = "nextPageToken";
|
49
|
+
|
50
|
+
private static final String OFFSET = "offset";
|
51
|
+
|
52
|
+
private static final String MAX_RETURN = "maxReturn";
|
53
|
+
|
54
|
+
private static final String MAX_BATCH_SIZE = "300";
|
55
|
+
|
56
|
+
private static final String DEFAULT_MAX_RETURN = "200";
|
57
|
+
|
58
|
+
private static final String RANGE_HEADER = "Range";
|
59
|
+
|
60
|
+
private static final String FILTER_TYPE = "filterType";
|
61
|
+
|
62
|
+
private static final String FILTER_VALUES = "filterValues";
|
63
|
+
|
64
|
+
private static final String FIELDS = "fields";
|
65
|
+
|
66
|
+
private static final int MAX_REQUEST_SIZE = 300;
|
67
|
+
|
68
|
+
private static final int CONNECT_TIMEOUT_IN_MILLIS = 30000;
|
69
|
+
private static final int IDLE_TIMEOUT_IN_MILLIS = 60000;
|
70
|
+
|
71
|
+
private String endPoint;
|
72
|
+
|
73
|
+
private Integer batchSize;
|
74
|
+
|
75
|
+
private Integer maxReturn;
|
76
|
+
|
77
|
+
private static final Logger LOGGER = Exec.getLogger(MarketoRestClient.class.getCanonicalName());
|
78
|
+
|
79
|
+
private static final Map<String, Type> TYPE_MAPPING = new ImmutableMap.Builder<String, Type>()
|
80
|
+
.put("datetime", Types.TIMESTAMP)
|
81
|
+
.put("email", Types.STRING)
|
82
|
+
.put("float", Types.DOUBLE)
|
83
|
+
.put("integer", Types.LONG)
|
84
|
+
.put("formula", Types.STRING)
|
85
|
+
.put("percent", Types.LONG)
|
86
|
+
.put("url", Types.STRING)
|
87
|
+
.put("phone", Types.STRING)
|
88
|
+
.put("textarea", Types.STRING)
|
89
|
+
.put("text", Types.STRING)
|
90
|
+
.put("string", Types.STRING)
|
91
|
+
.put("score", Types.LONG)
|
92
|
+
.put("boolean", Types.BOOLEAN)
|
93
|
+
.put("currency", Types.DOUBLE)
|
94
|
+
.put("date", Types.TIMESTAMP)
|
95
|
+
.put("reference", Types.STRING)
|
96
|
+
.build();
|
97
|
+
|
98
|
+
public interface PluginTask extends Task
|
99
|
+
{
|
100
|
+
@Config("account_id")
|
101
|
+
String getAccountId();
|
102
|
+
|
103
|
+
@Config("client_secret")
|
104
|
+
String getClientSecret();
|
105
|
+
|
106
|
+
@Config("client_id")
|
107
|
+
String getClientId();
|
108
|
+
|
109
|
+
@Config("marketo_limit_interval_milis")
|
110
|
+
@ConfigDefault("20000")
|
111
|
+
Integer getMarketoLimitIntervalMilis();
|
112
|
+
|
113
|
+
@Config("batch_size")
|
114
|
+
@ConfigDefault("300")
|
115
|
+
Integer getBatchSize();
|
116
|
+
void setBatchSize(Integer batchSize);
|
117
|
+
|
118
|
+
@Config("max_return")
|
119
|
+
@ConfigDefault("200")
|
120
|
+
Integer getMaxReturn();
|
121
|
+
void setMaxReturn(Integer maxReturn);
|
122
|
+
|
123
|
+
@Config("read_timeout_millis")
|
124
|
+
@ConfigDefault("60000")
|
125
|
+
Long getReadTimeoutMillis();
|
126
|
+
|
127
|
+
@Config("maximum_retries")
|
128
|
+
@ConfigDefault("7")
|
129
|
+
Integer getMaximumRetries();
|
130
|
+
|
131
|
+
@Config("initial_retry_interval_milis")
|
132
|
+
@ConfigDefault("20000")
|
133
|
+
Integer getInitialRetryIntervalMilis();
|
134
|
+
|
135
|
+
@Config("maximum_retries_interval_milis")
|
136
|
+
@ConfigDefault("120000")
|
137
|
+
Integer getMaximumRetriesIntervalMilis();
|
138
|
+
|
139
|
+
@Config("partner_api_key")
|
140
|
+
@ConfigDefault("null")
|
141
|
+
Optional<String> getPartnerApiKey();
|
142
|
+
}
|
143
|
+
|
144
|
+
public MarketoRestClient(PluginTask task)
|
145
|
+
{
|
146
|
+
this(MarketoUtils.getEndPoint(task.getAccountId()),
|
147
|
+
MarketoUtils.getIdentityEndPoint(task.getAccountId()),
|
148
|
+
task.getClientId(),
|
149
|
+
task.getClientSecret(),
|
150
|
+
task.getPartnerApiKey(),
|
151
|
+
task.getBatchSize(),
|
152
|
+
task.getMaxReturn(),
|
153
|
+
task.getReadTimeoutMillis(),
|
154
|
+
task.getMarketoLimitIntervalMilis(),
|
155
|
+
new Jetty92RetryHelper(task.getMaximumRetries(),
|
156
|
+
task.getInitialRetryIntervalMilis(),
|
157
|
+
task.getMaximumRetriesIntervalMilis(),
|
158
|
+
new DefaultJetty92ClientCreator(CONNECT_TIMEOUT_IN_MILLIS, IDLE_TIMEOUT_IN_MILLIS)));
|
159
|
+
}
|
160
|
+
|
161
|
+
public MarketoRestClient(String endPoint,
|
162
|
+
String identityEndPoint,
|
163
|
+
String clientId,
|
164
|
+
String clientSecret,
|
165
|
+
Optional<String> partnerApiKey,
|
166
|
+
Integer batchSize,
|
167
|
+
Integer maxReturn,
|
168
|
+
long readTimeoutMilis,
|
169
|
+
int marketoLimitIntervalMilis,
|
170
|
+
Jetty92RetryHelper retryHelper)
|
171
|
+
{
|
172
|
+
super(identityEndPoint, clientId, clientSecret, partnerApiKey, marketoLimitIntervalMilis, readTimeoutMilis, retryHelper);
|
173
|
+
this.endPoint = endPoint;
|
174
|
+
this.batchSize = batchSize;
|
175
|
+
this.maxReturn = maxReturn;
|
176
|
+
}
|
177
|
+
|
178
|
+
public List<MarketoField> describeLead()
|
179
|
+
{
|
180
|
+
MarketoResponse<ObjectNode> jsonResponse = doGet(endPoint + MarketoRESTEndpoint.DESCRIBE_LEAD.getEndpoint(), null, null, new MarketoResponseJetty92EntityReader<ObjectNode>(this.readTimeoutMillis));
|
181
|
+
List<MarketoField> marketoFields = new ArrayList<>();
|
182
|
+
List<ObjectNode> fields = jsonResponse.getResult();
|
183
|
+
for (int i = 0; i < fields.size(); i++) {
|
184
|
+
ObjectNode field = fields.get(i);
|
185
|
+
String dataType = field.get("dataType").asText();
|
186
|
+
if (field.has("rest")) {
|
187
|
+
ObjectNode restField = (ObjectNode) field.get("rest");
|
188
|
+
String name = restField.get("name").asText();
|
189
|
+
marketoFields.add(new MarketoField(name, dataType));
|
190
|
+
}
|
191
|
+
}
|
192
|
+
return marketoFields;
|
193
|
+
}
|
194
|
+
|
195
|
+
private Type getType(String dataType)
|
196
|
+
{
|
197
|
+
return TYPE_MAPPING.containsKey(dataType.toLowerCase()) ? TYPE_MAPPING.get(dataType.toLowerCase()) : Types.STRING;
|
198
|
+
}
|
199
|
+
|
200
|
+
public String createLeadBulkExtract(Date startTime, Date endTime, List<String> extractFields, String fitlerField)
|
201
|
+
{
|
202
|
+
MarketoBulkExtractRequest marketoBulkExtractRequest = getMarketoBulkExtractRequest(startTime, endTime, extractFields, fitlerField);
|
203
|
+
return sendCreateBulkExtractRequest(marketoBulkExtractRequest, MarketoRESTEndpoint.CREATE_LEAD_EXTRACT);
|
204
|
+
}
|
205
|
+
|
206
|
+
private MarketoBulkExtractRequest getMarketoBulkExtractRequest(Date startTime, Date endTime, List<String> extractFields, String rangeFilterName)
|
207
|
+
{
|
208
|
+
SimpleDateFormat timeFormat = new SimpleDateFormat(MarketoUtils.MARKETO_DATE_SIMPLE_DATE_FORMAT);
|
209
|
+
MarketoBulkExtractRequest marketoBulkExtractRequest = new MarketoBulkExtractRequest();
|
210
|
+
if (extractFields != null) {
|
211
|
+
marketoBulkExtractRequest.setFields(extractFields);
|
212
|
+
}
|
213
|
+
marketoBulkExtractRequest.setFormat("CSV");
|
214
|
+
Map<String, Object> filterMap = new HashMap<>();
|
215
|
+
DateRangeFilter dateRangeFilter = new DateRangeFilter();
|
216
|
+
dateRangeFilter.setStartAt(timeFormat.format(startTime));
|
217
|
+
dateRangeFilter.setEndAt(timeFormat.format(endTime));
|
218
|
+
filterMap.put(rangeFilterName, dateRangeFilter);
|
219
|
+
marketoBulkExtractRequest.setFilter(filterMap);
|
220
|
+
return marketoBulkExtractRequest;
|
221
|
+
}
|
222
|
+
|
223
|
+
public String createActivityExtract(List<Integer> activityTypeIds, Date startTime, Date endTime)
|
224
|
+
{
|
225
|
+
MarketoBulkExtractRequest marketoBulkExtractRequest = getMarketoBulkExtractRequest(startTime, endTime, null, "createdAt");
|
226
|
+
if (activityTypeIds != null && !activityTypeIds.isEmpty()) {
|
227
|
+
marketoBulkExtractRequest.getFilter().put("activityTypeIds", activityTypeIds);
|
228
|
+
}
|
229
|
+
return sendCreateBulkExtractRequest(marketoBulkExtractRequest, MarketoRESTEndpoint.CREATE_ACTIVITY_EXTRACT);
|
230
|
+
}
|
231
|
+
|
232
|
+
public String sendCreateBulkExtractRequest(MarketoBulkExtractRequest request, MarketoRESTEndpoint endpoint)
|
233
|
+
{
|
234
|
+
MarketoResponse<ObjectNode> marketoResponse = null;
|
235
|
+
try {
|
236
|
+
LOGGER.info("Send bulk extract request [{}]", request);
|
237
|
+
marketoResponse = doPost(endPoint + endpoint.getEndpoint(), null, null, OBJECT_MAPPER.writeValueAsString(request), new MarketoResponseJetty92EntityReader<ObjectNode>(readTimeoutMillis));
|
238
|
+
}
|
239
|
+
catch (JsonProcessingException e) {
|
240
|
+
LOGGER.error("Encounter exception when deserialize bulk extract request", e);
|
241
|
+
throw new DataException("Can't create bulk extract");
|
242
|
+
}
|
243
|
+
if (!marketoResponse.isSuccess()) {
|
244
|
+
MarketoError marketoError = marketoResponse.getErrors().get(0);
|
245
|
+
throw new DataException(marketoError.getCode() + ": " + marketoError.getMessage());
|
246
|
+
}
|
247
|
+
ObjectNode objectNode = marketoResponse.getResult().get(0);
|
248
|
+
return objectNode.get("exportId").asText();
|
249
|
+
}
|
250
|
+
|
251
|
+
public void startLeadBulkExtract(String exportId)
|
252
|
+
{
|
253
|
+
startBulkExtract(MarketoRESTEndpoint.START_LEAD_EXPORT_JOB, exportId);
|
254
|
+
}
|
255
|
+
|
256
|
+
public void startActitvityBulkExtract(String exportId)
|
257
|
+
{
|
258
|
+
startBulkExtract(MarketoRESTEndpoint.START_ACTIVITY_EXPORT_JOB, exportId);
|
259
|
+
}
|
260
|
+
|
261
|
+
private void startBulkExtract(MarketoRESTEndpoint marketoRESTEndpoint, String exportId)
|
262
|
+
{
|
263
|
+
MarketoResponse<ObjectNode> marketoResponse = doPost(endPoint + marketoRESTEndpoint.getEndpoint(
|
264
|
+
new ImmutableMap.Builder<String, String>().put("export_id", exportId).build()), null, null, null,
|
265
|
+
new MarketoResponseJetty92EntityReader<ObjectNode>(readTimeoutMillis));
|
266
|
+
if (!marketoResponse.isSuccess()) {
|
267
|
+
MarketoError error = marketoResponse.getErrors().get(0);
|
268
|
+
throw new DataException(String.format("Can't start job for export Job id : %s, error code: %s, error message: %s", exportId, error.getCode(), error.getMessage()));
|
269
|
+
}
|
270
|
+
}
|
271
|
+
|
272
|
+
/**
|
273
|
+
* Wait for lead bulk extract job
|
274
|
+
* Will block and wait until job status switch to complete
|
275
|
+
* If job run logger than bulk job timeout then will stop and throw exception
|
276
|
+
* If job status is failed or cancel will also throw exception
|
277
|
+
*
|
278
|
+
* @param exportId
|
279
|
+
* @throws InterruptedException
|
280
|
+
*/
|
281
|
+
public void waitLeadExportJobComplete(String exportId, int pollingInterval, int waitTimeout) throws InterruptedException
|
282
|
+
{
|
283
|
+
waitExportJobComplete(MarketoRESTEndpoint.GET_LEAD_EXPORT_STATUS, exportId, pollingInterval, waitTimeout);
|
284
|
+
}
|
285
|
+
|
286
|
+
/**
|
287
|
+
* Wait for activites bulk extract job
|
288
|
+
* Will block and wait until job status switch to complete
|
289
|
+
* If job run logger than bulk job timeout then will stop and throw exception
|
290
|
+
* If job status is failed or cancel will also throw exception
|
291
|
+
*
|
292
|
+
* @param exportId
|
293
|
+
* @throws InterruptedException
|
294
|
+
*/
|
295
|
+
public void waitActitvityExportJobComplete(String exportId, int pollingInterval, int waitTimeout) throws InterruptedException
|
296
|
+
{
|
297
|
+
waitExportJobComplete(MarketoRESTEndpoint.GET_ACTIVITY_EXPORT_STATUS, exportId, pollingInterval, waitTimeout);
|
298
|
+
}
|
299
|
+
|
300
|
+
private void waitExportJobComplete(MarketoRESTEndpoint marketoRESTEndpoint, String exportId, int pollingInterval, int waitTimeout) throws InterruptedException
|
301
|
+
{
|
302
|
+
long waitTime = 0;
|
303
|
+
long waitTimeoutMs = waitTimeout * 1000;
|
304
|
+
long now = System.currentTimeMillis();
|
305
|
+
while (true) {
|
306
|
+
MarketoResponse<ObjectNode> marketoResponse = doGet(this.endPoint + marketoRESTEndpoint.getEndpoint(
|
307
|
+
new ImmutableMap.Builder<String, String>().put("export_id", exportId).build()), null, null, new MarketoResponseJetty92EntityReader<ObjectNode>(readTimeoutMillis));
|
308
|
+
if (marketoResponse.isSuccess()) {
|
309
|
+
ObjectNode objectNode = marketoResponse.getResult().get(0);
|
310
|
+
String status = objectNode.get("status").asText();
|
311
|
+
if (status == null) {
|
312
|
+
throw new DataException("Can't get bulk extract status export job id: " + exportId);
|
313
|
+
}
|
314
|
+
LOGGER.info("Jobs [{}] status is [{}]", exportId, status);
|
315
|
+
switch (status) {
|
316
|
+
case "Completed":
|
317
|
+
LOGGER.info("Total wait time ms is [{}]", waitTime);
|
318
|
+
LOGGER.info("File size is [{}] bytes", objectNode.get("fileSize"));
|
319
|
+
return;
|
320
|
+
case "Failed":
|
321
|
+
throw new DataException("Bulk extract job failed exportId: " + exportId + " errorMessage: " + objectNode.get("errorMsg").asText());
|
322
|
+
case "Cancel":
|
323
|
+
throw new DataException("Bulk extract job canceled, exportId: " + exportId);
|
324
|
+
}
|
325
|
+
}
|
326
|
+
Thread.sleep(pollingInterval * 1000);
|
327
|
+
waitTime = System.currentTimeMillis() - now;
|
328
|
+
if (waitTime >= waitTimeoutMs) {
|
329
|
+
throw new DataException("Job timeout exception, exportJob: " + exportId + ", run longer than " + waitTimeout + " seconds");
|
330
|
+
}
|
331
|
+
}
|
332
|
+
}
|
333
|
+
|
334
|
+
public InputStream getLeadBulkExtractResult(String exportId, BulkExtractRangeHeader bulkExtractRangeHeader)
|
335
|
+
{
|
336
|
+
return getBulkExtractResult(MarketoRESTEndpoint.GET_LEAD_EXPORT_RESULT, exportId, bulkExtractRangeHeader);
|
337
|
+
}
|
338
|
+
|
339
|
+
public InputStream getActivitiesBulkExtractResult(String exportId, BulkExtractRangeHeader bulkExtractRangeHeader)
|
340
|
+
{
|
341
|
+
return getBulkExtractResult(MarketoRESTEndpoint.GET_ACTIVITY_EXPORT_RESULT, exportId, bulkExtractRangeHeader);
|
342
|
+
}
|
343
|
+
|
344
|
+
private InputStream getBulkExtractResult(MarketoRESTEndpoint endpoint, String exportId, BulkExtractRangeHeader bulkExtractRangeHeader)
|
345
|
+
{
|
346
|
+
LOGGER.info("Download bulk export job [{}]", exportId);
|
347
|
+
Map<String, String> headers = new HashMap<>();
|
348
|
+
if (bulkExtractRangeHeader != null) {
|
349
|
+
headers.put(RANGE_HEADER, bulkExtractRangeHeader.toRangeHeaderValue());
|
350
|
+
LOGGER.info("Range header value [{}]", bulkExtractRangeHeader.toRangeHeaderValue());
|
351
|
+
}
|
352
|
+
return doGet(this.endPoint + endpoint.getEndpoint(new ImmutableMap.Builder().put("export_id", exportId).build()), headers, null, new MarketoInputStreamResponseEntityReader(readTimeoutMillis));
|
353
|
+
}
|
354
|
+
|
355
|
+
public RecordPagingIterable<ObjectNode> getLists()
|
356
|
+
{
|
357
|
+
return getRecordWithTokenPagination(endPoint + MarketoRESTEndpoint.GET_LISTS.getEndpoint(), new ImmutableListMultimap.Builder<String, String>().put(BATCH_SIZE, MAX_BATCH_SIZE).build(), ObjectNode.class);
|
358
|
+
}
|
359
|
+
|
360
|
+
public RecordPagingIterable<ObjectNode> getPrograms()
|
361
|
+
{
|
362
|
+
return getRecordWithOffsetPagination(endPoint + MarketoRESTEndpoint.GET_PROGRAMS.getEndpoint(), new ImmutableListMultimap.Builder<String, String>().put(MAX_RETURN, DEFAULT_MAX_RETURN).build(), ObjectNode.class);
|
363
|
+
}
|
364
|
+
|
365
|
+
public RecordPagingIterable<ObjectNode> getLeadsByProgram(String programId, String fieldNames)
|
366
|
+
{
|
367
|
+
Multimap<String, String> multimap = ArrayListMultimap.create();
|
368
|
+
multimap.put("fields", fieldNames);
|
369
|
+
return getRecordWithTokenPagination(endPoint + MarketoRESTEndpoint.GET_LEADS_BY_PROGRAM.getEndpoint(new ImmutableMap.Builder().put("program_id", programId).build()), multimap, ObjectNode.class);
|
370
|
+
}
|
371
|
+
|
372
|
+
public RecordPagingIterable<ObjectNode> getLeadsByList(String listId, String fieldNames)
|
373
|
+
{
|
374
|
+
Multimap<String, String> multimap = ArrayListMultimap.create();
|
375
|
+
multimap.put("fields", fieldNames);
|
376
|
+
return getRecordWithTokenPagination(endPoint + MarketoRESTEndpoint.GET_LEADS_BY_LIST.getEndpoint(new ImmutableMap.Builder().put("list_id", listId).build()), multimap, ObjectNode.class);
|
377
|
+
}
|
378
|
+
|
379
|
+
public RecordPagingIterable<ObjectNode> getCampaign()
|
380
|
+
{
|
381
|
+
return getRecordWithTokenPagination(endPoint + MarketoRESTEndpoint.GET_CAMPAIGN.getEndpoint(), null, ObjectNode.class);
|
382
|
+
}
|
383
|
+
|
384
|
+
private <T> RecordPagingIterable<T> getRecordWithOffsetPagination(final String endPoint, final Multimap<String, String> parameters, final Class<T> recordClass)
|
385
|
+
{
|
386
|
+
return new RecordPagingIterable<>(new RecordPagingIterable.PagingFunction<RecordPagingIterable.OffsetPage<T>>()
|
387
|
+
{
|
388
|
+
@Override
|
389
|
+
public RecordPagingIterable.OffsetPage<T> getNextPage(RecordPagingIterable.OffsetPage<T> currentPage)
|
390
|
+
{
|
391
|
+
return getOffsetPage(currentPage.getNextOffSet());
|
392
|
+
}
|
393
|
+
|
394
|
+
@Override
|
395
|
+
public RecordPagingIterable.OffsetPage<T> getFirstPage()
|
396
|
+
{
|
397
|
+
return getOffsetPage(0);
|
398
|
+
}
|
399
|
+
|
400
|
+
private RecordPagingIterable.OffsetPage<T> getOffsetPage(int offset)
|
401
|
+
{
|
402
|
+
ImmutableListMultimap.Builder<String, String> params = new ImmutableListMultimap.Builder<>();
|
403
|
+
params.put(OFFSET, String.valueOf(offset));
|
404
|
+
params.put(MAX_RETURN, String.valueOf(maxReturn));
|
405
|
+
if (parameters != null) {
|
406
|
+
params.putAll(parameters);
|
407
|
+
}
|
408
|
+
MarketoResponse<T> marketoResponse = doGet(endPoint, null, params.build(), new MarketoResponseJetty92EntityReader<>(readTimeoutMillis, recordClass));
|
409
|
+
return new RecordPagingIterable.OffsetPage<>(marketoResponse.getResult(), offset + marketoResponse.getResult().size(), marketoResponse.getResult().size() == maxReturn);
|
410
|
+
}
|
411
|
+
});
|
412
|
+
}
|
413
|
+
private <T> RecordPagingIterable<T> getRecordWithTokenPagination(final String endPoint, final Multimap<String, String> parameters, final Class<T> recordClass)
|
414
|
+
{
|
415
|
+
return new RecordPagingIterable<>(new RecordPagingIterable.PagingFunction<RecordPagingIterable.TokenPage<T>>()
|
416
|
+
{
|
417
|
+
@Override
|
418
|
+
public RecordPagingIterable.TokenPage<T> getNextPage(RecordPagingIterable.TokenPage<T> currentPage)
|
419
|
+
{
|
420
|
+
return getTokenPage(currentPage);
|
421
|
+
}
|
422
|
+
@Override
|
423
|
+
public RecordPagingIterable.TokenPage<T> getFirstPage()
|
424
|
+
{
|
425
|
+
return getTokenPage(null);
|
426
|
+
}
|
427
|
+
|
428
|
+
@SuppressWarnings("unchecked")
|
429
|
+
private RecordPagingIterable.TokenPage<T> getTokenPage(RecordPagingIterable.TokenPage page)
|
430
|
+
{
|
431
|
+
ImmutableListMultimap.Builder params = new ImmutableListMultimap.Builder<>();
|
432
|
+
params.put("_method", "GET");
|
433
|
+
Fields fields = new Fields();
|
434
|
+
if (page != null) {
|
435
|
+
fields.add(NEXT_PAGE_TOKEN, page.getNextPageToken());
|
436
|
+
}
|
437
|
+
fields.add(BATCH_SIZE, String.valueOf(batchSize));
|
438
|
+
if (parameters != null) {
|
439
|
+
for (String key : parameters.keySet()) {
|
440
|
+
//params that is passed in should overwrite default
|
441
|
+
fields.remove(key);
|
442
|
+
for (String value : parameters.get(key)) {
|
443
|
+
fields.add(key, value);
|
444
|
+
}
|
445
|
+
}
|
446
|
+
}
|
447
|
+
//Let do GET Disguise in POST here to overcome Marketo URI Too long error
|
448
|
+
FormContentProvider formContentProvider = new FormContentProvider(fields);
|
449
|
+
MarketoResponse<T> marketoResponse = doPost(endPoint, null, params.build(), new MarketoResponseJetty92EntityReader<>(readTimeoutMillis, recordClass), formContentProvider);
|
450
|
+
return new RecordPagingIterable.TokenPage<>(marketoResponse.getResult(), marketoResponse.getNextPageToken(), marketoResponse.getNextPageToken() != null);
|
451
|
+
}
|
452
|
+
});
|
453
|
+
}
|
454
|
+
|
455
|
+
public Iterable<ObjectNode> getProgramsByTag(String tagType, String tagValue)
|
456
|
+
{
|
457
|
+
Multimap<String, String> multimap = ArrayListMultimap.create();
|
458
|
+
multimap.put("tagType", tagType);
|
459
|
+
multimap.put("tagValue", tagValue);
|
460
|
+
return getRecordWithOffsetPagination(endPoint + MarketoRESTEndpoint.GET_PROGRAMS_BY_TAG.getEndpoint(), multimap, ObjectNode.class);
|
461
|
+
}
|
462
|
+
|
463
|
+
public Iterable<ObjectNode> getProgramsByDateRange(Date earliestUpdatedAt, Date latestUpdatedAt, String filterType, List<String> filterValues)
|
464
|
+
{
|
465
|
+
SimpleDateFormat timeFormat = new SimpleDateFormat(MarketoUtils.MARKETO_DATE_SIMPLE_DATE_FORMAT);
|
466
|
+
Multimap<String, String> multimap = ArrayListMultimap.create();
|
467
|
+
multimap.put("earliestUpdatedAt", timeFormat.format(earliestUpdatedAt));
|
468
|
+
multimap.put("latestUpdatedAt", timeFormat.format(latestUpdatedAt));
|
469
|
+
// put filter params if exist.
|
470
|
+
if (filterType != null) {
|
471
|
+
multimap.put("filterType", filterType);
|
472
|
+
multimap.put("filterValues", StringUtils.join(filterValues, ","));
|
473
|
+
}
|
474
|
+
return getRecordWithOffsetPagination(endPoint + MarketoRESTEndpoint.GET_PROGRAMS.getEndpoint(), multimap, ObjectNode.class);
|
475
|
+
}
|
476
|
+
|
477
|
+
public List<MarketoField> describeCustomObject(String apiName)
|
478
|
+
{
|
479
|
+
MarketoResponse<ObjectNode> jsonResponse = doGet(endPoint + MarketoRESTEndpoint.GET_CUSTOM_OBJECT_DESCRIBE.getEndpoint(new ImmutableMap.Builder().put("api_name", apiName).build()), null, null, new MarketoResponseJetty92EntityReader<ObjectNode>(this.readTimeoutMillis));
|
480
|
+
if (jsonResponse.getResult().size() == 0) {
|
481
|
+
throw new ConfigException(String.format("Custom Object %s is not exits.", apiName));
|
482
|
+
}
|
483
|
+
List<MarketoField> marketoFields = new ArrayList<>();
|
484
|
+
JsonNode fieldNodes = jsonResponse.getResult().get(0).path("fields");
|
485
|
+
for (JsonNode node : fieldNodes) {
|
486
|
+
String dataType = node.get("dataType").asText();
|
487
|
+
String name = node.get("name").asText();
|
488
|
+
marketoFields.add(new MarketoField(name, dataType));
|
489
|
+
}
|
490
|
+
if (marketoFields.size() == 0) {
|
491
|
+
throw new ConfigException(String.format("Custom Object %s don't have any field data.", apiName));
|
492
|
+
}
|
493
|
+
return marketoFields;
|
494
|
+
}
|
495
|
+
private <T> RecordPagingIterable<T> getCustomObjectRecordWithPagination(final String endPoint, final String customObjectFilterType, final String customObjectFields, final Integer fromValue, final Integer toValue, final Class<T> recordClass)
|
496
|
+
{
|
497
|
+
return new RecordPagingIterable<>(new RecordPagingIterable.PagingFunction<RecordPagingIterable.OffsetWithTokenPage<T>>()
|
498
|
+
{
|
499
|
+
@Override
|
500
|
+
public RecordPagingIterable.OffsetWithTokenPage<T> getNextPage(RecordPagingIterable.OffsetWithTokenPage<T> currentPage)
|
501
|
+
{
|
502
|
+
return getOffsetPage(currentPage.getNextOffSet(), currentPage.getNextPageToken());
|
503
|
+
}
|
504
|
+
|
505
|
+
@Override
|
506
|
+
public RecordPagingIterable.OffsetWithTokenPage<T> getFirstPage()
|
507
|
+
{
|
508
|
+
return getOffsetPage(fromValue, "");
|
509
|
+
}
|
510
|
+
|
511
|
+
private RecordPagingIterable.OffsetWithTokenPage<T> getOffsetPage(int offset, String nextPageToken)
|
512
|
+
{
|
513
|
+
boolean isMoreResult = true;
|
514
|
+
boolean isEndOffset = false;
|
515
|
+
int nextOffset = offset + MAX_REQUEST_SIZE;
|
516
|
+
|
517
|
+
if (toValue != null) {
|
518
|
+
if (toValue <= nextOffset) {
|
519
|
+
nextOffset = toValue + 1;
|
520
|
+
isEndOffset = true;
|
521
|
+
}
|
522
|
+
}
|
523
|
+
StringBuilder filterValues = new StringBuilder();
|
524
|
+
for (int i = offset; i < (nextOffset - 1); i++) {
|
525
|
+
filterValues.append(String.valueOf(i)).append(",");
|
526
|
+
}
|
527
|
+
filterValues.append(String.valueOf(nextOffset - 1));
|
528
|
+
|
529
|
+
ImmutableListMultimap.Builder<String, String> params = new ImmutableListMultimap.Builder<>();
|
530
|
+
params.put(FILTER_TYPE, customObjectFilterType);
|
531
|
+
params.put(FILTER_VALUES, filterValues.toString());
|
532
|
+
if (StringUtils.isNotBlank(nextPageToken)) {
|
533
|
+
params.put(NEXT_PAGE_TOKEN, nextPageToken);
|
534
|
+
}
|
535
|
+
if (customObjectFields != null) {
|
536
|
+
params.put(FIELDS, customObjectFields);
|
537
|
+
}
|
538
|
+
MarketoResponse<T> marketoResponse = doGet(endPoint, null, params.build(), new MarketoResponseJetty92EntityReader<>(readTimeoutMillis, recordClass));
|
539
|
+
String nextToken = "";
|
540
|
+
if (StringUtils.isNotBlank(marketoResponse.getNextPageToken())) {
|
541
|
+
nextToken = marketoResponse.getNextPageToken();
|
542
|
+
//skip offset when nextPageToken is exits.
|
543
|
+
nextOffset = offset;
|
544
|
+
}
|
545
|
+
|
546
|
+
if (toValue == null) {
|
547
|
+
if (marketoResponse.getResult().isEmpty()) {
|
548
|
+
isMoreResult = false;
|
549
|
+
}
|
550
|
+
}
|
551
|
+
else {
|
552
|
+
if (isEndOffset && StringUtils.isBlank(nextToken)) {
|
553
|
+
isMoreResult = false;
|
554
|
+
}
|
555
|
+
}
|
556
|
+
return new RecordPagingIterable.OffsetWithTokenPage<>(marketoResponse.getResult(), nextOffset, nextToken, isMoreResult);
|
557
|
+
}
|
558
|
+
});
|
559
|
+
}
|
560
|
+
public Iterable<ObjectNode> getCustomObject(String customObjectAPIName, String customObjectFilterType, String customObjectFields, Integer fromValue, Integer toValue)
|
561
|
+
{
|
562
|
+
return getCustomObjectRecordWithPagination(endPoint + MarketoRESTEndpoint.GET_CUSTOM_OBJECT.getEndpoint(new ImmutableMap.Builder().put("api_name", customObjectAPIName).build()), customObjectFilterType, customObjectFields, fromValue, toValue, ObjectNode.class);
|
563
|
+
}
|
564
|
+
|
565
|
+
public Iterable<ObjectNode> getActivityTypes()
|
566
|
+
{
|
567
|
+
return getRecordWithOffsetPagination(endPoint + MarketoRESTEndpoint.GET_ACTIVITY_TYPES.getEndpoint(), new ImmutableListMultimap.Builder<String, String>().put(MAX_RETURN, DEFAULT_MAX_RETURN).build(), ObjectNode.class);
|
568
|
+
}
|
569
|
+
}
|