Skip to content

Commit 84d8d7c

Browse files
committed
Added an automatic setting to the PojoCodecProvider
Automatically creates a PojoCodec for any unseen class that contains serializable / deserializable properties. JAVA-2567
1 parent b83a114 commit 84d8d7c

File tree

25 files changed

+1317
-1096
lines changed

25 files changed

+1317
-1096
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright 2017 MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.bson.codecs.pojo;
18+
19+
import org.bson.BsonReader;
20+
import org.bson.BsonWriter;
21+
import org.bson.codecs.DecoderContext;
22+
import org.bson.codecs.EncoderContext;
23+
import org.bson.codecs.configuration.CodecConfigurationException;
24+
25+
import static java.lang.String.format;
26+
27+
final class AutomaticPojoCodec<T> extends PojoCodec<T> {
28+
private final PojoCodec<T> pojoCodec;
29+
30+
AutomaticPojoCodec(final PojoCodec<T> pojoCodec) {
31+
this.pojoCodec = pojoCodec;
32+
}
33+
34+
@Override
35+
public T decode(final BsonReader reader, final DecoderContext decoderContext) {
36+
try {
37+
return pojoCodec.decode(reader, decoderContext);
38+
} catch (CodecConfigurationException e) {
39+
throw new CodecConfigurationException(
40+
format("An exception occurred when decoding using the AutomaticPojoCodec.%n"
41+
+ "Decoding into a '%s' failed with the following exception:%n%n%s%n%n"
42+
+ "A custom Codec or PojoCodec may need to be explicitly configured and registered to handle this type.",
43+
pojoCodec.getEncoderClass().getSimpleName(), e.getMessage()), e);
44+
}
45+
}
46+
47+
@Override
48+
public void encode(final BsonWriter writer, final T value, final EncoderContext encoderContext) {
49+
try {
50+
pojoCodec.encode(writer, value, encoderContext);
51+
} catch (CodecConfigurationException e) {
52+
throw new CodecConfigurationException(
53+
format("An exception occurred when encoding using the AutomaticPojoCodec.%n"
54+
+ "Encoding a %s: '%s' failed with the following exception:%n%n%s%n%n"
55+
+ "A custom Codec or PojoCodec may need to be explicitly configured and registered to handle this type.",
56+
getEncoderClass().getSimpleName(), value, e.getMessage()), e);
57+
}
58+
}
59+
60+
@Override
61+
public Class<T> getEncoderClass() {
62+
return pojoCodec.getEncoderClass();
63+
}
64+
65+
@Override
66+
ClassModel<T> getClassModel() {
67+
return pojoCodec.getClassModel();
68+
}
69+
}

bson/src/main/org/bson/codecs/pojo/ConventionDefaultsImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public void apply(final ClassModelBuilder<?> classModelBuilder) {
2323
classModelBuilder.discriminatorKey("_t");
2424
}
2525
if (classModelBuilder.getDiscriminator() == null && classModelBuilder.getType() != null) {
26-
classModelBuilder.discriminator(classModelBuilder.getType().getSimpleName());
26+
classModelBuilder.discriminator(classModelBuilder.getType().getName());
2727
}
2828

2929
for (final PropertyModelBuilder<?> propertyModel : classModelBuilder.getPropertyModelBuilders()) {

bson/src/main/org/bson/codecs/pojo/CreatorExecutable.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ CodecConfigurationException getError(final String msg) {
111111

112112
void checkHasAnExecutable() {
113113
if (constructor == null && method == null) {
114-
throw new CodecConfigurationException(format("Cannot find a public constructor for '%s'", clazz.getSimpleName()));
114+
throw new CodecConfigurationException(format("Cannot find a public constructor for '%s'.", clazz.getSimpleName()));
115115
}
116116
}
117117

bson/src/main/org/bson/codecs/pojo/DiscriminatorLookup.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ final class DiscriminatorLookup {
3535
this.packages = packages;
3636
}
3737

38-
Class<?> lookup(final String discriminator) {
38+
public Class<?> lookup(final String discriminator) {
3939
if (discriminatorClassMap.containsKey(discriminator)) {
4040
return discriminatorClassMap.get(discriminator);
4141
}
@@ -53,6 +53,12 @@ Class<?> lookup(final String discriminator) {
5353
return clazz;
5454
}
5555

56+
void addClassModel(final ClassModel<?> classModel) {
57+
if (classModel.getDiscriminator() != null) {
58+
discriminatorClassMap.put(classModel.getDiscriminator(), classModel.getType());
59+
}
60+
}
61+
5662
private Class<?> getClassForName(final String discriminator) {
5763
Class<?> clazz = null;
5864
try {

bson/src/main/org/bson/codecs/pojo/LazyPojoCodec.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,16 @@
2525

2626
import java.util.concurrent.ConcurrentMap;
2727

28-
class LazyPojoCodec<T> implements Codec<T> {
28+
class LazyPojoCodec<T> extends PojoCodec<T> {
2929
private final ClassModel<T> classModel;
30-
private final PojoCodecProvider codecProvider;
3130
private final CodecRegistry registry;
3231
private final DiscriminatorLookup discriminatorLookup;
3332
private final ConcurrentMap<ClassModel<?>, Codec<?>> codecCache;
34-
private volatile PojoCodec<T> pojoCodec;
33+
private volatile PojoCodecImpl<T> pojoCodec;
3534

36-
LazyPojoCodec(final ClassModel<T> classModel, final PojoCodecProvider codecProvider, final CodecRegistry registry,
37-
final DiscriminatorLookup discriminatorLookup, final ConcurrentMap<ClassModel<?>, Codec<?>> codecCache) {
35+
LazyPojoCodec(final ClassModel<T> classModel, final CodecRegistry registry, final DiscriminatorLookup discriminatorLookup,
36+
final ConcurrentMap<ClassModel<?>, Codec<?>> codecCache) {
3837
this.classModel = classModel;
39-
this.codecProvider = codecProvider;
4038
this.registry = registry;
4139
this.discriminatorLookup = discriminatorLookup;
4240
this.codecCache = codecCache;
@@ -59,8 +57,13 @@ public T decode(final BsonReader reader, final DecoderContext decoderContext) {
5957

6058
private Codec<T> getPojoCodec() {
6159
if (pojoCodec == null) {
62-
pojoCodec = new PojoCodec<T>(classModel, codecProvider, registry, discriminatorLookup, codecCache, true);
60+
pojoCodec = new PojoCodecImpl<T>(classModel, registry, discriminatorLookup, codecCache, true);
6361
}
6462
return pojoCodec;
6563
}
64+
65+
@Override
66+
ClassModel<T> getClassModel() {
67+
return classModel;
68+
}
6669
}

0 commit comments

Comments
 (0)