Skip to content

Commit d8a6495

Browse files
authored
improve support for record multiple value custom fields (#52)
* improve support for record multiple value custom fields * update changelog * fix changelog * fix test
1 parent cf4dc8d commit d8a6495

File tree

11 files changed

+413
-15
lines changed

11 files changed

+413
-15
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22
The format is based on [Keep a Changelog](http://keepachangelog.com/)
33
and this project adheres to [Semantic Versioning](http://semver.org/).
44

5+
## 2.0.0 (03/05/2020)
6+
- [ISSUE-50](https://github.com/Crim/pardot-java-client/issues/50) Improve support for record multiple fields.
7+
8+
### Breaking Change
9+
10+
In order to better support record multiple value custom fields, the accessor on `Prospect` for `getCustomFields()` has been changed **FROM**
11+
`public Map<String, String> getCustomFields()` **TO** `public Map<String, ProspectCustomFieldValue> getCustomFields()`
12+
13+
For custom fields which are NOT record multiple value custom fields the accessor `public String getCustomField(final String customFieldName)` method will continue to return the stored value for the custom field.
14+
15+
For custom fields which ARE record multiple value custom fields the accessor `public String getCustomField(final String customFieldName)` method will only return the first stored value. You can use the new accessor
16+
`public List<String> getCustomFieldValues(final String customFieldName)` to get all stored values for record multiple value custom fields.
17+
18+
519
## 1.1.2 (02/20/2020)
620
#### Bugfixes
721
- [ISSUE-45](https://github.com/Crim/pardot-java-client/issues/45) Fixed bug preventing the library from auto-renewing a session when it expires.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ This client library is released on Maven Central. Add a new dependency to your
2121
<dependency>
2222
<groupId>com.darksci</groupId>
2323
<artifactId>pardot-api-client</artifactId>
24-
<version>1.1.2</version>
24+
<version>2.0.0</version>
2525
</dependency>
2626
```
2727

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.darksci</groupId>
88
<artifactId>pardot-api-client</artifactId>
9-
<version>1.1.2</version>
9+
<version>2.0.0</version>
1010
<packaging>jar</packaging>
1111

1212
<!-- Require Maven 3.5.0 -->

src/main/java/com/darksci/pardot/api/parser/JacksonFactory.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
package com.darksci.pardot.api.parser;
1919

20+
import com.darksci.pardot.api.parser.prospect.ProspectCustomFieldDeserializer;
21+
import com.darksci.pardot.api.response.customfield.ProspectCustomFieldValue;
2022
import com.fasterxml.jackson.databind.DeserializationFeature;
2123
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
2224
import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule;
@@ -30,15 +32,26 @@
3032
*/
3133
public class JacksonFactory {
3234

35+
/**
36+
* Cache mapper instance.
37+
*/
38+
private static final XmlMapper instance = newInstance();
39+
3340
/**
3441
* Creates properly configured Jackson XML Mapper instances.
3542
* @return XmlMapper instance.
3643
*/
3744
public static XmlMapper newInstance() {
45+
if (instance != null) {
46+
return instance;
47+
}
48+
3849
// Create new mapper
3950
final JacksonXmlModule module = new JacksonXmlModule();
4051
module.setDefaultUseWrapper(false);
41-
XmlMapper mapper = new XmlMapper(module);
52+
module.addDeserializer(ProspectCustomFieldValue.class, new ProspectCustomFieldDeserializer());
53+
54+
final XmlMapper mapper = new XmlMapper(module);
4255

4356
// Configure it
4457
mapper
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**
2+
* Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
5+
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
6+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
7+
* persons to whom the Software is furnished to do so, subject to the following conditions:
8+
*
9+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
10+
* Software.
11+
*
12+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
13+
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
14+
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
15+
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
16+
*/
17+
18+
package com.darksci.pardot.api.parser.prospect;
19+
20+
import com.darksci.pardot.api.response.customfield.ProspectCustomFieldValue;
21+
import com.fasterxml.jackson.core.JsonParser;
22+
import com.fasterxml.jackson.core.JsonToken;
23+
import com.fasterxml.jackson.databind.DeserializationContext;
24+
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
25+
26+
import java.io.IOException;
27+
import java.util.ArrayList;
28+
import java.util.List;
29+
30+
/**
31+
* Custom deserializer to be able to support Record Multiple custom fields.
32+
*/
33+
public class ProspectCustomFieldDeserializer extends StdDeserializer<ProspectCustomFieldValue> {
34+
35+
/**
36+
* Constructor.
37+
*/
38+
public ProspectCustomFieldDeserializer() {
39+
this(null);
40+
}
41+
42+
/**
43+
* Constructor.
44+
* @param vc the type of the class this handles.
45+
*/
46+
public ProspectCustomFieldDeserializer(final Class<?> vc) {
47+
super(vc);
48+
}
49+
50+
@Override
51+
public ProspectCustomFieldValue deserialize(final JsonParser parser, final DeserializationContext context) throws IOException {
52+
// Get the current custom field name.
53+
final String fieldName = parser.getCurrentName();
54+
55+
// Keep track of all the values associated with the field.
56+
final List<String> fieldValues = new ArrayList<>();
57+
58+
// If we have multiple values
59+
if (parser.getCurrentToken() == JsonToken.START_OBJECT) {
60+
// Loop until we hit end object
61+
while (parser.nextToken() != JsonToken.END_OBJECT) {
62+
// Pull out each value
63+
if (parser.getCurrentToken() == JsonToken.VALUE_STRING) {
64+
fieldValues.add(parser.getValueAsString());
65+
}
66+
}
67+
} else if (parser.getCurrentToken() == JsonToken.VALUE_STRING) {
68+
// If we have a single value, we just record the value as is.
69+
fieldValues.add(parser.getValueAsString());
70+
}
71+
72+
// Return our deserialized instance.
73+
return new ProspectCustomFieldValue(fieldName, fieldValues);
74+
}
75+
}

src/main/java/com/darksci/pardot/api/request/prospect/ProspectModifyRequest.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package com.darksci.pardot.api.request.prospect;
1919

2020
import com.darksci.pardot.api.request.BaseRequest;
21+
import com.darksci.pardot.api.response.customfield.ProspectCustomFieldValue;
2122
import com.darksci.pardot.api.response.prospect.Prospect;
2223

2324
import java.util.Map;
@@ -65,8 +66,18 @@ public T withProspect(final Prospect prospect) {
6566

6667
// Loop through and set custom fields
6768
if (prospect.getCustomFields() != null) {
68-
for (Map.Entry<String, String> entry: prospect.getCustomFields().entrySet()) {
69-
setParam(entry.getKey(), entry.getValue());
69+
for (ProspectCustomFieldValue customFieldValue : prospect.getCustomFields().values()) {
70+
// For single value custom fields.
71+
if (!customFieldValue.hasMultipleValues()) {
72+
setParam(customFieldValue.getFieldName(), customFieldValue.getValue());
73+
} else {
74+
// For multiple value fields, send as field_name_<index> = value
75+
int fieldIndex = 0;
76+
for (final String value : customFieldValue.getValues()) {
77+
setParam(customFieldValue.getFieldName() + "_" + fieldIndex, value);
78+
fieldIndex++;
79+
}
80+
}
7081
}
7182
}
7283

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/**
2+
* Copyright 2017, 2018, 2019, 2020 Stephen Powis https://github.com/Crim/pardot-java-client
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
5+
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
6+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
7+
* persons to whom the Software is furnished to do so, subject to the following conditions:
8+
*
9+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
10+
* Software.
11+
*
12+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
13+
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
14+
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
15+
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
16+
*/
17+
18+
package com.darksci.pardot.api.response.customfield;
19+
20+
import com.darksci.pardot.api.parser.prospect.ProspectCustomFieldDeserializer;
21+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
22+
23+
import java.util.ArrayList;
24+
import java.util.Collection;
25+
import java.util.List;
26+
27+
/**
28+
* Represents a Prospect CustomField value.
29+
* Since custom fields can be stored as a single value, or as a list of values (for record multiple fields),
30+
* this attempts to normalize the way these two types are accessed.
31+
*/
32+
@JsonDeserialize(using = ProspectCustomFieldDeserializer.class)
33+
public class ProspectCustomFieldValue {
34+
private final String fieldName;
35+
private final List<String> values = new ArrayList<>();
36+
37+
/**
38+
* Constructor for custom field which only has a single value.
39+
* @param fieldName name of the field.
40+
* @param value value of the field.
41+
*/
42+
public ProspectCustomFieldValue(final String fieldName, final String value) {
43+
this.fieldName = fieldName;
44+
if (value != null) {
45+
this.values.add(value);
46+
}
47+
}
48+
49+
/**
50+
* Constructor for custom field which has multiple values.
51+
* @param fieldName name of the field.
52+
* @param values values for the field.
53+
*/
54+
public ProspectCustomFieldValue(final String fieldName, final Collection<String> values) {
55+
this.fieldName = fieldName;
56+
if (values != null) {
57+
this.values.addAll(values);
58+
}
59+
}
60+
61+
public String getFieldName() {
62+
return fieldName;
63+
}
64+
65+
/**
66+
* The value of the custom field.
67+
* @return value of the custom field.
68+
* *NOTE* If this is a record multiple field with multiple values, this will return the first value only.
69+
*/
70+
public String getValue() {
71+
if (values.isEmpty()) {
72+
return null;
73+
}
74+
return values.get(0);
75+
}
76+
77+
public List<String> getValues() {
78+
return values;
79+
}
80+
81+
public boolean hasMultipleValues() {
82+
return getValues().size() > 1;
83+
}
84+
85+
public void addValue(final String value) {
86+
values.add(value);
87+
}
88+
89+
public void addValues(final Collection<String> values) {
90+
values.addAll(values);
91+
}
92+
93+
public void setValue(final String value) {
94+
values.clear();
95+
addValue(value);
96+
}
97+
98+
public void setValues(final Collection<String> values) {
99+
values.clear();
100+
addValues(values);
101+
}
102+
103+
@Override
104+
public String toString() {
105+
return "ProspectCustomFieldValue{"
106+
+ "fieldName='" + fieldName + '\''
107+
+ ", values=" + values
108+
+ '}';
109+
}
110+
}

0 commit comments

Comments
 (0)