This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git


The following commit(s) were added to refs/heads/master by this push:
     new 4eef116  [SCB-946] serialize/deseriaze List<List<X>>/List<Map<X, 
Y>>/Map<X, List<Y>>/Map<X, Map<Y, Z>>
4eef116 is described below

commit 4eef116f8e9e530073c0a758489d8bd144c391cb
Author: wujimin <[email protected]>
AuthorDate: Wed Dec 5 22:09:48 2018 +0800

    [SCB-946] serialize/deseriaze List<List<X>>/List<Map<X, Y>>/Map<X, 
List<Y>>/Map<X, Map<Y, Z>>
---
 .../foundation/protobuf/ProtoMapper.java           |  15 ++
 .../foundation/protobuf/internal/ProtoConst.java   |   2 +
 .../internal/RootPropertyWrapDeserializer.java     |  37 +++
 .../protobuf/internal/bean/PropertyWrapper.java    |  21 ++
 .../internal/schema/MessageAsFieldSchema.java      |   2 +-
 ....java => PropertyWrapMessageAsFieldSchema.java} |  32 ++-
 ...dSchema.java => PropertyWrapMessageSchema.java} |  29 +--
 .../protobuf/internal/schema/SchemaManager.java    |  11 +
 .../deserializer/DeserializerSchemaManager.java    |  21 +-
 .../schema/serializer/SerializerSchemaManager.java |  17 +-
 .../protobuf/internal/TestModelWrap.java           | 247 +++++++++++++++++++++
 .../src/test/resources/model.proto                 | 108 +++++++++
 12 files changed, 502 insertions(+), 40 deletions(-)

diff --git 
a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/ProtoMapper.java
 
b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/ProtoMapper.java
index 860a9f6..0af2afb 100644
--- 
a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/ProtoMapper.java
+++ 
b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/ProtoMapper.java
@@ -20,7 +20,9 @@ import java.lang.reflect.Type;
 import java.util.Map;
 
 import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
+import 
org.apache.servicecomb.foundation.protobuf.internal.RootPropertyWrapDeserializer;
 import 
org.apache.servicecomb.foundation.protobuf.internal.bean.BeanDescriptorManager;
+import 
org.apache.servicecomb.foundation.protobuf.internal.bean.PropertyWrapper;
 import 
org.apache.servicecomb.foundation.protobuf.internal.schema.deserializer.DeserializerSchemaManager;
 import 
org.apache.servicecomb.foundation.protobuf.internal.schema.serializer.SerializerSchemaManager;
 
@@ -105,4 +107,17 @@ public class ProtoMapper {
   public RootDeserializer createRootDeserializer(JavaType javaType, Message 
message) {
     return deserializerSchemaManager.createRootDeserializer(javaType, message);
   }
+
+  public RootDeserializer createPropertyRootDeserializer(String 
shortWrapMessageName, Type propertyType) {
+    Message message = proto.getMessage(shortWrapMessageName);
+    if (!deserializerSchemaManager.isWrapProperty(message)) {
+      return createRootDeserializer(propertyType, shortWrapMessageName);
+    }
+
+    JavaType propertyWrapJavaType = 
TypeFactory.defaultInstance().constructParametricType(
+        PropertyWrapper.class,
+        TypeFactory.defaultInstance().constructType(propertyType));
+    RootDeserializer rootDeserializer = 
createRootDeserializer(propertyWrapJavaType, message);
+    return new RootPropertyWrapDeserializer(rootDeserializer);
+  }
 }
diff --git 
a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/ProtoConst.java
 
