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;
+}