Skip to content

Commit

Permalink
Fixes rgushel#4
Browse files Browse the repository at this point in the history
  • Loading branch information
kgorozhankin committed Mar 13, 2017
1 parent 75fa611 commit 6dfc6cb
Show file tree
Hide file tree
Showing 10 changed files with 1,016 additions and 41 deletions.
17 changes: 7 additions & 10 deletions src/main/java/net/badata/protobuf/converter/Converter.java
Original file line number Diff line number Diff line change
Expand Up @@ -192,14 +192,13 @@ private void fillDomainField(final FieldResolver fieldResolver, final MappingRes
throws WriteException {
DomainWriter fieldWriter = new DomainWriter(mappingResult.getDestination());
Object mappedValue = mappingResult.getValue();
Field field = fieldResolver.getField();
switch (mappingResult.getCode()) {
case NESTED_MAPPING:
fieldWriter.write(fieldResolver, createNestedConverter().toDomain(field.getType(), (Message)
mappedValue));
fieldWriter.write(fieldResolver, createNestedConverter().toDomain(fieldResolver.getDomainType(),
(Message) mappedValue));
break;
case COLLECTION_MAPPING:
Class<?> collectionType = FieldUtils.extractCollectionType(field);
Class<?> collectionType = FieldUtils.extractCollectionType(fieldResolver.getField());
if (FieldUtils.isComplexType(collectionType)) {
mappedValue = createDomainValueList(collectionType, mappedValue);
}
Expand Down Expand Up @@ -302,20 +301,18 @@ private void fillProtobufField(final FieldResolver fieldResolver, final MappingR
throws WriteException {
ProtobufWriter fieldWriter = new ProtobufWriter((Message.Builder) mappingResult.getDestination());
Object mappedValue = mappingResult.getValue();
Field field = fieldResolver.getField();
switch (mappingResult.getCode()) {
case NESTED_MAPPING:
Class<? extends Message> protobufClass = MessageUtils
.getMessageType(mappingResult.getDestination(),
FieldUtils.createProtobufGetterName(fieldResolver));
Class<? extends Message> protobufClass = MessageUtils.getMessageType(mappingResult.getDestination(),
FieldUtils.createProtobufGetterName(fieldResolver));
fieldWriter.write(fieldResolver, createNestedConverter().toProtobuf(protobufClass, mappedValue));
break;
case COLLECTION_MAPPING:
Class<?> collectionType = FieldUtils.extractCollectionType(field);
Class<?> collectionType = FieldUtils.extractCollectionType(fieldResolver.getField());
if (FieldUtils.isComplexType(collectionType)) {
Class<? extends Message> protobufCollectionClass = MessageUtils.getMessageCollectionType(
mappingResult.getDestination(), FieldUtils.createProtobufGetterName(fieldResolver));
mappedValue = createProtobufValueList(protobufCollectionClass, field.getType(),
mappedValue = createProtobufValueList(protobufCollectionClass, fieldResolver.getDomainType(),
(Collection) mappedValue);
}
case MAPPED:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import net.badata.protobuf.converter.exception.ConverterException;
import net.badata.protobuf.converter.exception.WriteException;
import net.badata.protobuf.converter.utils.AnnotationUtils;
import net.badata.protobuf.converter.utils.FieldUtils;

import java.lang.reflect.Field;

Expand All @@ -40,18 +41,25 @@ public class AnnotatedFieldResolverFactoryImpl implements FieldResolverFactory {
public FieldResolver createResolver(final Field field) {
DefaultFieldResolverImpl fieldResolver = new DefaultFieldResolverImpl(field);
if (field.isAnnotationPresent(ProtoField.class)) {
ProtoField protoField = field.getAnnotation(ProtoField.class);
if (!"".equals(protoField.name())) {
fieldResolver.setProtobufName(protoField.name());
}
try {
fieldResolver.setConverter(AnnotationUtils.createTypeConverter(protoField));
fieldResolver.setNullValueInspector(AnnotationUtils.createNullValueInspector(protoField));
fieldResolver.setDefaultValue(AnnotationUtils.createDefaultValue(protoField));
initializeFieldResolver(fieldResolver, field.getAnnotation(ProtoField.class));
} catch (WriteException e) {
throw new ConverterException("Can't create field resolver", e);
throw new ConverterException("Can't initialize field resolver", e);
}
}
return fieldResolver;
}

private void initializeFieldResolver(final DefaultFieldResolverImpl resolver, final ProtoField annotation) throws
WriteException {
if (!"".equals(annotation.name())) {
resolver.setProtobufName(annotation.name());
}
Class<?> protobufType = FieldUtils.extractProtobufFieldType(annotation.converter(), resolver.getProtobufType());
resolver.setProtobufType(protobufType);
resolver.setConverter(AnnotationUtils.createTypeConverter(annotation));
resolver.setNullValueInspector(AnnotationUtils.createNullValueInspector(annotation));
resolver.setDefaultValue(AnnotationUtils.createDefaultValue(annotation));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public class DefaultFieldResolverImpl implements FieldResolver {
private final Field field;
private String domainName;
private String protobufName;
private Class<?> domainType;
private Class<?> protobufType;
private TypeConverter<?, ?> converter;
private NullValueInspector nullValueInspector;
private DefaultValue defaultValue;
Expand All @@ -50,6 +52,8 @@ public DefaultFieldResolverImpl(final Field field) {
this.field = field;
this.domainName = field.getName();
this.protobufName = field.getName();
this.domainType = field.getType();
this.protobufType = field.getType();
this.converter = new DefaultConverterImpl();
this.nullValueInspector = new DefaultNullValueInspectorImpl();
this.defaultValue = new SimpleDefaultValueImpl();
Expand Down Expand Up @@ -79,6 +83,16 @@ public String getProtobufName() {
return protobufName;
}

@Override
public Class<?> getDomainType() {
return domainType;
}

@Override
public Class<?> getProtobufType() {
return protobufType;
}

/**
* {@inheritDoc}
*/
Expand All @@ -103,19 +117,51 @@ public DefaultValue getDefaultValue() {
return defaultValue;
}

/**
* Setter for protobuf field name.
*
* @param protobufName name of the protobuf field.
*/
public void setProtobufName(final String protobufName) {
this.protobufName = protobufName;
}

/**
* Setter for protobuf field type.
*
* @param protobufType type of the protobuf field.
*/
public void setProtobufType(final Class<?> protobufType) {
this.protobufType = protobufType;
}

/**
* Setter for converter instance.
*
* @param converter Instance of field converter.
*/
public void setConverter(final TypeConverter<?, ?> converter) {
this.converter = converter;
}


/**
* Setter for protobuf field nullability inspector.
*
* @param nullValueInspector Instance of class that perform nullability check for protobuf field value.
*/
public void setNullValueInspector(final NullValueInspector nullValueInspector) {
this.nullValueInspector = nullValueInspector;
}

/**
* Setter for domain field default value generator.
*
* @param defaultValue Instance of class that generates default value for domain object field.
*/
public void setDefaultValue(final DefaultValue defaultValue) {
this.defaultValue = defaultValue;
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,20 @@ public interface FieldResolver {
*/
String getProtobufName();

/**
* Getter for domain class field type.
*
* @return String with domain field type.
*/
Class<?> getDomainType();

/**
* Getter for protobuf message field type.
*
* @return String with protobuf field type.
*/
Class<?> getProtobufType();

/**
* Getter for field type converter.
*
Expand Down
64 changes: 43 additions & 21 deletions src/main/java/net/badata/protobuf/converter/utils/FieldUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,23 @@
import net.badata.protobuf.converter.annotation.ProtoClass;
import net.badata.protobuf.converter.annotation.ProtoClasses;
import net.badata.protobuf.converter.resolver.FieldResolver;
import net.badata.protobuf.converter.type.TypeConverter;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;

/**
* Created by jsjem on 25.04.2016.
*/
public final class FieldUtils {


private static final String GETTER_PREFIX = "get";
private static final String SETTER_PREFIX = "set";
private static final String BOOLEAN_GETTER_PREFIX = "is";
private static final String PROTOBUF_LIST_GETTER_POSTFIX = "List";
private static final String PROTOBUF_LIST_SETTER_PREFIX = "addAll";
private static final String PROTOBUF_NESTED_BUILDER_POSTFIX = "Builder";


/**
* Check whether field has own mapper.
Expand Down Expand Up @@ -68,7 +67,17 @@ public static boolean isComplexType(final Class<?> type) {
* @return true if field type implements {@link java.util.Collection}, otherwise false.
*/
public static boolean isCollectionType(final Field field) {
return Collection.class.isAssignableFrom(field.getType());
return isCollectionType(field.getType());
}

/**
* Check whether class implements Collection interface.
*
* @param type Testing class.
* @return true if class implements {@link java.util.Collection}, otherwise false.
*/
public static boolean isCollectionType(final Class<?> type) {
return Collection.class.isAssignableFrom(type);
}

/**
Expand All @@ -79,7 +88,7 @@ public static boolean isCollectionType(final Field field) {
*/
public static String createProtobufGetterName(final FieldResolver fieldResolver) {
String getterName = StringUtils.createMethodName(GETTER_PREFIX, fieldResolver.getProtobufName());
if (isCollectionType(fieldResolver.getField())) {
if (isCollectionType(fieldResolver.getProtobufType())) {
return getterName + PROTOBUF_LIST_GETTER_POSTFIX;
}
return getterName;
Expand All @@ -92,31 +101,20 @@ public static String createProtobufGetterName(final FieldResolver fieldResolver)
* @return Protobuf field setter name.
*/
public static String createProtobufSetterName(final FieldResolver fieldResolver) {
if (isCollectionType(fieldResolver.getField())) {
if (isCollectionType(fieldResolver.getProtobufType())) {
return StringUtils.createMethodName(PROTOBUF_LIST_SETTER_PREFIX, fieldResolver.getProtobufName());
}
return StringUtils.createMethodName(SETTER_PREFIX, fieldResolver.getProtobufName());
}

/**
* Create protobuf builder getter name for complex domain field.
*
* @param fieldResolver Domain object field resolver.
* @return Protobuf field builder getter name.
*/
public static String createProtobufBuilderName(final FieldResolver fieldResolver) {
String getterName = StringUtils.createMethodName(GETTER_PREFIX, fieldResolver.getProtobufName());
return getterName + PROTOBUF_NESTED_BUILDER_POSTFIX;
}

/**
* Create domain field getter name.
*
* @param fieldResolver Domain object field resolver.
* @return Domain field getter name.
*/
public static String createDomainGetterName(final FieldResolver fieldResolver) {
if (fieldResolver.getField().getType() == boolean.class) {
if (fieldResolver.getDomainType() == boolean.class) {
return StringUtils.createMethodName(BOOLEAN_GETTER_PREFIX, fieldResolver.getDomainName());
}
return StringUtils.createMethodName(GETTER_PREFIX, fieldResolver.getDomainName());
Expand All @@ -136,11 +134,35 @@ public static String createDomainSetterName(final FieldResolver fieldResolver) {
* Extract parameter type of the collection.
*
* @param field Field with type derived from {@link java.util.Collection}.
* @return Collection parameter.
* @return Collection generic type.
*/
public static Class<?> extractCollectionType(final Field field) {
ParameterizedType stringListType = (ParameterizedType) field.getGenericType();
return (Class<?>) stringListType.getActualTypeArguments()[0];
ParameterizedType genericType = (ParameterizedType) field.getGenericType();
return (Class<?>) genericType.getActualTypeArguments()[0];
}

/**
* Extract protobuf field type from type converter.
*
* @param typeConverterClass field converter type.
* @param defaultType Default protobuf field type.
* @return Protobuf field type declared in the type converter class or default type when it is unable to extract
* field type from converter.
*/
public static Class<?> extractProtobufFieldType(final Class<? extends TypeConverter> typeConverterClass,
final Class<?> defaultType) {
Type[] interfaceTypes = typeConverterClass.getGenericInterfaces();
for (Type interfaceType : interfaceTypes) {
ParameterizedType parameterizedType = (ParameterizedType) interfaceType;
if (parameterizedType.getRawType().equals(TypeConverter.class)) {
Type extractedType = parameterizedType.getActualTypeArguments()[1];
if (extractedType instanceof ParameterizedType) {
return (Class<?>) ((ParameterizedType) extractedType).getRawType();
}
return Object.class.equals(extractedType) ? defaultType : (Class<?>) extractedType;
}
}
return defaultType;
}

private FieldUtils() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ protected void write(final Object destination, final FieldResolver fieldResolver
DefaultValue defaultValueCreator = fieldResolver.getDefaultValue();
TypeConverter<?, ?> typeConverter = fieldResolver.getTypeConverter();
if (nullInspector.isNull(value)) {
writeValue(destination, fieldResolver, defaultValueCreator.generateValue(fieldResolver.getField().getType()));
writeValue(destination, fieldResolver, defaultValueCreator.generateValue(fieldResolver.getDomainType()));
} else {
writeValue(destination, fieldResolver, typeConverter.toDomainValue(value));
}
Expand All @@ -64,7 +64,7 @@ protected void write(final Object destination, final FieldResolver fieldResolver
private void writeValue(final Object destination, final FieldResolver fieldResolver, final Object value) throws WriteException {
String setterName = FieldUtils.createDomainSetterName(fieldResolver);
try {
destinationClass.getMethod(setterName, fieldResolver.getField().getType()).invoke(destination, value);
destinationClass.getMethod(setterName, fieldResolver.getDomainType()).invoke(destination, value);
} catch (IllegalAccessException e) {
throw new WriteException(
String.format("Access denied. '%s.%s()'", destinationClass.getName(), setterName));
Expand Down
Loading

0 comments on commit 6dfc6cb

Please sign in to comment.