b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/ProtoConst.java
index 53ec0c2..72f3764 100644
--- 
a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/ProtoConst.java
+++ 
b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/ProtoConst.java
@@ -30,6 +30,8 @@ public final class ProtoConst {
   private ProtoConst() {
   }
 
+  public static String ANNOTATION_WRAP_PROPERTY = "@WrapProperty";
+
   public static String OP_HINT = " scb:";
 
   public static String PACK_SCHEMA = "type.googleapis.com/";
diff --git 
a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/RootPropertyWrapDeserializer.java
 
b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/RootPropertyWrapDeserializer.java
new file mode 100644
index 0000000..ab64699
--- /dev/null
+++ 
b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/RootPropertyWrapDeserializer.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.servicecomb.foundation.protobuf.internal;
+
+import java.io.IOException;
+
+import org.apache.servicecomb.foundation.protobuf.RootDeserializer;
+import 
org.apache.servicecomb.foundation.protobuf.internal.bean.PropertyWrapper;
+
+public class RootPropertyWrapDeserializer extends RootDeserializer {
+  private final RootDeserializer rootDeserializer;
+
+  public RootPropertyWrapDeserializer(RootDeserializer rootDeserializer) {
+    super(null, null);
+    this.rootDeserializer = rootDeserializer;
+  }
+
+  @Override
+  public <T> T deserialize(byte[] bytes) throws IOException {
+    PropertyWrapper<T> propertyWrapper = rootDeserializer.deserialize(bytes);
+    return propertyWrapper.value;
+  }
+}
diff --git 
a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/bean/PropertyWrapper.java
 
b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/bean/PropertyWrapper.java
new file mode 100644
index 0000000..17b8d41
--- /dev/null
+++ 
b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/bean/PropertyWrapper.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.servicecomb.foundation.protobuf.internal.bean;
+
+public class PropertyWrapper<T> {
+  public T value;
+}
diff --git 
a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/MessageAsFieldSchema.java
 
b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/MessageAsFieldSchema.java
index 6ab4b8e..cb5df01 100644
--- 
a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/MessageAsFieldSchema.java
+++ 
b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/MessageAsFieldSchema.java
@@ -24,7 +24,7 @@ import io.protostuff.Schema;
 import io.protostuff.compiler.model.Field;
 
 public class MessageAsFieldSchema extends FieldSchema {
-  private Schema<Object> schema;
+  protected Schema<Object> schema;
 
   public MessageAsFieldSchema(Field protoField, Schema<Object> schema) {
     super(protoField);
diff --git 
a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/MessageAsFieldSchema.java
 
b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/PropertyWrapMessageAsFieldSchema.java
similarity index 59%
copy from 
foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/MessageAsFieldSchema.java
copy to 
foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/PropertyWrapMessageAsFieldSchema.java
index 6ab4b8e..0a1e7c0 100644
--- 
a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/MessageAsFieldSchema.java
+++ 
b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/PropertyWrapMessageAsFieldSchema.java
@@ -17,34 +17,46 @@
 package org.apache.servicecomb.foundation.protobuf.internal.schema;
 
 import java.io.IOException;
+import java.util.List;
 
 import io.protostuff.Input;
 import io.protostuff.Output;
 import io.protostuff.Schema;
 import io.protostuff.compiler.model.Field;
+import io.protostuff.runtime.MessageSchema;
 
-public class MessageAsFieldSchema extends FieldSchema {
-  private Schema<Object> schema;
+/**
+ *
+ */
+public class PropertyWrapMessageAsFieldSchema extends MessageAsFieldSchema {
+  private PropertyWrapMessageSchema propertyWrapMessageSchema;
+
+  private FieldSchema fieldSchema;
+
+  public PropertyWrapMessageAsFieldSchema(Field protoField, Schema<Object> 
schema) {
+    super(protoField, schema);
+
+    List<io.protostuff.runtime.Field<Object>> list = ((MessageSchema) 
schema).getFields();
+    this.fieldSchema = (FieldSchema) list.get(0);
 
-  public MessageAsFieldSchema(Field protoField, Schema<Object> schema) {
-    super(protoField);
-    this.schema = schema;
+    propertyWrapMessageSchema = new PropertyWrapMessageSchema();
+    propertyWrapMessageSchema.setFieldSchema(fieldSchema);
   }
 
   @Override
   public void writeTo(Output output, Object value) throws IOException {
-    output.writeObject(number, value, schema, false);
+    output.writeObject(number, value, propertyWrapMessageSchema, false);
   }
 
   @Override
   public Object readFrom(Input input) throws IOException {
-    return input.mergeObject(null, schema);
+    Object instance = schema.newMessage();
+    input.mergeObject(instance, schema);
+    return fieldSchema.getter.get(instance);
   }
 
   @Override
   public void mergeFrom(Input input, Object message) throws IOException {
-    Object existing = getter.get(message);
-    Object fieldValue = input.mergeObject(existing, schema);
-    setter.set(message, fieldValue);
+    throw new UnsupportedOperationException();
   }
 }
diff --git 
a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/MessageAsFieldSchema.java
 
b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/PropertyWrapMessageSchema.java
similarity index 55%
copy from 
foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/MessageAsFieldSchema.java
copy to 
foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/PropertyWrapMessageSchema.java
index 6ab4b8e..b585d64 100644
--- 
a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/MessageAsFieldSchema.java
+++ 
b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/PropertyWrapMessageSchema.java
@@ -18,33 +18,18 @@ package 
org.apache.servicecomb.foundation.protobuf.internal.schema;
 
 import java.io.IOException;
 
-import io.protostuff.Input;
 import io.protostuff.Output;
-import io.protostuff.Schema;
-import io.protostuff.compiler.model.Field;
+import io.protostuff.runtime.MessageSchema;
 
-public class MessageAsFieldSchema extends FieldSchema {
-  private Schema<Object> schema;
+public class PropertyWrapMessageSchema extends MessageSchema {
+  private FieldSchema fieldSchema;
 
-  public MessageAsFieldSchema(Field protoField, Schema<Object> schema) {
-    super(protoField);
-    this.schema = schema;
+  public void setFieldSchema(FieldSchema fieldSchema) {
+    this.fieldSchema = fieldSchema;
   }
 
   @Override
-  public void writeTo(Output output, Object value) throws IOException {
-    output.writeObject(number, value, schema, false);
-  }
-
-  @Override
-  public Object readFrom(Input input) throws IOException {
-    return input.mergeObject(null, schema);
-  }
-
-  @Override
-  public void mergeFrom(Input input, Object message) throws IOException {
-    Object existing = getter.get(message);
-    Object fieldValue = input.mergeObject(existing, schema);
-    setter.set(message, fieldValue);
+  public void writeTo(Output output, Object message) throws IOException {
+    fieldSchema.writeTo(output, message);
   }
 }
diff --git 
a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/SchemaManager.java
 
b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/SchemaManager.java
index 5e7d507..fe9978d 100644
--- 
a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/SchemaManager.java
+++ 
b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/SchemaManager.java
@@ -35,8 +35,11 @@ import 
org.apache.servicecomb.foundation.protobuf.internal.schema.scalar.UInt32S
 import 
org.apache.servicecomb.foundation.protobuf.internal.schema.scalar.UInt64Schema;
 
 import io.protostuff.compiler.model.Field;
+import io.protostuff.compiler.model.FieldContainer;
+import io.protostuff.compiler.model.Message;
 import io.protostuff.compiler.model.Proto;
 import io.protostuff.compiler.model.ScalarFieldType;
+import io.protostuff.runtime.MessageSchema;
 
 public class SchemaManager {
   protected final ProtoMapper protoMapper;
@@ -52,6 +55,14 @@ public class SchemaManager {
     return !repeated && 
protoField.getType().getCanonicalName().equals(ProtoConst.ANY.getCanonicalName());
   }
 
+  public boolean isWrapProperty(FieldContainer fieldContainer) {
+    return 
fieldContainer.getCommentLines().contains(ProtoConst.ANNOTATION_WRAP_PROPERTY);
+  }
+
+  protected MessageSchema newMessageSchema(Message message) {
+    return new MessageSchema();
+  }
+
   protected FieldSchema createScalarField(Field protoField) {
     switch ((ScalarFieldType) protoField.getType()) {
       case INT32:
diff --git 
a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/DeserializerSchemaManager.java
 
b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/DeserializerSchemaManager.java
index b42efc0..1bfb0d5 100644
--- 
a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/DeserializerSchemaManager.java
+++ 
b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/DeserializerSchemaManager.java
@@ -28,10 +28,12 @@ import 
org.apache.servicecomb.foundation.protobuf.RootDeserializer;
 import org.apache.servicecomb.foundation.protobuf.internal.bean.BeanDescriptor;
 import org.apache.servicecomb.foundation.protobuf.internal.bean.BeanFactory;
 import 
org.apache.servicecomb.foundation.protobuf.internal.bean.PropertyDescriptor;
+import 
org.apache.servicecomb.foundation.protobuf.internal.bean.PropertyWrapper;
 import org.apache.servicecomb.foundation.protobuf.internal.schema.AnySchema;
 import org.apache.servicecomb.foundation.protobuf.internal.schema.FieldSchema;
 import org.apache.servicecomb.foundation.protobuf.internal.schema.MapSchema;
 import 
org.apache.servicecomb.foundation.protobuf.internal.schema.MessageAsFieldSchema;
+import 
org.apache.servicecomb.foundation.protobuf.internal.schema.PropertyWrapMessageAsFieldSchema;
 import 
org.apache.servicecomb.foundation.protobuf.internal.schema.RepeatedSchema;
 import 
org.apache.servicecomb.foundation.protobuf.internal.schema.SchemaCreateContext;
 import 
org.apache.servicecomb.foundation.protobuf.internal.schema.SchemaManager;
@@ -39,6 +41,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.type.TypeFactory;
 
 import io.protostuff.compiler.model.Field;
 import io.protostuff.compiler.model.Message;
@@ -69,14 +72,13 @@ public class DeserializerSchemaManager extends 
SchemaManager {
     return new RootDeserializer(beanDescriptor, schema);
   }
 
-  protected MessageSchema createSchema(SchemaCreateContext context, JavaType 
javaType,
-      Message message) {
+  public MessageSchema createSchema(SchemaCreateContext context, JavaType 
javaType, Message message) {
     MessageSchema schema = context.getSchemas().get(message.getName());
     if (schema != null) {
       return schema;
     }
 
-    schema = new MessageSchema();
+    schema = newMessageSchema(message);
     context.getSchemas().put(message.getName(), schema);
 
     doCreateSchema(context, schema, javaType, message);
@@ -87,11 +89,17 @@ public class DeserializerSchemaManager extends 
SchemaManager {
   protected void doCreateSchema(SchemaCreateContext context, MessageSchema 
schema,
       JavaType javaType,
       Message message) {
+    if (javaType.isJavaLangObject()) {
+      javaType = TypeFactory.defaultInstance().constructType(Map.class);
+    }
     if (Map.class.isAssignableFrom(javaType.getRawClass())) {
       doCreateSchemaToMap(context, schema, javaType, message);
       return;
     }
 
+    if (isWrapProperty(message) && 
(!javaType.getRawClass().equals(PropertyWrapper.class))) {
+      javaType = 
TypeFactory.defaultInstance().constructParametricType(PropertyWrapper.class, 
javaType);
+    }
     BeanDescriptor beanDescriptor = 
protoMapper.getBeanDescriptorManager().getOrCreateBeanDescriptor(javaType);
 
     List<io.protostuff.runtime.Field<Object>> fieldSchemas = new ArrayList<>();
@@ -177,7 +185,12 @@ public class DeserializerSchemaManager extends 
SchemaManager {
 
     // message
     MessageSchema messageSchema = createSchema(context, javaType, (Message) 
protoField.getType());
-    MessageAsFieldSchema messageAsFieldSchema = new 
MessageAsFieldSchema(protoField, messageSchema);
+    MessageAsFieldSchema messageAsFieldSchema;
+    if (isWrapProperty((Message) protoField.getType())) {
+      messageAsFieldSchema = new PropertyWrapMessageAsFieldSchema(protoField, 
messageSchema);
+    } else {
+      messageAsFieldSchema = new MessageAsFieldSchema(protoField, 
messageSchema);
+    }
     return messageAsFieldSchema;
   }
 }
diff --git 
a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/SerializerSchemaManager.java
 
b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/SerializerSchemaManager.java
index 296e1bc..85cf7a9 100644
--- 
a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/SerializerSchemaManager.java
+++ 
b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/SerializerSchemaManager.java
@@ -27,6 +27,8 @@ import 
org.apache.servicecomb.foundation.protobuf.internal.schema.AnySchema;
 import org.apache.servicecomb.foundation.protobuf.internal.schema.FieldSchema;
 import org.apache.servicecomb.foundation.protobuf.internal.schema.MapSchema;
 import 
org.apache.servicecomb.foundation.protobuf.internal.schema.MessageAsFieldSchema;
+import 
org.apache.servicecomb.foundation.protobuf.internal.schema.PropertyWrapMessageAsFieldSchema;
+import 
org.apache.servicecomb.foundation.protobuf.internal.schema.PropertyWrapMessageSchema;
 import 
org.apache.servicecomb.foundation.protobuf.internal.schema.RepeatedSchema;
 import 
org.apache.servicecomb.foundation.protobuf.internal.schema.SchemaCreateContext;
 import 
org.apache.servicecomb.foundation.protobuf.internal.schema.SchemaManager;
@@ -66,7 +68,11 @@ public class SerializerSchemaManager extends SchemaManager {
 
   protected RootSerializer createRootSerializer(SchemaCreateContext context, 
Message message) {
     MessageSchema schema = createSchema(context, message);
-
+    if (isWrapProperty(message)) {
+      FieldSchema fieldSchema = (FieldSchema) schema.getFields().get(0);
+      schema = new PropertyWrapMessageSchema();
+      ((PropertyWrapMessageSchema) schema).setFieldSchema(fieldSchema);
+    }
     return new RootSerializer(schema);
   }
 
@@ -76,7 +82,7 @@ public class SerializerSchemaManager extends SchemaManager {
       return schema;
     }
 
-    schema = new MessageSchema();
+    schema = newMessageSchema(message);
     context.getSchemas().put(message.getName(), schema);
 
     List<io.protostuff.runtime.Field<Object>> fieldSchemas = new ArrayList<>();
@@ -119,7 +125,12 @@ public class SerializerSchemaManager extends SchemaManager 
{
 
     // message
     MessageSchema messageSchema = createSchema(context, (Message) 
protoField.getType());
-    MessageAsFieldSchema messageAsFieldSchema = new 
MessageAsFieldSchema(protoField, messageSchema);
+    MessageAsFieldSchema messageAsFieldSchema;
+    if (isWrapProperty((Message) protoField.getType())) {
+      messageAsFieldSchema = new PropertyWrapMessageAsFieldSchema(protoField, 
messageSchema);
+    } else {
+      messageAsFieldSchema = new MessageAsFieldSchema(protoField, 
messageSchema);
+    }
     return messageAsFieldSchema;
   }
 }
diff --git 
a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/TestModelWrap.java
 
b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/TestModelWrap.java
new file mode 100644
index 0000000..94937c2
--- /dev/null
+++ 
b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/TestModelWrap.java
@@ -0,0 +1,247 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.servicecomb.foundation.protobuf.internal;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.servicecomb.foundation.protobuf.ProtoMapper;
+import org.apache.servicecomb.foundation.protobuf.ProtoMapperFactory;
+import org.apache.servicecomb.foundation.protobuf.RootDeserializer;
+import org.apache.servicecomb.foundation.protobuf.RootSerializer;
+import org.junit.Assert;
+import org.junit.Test;
+
+import io.vertx.core.json.Json;
+
+public class TestModelWrap {
+  protected static ProtoMapperFactory factory = new ProtoMapperFactory();
+
+  protected static ProtoMapper modelProtoMapper = 
factory.createFromName("model.proto");
+
+  public static class User {
+    public String name;
+
+    public User(String name) {
+      this.name = name;
+    }
+  }
+
+  static User user = new User("uName");
+
+  public static class PojoModel {
+    public List<List<User>> listListUser;
+
+    public List<Map<String, User>> listMapUser;
+
+    public Map<String, List<User>> mapListUser;
+
+    public Map<String, Map<String, User>> mapMapUser;
+
+    public List<List<List<User>>> listListListUser;
+
+    public List<List<Map<String, User>>> listListMapUser;
+
+    public List<Map<String, List<User>>> listMapListUser;
+
+    public List<Map<String, Map<String, User>>> listMapMapUser;
+
+    public Map<String, List<List<User>>> mapListListUser;
+
+    public Map<String, List<Map<String, User>>> mapListMapUser;
+
+    public Map<String, Map<String, List<User>>> mapMapListUser;
+
+    public Map<String, Map<String, Map<String, User>>> mapMapMapUser;
+
+    public void init() {
+      listListUser = Arrays.asList(Arrays.asList(user));
+      listMapUser = Arrays.asList(Collections.singletonMap(user.name, user));
+      mapListUser = Collections.singletonMap("k1", Arrays.asList(user));
+      mapMapUser = Collections.singletonMap("k1", 
Collections.singletonMap(user.name, user));
+
+      listListListUser = Arrays.asList(Arrays.asList(Arrays.asList(user)));
+      listListMapUser = 
Arrays.asList(Arrays.asList(Collections.singletonMap(user.name, user)));
+      listMapListUser = Arrays.asList(Collections.singletonMap("k1", 
Arrays.asList(user)));
+      listMapMapUser = Arrays.asList(Collections.singletonMap("k1", 
Collections.singletonMap(user.name, user)));
+      mapListListUser = Collections.singletonMap("k1", 
Arrays.asList(Arrays.asList(user)));
+      mapListMapUser = Collections.singletonMap("k1", 
Arrays.asList(Collections.singletonMap(user.name, user)));
+      mapMapListUser = Collections.singletonMap("k1", 
Collections.singletonMap("k1", Arrays.asList(user)));
+      mapMapMapUser = Collections
+          .singletonMap("k1", Collections.singletonMap("k1", 
Collections.singletonMap(user.name, user)));
+    }
+  }
+
+  public static class ProtoModel {
+    public List<ProtoListUser> listListUser;
+
+    public List<ProtoMapUser> listMapUser;
+
+    public Map<String, ProtoListUser> mapListUser;
+
+    public Map<String, ProtoMapUser> mapMapUser;
+
+    public List<ProtoListListUser> listListListUser;
+
+    public List<ProtoListMapUser> listListMapUser;
+
+    public List<ProtoMapListUser> listMapListUser;
+
+    public List<ProtoMapMapUser> listMapMapUser;
+
+    public Map<String, ProtoListListUser> mapListListUser;
+
+    public Map<String, ProtoListMapUser> mapListMapUser;
+
+    public Map<String, ProtoMapListUser> mapMapListUser;
+
+    public Map<String, ProtoMapMapUser> mapMapMapUser;
+
+    public void init() {
+      ProtoListUser protoListUser = new ProtoListUser();
+      protoListUser.init();
+
+      ProtoMapUser protoMapUser = new ProtoMapUser();
+      protoMapUser.init();
+
+      ProtoListListUser protoListListUser = new ProtoListListUser();
+      protoListListUser.init();
+
+      ProtoListMapUser protoListMapUser = new ProtoListMapUser();
+      protoListMapUser.init();
+
+      ProtoMapListUser protoMapListUser = new ProtoMapListUser();
+      protoMapListUser.init();
+
+      ProtoMapMapUser protoMapMapUser = new ProtoMapMapUser();
+      protoMapMapUser.init();
+
+      listListUser = Arrays.asList(protoListUser);
+      listMapUser = Arrays.asList(protoMapUser);
+      mapListUser = Collections.singletonMap("k1", protoListUser);
+      mapMapUser = Collections.singletonMap("k1", protoMapUser);
+
+      listListListUser = Arrays.asList(protoListListUser);
+      listListMapUser = Arrays.asList(protoListMapUser);
+      listMapListUser = Arrays.asList(protoMapListUser);
+      listMapMapUser = Arrays.asList(protoMapMapUser);
+      mapListListUser = Collections.singletonMap("k1", protoListListUser);
+      mapListMapUser = Collections.singletonMap("k1", protoListMapUser);
+      mapMapListUser = Collections.singletonMap("k1", protoMapListUser);
+      mapMapMapUser = Collections.singletonMap("k1", protoMapMapUser);
+    }
+  }
+
+  public static class ProtoListListUser {
+    public List<ProtoListUser> value;
+
+    public void init() {
+      ProtoListUser protoListUser = new ProtoListUser();
+      protoListUser.init();
+      value = Arrays.asList(protoListUser);
+    }
+  }
+
+  public static class ProtoListMapUser {
+    public List<ProtoMapUser> value;
+
+    public void init() {
+      ProtoMapUser protoMapUser = new ProtoMapUser();
+      protoMapUser.init();
+      value = Arrays.asList(protoMapUser);
+    }
+  }
+
+  public static class ProtoMapListUser {
+    public Map<String, ProtoListUser> value;
+
+    public void init() {
+      ProtoListUser protoListUser = new ProtoListUser();
+      protoListUser.init();
+      value = Collections.singletonMap("k1", protoListUser);
+    }
+  }
+
+  public static class ProtoMapMapUser {
+    public Map<String, ProtoMapUser> value;
+
+    public void init() {
+      ProtoMapUser protoMapUser = new ProtoMapUser();
+      protoMapUser.init();
+      value = Collections.singletonMap("k1", protoMapUser);
+    }
+  }
+
+  public static class ProtoListUser {
+    public List<User> value;
+
+    public void init() {
+      value = Arrays.asList(user);
+    }
+  }
+
+  public static class ProtoMapUser {
+    public Map<String, User> value;
+
+    public void init() {
+      value = Collections.singletonMap(user.name, user);
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void pojoModel() throws IOException {
+    RootSerializer pojoSerializer = 
modelProtoMapper.findRootSerializer("PojoModel");
+    RootDeserializer pojoMapDeserializer = 
modelProtoMapper.createRootDeserializer(Map.class, "PojoModel");
+    RootDeserializer pojoModelDeserializer = 
modelProtoMapper.createRootDeserializer(PojoModel.class, "PojoModel");
+
+    RootSerializer protoSerializer = 
modelProtoMapper.findRootSerializer("ProtoModel");
+    RootDeserializer protoMapDeserializer = 
modelProtoMapper.createRootDeserializer(Map.class, "ProtoModel");
+    RootDeserializer protoModelDeserializer = 
modelProtoMapper.createRootDeserializer(ProtoModel.class, "ProtoModel");
+
+    PojoModel pojoModel = new PojoModel();
+    pojoModel.init();
+    String jsonPojoModel = Json.encode(pojoModel);
+    Map<String, Object> mapFromPojoModel = (Map<String, Object>) 
Json.decodeValue(jsonPojoModel, Map.class);
+
+    ProtoModel protoModel = new ProtoModel();
+    protoModel.init();
+    String jsonProtoModel = Json.encode(protoModel);
+    Map<String, Object> mapFromProtoModel = (Map<String, Object>) 
Json.decodeValue(jsonProtoModel, Map.class);
+
+    // serialize
+    byte[] bytes = protoSerializer.serialize(protoModel);
+    Assert.assertArrayEquals(bytes, 
protoSerializer.serialize(mapFromProtoModel));
+    Assert.assertArrayEquals(bytes, pojoSerializer.serialize(pojoModel));
+    Assert.assertArrayEquals(bytes, 
pojoSerializer.serialize(mapFromPojoModel));
+
+    // deserialize pojoModel
+    PojoModel newPojoModel = pojoModelDeserializer.deserialize(bytes);
+    Assert.assertEquals(jsonPojoModel, Json.encode(newPojoModel));
+    Map<String, Object> mapFromNewPojoModel = 
pojoMapDeserializer.deserialize(bytes);
+    Assert.assertEquals(jsonPojoModel, Json.encode(mapFromNewPojoModel));
+
+    // deserialize protoModel
+    ProtoModel newProtoModel = protoModelDeserializer.deserialize(bytes);
+    Assert.assertEquals(jsonProtoModel, Json.encode(newProtoModel));
+    Map<String, Object> mapFromNewProtoModel = 
protoMapDeserializer.deserialize(bytes);
+    Assert.assertEquals(jsonProtoModel, Json.encode(mapFromNewProtoModel));
+  }
+}
diff --git a/foundations/foundation-protobuf/src/test/resources/model.proto 
b/foundations/foundation-protobuf/src/test/resources/model.proto
new file mode 100644
index 0000000..c72ec7d
--- /dev/null
+++ b/foundations/foundation-protobuf/src/test/resources/model.proto
@@ -0,0 +1,108 @@
+/*
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You 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.
+ */
+
+syntax = "proto3";
+
+message PojoModel {
+  repeated PojoListUser listListUser = 1;
+  repeated PojoMapUser listMapUser = 2;
+  map<string, PojoListUser> mapListUser = 3;
+  map<string, PojoMapUser> mapMapUser = 4;
+
+  repeated PojoListListUser listListListUser = 5;
+  repeated PojoListMapUser listListMapUser = 6;
+  repeated PojoMapListUser listMapListUser = 7;
+  repeated PojoMapMapUser listMapMapUser = 8;
+  map<string, PojoListListUser> mapListListUser = 9;
+  map<string, PojoListMapUser> mapListMapUser = 10;
+  map<string, PojoMapListUser> mapMapListUser = 11;
+  map<string, PojoMapMapUser> mapMapMapUser = 12;
+}
+
+message ProtoModel {
+  repeated ProtoListUser listListUser = 1;
+  repeated ProtoMapUser listMapUser = 2;
+  map<string, ProtoListUser> mapListUser = 3;
+  map<string, ProtoMapUser> mapMapUser = 4;
+
+  repeated ProtoListListUser listListListUser = 5;
+  repeated ProtoListMapUser listListMapUser = 6;
+  repeated ProtoMapListUser listMapListUser = 7;
+  repeated ProtoMapMapUser listMapMapUser = 8;
+  map<string, ProtoListListUser> mapListListUser = 9;
+  map<string, ProtoListMapUser> mapListMapUser = 10;
+  map<string, ProtoMapListUser> mapMapListUser = 11;
+  map<string, ProtoMapMapUser> mapMapMapUser = 12;
+}
+
+//@WrapProperty
+message PojoListListUser {
+  repeated PojoListUser value = 1;
+}
+
+//@WrapProperty
+message PojoListMapUser {
+  repeated PojoMapUser value = 1;
+}
+
+//@WrapProperty
+message PojoMapListUser {
+  map<string, PojoListUser> value = 1;
+}
+
+//@WrapProperty
+message PojoMapMapUser {
+  map<string, PojoMapUser> value = 1;
+}
+
+//@WrapProperty
+message PojoListUser {
+  repeated User value = 1;
+}
+
+//@WrapProperty
+message PojoMapUser {
+  map<string, User> value = 1;
+}
+
+message User {
+  string name = 1;
+}
+
+message ProtoListListUser {
+  repeated ProtoListUser value = 1;
+}
+
+message ProtoListMapUser {
+  repeated ProtoMapUser value = 1;
+}
+
+message ProtoMapListUser {
+  map<string, ProtoListUser> value = 1;
+}
+
+message ProtoMapMapUser {
+  map<string, ProtoMapUser> value = 1;
+}
+
+message ProtoListUser {
+  repeated User value = 1;
+}
+
+message ProtoMapUser {
+  map<string, User> value = 1;
+}

Reply via email to