Skip to content

Commit

Permalink
[ISSUE: 696] fixes nested proto3 messages ClassNotFoundException (#697)
Browse files Browse the repository at this point in the history
* fixes nested proto3 messages ClassNotFoundException

* proto3 msg container names in reverse order.

* missing license header
  • Loading branch information
Adonis Charalambidis authored and garethahealy committed Aug 31, 2018
1 parent d68728c commit ccb55b0
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

Expand All @@ -27,7 +28,7 @@
import com.github.dozermapper.core.util.MappingUtils;
import com.google.common.base.CaseFormat;
import com.google.protobuf.ByteString;
import com.google.protobuf.DescriptorProtos;
import com.google.protobuf.DescriptorProtos.FileOptions;
import com.google.protobuf.Descriptors;
import com.google.protobuf.Message;
import com.google.protobuf.ProtocolMessageEnum;
Expand Down Expand Up @@ -207,23 +208,33 @@ private static Class<?> getJavaClassIgnoreRepeated(final Descriptors.FieldDescri
return getEnumClassByEnumDescriptor(descriptor.getEnumType(), beanContainer);
case MESSAGE:
return MappingUtils.loadClass(StringUtils.join(
getFullyQualifiedClassName(descriptor.getMessageType().getFile().getOptions(), descriptor.getMessageType().getName()), '.'), beanContainer);
getFullyQualifiedClassName(descriptor.getMessageType().getContainingType(),
descriptor.getMessageType().getFile().getOptions(),
descriptor.getMessageType().getName()), '.'), beanContainer);
default:
throw new MappingException("Unable to find " + descriptor.getJavaType());
}
}

private static String[] getFullyQualifiedClassName(DescriptorProtos.FileOptions options, String name) {
if (options.getJavaMultipleFiles()) {
return new String[] {options.getJavaPackage(), name};
private static String[] getFullyQualifiedClassName(Descriptors.Descriptor container, final FileOptions fileOpts, String name) {

if (fileOpts.getJavaMultipleFiles()) {
LinkedList<String> fqnSegments = new LinkedList<>();
fqnSegments.push(name);
while (container != null) {
fqnSegments.push(container.getName());
container = container.getContainingType();
}
fqnSegments.push(fileOpts.getJavaPackage());
return fqnSegments.toArray(new String[] {});
}

return new String[] {options.getJavaPackage(), options.getJavaOuterClassname(), name};
return new String[] {fileOpts.getJavaPackage(), fileOpts.getJavaOuterClassname(), name};
}

@SuppressWarnings("unchecked")
private static Class<? extends Enum> getEnumClassByEnumDescriptor(Descriptors.EnumDescriptor descriptor, BeanContainer beanContainer) {
String name = StringUtils.join(getFullyQualifiedClassName(descriptor.getFile().getOptions(), descriptor.getName()), '.');
String name = StringUtils.join(getFullyQualifiedClassName(descriptor.getContainingType(), descriptor.getFile().getOptions(), descriptor.getName()), '.');
return (Class<? extends Enum>)MappingUtils.loadClass(name, beanContainer);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@

import com.github.dozermapper.core.DozerBeanMapperBuilder;
import com.github.dozermapper.core.Mapper;
import com.github.dozermapper.protobuf.vo.proto.TestContainerObject;
import com.github.dozermapper.protobuf.vo.proto.NestedObject;
import com.github.dozermapper.protobuf.vo.proto.TestObject;
import com.github.dozermapper.protobuf.vo.proto.TestContainerObject.TestContainedEnum;
import com.github.dozermapper.protobuf.vo.protomultiple.ContainerObject;
import com.github.dozermapper.protobuf.vo.protomultiple.ContainerObject.ContainedEnum;
import com.github.dozermapper.protobuf.vo.protomultiple.SimpleProtoTestObject;

import org.junit.BeforeClass;
Expand Down Expand Up @@ -68,4 +72,37 @@ public void canSimpleFromProto() {
assertNotNull(result.getNested().getOne());
assertEquals(simpleProtoTestObject.getNested().getOne(), result.getNested().getOne());
}

@Test
public void canNestedObjectToProto() {
TestContainerObject containerObject = new TestContainerObject();
containerObject.setEnum1(TestContainedEnum.VALUE2);
containerObject.setObj1(new TestContainerObject.TestContainedObject());
containerObject.getObj1().setC1("ABC");

ContainerObject result = mapper.map(containerObject, ContainerObject.class);
assertNotNull(result);
assertNotNull(result.getEnum1());
assertNotNull(result.getObj1());
assertNotNull(result.getObj1().getC1());
assertEquals(containerObject.getObj1().getC1(), result.getObj1().getC1());
assertEquals(containerObject.getEnum1().name(), result.getEnum1().name());
}

@Test
public void canNestedObjectFromProto() {
ContainerObject.Builder containerBuiler = ContainerObject.newBuilder();
containerBuiler.setEnum1(ContainedEnum.VALUE2);
containerBuiler.setObj1(ContainerObject.ContainedObject.newBuilder().setC1("ABC").build());
ContainerObject container = containerBuiler.build();
TestContainerObject result = mapper.map(container, TestContainerObject.class);
assertNotNull(result);
assertNotNull(result.getEnum1());
assertNotNull(result.getObj1());
assertNotNull(result.getObj1().getC1());
assertEquals(container.getObj1().getC1(), result.getObj1().getC1());
assertEquals(container.getEnum1().name(), result.getEnum1().name());


}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2005-2018 Dozer Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.dozermapper.protobuf.vo.proto;

public class TestContainerObject {
public enum TestContainedEnum {
VALUE1, VALUE2;
}

public static class TestContainedObject{
private String c1;

public TestContainedObject() {

}

public String getC1() {
return c1;
}

public void setC1(String c1) {
this.c1 = c1;
}
}

private TestContainedObject obj1;
private TestContainedEnum enum1;

public TestContainerObject() {
}

public TestContainedEnum getEnum1() {
return enum1;
}

public TestContainedObject getObj1() {
return obj1;
}

public void setEnum1(TestContainedEnum enum1) {
this.enum1 = enum1;
}

public void setObj1(TestContainedObject obj1) {
this.obj1 = obj1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,18 @@ message TestObject {
message SimpleProtoTestObject {
TestObject nested = 1;
}

message ContainerObject {

enum ContainedEnum {
VALUE1 = 0;
VALUE2 = 1;
}

message ContainedObject {
string c1 = 1;
}

ContainedObject obj1 = 1;
ContainedEnum enum1 = 2;
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,26 @@
</field>
</mapping>

<mapping wildcard="false">
<class-a>com.github.dozermapper.protobuf.vo.proto.TestContainerObject.TestContainedObject</class-a>
<class-b>com.github.dozermapper.protobuf.vo.protomultiple.ContainerObject.ContainedObject</class-b>
<field>
<a>c1</a>
<b>c1</b>
</field>
</mapping>

<mapping wildcard="false">
<class-a>com.github.dozermapper.protobuf.vo.proto.TestContainerObject</class-a>
<class-b>com.github.dozermapper.protobuf.vo.protomultiple.ContainerObject</class-b>
<field>
<a>obj1</a>
<b>obj1</b>
</field>
<field>
<a>enum1</a>
<b>enum1</b>
</field>
</mapping>

</mappings>

0 comments on commit ccb55b0

Please sign in to comment.