Skip to content

Commit

Permalink
Merge pull request #113 from HubSpot/jh/rm-naming-strategy-base
Browse files Browse the repository at this point in the history
Remove references to PropertyNamingStrategyBase
  • Loading branch information
jhaber authored Dec 30, 2023
2 parents ccfb558 + b6c0a4b commit ad50263
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 124 deletions.
Original file line number Diff line number Diff line change
@@ -1,97 +1,75 @@
package com.hubspot.jackson.datatype.protobuf;

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.PropertyNamingStrategies.NamingBase;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.PropertyNamingStrategy.PropertyNamingStrategyBase;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
import com.fasterxml.jackson.databind.introspect.AnnotationMap;
import com.fasterxml.jackson.databind.introspect.TypeResolutionContext;
import com.google.common.base.CaseFormat;
import java.lang.reflect.Method;
import com.google.protobuf.Message;
import java.lang.reflect.Field;

@SuppressWarnings("serial")
public class PropertyNamingStrategyWrapper extends PropertyNamingStrategyBase {
public class PropertyNamingStrategyWrapper {

private static final PropertyNamingStrategyBase SNAKE_TO_CAMEL = new SnakeToCamelNamingStrategy();
private static final PropertyNamingStrategyBase NO_OP = new NoOpNamingStrategy();
private static final PropertyNamingStrategy SNAKE_TO_CAMEL = new SnakeToCamelNamingStrategy();
private static final PropertyNamingStrategy NO_OP = new NoOpNamingStrategy();

private final PropertyNamingStrategyBase delegate;
private final Class<?> messageType;
private final MapperConfig<?> mapperConfig;
private final PropertyNamingStrategy delegate;

public PropertyNamingStrategyWrapper(PropertyNamingStrategy delegate) {
if (delegate instanceof PropertyNamingStrategyBase) {
this.delegate = (PropertyNamingStrategyBase) delegate;
} else if (NamingBaseAdapter.extendsNamingBase(delegate)) {
this.delegate = new NamingBaseAdapter(delegate);
} else if (delegate == PropertyNamingStrategy.LOWER_CAMEL_CASE) {
public PropertyNamingStrategyWrapper(
Class<? extends Message> messageType,
MapperConfig<?> mapperConfig
) {
this.messageType = messageType;
this.mapperConfig = mapperConfig;

if (mapperConfig.getPropertyNamingStrategy() == null) {
this.delegate = SNAKE_TO_CAMEL;
} else if (
mapperConfig.getPropertyNamingStrategy() ==
PropertyNamingStrategies.LOWER_CAMEL_CASE
) {
this.delegate = NO_OP;
} else {
this.delegate = SNAKE_TO_CAMEL;
this.delegate = mapperConfig.getPropertyNamingStrategy();
}
}

@Override
public String translate(String fieldName) {
return delegate.translate(fieldName);
AnnotatedField annotatedField = null;
try {
Field field = messageType.getDeclaredField(fieldName + "_");
annotatedField =
new AnnotatedField(
new TypeResolutionContext.Empty(mapperConfig.getTypeFactory()),
field,
new AnnotationMap()
);
} catch (ReflectiveOperationException e) {
// ignored
}

return delegate.nameForField(mapperConfig, annotatedField, fieldName);
}

private static class SnakeToCamelNamingStrategy extends PropertyNamingStrategyBase {
private static class SnakeToCamelNamingStrategy extends NamingBase {

@Override
public String translate(String fieldName) {
return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, fieldName);
}
}

private static class NoOpNamingStrategy extends PropertyNamingStrategyBase {
private static class NoOpNamingStrategy extends NamingBase {

@Override
public String translate(String fieldName) {
return fieldName;
}
}

private static class NamingBaseAdapter extends PropertyNamingStrategyBase {

private static final Class<?> NAMING_BASE = tryToLoadNamingBase();
private static final Method TRANSLATE_METHOD = tryToLoadTranslateMethod(NAMING_BASE);

private final PropertyNamingStrategy delegate;

private NamingBaseAdapter(PropertyNamingStrategy delegate) {
this.delegate = delegate;
}

public static boolean extendsNamingBase(PropertyNamingStrategy namingStrategy) {
return NAMING_BASE != null && NAMING_BASE.isInstance(namingStrategy);
}

@Override
public String translate(String fieldName) {
try {
return (String) TRANSLATE_METHOD.invoke(delegate, fieldName);
} catch (ReflectiveOperationException e) {
throw new RuntimeException("Unable to invoke translate method", e);
}
}

private static Class<?> tryToLoadNamingBase() {
try {
return Class.forName(
"com.fasterxml.jackson.databind.PropertyNamingStrategies$NamingBase"
);
} catch (ClassNotFoundException e) {
return null;
}
}

private static Method tryToLoadTranslateMethod(Class<?> namingBase) {
if (namingBase == null) {
return null;
} else {
try {
return namingBase.getMethod("translate", String.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException(
"Unable to find translate method on class: " + namingBase
);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.PropertyNamingStrategy.PropertyNamingStrategyBase;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.ExtensionRegistry.ExtensionInfo;
Expand All @@ -27,6 +26,8 @@
public class MessageDeserializer<T extends Message, V extends Builder>
extends ProtobufDeserializer<T, V> {

private final Class<T> messageType;

@SuppressFBWarnings(value = "SE_BAD_FIELD")
private final ProtobufJacksonConfig config;

Expand All @@ -48,8 +49,10 @@ public MessageDeserializer(

public MessageDeserializer(Class<T> messageType, ProtobufJacksonConfig config) {
super(messageType);
this.messageType = messageType;
this.config = config;
this.propertyNamingCache = PropertyNamingCache.forDescriptor(getDescriptor(), config);
this.propertyNamingCache =
PropertyNamingCache.forDescriptor(getDescriptor(), messageType, config);
}

@Override
Expand All @@ -75,7 +78,7 @@ protected void populate(V builder, JsonParser parser, DeserializationContext con

final Descriptor descriptor = builder.getDescriptorForType();
final Function<String, FieldDescriptor> fieldLookup = propertyNamingCache.forDeserialization(
context.getConfig().getPropertyNamingStrategy()
context.getConfig()
);
final Map<String, ExtensionInfo> extensionLookup;
if (builder instanceof ExtendableMessageOrBuilder<?>) {
Expand Down Expand Up @@ -116,8 +119,9 @@ private Map<String, ExtensionInfo> buildExtensionLookup(
Descriptor descriptor,
DeserializationContext context
) {
PropertyNamingStrategyBase namingStrategy = new PropertyNamingStrategyWrapper(
context.getConfig().getPropertyNamingStrategy()
PropertyNamingStrategyWrapper namingStrategy = new PropertyNamingStrategyWrapper(
messageType,
context.getConfig()
);

Map<String, ExtensionInfo> extensionLookup = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,11 @@ public void serialize(
boolean writeEmptyCollections =
include != Include.NON_DEFAULT && include != Include.NON_EMPTY;

Descriptor descriptor = message.getDescriptorForType();
Function<FieldDescriptor, String> propertyNaming = getPropertyNaming(
descriptor,
message,
serializerProvider
);
Descriptor descriptor = message.getDescriptorForType();
List<FieldDescriptor> fields = descriptor.getFields();
if (message instanceof ExtendableMessageOrBuilder<?>) {
fields = new ArrayList<>(fields);
Expand Down Expand Up @@ -146,13 +146,12 @@ public void acceptJsonFormatVisitor(
JavaType typeHint
) throws JsonMappingException {
Message defaultInstance = defaultInstance(typeHint);
Descriptor descriptor = defaultInstance.getDescriptorForType();
Function<FieldDescriptor, String> propertyNaming = getPropertyNaming(
descriptor,
defaultInstance,
visitor.getProvider()
);

new MessageSchemaGenerator(defaultInstance, descriptor, getConfig(), propertyNaming)
new MessageSchemaGenerator(defaultInstance, getConfig(), propertyNaming)
.acceptJsonFormatVisitor(visitor, typeHint);
}

Expand Down Expand Up @@ -182,22 +181,26 @@ private static Message defaultInstance(JavaType typeHint) {
}

private Function<FieldDescriptor, String> getPropertyNaming(
Descriptor descriptor,
MessageOrBuilder messageOrBuilder,
SerializerProvider serializerProvider
) {
Descriptor descriptor = messageOrBuilder.getDescriptorForType();
PropertyNamingCache cache = propertyNamingCache.get(descriptor);
if (cache == null) {
// use computeIfAbsent as a fallback since it allocates
cache =
propertyNamingCache.computeIfAbsent(
descriptor,
ignored -> PropertyNamingCache.forDescriptor(descriptor, getConfig())
ignored ->
PropertyNamingCache.forDescriptor(
descriptor,
messageOrBuilder.getDefaultInstanceForType().getClass(),
getConfig()
)
);
}

return cache.forSerialization(
serializerProvider.getConfig().getPropertyNamingStrategy()
);
return cache.forSerialization(serializerProvider.getConfig());
}

private static boolean supportsFieldPresence(FieldDescriptor field) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,15 @@
public class MessageSchemaGenerator implements JsonFormatVisitable {

private final Message defaultInstance;
private final Descriptor descriptor;
private final ProtobufJacksonConfig config;
private final Function<FieldDescriptor, String> propertyNaming;

public MessageSchemaGenerator(
Message defaultInstance,
Descriptor descriptor,
ProtobufJacksonConfig config,
Function<FieldDescriptor, String> propertyNaming
) {
this.defaultInstance = defaultInstance;
this.descriptor = descriptor;
this.config = config;
this.propertyNaming = propertyNaming;
}
Expand All @@ -46,6 +43,7 @@ public void acceptJsonFormatVisitor(
) throws JsonMappingException {
JsonObjectFormatVisitor objectVisitor = visitor.expectObjectFormat(typeHint);

Descriptor descriptor = defaultInstance.getDescriptorForType();
List<FieldDescriptor> fields = new ArrayList<>(descriptor.getFields());
if (defaultInstance instanceof ExtendableMessageOrBuilder<?>) {
for (ExtensionInfo extensionInfo : config
Expand Down
Loading

0 comments on commit ad50263

Please sign in to comment.