Skip to content

Commit ef48589

Browse files
author
Chris Cho
authored
DOCSP-23217: Add OptionalPropertyCodecProviderExample for testing (#241)
* DOCSP-23217: Add OptionalPropertyCodecProviderExample for testing
1 parent 90c8e7f commit ef48589

File tree

6 files changed

+238
-46
lines changed

6 files changed

+238
-46
lines changed

source/fundamentals/data-formats/pojo-customization.txt

Lines changed: 4 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -588,52 +588,10 @@ You can use the following implementation of ``PropertyCodecProvider`` to
588588
retrieve your custom Codec. This implementation uses the
589589
``TypeWithTypeParameters`` interface to access the type information.
590590

591-
.. code-block:: java
592-
593-
public class OptionalPropertyCodecProvider implements PropertyCodecProvider {
594-
595-
@Override
596-
@SuppressWarnings({"rawtypes", "unchecked"})
597-
public <T> Codec<T> get(final TypeWithTypeParameters<T> type, final PropertyCodecRegistry registry) {
598-
// Check the main type and number of generic parameters
599-
if (Optional.class.isAssignableFrom(type.getType()) && type.getTypeParameters().size() == 1) {
600-
// Get the codec for the concrete type of the Optional, as its declared in the POJO.
601-
Codec<?> valueCodec = registry.get(type.getTypeParameters().get(0));
602-
return new OptionalCodec(type.getType(), valueCodec);
603-
} else {
604-
return null;
605-
}
606-
}
607-
608-
private static final class OptionalCodec<T> implements Codec<Optional<T>> {
609-
private final Class<Optional<T>> encoderClass;
610-
private final Codec<T> codec;
611-
612-
private OptionalCodec(final Class<Optional<T>> encoderClass, final Codec<T> codec) {
613-
this.encoderClass = encoderClass;
614-
this.codec = codec;
615-
}
616-
617-
@Override
618-
public void encode(final BsonWriter writer, final Optional<T> optionalValue, final EncoderContext encoderContext) {
619-
if (optionalValue != null && optionalValue.isPresent()) {
620-
codec.encode(writer, optionalValue.get(), encoderContext);
621-
} else {
622-
writer.writeNull();
623-
}
624-
}
625-
626-
@Override
627-
public Optional<T> decode(final BsonReader reader, final DecoderContext context) {
628-
return Optional.of(codec.decode(reader, context));
629-
}
630-
631-
@Override
632-
public Class<Optional<T>> getEncoderClass() {
633-
return encoderClass;
634-
}
635-
}
636-
}
591+
.. literalinclude:: /includes/fundamentals/code-snippets/optional-codec-provider/OptionalPropertyCodecProvider.java
592+
:language: java
593+
:start-after: start optionalPropertyCodecProvider
594+
:end-before: end optionalPropertyCodecProvider
637595

638596
Register your ``OptionalPropertyCodecProvider`` in your ``PojoCodecProvider``
639597
and the package that contains your POJO as follows:
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package org.example.pojos;
2+
3+
public class Address {
4+
private String street;
5+
private String city;
6+
7+
public Address() {}
8+
9+
public Address(String street, String city) {
10+
this.street = street;
11+
this.city = city;
12+
}
13+
14+
public String getStreet() {
15+
return street;
16+
}
17+
public void setStreet(String street) {
18+
this.street = street;
19+
}
20+
public String getCity() {
21+
return city;
22+
}
23+
public void setCity(String city) {
24+
this.city = city;
25+
}
26+
27+
@Override
28+
public String toString() {
29+
return "Address [street=" + street + ", city=" + city + "]";
30+
}
31+
32+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package org.example.pojos;
2+
3+
import java.util.Optional;
4+
5+
6+
public class ApplicationUser {
7+
8+
private Optional<Address> optionalAddress;
9+
private Optional<Subscription> optionalSubscription;
10+
private String name;
11+
12+
public ApplicationUser() {}
13+
public ApplicationUser(String name) {
14+
this.name = name;
15+
}
16+
17+
public Optional<Address> getOptionalAddress() {
18+
return optionalAddress;
19+
}
20+
public void setOptionalAddress(Optional<Address> optionalAddress) {
21+
this.optionalAddress = optionalAddress;
22+
}
23+
public Optional<Subscription> getOptionalSubscription() {
24+
return optionalSubscription;
25+
}
26+
public void setOptionalSubscription(Optional<Subscription> optionalSubscription) {
27+
this.optionalSubscription = optionalSubscription;
28+
}
29+
public String getName() {
30+
return name;
31+
}
32+
public void setName(String name) {
33+
this.name = name;
34+
}
35+
@Override
36+
public String toString() {
37+
return "ApplicationUser [optionalAddress=" + optionalAddress + ", optionalSubscription=" + optionalSubscription
38+
+ ", name=" + name + "]";
39+
}
40+
41+
42+
43+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package org.example.pojos;
2+
3+
import java.util.Optional;
4+
5+
import org.bson.BsonReader;
6+
import org.bson.BsonWriter;
7+
import org.bson.codecs.Codec;
8+
import org.bson.codecs.DecoderContext;
9+
import org.bson.codecs.EncoderContext;
10+
import org.bson.codecs.pojo.PropertyCodecProvider;
11+
import org.bson.codecs.pojo.PropertyCodecRegistry;
12+
import org.bson.codecs.pojo.TypeWithTypeParameters;
13+
14+
// start optionalPropertyCodecProvider
15+
public class OptionalPropertyCodecProvider implements PropertyCodecProvider {
16+
17+
@Override
18+
@SuppressWarnings({"rawtypes", "unchecked"})
19+
public <T> Codec<T> get(final TypeWithTypeParameters<T> type, final PropertyCodecRegistry registry) {
20+
// Check the main type and number of generic parameters
21+
if (Optional.class.isAssignableFrom(type.getType()) && type.getTypeParameters().size() == 1) {
22+
// Get the codec for the concrete type of the Optional, as its declared in the POJO.
23+
Codec<?> valueCodec = registry.get(type.getTypeParameters().get(0));
24+
return new OptionalCodec(type.getType(), valueCodec);
25+
} else {
26+
return null;
27+
}
28+
}
29+
30+
private static final class OptionalCodec<T> implements Codec<Optional<T>> {
31+
private final Class<Optional<T>> encoderClass;
32+
private final Codec<T> codec;
33+
34+
private OptionalCodec(final Class<Optional<T>> encoderClass, final Codec<T> codec) {
35+
this.encoderClass = encoderClass;
36+
this.codec = codec;
37+
}
38+
39+
@Override
40+
public void encode(final BsonWriter writer, final Optional<T> optionalValue, final EncoderContext encoderContext) {
41+
if (optionalValue != null && optionalValue.isPresent()) {
42+
codec.encode(writer, optionalValue.get(), encoderContext);
43+
} else {
44+
writer.writeNull();
45+
}
46+
}
47+
48+
@Override
49+
public Optional<T> decode(final BsonReader reader, final DecoderContext context) {
50+
return Optional.of(codec.decode(reader, context));
51+
}
52+
53+
@Override
54+
public Class<Optional<T>> getEncoderClass() {
55+
return encoderClass;
56+
}
57+
}
58+
}
59+
// end optionalPropertyCodecProvider
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package org.example.pojos;
2+
3+
import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
4+
5+
import java.util.Optional;
6+
7+
import org.bson.codecs.configuration.CodecProvider;
8+
import org.bson.codecs.configuration.CodecRegistries;
9+
import org.bson.codecs.configuration.CodecRegistry;
10+
import org.bson.codecs.pojo.PojoCodecProvider;
11+
12+
import com.mongodb.MongoClientSettings;
13+
import com.mongodb.client.MongoClient;
14+
import com.mongodb.client.MongoClients;
15+
import com.mongodb.client.MongoCollection;
16+
import com.mongodb.client.MongoCursor;
17+
import com.mongodb.client.MongoDatabase;
18+
19+
public class OptionalPropertyExample {
20+
21+
public static void main(String[] args) {
22+
CodecProvider pojoCodecProvider = PojoCodecProvider.builder()
23+
.register("githubdocs")
24+
.register(new OptionalPropertyCodecProvider()) // comment this out to make the code fail
25+
.build();
26+
27+
CodecRegistry registry = CodecRegistries.fromRegistries(
28+
MongoClientSettings.getDefaultCodecRegistry(),
29+
fromProviders(pojoCodecProvider));
30+
31+
String uri = "mongodb://localhost:27017";
32+
33+
try (MongoClient mongoClient = MongoClients.create(uri)) {
34+
35+
MongoDatabase database = mongoClient.getDatabase("sample_pojo").withCodecRegistry(registry);
36+
MongoCollection<ApplicationUser> collection = database.getCollection("appUser", ApplicationUser.class);
37+
38+
ApplicationUser appUser = new ApplicationUser("Chris");
39+
Address addr = new Address("New York City", "Broadway");
40+
appUser.setOptionalAddress(Optional.ofNullable(addr));
41+
collection.insertOne(appUser);
42+
43+
ApplicationUser anotherAppUser = new ApplicationUser("Sirhc");
44+
Subscription sub = new Subscription("Monthly", "12-Month Plan");
45+
anotherAppUser.setOptionalAddress(Optional.ofNullable(new Address()));
46+
anotherAppUser.setOptionalSubscription(Optional.ofNullable(sub));
47+
collection.insertOne(anotherAppUser);
48+
49+
MongoCursor<ApplicationUser> results = collection.find().iterator();
50+
while(results.hasNext()) {
51+
ApplicationUser result = results.next();
52+
StringBuilder sb = new StringBuilder(result.getName() + ": ");
53+
54+
if (result.getOptionalSubscription() != null && result.getOptionalSubscription().isPresent()) {
55+
sb.append(result.getOptionalSubscription().get().toString());
56+
}
57+
if (result.getOptionalAddress() != null && result.getOptionalAddress().isPresent()) {
58+
sb.append(result.getOptionalAddress().get().toString());
59+
}
60+
61+
System.out.println(sb);
62+
}
63+
}
64+
65+
66+
}
67+
68+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package org.example.pojos;
2+
3+
public class Subscription {
4+
private String type;
5+
private String subName;
6+
7+
public Subscription() {}
8+
9+
public Subscription(String type, String subName) {
10+
this.type = type;
11+
this.subName = subName;
12+
}
13+
14+
public String getType() {
15+
return type;
16+
}
17+
public void setType(String type) {
18+
this.type = type;
19+
}
20+
public String getSubName() {
21+
return subName;
22+
}
23+
public void setSubName(String subName) {
24+
this.subName = subName;
25+
}
26+
27+
@Override
28+
public String toString() {
29+
return "Subscription [type=" + type + ", subName=" + subName + "]";
30+
}
31+
32+
}

0 commit comments

Comments
 (0)