Skip to content

Commit d64ba2d

Browse files
committed
PojoCodec PR stylistic code clean ups and extra tests.
1 parent 766a600 commit d64ba2d

16 files changed

+445
-136
lines changed

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

Lines changed: 0 additions & 46 deletions
This file was deleted.
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
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.Codec;
22+
import org.bson.codecs.DecoderContext;
23+
import org.bson.codecs.EncoderContext;
24+
import org.bson.codecs.configuration.CodecConfigurationException;
25+
import org.bson.codecs.configuration.CodecRegistry;
26+
27+
28+
final class EnumPropertyCodecProvider implements PropertyCodecProvider {
29+
private final CodecRegistry codecRegistry;
30+
31+
EnumPropertyCodecProvider(final CodecRegistry codecRegistry) {
32+
this.codecRegistry = codecRegistry;
33+
}
34+
35+
@SuppressWarnings({"unchecked", "rawtypes"})
36+
@Override
37+
public <T> Codec<T> get(final TypeWithTypeParameters<T> type, final PropertyCodecRegistry propertyCodecRegistry) {
38+
Class<T> clazz = type.getType();
39+
if (Enum.class.isAssignableFrom(clazz)) {
40+
try {
41+
return codecRegistry.get(clazz);
42+
} catch (CodecConfigurationException e) {
43+
return (Codec<T>) new EnumCodec(clazz);
44+
}
45+
}
46+
return null;
47+
}
48+
49+
private static class EnumCodec<T extends Enum<T>> implements Codec<T> {
50+
private final Class<T> clazz;
51+
52+
EnumCodec(final Class<T> clazz) {
53+
this.clazz = clazz;
54+
}
55+
56+
@Override
57+
public void encode(final BsonWriter writer, final T value, final EncoderContext encoderContext) {
58+
writer.writeString(value.name());
59+
}
60+
61+
@Override
62+
public Class<T> getEncoderClass() {
63+
return clazz;
64+
}
65+
66+
@Override
67+
public T decode(final BsonReader reader, final DecoderContext decoderContext) {
68+
return Enum.valueOf(clazz, reader.readString());
69+
}
70+
}
71+
72+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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.codecs.Codec;
20+
import org.bson.codecs.configuration.CodecRegistry;
21+
22+
final class FallbackPropertyCodecProvider implements PropertyCodecProvider {
23+
private final CodecRegistry codecRegistry;
24+
private final PojoCodec<?> pojoCodec;
25+
26+
FallbackPropertyCodecProvider(final PojoCodec<?> pojoCodec, final CodecRegistry codecRegistry) {
27+
this.pojoCodec = pojoCodec;
28+
this.codecRegistry = codecRegistry;
29+
}
30+
31+
@SuppressWarnings("unchecked")
32+
@Override
33+
public <S> Codec<S> get(final TypeWithTypeParameters<S> type, final PropertyCodecRegistry propertyCodecRegistry) {
34+
Class<S> clazz = type.getType();
35+
if (clazz == pojoCodec.getEncoderClass()) {
36+
return (Codec<S>) pojoCodec;
37+
}
38+
return codecRegistry.get(type.getType());
39+
}
40+
}

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

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,10 @@ final class InstanceCreatorImpl<T> implements InstanceCreator<T> {
4242
this.cachedValues = new HashMap<PropertyModel<?>, Object>();
4343
this.properties = new HashMap<String, Integer>();
4444

45-
if (creatorExecutable.getIdPropertyIndex() != null) {
46-
this.properties.put(ClassModelBuilder.ID_PROPERTY_NAME, creatorExecutable.getIdPropertyIndex());
47-
}
48-
4945
for (int i = 0; i < creatorExecutable.getProperties().size(); i++) {
50-
if (creatorExecutable.getIdPropertyIndex() == null || !creatorExecutable.getIdPropertyIndex().equals(i)) {
51-
// Skip the ID property
46+
if (creatorExecutable.getIdPropertyIndex() != null && creatorExecutable.getIdPropertyIndex() == i) {
47+
this.properties.put(ClassModelBuilder.ID_PROPERTY_NAME, creatorExecutable.getIdPropertyIndex());
48+
} else {
5249
this.properties.put(creatorExecutable.getProperties().get(i).value(), i);
5350
}
5451
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public T decode(final BsonReader reader, final DecoderContext decoderContext) {
5959

6060
private Codec<T> getPojoCodec() {
6161
if (pojoCodec == null) {
62-
pojoCodec = new PojoCodecImpl<T>(classModel, registry, null, propertyCodecRegistry, discriminatorLookup, codecCache, true);
62+
pojoCodec = new PojoCodecImpl<T>(classModel, registry, propertyCodecRegistry, discriminatorLookup, codecCache, true);
6363
}
6464
return pojoCodec;
6565
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ static <T> void configureClassModelBuilder(final ClassModelBuilder<T> classModel
123123
currentClass = currentClass.getSuperclass();
124124
}
125125

126+
if (currentClass.isInterface()) {
127+
annotations.addAll(asList(currentClass.getDeclaredAnnotations()));
128+
}
129+
126130
for (String propertyName : propertyNames) {
127131
PropertyMetadata<?> propertyMetadata = propertyNameMap.get(propertyName);
128132
if (propertyMetadata.isSerializable() || propertyMetadata.isDeserializable()) {

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

Lines changed: 16 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -49,26 +49,30 @@ final class PojoCodecImpl<T> extends PojoCodec<T> {
4949
private final ConcurrentMap<ClassModel<?>, Codec<?>> codecCache;
5050
private final boolean specialized;
5151

52-
PojoCodecImpl(final ClassModel<T> classModel, final CodecRegistry registry, final List<PropertyCodecProvider> propertyCodecProviders,
53-
final DiscriminatorLookup discriminatorLookup) {
54-
this(classModel, registry, propertyCodecProviders, null, discriminatorLookup,
55-
new ConcurrentHashMap<ClassModel<?>, Codec<?>>(), shouldSpecialize(classModel));
52+
PojoCodecImpl(final ClassModel<T> classModel, final CodecRegistry codecRegistry,
53+
final List<PropertyCodecProvider> propertyCodecProviders, final DiscriminatorLookup discriminatorLookup) {
54+
this.classModel = classModel;
55+
this.registry = fromRegistries(fromCodecs(this), codecRegistry);
56+
this.discriminatorLookup = discriminatorLookup;
57+
this.codecCache = new ConcurrentHashMap<ClassModel<?>, Codec<?>>();
58+
this.propertyCodecRegistry = new PropertyCodecRegistryImpl(this, registry, propertyCodecProviders);
59+
this.specialized = shouldSpecialize(classModel);
60+
specialize();
5661
}
5762

58-
PojoCodecImpl(final ClassModel<T> classModel, final CodecRegistry registry, final List<PropertyCodecProvider> propertyCodecProviders,
59-
final PropertyCodecRegistry propertyCodecRegistry, final DiscriminatorLookup discriminatorLookup,
60-
final ConcurrentMap<ClassModel<?>, Codec<?>> codecCache, final boolean specialized) {
63+
PojoCodecImpl(final ClassModel<T> classModel, final CodecRegistry registry, final PropertyCodecRegistry propertyCodecRegistry,
64+
final DiscriminatorLookup discriminatorLookup, final ConcurrentMap<ClassModel<?>, Codec<?>> codecCache,
65+
final boolean specialized) {
6166
this.classModel = classModel;
6267
this.registry = fromRegistries(fromCodecs(this), registry);
6368
this.discriminatorLookup = discriminatorLookup;
6469
this.codecCache = codecCache;
65-
if (propertyCodecRegistry == null) {
66-
this.propertyCodecRegistry = new PropertyCodecRegistryImpl(propertyCodecProviders);
67-
} else {
68-
this.propertyCodecRegistry = propertyCodecRegistry;
69-
}
70+
this.propertyCodecRegistry = propertyCodecRegistry;
7071
this.specialized = specialized;
72+
specialize();
73+
}
7174

75+
private void specialize() {
7276
if (specialized) {
7377
codecCache.put(classModel, this);
7478
for (PropertyModel<?> propertyModel : classModel.getPropertyModels()) {
@@ -336,62 +340,4 @@ private static <T> boolean shouldSpecialize(final ClassModel<T> classModel) {
336340
}
337341
return true;
338342
}
339-
340-
@SuppressWarnings({"rawtypes", "unchecked"})
341-
private final class EnumPropertyCodecProvider implements PropertyCodecProvider {
342-
@Override
343-
public <S> Codec<S> get(final TypeWithTypeParameters<S> type, final PropertyCodecRegistry propertyCodecRegistry) {
344-
Class<S> clazz = type.getType();
345-
if (Enum.class.isAssignableFrom(clazz)) {
346-
try {
347-
return registry.get(clazz);
348-
} catch (CodecConfigurationException e) {
349-
return new EnumCodec(clazz);
350-
}
351-
}
352-
return null;
353-
}
354-
}
355-
356-
@SuppressWarnings({"rawtypes", "unchecked"})
357-
private final class FallbackPropertyCodecProvider implements PropertyCodecProvider {
358-
@Override
359-
public <S> Codec<S> get(final TypeWithTypeParameters<S> type, final PropertyCodecRegistry propertyCodecRegistry) {
360-
Class<S> clazz = type.getType();
361-
Codec<S> codec = null;
362-
if (classModel.getType().equals(clazz)) {
363-
codec = (Codec<S>) PojoCodecImpl.this;
364-
}
365-
if (codec == null) {
366-
codec = registry.get(clazz);
367-
}
368-
return codec;
369-
}
370-
}
371-
372-
@SuppressWarnings({"rawtypes", "unchecked"})
373-
private final class PropertyCodecRegistryImpl implements PropertyCodecRegistry {
374-
private final List<PropertyCodecProvider> propertyCodecProviders;
375-
376-
private PropertyCodecRegistryImpl(final List<PropertyCodecProvider> propertyCodecProviders) {
377-
List<PropertyCodecProvider> augmentedProviders = new ArrayList<PropertyCodecProvider>();
378-
augmentedProviders.addAll(propertyCodecProviders);
379-
augmentedProviders.add(new CollectionPropertyCodecProvider());
380-
augmentedProviders.add(new MapPropertyCodecProvider());
381-
augmentedProviders.add(new EnumPropertyCodecProvider());
382-
augmentedProviders.add(new FallbackPropertyCodecProvider());
383-
this.propertyCodecProviders = augmentedProviders;
384-
}
385-
386-
@Override
387-
public <S> Codec<S> get(final TypeWithTypeParameters<S> type) {
388-
for (PropertyCodecProvider propertyCodecProvider : propertyCodecProviders) {
389-
Codec<S> codec = propertyCodecProvider.get(type, this);
390-
if (codec != null) {
391-
return codec;
392-
}
393-
}
394-
return null;
395-
}
396-
}
397343
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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.codecs.Codec;
20+
import org.bson.codecs.configuration.CodecRegistry;
21+
22+
import java.util.ArrayList;
23+
import java.util.List;
24+
25+
class PropertyCodecRegistryImpl implements PropertyCodecRegistry {
26+
private final List<PropertyCodecProvider> propertyCodecProviders;
27+
28+
PropertyCodecRegistryImpl(final PojoCodec<?> pojoCodec, final CodecRegistry codecRegistry,
29+
final List<PropertyCodecProvider> propertyCodecProviders) {
30+
List<PropertyCodecProvider> augmentedProviders = new ArrayList<PropertyCodecProvider>();
31+
if (propertyCodecProviders != null) {
32+
augmentedProviders.addAll(propertyCodecProviders);
33+
}
34+
augmentedProviders.add(new CollectionPropertyCodecProvider());
35+
augmentedProviders.add(new MapPropertyCodecProvider());
36+
augmentedProviders.add(new EnumPropertyCodecProvider(codecRegistry));
37+
augmentedProviders.add(new FallbackPropertyCodecProvider(pojoCodec, codecRegistry));
38+
this.propertyCodecProviders = augmentedProviders;
39+
}
40+
41+
@Override
42+
public <S> Codec<S> get(final TypeWithTypeParameters<S> type) {
43+
for (PropertyCodecProvider propertyCodecProvider : propertyCodecProviders) {
44+
Codec<S> codec = propertyCodecProvider.get(type, this);
45+
if (codec != null) {
46+
return codec;
47+
}
48+
}
49+
return null;
50+
}
51+
}

bson/src/test/unit/org/bson/codecs/pojo/PojoCustomTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
import org.bson.codecs.pojo.entities.InvalidMapPropertyCodecProvider;
3535
import org.bson.codecs.pojo.entities.InvalidSetterArgsModel;
3636
import org.bson.codecs.pojo.entities.Optional;
37-
import org.bson.codecs.pojo.entities.OptionalPropertyCodecProviderForTest;
37+
import org.bson.codecs.pojo.entities.OptionalPropertyCodecProvider;
3838
import org.bson.codecs.pojo.entities.PrimitivesModel;
3939
import org.bson.codecs.pojo.entities.SimpleEnum;
4040
import org.bson.codecs.pojo.entities.SimpleEnumModel;
@@ -272,14 +272,14 @@ public void testCanHandleTopLevelGenericIfHasCodec() {
272272
@Test
273273
public void testCustomRegisteredPropertyCodecWithValue() {
274274
CustomPropertyCodecOptionalModel model = new CustomPropertyCodecOptionalModel(Optional.of("foo"));
275-
roundTrip(getPojoCodecProviderBuilder(CustomPropertyCodecOptionalModel.class).register(new OptionalPropertyCodecProviderForTest()),
275+
roundTrip(getPojoCodecProviderBuilder(CustomPropertyCodecOptionalModel.class).register(new OptionalPropertyCodecProvider()),
276276
model, "{'optionalField': 'foo'}");
277277
}
278278

279279
@Test
280280
public void testCustomRegisteredPropertyCodecOmittedValue() {
281281
CustomPropertyCodecOptionalModel model = new CustomPropertyCodecOptionalModel(Optional.<String>empty());
282-
roundTrip(getPojoCodecProviderBuilder(CustomPropertyCodecOptionalModel.class).register(new OptionalPropertyCodecProviderForTest()),
282+
roundTrip(getPojoCodecProviderBuilder(CustomPropertyCodecOptionalModel.class).register(new OptionalPropertyCodecProvider()),
283283
model, "{'optionalField': null}");
284284
}
285285

0 commit comments

Comments
 (0)