[Dubbo-7029] new format ServiceDefinition (#7029)

This commit is contained in:
Robert LU 2021-01-10 19:02:52 +08:00 committed by GitHub
parent c4815f5602
commit 7580232b4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 483 additions and 271 deletions

View File

@ -55,6 +55,7 @@ public interface EventListener<E extends Event> extends java.util.EventListener,
* {@link Integer#MIN_VALUE} indicates the highest priority. The default value is {@link Integer#MAX_VALUE}.
* The comparison rule , refer to {@link #compareTo}.
*/
@Override
default int getPriority() {
return NORMAL_PRIORITY;
}

View File

@ -100,6 +100,7 @@ public class PrioritizedTest {
this.value = value;
}
@Override
public int getPriority() {
return value;
}

View File

@ -39,6 +39,7 @@ public class DefaultCharSequence implements CharSequence, Prioritized {
return null;
}
@Override
public int getPriority() {
return MAX_PRIORITY;
}

View File

@ -106,7 +106,7 @@ public class GenericServiceTest {
FullServiceDefinition fullServiceDefinition = ServiceDefinitionBuilder.buildFullDefinition(DemoService.class);
MethodDefinition methodDefinition = getMethod("complexCompute", fullServiceDefinition.getMethods());
Map mapObject = createComplexObject(fullServiceDefinition,var1, var2, l, var3, var4, testEnum);
Map mapObject = createComplexObject(fullServiceDefinition, var1, var2, l, var3, var4, testEnum);
ComplexObject complexObject = map2bean(mapObject);
Invoker<GenericService> invoker = protocol.refer(GenericService.class, url);
@ -172,32 +172,32 @@ public class GenericServiceTest {
TypeDefinition inner2TypeDefinition = null;
TypeDefinition inner3TypeDefinition = null;
for (TypeDefinition typeDefinition : typeDefinitions) {
if (typeDefinition.getType().equals(ComplexObject.class.getName())) {
if (typeDefinition.getType().equals(ComplexObject.class.getCanonicalName())) {
topTypeDefinition = typeDefinition;
} else if (typeDefinition.getType().equals(ComplexObject.InnerObject.class.getName())) {
} else if (typeDefinition.getType().equals(ComplexObject.InnerObject.class.getCanonicalName())) {
innerTypeDefinition = typeDefinition;
} else if (typeDefinition.getType().contains(ComplexObject.InnerObject2.class.getName())) {
} else if (typeDefinition.getType().equals(ComplexObject.InnerObject2.class.getCanonicalName())) {
inner2TypeDefinition = typeDefinition;
} else if (typeDefinition.getType().equals(ComplexObject.InnerObject3.class.getName())) {
} else if (typeDefinition.getType().equals(ComplexObject.InnerObject3.class.getCanonicalName())) {
inner3TypeDefinition = typeDefinition;
}
}
Assertions.assertEquals(topTypeDefinition.getProperties().get("v").getType(), "long");
Assertions.assertEquals(topTypeDefinition.getProperties().get("maps").getType(), "java.util.Map<java.lang.String,java.lang.String>");
Assertions.assertEquals(topTypeDefinition.getProperties().get("innerObject").getType(), "org.apache.dubbo.service.ComplexObject$InnerObject");
Assertions.assertEquals(topTypeDefinition.getProperties().get("intList").getType(), "java.util.List<java.lang.Integer>");
Assertions.assertEquals(topTypeDefinition.getProperties().get("strArrays").getType(), "java.lang.String[]");
Assertions.assertEquals(topTypeDefinition.getProperties().get("innerObject3").getType(), "org.apache.dubbo.service.ComplexObject.InnerObject3[]");
Assertions.assertEquals(topTypeDefinition.getProperties().get("testEnum").getType(), "org.apache.dubbo.service.ComplexObject.TestEnum");
Assertions.assertEquals(topTypeDefinition.getProperties().get("innerObject2").getType(), "java.util.List<org.apache.dubbo.service.ComplexObject$InnerObject2>");
Assertions.assertEquals("long", topTypeDefinition.getProperties().get("v"));
Assertions.assertEquals("java.util.Map<java.lang.String,java.lang.String>", topTypeDefinition.getProperties().get("maps"));
Assertions.assertEquals("org.apache.dubbo.service.ComplexObject.InnerObject", topTypeDefinition.getProperties().get("innerObject"));
Assertions.assertEquals("java.util.List<java.lang.Integer>", topTypeDefinition.getProperties().get("intList"));
Assertions.assertEquals("java.lang.String[]", topTypeDefinition.getProperties().get("strArrays"));
Assertions.assertEquals("org.apache.dubbo.service.ComplexObject.InnerObject3[]", topTypeDefinition.getProperties().get("innerObject3"));
Assertions.assertEquals("org.apache.dubbo.service.ComplexObject.TestEnum", topTypeDefinition.getProperties().get("testEnum"));
Assertions.assertEquals("java.util.List<org.apache.dubbo.service.ComplexObject.InnerObject2>", topTypeDefinition.getProperties().get("innerObject2"));
Assertions.assertSame(innerTypeDefinition.getProperties().get("innerA").getType(), "java.lang.String");
Assertions.assertSame(innerTypeDefinition.getProperties().get("innerB").getType(), "int");
Assertions.assertSame("java.lang.String", innerTypeDefinition.getProperties().get("innerA"));
Assertions.assertSame("int", innerTypeDefinition.getProperties().get("innerB"));
Assertions.assertSame(inner2TypeDefinition.getProperties().get("innerA2").getType(), "java.lang.String");
Assertions.assertSame(inner2TypeDefinition.getProperties().get("innerB2").getType(), "int");
Assertions.assertSame("java.lang.String", inner2TypeDefinition.getProperties().get("innerA2"));
Assertions.assertSame("int", inner2TypeDefinition.getProperties().get("innerB2"));
Assertions.assertSame(inner3TypeDefinition.getProperties().get("innerA3").getType(), "java.lang.String");
Assertions.assertSame("java.lang.String", inner3TypeDefinition.getProperties().get("innerA3"));
Map<String, Object> result = new HashMap<>();
result.put("v", l);

View File

@ -19,6 +19,7 @@ package org.apache.dubbo.metadata.definition;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.ClassUtils;
import org.apache.dubbo.metadata.definition.builder.DefaultTypeBuilder;
import org.apache.dubbo.metadata.definition.builder.TypeBuilder;
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
@ -30,7 +31,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.apache.dubbo.common.utils.ClassUtils.isSimpleType;
/**
* 2015/1/27.
@ -45,18 +45,17 @@ public class TypeDefinitionBuilder {
BUILDERS = new ArrayList<>(tbs);
}
public static TypeDefinition build(Type type, Class<?> clazz, Map<Class<?>, TypeDefinition> typeCache) {
public static TypeDefinition build(Type type, Class<?> clazz, Map<String, TypeDefinition> typeCache) {
TypeBuilder builder = getGenericTypeBuilder(type, clazz);
TypeDefinition td;
if (builder != null) {
if (clazz.isPrimitive() || ClassUtils.isSimpleType(clazz)) { // changed since 2.7.6
td = new TypeDefinition(clazz.getCanonicalName());
typeCache.put(clazz.getCanonicalName(), td);
} else if (builder != null) {
td = builder.build(type, clazz, typeCache);
td.setTypeBuilderName(builder.getClass().getName());
} else {
td = DefaultTypeBuilder.build(clazz, typeCache);
td.setTypeBuilderName(DefaultTypeBuilder.class.getName());
}
if (isSimpleType(clazz)) { // changed since 2.7.6
td.setProperties(null);
}
return td;
}
@ -75,7 +74,7 @@ public class TypeDefinitionBuilder {
return null;
}
private Map<Class<?>, TypeDefinition> typeCache = new HashMap<>();
private Map<String, TypeDefinition> typeCache = new HashMap<>();
public TypeDefinition build(Type type, Class<?> clazz) {
return build(type, clazz, typeCache);

View File

@ -36,13 +36,21 @@ public class ArrayTypeBuilder implements TypeBuilder {
}
@Override
public TypeDefinition build(Type type, Class<?> clazz, Map<Class<?>, TypeDefinition> typeCache) {
public TypeDefinition build(Type type, Class<?> clazz, Map<String, TypeDefinition> typeCache) {
final String canonicalName = clazz.getCanonicalName();
TypeDefinition td = typeCache.get(canonicalName);
if (td != null) {
return td;
}
td = new TypeDefinition(canonicalName);
typeCache.put(canonicalName, td);
// Process the component type of an array.
Class<?> componentType = clazz.getComponentType();
TypeDefinitionBuilder.build(componentType, componentType, typeCache);
final String canonicalName = clazz.getCanonicalName();
return new TypeDefinition(canonicalName);
TypeDefinition itemTd = TypeDefinitionBuilder.build(componentType, componentType, typeCache);
if (itemTd != null) {
td.getItems().add(itemTd.getType());
}
return td;
}
}

View File

@ -18,6 +18,7 @@ package org.apache.dubbo.metadata.definition.builder;
import org.apache.dubbo.metadata.definition.TypeDefinitionBuilder;
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import org.apache.dubbo.metadata.definition.util.ClassUtils;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
@ -40,9 +41,9 @@ public class CollectionTypeBuilder implements TypeBuilder {
}
@Override
public TypeDefinition build(Type type, Class<?> clazz, Map<Class<?>, TypeDefinition> typeCache) {
public TypeDefinition build(Type type, Class<?> clazz, Map<String, TypeDefinition> typeCache) {
if (!(type instanceof ParameterizedType)) {
return new TypeDefinition(clazz.getName());
return new TypeDefinition(clazz.getCanonicalName());
}
ParameterizedType parameterizedType = (ParameterizedType) type;
@ -54,17 +55,29 @@ public class CollectionTypeBuilder implements TypeBuilder {
type, actualTypeArgs));
}
String colType = ClassUtils.getCanonicalNameForParameterizedType(parameterizedType);
TypeDefinition td = typeCache.get(colType);
if (td != null) {
return td;
}
td = new TypeDefinition(colType);
typeCache.put(colType, td);
Type actualType = actualTypeArgs[0];
TypeDefinition itemTd = null;
if (actualType instanceof ParameterizedType) {
// Nested collection or map.
Class<?> rawType = (Class<?>) ((ParameterizedType) actualType).getRawType();
TypeDefinitionBuilder.build(actualType, rawType, typeCache);
itemTd = TypeDefinitionBuilder.build(actualType, rawType, typeCache);
} else if (actualType instanceof Class<?>) {
Class<?> actualClass = (Class<?>) actualType;
TypeDefinitionBuilder.build(null, actualClass, typeCache);
itemTd = TypeDefinitionBuilder.build(null, actualClass, typeCache);
}
if (itemTd != null) {
td.getItems().add(itemTd.getType());
}
return new TypeDefinition(type.toString());
return td;
}
}

View File

@ -31,15 +31,16 @@ import java.util.Map;
*/
public final class DefaultTypeBuilder {
public static TypeDefinition build(Class<?> clazz, Map<Class<?>, TypeDefinition> typeCache) {
// final String canonicalName = clazz.getCanonicalName();
final String name = clazz.getName();
public static TypeDefinition build(Class<?> clazz, Map<String, TypeDefinition> typeCache) {
final String canonicalName = clazz.getCanonicalName();
TypeDefinition td = new TypeDefinition(name);
// Try to get a cached definition
if (typeCache.containsKey(clazz)) {
return typeCache.get(clazz);
TypeDefinition td = typeCache.get(canonicalName);
if (td != null) {
return td;
}
td = new TypeDefinition(canonicalName);
typeCache.put(canonicalName, td);
// Primitive type
if (!JaketConfigurationUtils.needAnalyzing(clazz)) {
@ -47,21 +48,15 @@ public final class DefaultTypeBuilder {
}
// Custom type
TypeDefinition ref = new TypeDefinition(name);
ref.set$ref(name);
typeCache.put(clazz, ref);
List<Field> fields = ClassUtils.getNonStaticFields(clazz);
for (Field field : fields) {
String fieldName = field.getName();
Class<?> fieldClass = field.getType();
Type fieldType = field.getGenericType();
TypeDefinition fieldTd = TypeDefinitionBuilder.build(fieldType, fieldClass, typeCache);
td.getProperties().put(fieldName, fieldTd);
td.getProperties().put(fieldName, fieldTd.getType());
}
typeCache.put(clazz, td);
return td;
}

View File

@ -16,6 +16,9 @@
*/
package org.apache.dubbo.metadata.definition.builder;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.metadata.definition.TypeDefinitionBuilder;
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import java.lang.reflect.Method;
@ -26,6 +29,7 @@ import java.util.Map;
* 2015/1/27.
*/
public class EnumTypeBuilder implements TypeBuilder {
private static final Logger logger = LoggerFactory.getLogger(TypeDefinitionBuilder.class);
@Override
public boolean accept(Type type, Class<?> clazz) {
@ -36,8 +40,15 @@ public class EnumTypeBuilder implements TypeBuilder {
}
@Override
public TypeDefinition build(Type type, Class<?> clazz, Map<Class<?>, TypeDefinition> typeCache) {
TypeDefinition td = new TypeDefinition(clazz.getCanonicalName());
public TypeDefinition build(Type type, Class<?> clazz, Map<String, TypeDefinition> typeCache) {
String canonicalName = clazz.getCanonicalName();
TypeDefinition td = typeCache.get(canonicalName);
if (td != null) {
return td;
}
td = new TypeDefinition(canonicalName);
typeCache.put(canonicalName, td);
try {
Method methodValues = clazz.getDeclaredMethod("values");
@ -47,12 +58,11 @@ public class EnumTypeBuilder implements TypeBuilder {
Object value = values[i];
td.getEnums().add(value.toString());
}
return td;
} catch (Throwable t) {
td.setId("-1");
logger.error("There is an error while process class " + clazz, t);
}
typeCache.put(clazz, td);
return td;
return null;
}
}

View File

@ -18,6 +18,7 @@ package org.apache.dubbo.metadata.definition.builder;
import org.apache.dubbo.metadata.definition.TypeDefinitionBuilder;
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import org.apache.dubbo.metadata.definition.util.ClassUtils;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
@ -44,9 +45,9 @@ public class MapTypeBuilder implements TypeBuilder {
}
@Override
public TypeDefinition build(Type type, Class<?> clazz, Map<Class<?>, TypeDefinition> typeCache) {
public TypeDefinition build(Type type, Class<?> clazz, Map<String, TypeDefinition> typeCache) {
if (!(type instanceof ParameterizedType)) {
return new TypeDefinition(clazz.getName());
return new TypeDefinition(clazz.getCanonicalName());
}
ParameterizedType parameterizedType = (ParameterizedType) type;
@ -65,9 +66,15 @@ public class MapTypeBuilder implements TypeBuilder {
* {@link ParameterizedType#toString()}
* @see sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
*/
String mapType = replace(type.toString(), ", ", ",");
String mapType = ClassUtils.getCanonicalNameForParameterizedType(parameterizedType);
mapType = replace(mapType, ", ", ",");
TypeDefinition typeDefinition = new TypeDefinition(mapType);
TypeDefinition td = typeCache.get(mapType);
if (td != null) {
return td;
}
td = new TypeDefinition(mapType);
typeCache.put(mapType, td);
for (int i = 0; i < actualTypeArgsLength; i++) {
Type actualType = actualTypeArgs[i];
@ -79,9 +86,10 @@ public class MapTypeBuilder implements TypeBuilder {
} else if (isClass(actualType)) {
item = TypeDefinitionBuilder.build(null, rawType, typeCache);
}
typeDefinition.getItems().add(item);
if (item != null) {
td.getItems().add(item.getType());
}
}
return typeDefinition;
return td;
}
}

View File

@ -37,6 +37,6 @@ public interface TypeBuilder extends Prioritized {
/**
* Build type definition with the type or class.
*/
TypeDefinition build(Type type, Class<?> clazz, Map<Class<?>, TypeDefinition> typeCache);
TypeDefinition build(Type type, Class<?> clazz, Map<String, TypeDefinition> typeCache);
}

View File

@ -30,6 +30,12 @@ public class MethodDefinition implements Serializable {
private String name;
private String[] parameterTypes;
private String returnType;
/**
* @deprecated please use parameterTypes,
* and find TypeDefinition in org.apache.dubbo.metadata.definition.model.ServiceDefinition#types
*/
@Deprecated
private List<TypeDefinition> parameters;
public String getName() {
@ -84,14 +90,11 @@ public class MethodDefinition implements Serializable {
MethodDefinition that = (MethodDefinition) o;
return Objects.equals(getName(), that.getName()) &&
Arrays.equals(getParameterTypes(), that.getParameterTypes()) &&
Objects.equals(getReturnType(), that.getReturnType()) &&
Objects.equals(getParameters(), that.getParameters());
Objects.equals(getReturnType(), that.getReturnType());
}
@Override
public int hashCode() {
int result = Objects.hash(getName(), getReturnType(), getParameters());
result = 31 * result + Arrays.hashCode(getParameterTypes());
return result;
return Objects.hash(getName(), getReturnType(), getParameterTypes());
}
}

View File

@ -16,6 +16,8 @@
*/
package org.apache.dubbo.metadata.definition.model;
import org.apache.dubbo.metadata.definition.util.ClassUtils;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@ -26,9 +28,25 @@ import java.util.Objects;
*/
public class ServiceDefinition implements Serializable {
/**
* the canonical name of interface
*
* @see Class#getCanonicalName()
*/
private String canonicalName;
/**
* the location of class file
*
* @see ClassUtils#getCodeSource(Class)
*/
private String codeSource;
private List<MethodDefinition> methods;
/**
* the definitions of type
*/
private List<TypeDefinition> types;
public String getCanonicalName() {

View File

@ -19,6 +19,8 @@ package org.apache.dubbo.metadata.definition.model;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -30,15 +32,35 @@ import java.util.Objects;
*/
public class TypeDefinition implements Serializable {
private String id;
/**
* the name of type
*
* @see Class#getCanonicalName()
* @see org.apache.dubbo.metadata.definition.util.ClassUtils#getCanonicalNameForParameterizedType(ParameterizedType)
*/
private String type;
/**
* the items(generic parameter) of Map/List(ParameterizedType)
* <p>
* if this type is not ParameterizedType, the items is null or empty
*/
@SerializedName("items")
private List<TypeDefinition> items;
private List<String> items;
/**
* the enum's value
* <p>
* If this type is not enum, enums is null or empty
*/
@SerializedName("enum")
private List<String> enums;
private String $ref;
private Map<String, TypeDefinition> properties;
private String typeBuilderName;
/**
* the key is property name,
* the value is property's type name
*/
private Map<String, String> properties;
public TypeDefinition() {
}
@ -47,29 +69,21 @@ public class TypeDefinition implements Serializable {
this.type = type;
}
public String get$ref() {
return $ref;
}
public List<String> getEnums() {
if (enums == null) {
enums = new ArrayList<String>();
enums = new ArrayList<>();
}
return enums;
}
public String getId() {
return id;
}
public List<TypeDefinition> getItems() {
public List<String> getItems() {
if (items == null) {
items = new ArrayList<>();
}
return items;
}
public Map<String, TypeDefinition> getProperties() {
public Map<String, String> getProperties() {
if (properties == null) {
properties = new HashMap<>();
}
@ -80,27 +94,15 @@ public class TypeDefinition implements Serializable {
return type;
}
public String getTypeBuilderName() {
return typeBuilderName;
}
public void set$ref(String $ref) {
this.$ref = $ref;
}
public void setEnums(List<String> enums) {
this.enums = enums;
}
public void setId(String id) {
this.id = id;
}
public void setItems(List<TypeDefinition> items) {
public void setItems(List<String> items) {
this.items = items;
}
public void setProperties(Map<String, TypeDefinition> properties) {
public void setProperties(Map<String, String> properties) {
this.properties = properties;
}
@ -108,13 +110,9 @@ public class TypeDefinition implements Serializable {
this.type = type;
}
public void setTypeBuilderName(String typeBuilderName) {
this.typeBuilderName = typeBuilderName;
}
@Override
public String toString() {
return "TypeDefinition [id=" + id + ", type=" + type + ", properties=" + properties + ", $ref=" + $ref + "]";
return "TypeDefinition [type=" + type + ", properties=" + properties + "]";
}
@Override
@ -126,16 +124,14 @@ public class TypeDefinition implements Serializable {
return false;
}
TypeDefinition that = (TypeDefinition) o;
return Objects.equals(getId(), that.getId()) &&
Objects.equals(getType(), that.getType()) &&
return Objects.equals(getType(), that.getType()) &&
Objects.equals(getItems(), that.getItems()) &&
Objects.equals(getEnums(), that.getEnums()) &&
Objects.equals(get$ref(), that.get$ref()) &&
Objects.equals(getProperties(), that.getProperties());
}
@Override
public int hashCode() {
return Objects.hash(getId(), getType(), getItems(), getEnums(), get$ref(), getProperties());
return Objects.hash(getType(), getItems(), getEnums(), getProperties());
}
}

View File

@ -16,9 +16,13 @@
*/
package org.apache.dubbo.metadata.definition.util;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;
@ -106,6 +110,57 @@ public final class ClassUtils {
return result;
}
public static String getCanonicalNameForParameterizedType(ParameterizedType parameterizedType) {
StringBuilder sb = new StringBuilder();
Type ownerType = parameterizedType.getOwnerType();
Class<?> rawType = (Class) parameterizedType.getRawType();
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
if (ownerType != null) {
if (ownerType instanceof Class) {
sb.append(((Class) ownerType).getName());
} else {
sb.append(ownerType.toString());
}
sb.append(".");
if (ownerType instanceof ParameterizedTypeImpl) {
// Find simple name of nested type by removing the
// shared prefix with owner.
sb.append(rawType.getName().replace(((Class) ((ParameterizedType) ownerType).getRawType()).getName() + "$",
""));
} else {
sb.append(rawType.getSimpleName());
}
} else {
sb.append(rawType.getCanonicalName());
}
if (actualTypeArguments != null &&
actualTypeArguments.length > 0) {
sb.append("<");
boolean first = true;
for (Type t : actualTypeArguments) {
if (!first) {
sb.append(", ");
}
if (t instanceof Class) {
Class c = (Class) t;
sb.append(c.getCanonicalName());
} else if (t instanceof ParameterizedType) {
sb.append(getCanonicalNameForParameterizedType((ParameterizedType) t));
} else {
sb.append(t.toString());
}
first = false;
}
sb.append(">");
}
return sb.toString();
}
private ClassUtils() {
}
}

View File

@ -68,6 +68,7 @@ public class DefaultValueParameterProcessor extends AbstractAnnotatedMethodParam
}
}
@Override
public int getPriority() {
return MIN_PRIORITY;
}

View File

@ -16,10 +16,6 @@
*/
package org.apache.dubbo.metadata.definition;
import org.apache.dubbo.metadata.definition.builder.CollectionTypeBuilder;
import org.apache.dubbo.metadata.definition.builder.DefaultTypeBuilder;
import org.apache.dubbo.metadata.definition.builder.EnumTypeBuilder;
import org.apache.dubbo.metadata.definition.builder.MapTypeBuilder;
import org.apache.dubbo.metadata.definition.common.ClassExtendsMap;
import org.apache.dubbo.metadata.definition.common.ColorEnum;
import org.apache.dubbo.metadata.definition.common.OuterClass;
@ -40,6 +36,7 @@ import org.junit.jupiter.api.Test;
public class MetadataTest {
/**
*
*/
@Test
public void testInnerClassType() {
@ -47,10 +44,9 @@ public class MetadataTest {
TypeDefinition td = builder.build(OuterClass.InnerClass.class, OuterClass.InnerClass.class);
System.out.println(">> testInnerClassType: " + new Gson().toJson(td));
Assertions.assertEquals("org.apache.dubbo.metadata.definition.common.OuterClass$InnerClass", td.getType());
Assertions.assertEquals("org.apache.dubbo.metadata.definition.common.OuterClass.InnerClass", td.getType());
Assertions.assertEquals(1, td.getProperties().size());
Assertions.assertNotNull(td.getProperties().get("name"));
Assertions.assertEquals(DefaultTypeBuilder.class.getName(), td.getTypeBuilderName());
ServiceDefinition sd = MetadataUtils.generateMetadata(TestService.class);
System.out.println(">> testInnerClassType: " + new Gson().toJson(sd));
@ -58,7 +54,7 @@ public class MetadataTest {
Assertions.assertEquals(TestService.class.getMethods().length, sd.getMethods().size());
boolean containsType = false;
for (TypeDefinition type : sd.getTypes()) {
if (type.getType().equals("org.apache.dubbo.metadata.definition.common.OuterClass$InnerClass")) {
if (type.getType().equals("org.apache.dubbo.metadata.definition.common.OuterClass.InnerClass")) {
containsType = true;
break;
}
@ -76,10 +72,8 @@ public class MetadataTest {
Assertions.assertEquals("org.apache.dubbo.metadata.definition.common.ResultWithRawCollections", td.getType());
Assertions.assertEquals(2, td.getProperties().size());
Assertions.assertEquals("java.util.Map", td.getProperties().get("map").getType());
Assertions.assertEquals(MapTypeBuilder.class.getName(), td.getProperties().get("map").getTypeBuilderName());
Assertions.assertEquals("java.util.List", td.getProperties().get("list").getType());
Assertions.assertEquals(CollectionTypeBuilder.class.getName(), td.getProperties().get("list").getTypeBuilderName());
Assertions.assertEquals("java.util.Map", td.getProperties().get("map"));
Assertions.assertEquals("java.util.List", td.getProperties().get("list"));
ServiceDefinition sd = MetadataUtils.generateMetadata(TestService.class);
System.out.println(">> testRawMap: " + new Gson().toJson(sd));
@ -103,7 +97,6 @@ public class MetadataTest {
System.out.println(">> testEnum: " + new Gson().toJson(td));
Assertions.assertEquals("org.apache.dubbo.metadata.definition.common.ColorEnum", td.getType());
Assertions.assertEquals(EnumTypeBuilder.class.getName(), td.getTypeBuilderName());
Assertions.assertEquals(3, td.getEnums().size());
Assertions.assertTrue(td.getEnums().contains("RED"));
Assertions.assertTrue(td.getEnums().contains("YELLOW"));
@ -131,7 +124,6 @@ public class MetadataTest {
System.out.println(">> testExtendsMap: " + new Gson().toJson(td));
Assertions.assertEquals("org.apache.dubbo.metadata.definition.common.ClassExtendsMap", td.getType());
Assertions.assertEquals(MapTypeBuilder.class.getName(), td.getTypeBuilderName());
Assertions.assertEquals(0, td.getProperties().size());
ServiceDefinition sd = MetadataUtils.generateMetadata(TestService.class);

View File

@ -21,7 +21,6 @@ import org.apache.dubbo.metadata.definition.model.MethodDefinition;
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import org.apache.dubbo.metadata.definition.service.ComplexObject;
import org.apache.dubbo.metadata.definition.service.DemoService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -58,41 +57,44 @@ public class ServiceDefinitionBuilderTest {
String[].class.getCanonicalName(), "java.util.List<java.lang.Integer>", ComplexObject.TestEnum.class.getCanonicalName()}));
Assertions.assertEquals(findComplexObject.getReturnType(), ComplexObject.class.getCanonicalName());
List<TypeDefinition> typeDefinitions = fullServiceDefinition.getTypes();
TypeDefinition topTypeDefinition = null;
TypeDefinition innerTypeDefinition = null;
TypeDefinition inner2TypeDefinition = null;
TypeDefinition inner3TypeDefinition = null;
TypeDefinition listTypeDefinition = null;
for (TypeDefinition typeDefinition : typeDefinitions) {
if (typeDefinition.getType().equals(ComplexObject.class.getName())) {
if (typeDefinition.getType().equals(ComplexObject.class.getCanonicalName())) {
topTypeDefinition = typeDefinition;
} else if (typeDefinition.getType().equals(ComplexObject.InnerObject.class.getName())) {
} else if (typeDefinition.getType().equals(ComplexObject.InnerObject.class.getCanonicalName())) {
innerTypeDefinition = typeDefinition;
} else if (typeDefinition.getType().contains(ComplexObject.InnerObject2.class.getName())) {
} else if (typeDefinition.getType().equals(ComplexObject.InnerObject2.class.getCanonicalName())) {
inner2TypeDefinition = typeDefinition;
} else if (typeDefinition.getType().equals(ComplexObject.InnerObject3.class.getName())) {
} else if (typeDefinition.getType().equals(ComplexObject.InnerObject3.class.getCanonicalName())) {
inner3TypeDefinition = typeDefinition;
} else if (typeDefinition.getType().equals("java.util.List<java.lang.Integer>")) {
listTypeDefinition = typeDefinition;
}
}
Assertions.assertEquals(topTypeDefinition.getProperties().get("v").getType(), "long");
Assertions.assertEquals(topTypeDefinition.getProperties().get("maps").getType(), "java.util.Map<java.lang.String,java.lang.String>");
Assertions.assertEquals(topTypeDefinition.getProperties().get("innerObject").getType(), ComplexObject.InnerObject.class.getName());
Assertions.assertEquals(topTypeDefinition.getProperties().get("intList").getType(), "java.util.List<java.lang.Integer>");
Assertions.assertEquals(topTypeDefinition.getProperties().get("strArrays").getType(), "java.lang.String[]");
Assertions.assertEquals(topTypeDefinition.getProperties().get("innerObject3").getType(), "org.apache.dubbo.metadata.definition.service.ComplexObject.InnerObject3[]");
Assertions.assertEquals(topTypeDefinition.getProperties().get("testEnum").getType(), "org.apache.dubbo.metadata.definition.service.ComplexObject.TestEnum");
Assertions.assertEquals(topTypeDefinition.getProperties().get("innerObject2").getType(), "java.util.Set<org.apache.dubbo.metadata.definition.service.ComplexObject$InnerObject2>");
Assertions.assertEquals("long", topTypeDefinition.getProperties().get("v"));
Assertions.assertEquals("java.util.Map<java.lang.String,java.lang.String>", topTypeDefinition.getProperties().get("maps"));
Assertions.assertEquals(ComplexObject.InnerObject.class.getCanonicalName(), topTypeDefinition.getProperties().get("innerObject"));
Assertions.assertEquals("java.util.List<java.lang.Integer>", topTypeDefinition.getProperties().get("intList"));
Assertions.assertEquals("java.lang.String[]", topTypeDefinition.getProperties().get("strArrays"));
Assertions.assertEquals("org.apache.dubbo.metadata.definition.service.ComplexObject.InnerObject3[]", topTypeDefinition.getProperties().get("innerObject3"));
Assertions.assertEquals("org.apache.dubbo.metadata.definition.service.ComplexObject.TestEnum", topTypeDefinition.getProperties().get("testEnum"));
Assertions.assertEquals("java.util.Set<org.apache.dubbo.metadata.definition.service.ComplexObject.InnerObject2>", topTypeDefinition.getProperties().get("innerObject2"));
Assertions.assertSame(innerTypeDefinition.getProperties().get("innerA").getType(), "java.lang.String");
Assertions.assertSame(innerTypeDefinition.getProperties().get("innerB").getType(), "int");
Assertions.assertSame("java.lang.String", innerTypeDefinition.getProperties().get("innerA"));
Assertions.assertSame("int", innerTypeDefinition.getProperties().get("innerB"));
Assertions.assertSame(inner2TypeDefinition.getProperties().get("innerA2").getType(), "java.lang.String");
Assertions.assertSame(inner2TypeDefinition.getProperties().get("innerB2").getType(), "int");
Assertions.assertSame("java.lang.String", inner2TypeDefinition.getProperties().get("innerA2"));
Assertions.assertSame("int", inner2TypeDefinition.getProperties().get("innerB2"));
Assertions.assertSame(inner3TypeDefinition.getProperties().get("innerA3").getType(), "java.lang.String");
Assertions.assertSame("java.lang.String", inner3TypeDefinition.getProperties().get("innerA3"));
Assertions.assertEquals(Integer.class.getCanonicalName(), listTypeDefinition.getItems().get(0));
}
}

View File

@ -27,6 +27,7 @@ import java.util.Map;
*/
public class Test3TypeBuilder implements TypeBuilder {
// it is smaller than the implements of TypeBuilder
@Override
public int getPriority(){
return 10;
}
@ -37,7 +38,7 @@ public class Test3TypeBuilder implements TypeBuilder {
}
@Override
public TypeDefinition build(Type type, Class<?> clazz, Map<Class<?>, TypeDefinition> typeCache) {
public TypeDefinition build(Type type, Class<?> clazz, Map<String, TypeDefinition> typeCache) {
return null;
}
}

View File

@ -27,6 +27,7 @@ import java.util.Map;
*/
public class TestTypeBuilder implements TypeBuilder {
// it is smaller than the implements of TypeBuilder
@Override
public int getPriority(){
return -3;
}
@ -37,7 +38,7 @@ public class TestTypeBuilder implements TypeBuilder {
}
@Override
public TypeDefinition build(Type type, Class<?> clazz, Map<Class<?>, TypeDefinition> typeCache) {
public TypeDefinition build(Type type, Class<?> clazz, Map<String, TypeDefinition> typeCache) {
return null;
}
}

View File

@ -16,17 +16,17 @@
*/
package org.apache.dubbo.metadata.definition.protobuf;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.metadata.definition.TypeDefinitionBuilder;
import org.apache.dubbo.metadata.definition.builder.TypeBuilder;
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import com.google.protobuf.ByteString;
import com.google.protobuf.Descriptors;
import com.google.protobuf.GeneratedMessageV3;
import com.google.protobuf.ProtocolStringList;
import com.google.protobuf.UnknownFieldSet;
import org.apache.dubbo.common.lang.Prioritized;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.metadata.definition.TypeDefinitionBuilder;
import org.apache.dubbo.metadata.definition.builder.TypeBuilder;
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
@ -36,7 +36,7 @@ import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ProtobufTypeBuilder implements TypeBuilder {
public class ProtobufTypeBuilder implements TypeBuilder, Prioritized {
private final Logger logger = LoggerFactory.getLogger(getClass());
private static final Pattern MAP_PATTERN = Pattern.compile("^java\\.util\\.Map<(\\S+), (\\S+)>$");
private static final Pattern LIST_PATTERN = Pattern.compile("^java\\.util\\.List<(\\S+)>$");
@ -55,6 +55,11 @@ public class ProtobufTypeBuilder implements TypeBuilder {
}
}
@Override
public int getPriority() {
return -1;
}
@Override
public boolean accept(Type type, Class<?> clazz) {
if (clazz == null) {
@ -65,11 +70,16 @@ public class ProtobufTypeBuilder implements TypeBuilder {
}
@Override
public TypeDefinition build(Type type, Class<?> clazz, Map<Class<?>, TypeDefinition> typeCache) {
TypeDefinition typeDefinition = new TypeDefinition(clazz.getName());
public TypeDefinition build(Type type, Class<?> clazz, Map<String, TypeDefinition> typeCache) {
String canonicalName = clazz.getCanonicalName();
TypeDefinition typeDefinition = typeCache.get(canonicalName);
if (typeDefinition != null) {
return typeDefinition;
}
try {
GeneratedMessageV3.Builder builder = getMessageBuilder(clazz);
typeDefinition = buildProtobufTypeDefinition(clazz, builder, typeCache);
typeCache.put(canonicalName, typeDefinition);
} catch (Exception e) {
logger.info("TypeDefinition build failed.", e);
}
@ -82,48 +92,50 @@ public class ProtobufTypeBuilder implements TypeBuilder {
return (GeneratedMessageV3.Builder) method.invoke(null, null);
}
private TypeDefinition buildProtobufTypeDefinition(Class<?> clazz, GeneratedMessageV3.Builder builder, Map<Class<?>, TypeDefinition> typeCache) {
TypeDefinition typeDefinition = new TypeDefinition(clazz.getName());
private TypeDefinition buildProtobufTypeDefinition(Class<?> clazz, GeneratedMessageV3.Builder builder, Map<String, TypeDefinition> typeCache) {
String canonicalName = clazz.getCanonicalName();
TypeDefinition td = new TypeDefinition(canonicalName);
if (builder == null) {
return typeDefinition;
return td;
}
Map<String, TypeDefinition> properties = new HashMap<>();
Map<String, String> properties = new HashMap<>();
Method[] methods = builder.getClass().getDeclaredMethods();
for (Method method : methods) {
String methodName = method.getName();
if (isSimplePropertySettingMethod(method)) {
// property of custom type or primitive type
properties.put(generateSimpleFiledName(methodName), TypeDefinitionBuilder.build(method.getGenericParameterTypes()[0], method.getParameterTypes()[0], typeCache));
TypeDefinition fieldTd = TypeDefinitionBuilder.build(method.getGenericParameterTypes()[0], method.getParameterTypes()[0], typeCache);
properties.put(generateSimpleFiledName(methodName), fieldTd.getType());
} else if (isMapPropertySettingMethod(method)) {
// property of map
Type type = method.getGenericParameterTypes()[0];
String fieldName = generateMapFieldName(methodName);
validateMapType(fieldName, type.toString());
properties.put(fieldName, TypeDefinitionBuilder.build(type, method.getParameterTypes()[0], typeCache));
TypeDefinition fieldTd = TypeDefinitionBuilder.build(type, method.getParameterTypes()[0], typeCache);
properties.put(fieldName, fieldTd.getType());
} else if (isListPropertyGettingMethod(method)) {
// property of list
Type type = method.getGenericReturnType();
String fieldName = generateListFieldName(methodName);
TypeDefinition td;
TypeDefinition fieldTd;
if (ProtocolStringList.class.isAssignableFrom(method.getReturnType())) {
// property defined as "repeated string" transform to ProtocolStringList,
// should be build as List<String>.
td = TypeDefinitionBuilder.build(STRING_LIST_TYPE, List.class, typeCache);
fieldTd = TypeDefinitionBuilder.build(STRING_LIST_TYPE, List.class, typeCache);
} else {
// property without generic type should not be build ex method return List
if (!LIST_PATTERN.matcher(type.toString()).matches()) {
continue;
}
td = TypeDefinitionBuilder.build(type, method.getReturnType(), typeCache);
fieldTd = TypeDefinitionBuilder.build(type, method.getReturnType(), typeCache);
}
properties.put(fieldName, td);
properties.put(fieldName, fieldTd.getType());
}
}
typeDefinition.setProperties(properties);
typeCache.put(clazz, typeDefinition);
return typeDefinition;
td.setProperties(properties);
return td;
}
/**

View File

@ -21,9 +21,9 @@ import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
import org.apache.dubbo.metadata.definition.model.MethodDefinition;
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import org.apache.dubbo.metadata.definition.protobuf.model.ServiceInterface;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.Map;
import static org.hamcrest.CoreMatchers.equalTo;
@ -39,6 +39,7 @@ public class ProtobufTypeBuilderTest {
// TEST Pb Service metaData builder
FullServiceDefinition serviceDefinition = ServiceDefinitionBuilder.buildFullDefinition(ServiceInterface.class);
MethodDefinition methodDefinition = serviceDefinition.getMethods().get(0);
List<TypeDefinition> types = serviceDefinition.getTypes();
String parameterName = methodDefinition.getParameterTypes()[0];
TypeDefinition typeDefinition = null;
for (TypeDefinition type : serviceDefinition.getTypes()) {
@ -47,27 +48,41 @@ public class ProtobufTypeBuilderTest {
break;
}
}
Map<String, TypeDefinition> propertiesMap = typeDefinition.getProperties();
Map<String, String> propertiesMap = typeDefinition.getProperties();
assertThat(propertiesMap.size(), is(11));
assertThat(propertiesMap.containsKey("money"), is(true));
assertThat(propertiesMap.get("money").getType(), equalTo("double"));
assertThat(getTypeName(propertiesMap.get("money"), types), equalTo("double"));
assertThat(propertiesMap.containsKey("cash"), is(true));
assertThat(propertiesMap.get("cash").getType(), equalTo("float"));
assertThat(getTypeName(propertiesMap.get("cash"), types), equalTo("float"));
assertThat(propertiesMap.containsKey("age"), is(true));
assertThat(propertiesMap.get("age").getType(), equalTo("int"));
assertThat(getTypeName(propertiesMap.get("age"), types), equalTo("int"));
assertThat(propertiesMap.containsKey("num"), is(true));
assertThat(propertiesMap.get("num").getType(), equalTo("long"));
assertThat(getTypeName(propertiesMap.get("num"), types), equalTo("long"));
assertThat(propertiesMap.containsKey("sex"), is(true));
assertThat(propertiesMap.get("sex").getType(), equalTo("boolean"));
assertThat(getTypeName(propertiesMap.get("sex"), types), equalTo("boolean"));
assertThat(propertiesMap.containsKey("name"), is(true));
assertThat(propertiesMap.get("name").getType(), equalTo("java.lang.String"));
assertThat(getTypeName(propertiesMap.get("name"), types), equalTo("java.lang.String"));
assertThat(propertiesMap.containsKey("msg"), is(true));
assertThat(propertiesMap.get("msg").getType(), equalTo("com.google.protobuf.ByteString"));
assertThat(getTypeName(propertiesMap.get("msg"), types),
equalTo("com.google.protobuf.ByteString"));
assertThat(propertiesMap.containsKey("phone"), is(true));
assertThat(propertiesMap.get("phone").getType(), equalTo("java.util.List<org.apache.dubbo.metadata.definition.protobuf.model.GooglePB$PhoneNumber>"));
assertThat(getTypeName(propertiesMap.get("phone"), types),
equalTo("java.util.List<org.apache.dubbo.metadata.definition.protobuf.model.GooglePB.PhoneNumber>"));
assertThat(propertiesMap.containsKey("doubleMap"), is(true));
assertThat(propertiesMap.get("doubleMap").getType(), equalTo("java.util.Map<java.lang.String,org.apache.dubbo.metadata.definition.protobuf.model.GooglePB$PhoneNumber>"));
assertThat(propertiesMap.get("bytesList").getType(), equalTo("java.util.List<com.google.protobuf.ByteString>"));
assertThat(propertiesMap.get("bytesMap").getType(), equalTo("java.util.Map<java.lang.String,com.google.protobuf.ByteString>"));
assertThat(getTypeName(propertiesMap.get("doubleMap"), types),
equalTo("java.util.Map<java.lang.String,org.apache.dubbo.metadata.definition.protobuf.model.GooglePB.PhoneNumber>"));
assertThat(getTypeName(propertiesMap.get("bytesList"), types),
equalTo("java.util.List<com.google.protobuf.ByteString>"));
assertThat(getTypeName(propertiesMap.get("bytesMap"), types),
equalTo("java.util.Map<java.lang.String,com.google.protobuf.ByteString>"));
}
private static String getTypeName(String type, List<TypeDefinition> types) {
for (TypeDefinition typeDefinition : types) {
if (type.equals(typeDefinition.getType())) {
return typeDefinition.getType();
}
}
return type;
}
}

View File

@ -22,15 +22,16 @@ import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.TypeMirror;
import java.lang.reflect.Array;
import java.util.Map;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isArrayType;
/**
* {@link TypeDefinitionBuilder} for Java {@link Array}
* {@link TypeBuilder} for Java {@link Array}
*
* @since 2.7.6
*/
public class ArrayTypeDefinitionBuilder implements TypeDefinitionBuilder<ArrayType> {
public class ArrayTypeDefinitionBuilder implements TypeBuilder<ArrayType> {
@Override
public boolean accept(ProcessingEnvironment processingEnv, TypeMirror type) {
@ -38,9 +39,13 @@ public class ArrayTypeDefinitionBuilder implements TypeDefinitionBuilder<ArrayTy
}
@Override
public void build(ProcessingEnvironment processingEnv, ArrayType type, TypeDefinition typeDefinition) {
public TypeDefinition build(ProcessingEnvironment processingEnv, ArrayType type, Map<String, TypeDefinition> typeCache) {
TypeDefinition typeDefinition = new TypeDefinition(type.toString());
TypeMirror componentType = type.getComponentType();
typeDefinition.getItems().add(TypeDefinitionBuilder.build(processingEnv, componentType));
TypeDefinition subTypeDefinition = TypeDefinitionBuilder.build(processingEnv, componentType, typeCache);
typeDefinition.getItems()
.add(subTypeDefinition.getType());
return typeDefinition;
}
@Override

View File

@ -25,10 +25,11 @@ import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
/**
* {@link TypeDefinitionBuilder} for Java {@link Collection}
* {@link TypeBuilder} for Java {@link Collection}
*
* @since 2.7.6
*/
@ -45,13 +46,17 @@ public class CollectionTypeDefinitionBuilder implements DeclaredTypeDefinitionBu
}
@Override
public void build(ProcessingEnvironment processingEnv, DeclaredType type, TypeDefinition typeDefinition) {
public TypeDefinition build(ProcessingEnvironment processingEnv, DeclaredType type, Map<String, TypeDefinition> typeCache) {
String typeName = type.toString();
TypeDefinition typeDefinition = new TypeDefinition(typeName);
// Generic Type arguments
type.getTypeArguments()
.stream()
.map(typeArgument -> TypeDefinitionBuilder.build(processingEnv, typeArgument)) // build the TypeDefinition from typeArgument
.map(typeArgument -> TypeDefinitionBuilder.build(processingEnv, typeArgument, typeCache)) // build the TypeDefinition from typeArgument
.filter(Objects::nonNull)
.map(TypeDefinition::getType)
.forEach(typeDefinition.getItems()::add); // Add into the declared TypeDefinition
return typeDefinition;
}
@Override

View File

@ -23,11 +23,11 @@ import javax.lang.model.type.TypeMirror;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.ofDeclaredType;
/**
* An interface of {@link TypeDefinitionBuilder} for {@link DeclaredType}
* An interface of {@link TypeBuilder} for {@link DeclaredType}
*
* @since 2.7.6
*/
public interface DeclaredTypeDefinitionBuilder extends TypeDefinitionBuilder<DeclaredType> {
public interface DeclaredTypeDefinitionBuilder extends TypeBuilder<DeclaredType> {
@Override
default boolean accept(ProcessingEnvironment processingEnv, TypeMirror type) {

View File

@ -24,11 +24,13 @@ import javax.lang.model.element.Element;
import javax.lang.model.element.Name;
import javax.lang.model.type.DeclaredType;
import java.util.Map;
import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.getDeclaredFields;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isEnumType;
/**
* {@link TypeDefinitionBuilder} for Java {@link Enum}
* {@link TypeBuilder} for Java {@link Enum}
*
* @since 2.7.6
*/
@ -40,12 +42,14 @@ public class EnumTypeDefinitionBuilder implements DeclaredTypeDefinitionBuilder
}
@Override
public void build(ProcessingEnvironment processingEnv, DeclaredType type, TypeDefinition typeDefinition) {
public TypeDefinition build(ProcessingEnvironment processingEnv, DeclaredType type, Map<String, TypeDefinition> typeCache) {
TypeDefinition typeDefinition = new TypeDefinition(type.toString());
getDeclaredFields(type, FieldUtils::isEnumMemberField)
.stream()
.map(Element::getSimpleName)
.map(Name::toString)
.forEach(typeDefinition.getEnums()::add);
return typeDefinition;
}
@Override

View File

@ -22,12 +22,14 @@ import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import java.util.Map;
import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.getNonStaticFields;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getType;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isClassType;
/**
* {@link TypeDefinitionBuilder} for General Object
* {@link TypeBuilder} for General Object
*
* @since 2.7.6
*/
@ -39,23 +41,26 @@ public class GeneralTypeDefinitionBuilder implements DeclaredTypeDefinitionBuild
}
@Override
public void build(ProcessingEnvironment processingEnv, DeclaredType type, TypeDefinition typeDefinition) {
public TypeDefinition build(ProcessingEnvironment processingEnv, DeclaredType type, Map<String, TypeDefinition> typeCache) {
String typeName = type.toString();
TypeElement typeElement = getType(processingEnv, typeName);
buildProperties(processingEnv, typeElement, typeDefinition);
return buildProperties(processingEnv, typeElement, typeCache);
}
protected void buildProperties(ProcessingEnvironment processingEnv, TypeElement type, TypeDefinition definition) {
protected TypeDefinition buildProperties(ProcessingEnvironment processingEnv, TypeElement type, Map<String, TypeDefinition> typeCache) {
TypeDefinition definition = new TypeDefinition(type.toString());
getNonStaticFields(type).forEach(field -> {
String fieldName = field.getSimpleName().toString();
TypeDefinition propertyType = TypeDefinitionBuilder.build(processingEnv, field);
TypeDefinition propertyType = TypeDefinitionBuilder.build(processingEnv, field, typeCache);
if (propertyType != null) {
definition.getProperties().put(fieldName, propertyType);
typeCache.put(propertyType.getType(), propertyType);
definition.getProperties().put(fieldName, propertyType.getType());
}
});
return definition;
}
@Override

View File

@ -28,7 +28,7 @@ import java.util.Map;
import java.util.Objects;
/**
* {@link TypeDefinitionBuilder} for Java {@link Map}
* {@link TypeBuilder} for Java {@link Map}
*
* @since 2.7.6
*/
@ -45,14 +45,16 @@ public class MapTypeDefinitionBuilder implements DeclaredTypeDefinitionBuilder {
}
@Override
public void build(ProcessingEnvironment processingEnv, DeclaredType type, TypeDefinition typeDefinition) {
public TypeDefinition build(ProcessingEnvironment processingEnv, DeclaredType type, Map<String, TypeDefinition> typeCache) {
TypeDefinition typeDefinition = new TypeDefinition(type.toString());
// Generic Type arguments
type.getTypeArguments()
.stream()
.map(typeArgument -> TypeDefinitionBuilder.build(processingEnv, typeArgument)) // build the TypeDefinition from typeArgument
.map(typeArgument -> TypeDefinitionBuilder.build(processingEnv, typeArgument, typeCache)) // build the TypeDefinition from typeArgument
.filter(Objects::nonNull)
.map(TypeDefinition::getType)
.forEach(typeDefinition.getItems()::add); // Add into the declared TypeDefinition
return typeDefinition;
}
@Override

View File

@ -22,6 +22,7 @@ import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.ExecutableElement;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getMethodName;
@ -36,18 +37,18 @@ import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.g
*/
public interface MethodDefinitionBuilder {
static MethodDefinition build(ProcessingEnvironment processingEnv, ExecutableElement method) {
static MethodDefinition build(ProcessingEnvironment processingEnv, ExecutableElement method, Map<String, TypeDefinition> typeCache) {
MethodDefinition methodDefinition = new MethodDefinition();
methodDefinition.setName(getMethodName(method));
methodDefinition.setReturnType(getReturnType(method));
methodDefinition.setParameterTypes(getMethodParameterTypes(method));
methodDefinition.setParameters(getMethodParameters(processingEnv, method));
methodDefinition.setParameters(getMethodParameters(processingEnv, method, typeCache));
return methodDefinition;
}
static List<TypeDefinition> getMethodParameters(ProcessingEnvironment processingEnv, ExecutableElement method) {
static List<TypeDefinition> getMethodParameters(ProcessingEnvironment processingEnv, ExecutableElement method, Map<String, TypeDefinition> typeCache) {
return method.getParameters().stream()
.map(element -> TypeDefinitionBuilder.build(processingEnv, element))
.map(element -> TypeDefinitionBuilder.build(processingEnv, element, typeCache))
.collect(Collectors.toList());
}
}

View File

@ -22,14 +22,16 @@ import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeMirror;
import java.util.Map;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isPrimitiveType;
/**
* {@link TypeDefinitionBuilder} for Java {@link PrimitiveType primitve type}
* {@link TypeBuilder} for Java {@link PrimitiveType primitve type}
*
* @since 2.7.6
*/
public class PrimitiveTypeDefinitionBuilder implements TypeDefinitionBuilder<PrimitiveType> {
public class PrimitiveTypeDefinitionBuilder implements TypeBuilder<PrimitiveType> {
@Override
public boolean accept(ProcessingEnvironment processingEnv, TypeMirror type) {
@ -37,8 +39,9 @@ public class PrimitiveTypeDefinitionBuilder implements TypeDefinitionBuilder<Pri
}
@Override
public void build(ProcessingEnvironment processingEnv, PrimitiveType type, TypeDefinition typeDefinition) {
// DO NOTHING
public TypeDefinition build(ProcessingEnvironment processingEnv, PrimitiveType type, Map<String, TypeDefinition> typeCache) {
TypeDefinition typeDefinition = new TypeDefinition(type.toString());
return typeDefinition;
}
@Override

View File

@ -17,10 +17,15 @@
package org.apache.dubbo.metadata.annotation.processing.builder;
import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.TypeElement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getPublicNonStaticMethods;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getHierarchicalTypes;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getResourceName;
@ -38,19 +43,21 @@ public interface ServiceDefinitionBuilder {
serviceDefinition.setCanonicalName(type.toString());
serviceDefinition.setCodeSource(getResourceName(type.toString()));
Map<String, TypeDefinition> types = new HashMap<>();
// Get all super types and interface excluding the specified type
// and then the result will be added into ServiceDefinition#getTypes()
getHierarchicalTypes(type.asType(), Object.class)
.stream()
.map(t -> TypeDefinitionBuilder.build(processingEnv, t))
.forEach(serviceDefinition.getTypes()::add);
.forEach(t -> TypeDefinitionBuilder.build(processingEnv, t, types));
// Get all declared methods that will be added into ServiceDefinition#getMethods()
getPublicNonStaticMethods(type, Object.class)
.stream()
.map(method -> MethodDefinitionBuilder.build(processingEnv, method))
.map(method -> MethodDefinitionBuilder.build(processingEnv, method, types))
.forEach(serviceDefinition.getMethods()::add);
serviceDefinition.setTypes(new ArrayList<>(types.values()));
return serviceDefinition;
}
}

View File

@ -22,11 +22,13 @@ import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.type.DeclaredType;
import java.util.Map;
import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isSimpleType;
/**
* {@link TypeDefinitionBuilder} for {@link TypeUtils#SIMPLE_TYPES Java Simple Type}
* {@link TypeBuilder} for {@link TypeUtils#SIMPLE_TYPES Java Simple Type}
*
* @since 2.7.6
*/
@ -38,8 +40,9 @@ public class SimpleTypeDefinitionBuilder implements DeclaredTypeDefinitionBuilde
}
@Override
public void build(ProcessingEnvironment processingEnv, DeclaredType type, TypeDefinition typeDefinition) {
// DO NOTHING
public TypeDefinition build(ProcessingEnvironment processingEnv, DeclaredType type, Map<String, TypeDefinition> typeCache) {
TypeDefinition td = new TypeDefinition(type.toString());
return td;
}
@Override

View File

@ -0,0 +1,31 @@
package org.apache.dubbo.metadata.annotation.processing.builder;
import org.apache.dubbo.common.extension.SPI;
import org.apache.dubbo.common.lang.Prioritized;
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.type.TypeMirror;
import java.util.Map;
@SPI
public interface TypeBuilder<T extends TypeMirror> extends Prioritized {
/**
* Test the specified {@link TypeMirror type} is accepted or not
*
* @param processingEnv {@link ProcessingEnvironment}
* @param type {@link TypeMirror type}
* @return <code>true</code> if accepted
*/
boolean accept(ProcessingEnvironment processingEnv, TypeMirror type);
/**
* Build the instance of {@link TypeDefinition}
*
* @param processingEnv {@link ProcessingEnvironment}
* @param type {@link T type}
* @return an instance of {@link TypeDefinition}
*/
TypeDefinition build(ProcessingEnvironment processingEnv, T type, Map<String, TypeDefinition> typeCache);
}

View File

@ -16,13 +16,14 @@
*/
package org.apache.dubbo.metadata.annotation.processing.builder;
import org.apache.dubbo.common.extension.SPI;
import org.apache.dubbo.common.lang.Prioritized;
import org.apache.dubbo.metadata.annotation.processing.builder.TypeBuilder;
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.type.TypeMirror;
import java.util.Map;
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
@ -31,28 +32,8 @@ import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoad
*
* @since 2.7.6
*/
@SPI
public interface TypeDefinitionBuilder<T extends TypeMirror> extends Prioritized {
/**
* Test the specified {@link TypeMirror type} is accepted or not
*
* @param processingEnv {@link ProcessingEnvironment}
* @param type {@link TypeMirror type}
* @return <code>true</code> if accepted
*/
boolean accept(ProcessingEnvironment processingEnv, TypeMirror type);
/**
* Build the instance of {@link TypeDefinition}
*
* @param processingEnv {@link ProcessingEnvironment}
* @param type {@link T type}
* @param typeDefinition {@link TypeDefinition} to be built
* @return an instance of {@link TypeDefinition}
*/
void build(ProcessingEnvironment processingEnv, T type, TypeDefinition typeDefinition);
/**
* Build the instance of {@link TypeDefinition} from the specified {@link Element element}
*
@ -60,8 +41,8 @@ public interface TypeDefinitionBuilder<T extends TypeMirror> extends Prioritized
* @param element {@link Element source element}
* @return non-null
*/
static TypeDefinition build(ProcessingEnvironment processingEnv, Element element) {
TypeDefinition typeDefinition = build(processingEnv, element.asType());
static TypeDefinition build(ProcessingEnvironment processingEnv, Element element, Map<String, TypeDefinition> typeCache) {
TypeDefinition typeDefinition = build(processingEnv, element.asType(), typeCache);
// Comment this code for the compatibility
// typeDefinition.set$ref(element.toString());
return typeDefinition;
@ -74,23 +55,23 @@ public interface TypeDefinitionBuilder<T extends TypeMirror> extends Prioritized
* @param type {@link TypeMirror type}
* @return non-null
*/
static TypeDefinition build(ProcessingEnvironment processingEnv, TypeMirror type) {
String typeName = type.toString();
TypeDefinition typeDefinition = new TypeDefinition(typeName);
static TypeDefinition build(ProcessingEnvironment processingEnv, TypeMirror type, Map<String, TypeDefinition> typeCache) {
// Build by all instances of TypeDefinitionBuilder that were loaded By Java SPI
getExtensionLoader(TypeDefinitionBuilder.class)
TypeDefinition typeDefinition = getExtensionLoader(TypeBuilder.class)
.getSupportedExtensionInstances()
.stream()
// load(TypeDefinitionBuilder.class, TypeDefinitionBuilder.class.getClassLoader())
.filter(builder -> builder.accept(processingEnv, type))
.findFirst()
.ifPresent(builder -> {
builder.build(processingEnv, type, typeDefinition);
.map(builder -> {
return builder.build(processingEnv, type, typeCache);
// typeDefinition.setTypeBuilderName(builder.getClass().getName());
});
}).orElse(null);
if (typeDefinition != null) {
typeCache.put(typeDefinition.getType(), typeDefinition);
}
return typeDefinition;
}
}

View File

@ -215,7 +215,7 @@ public abstract class AbstractServiceRestMetadataResolver implements ServiceRest
protected MethodDefinition resolveMethodDefinition(ProcessingEnvironment processingEnv, TypeElement serviceType,
ExecutableElement method) {
return build(processingEnv, method);
return build(processingEnv, method, new HashMap<>());
}
protected void processAnnotatedMethodParameters(ExecutableElement method, TypeElement type,

View File

@ -69,6 +69,7 @@ public class DefaultValueParameterProcessor extends AbstractAnnotatedMethodParam
}
}
@Override
public int getPriority() {
return MIN_PRIORITY;
}

View File

@ -26,6 +26,8 @@ import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.stream.Stream;
@ -108,10 +110,12 @@ public class ArrayTypeDefinitionBuilderTest extends AbstractAnnotationProcessing
}
static void buildAndAssertTypeDefinition(ProcessingEnvironment processingEnv, VariableElement field,
String expectedType, String compositeType, TypeDefinitionBuilder builder,
String expectedType, String compositeType, TypeBuilder builder,
BiConsumer<TypeDefinition, TypeDefinition>... assertions) {
TypeDefinition typeDefinition = TypeDefinitionBuilder.build(processingEnv, field);
TypeDefinition subTypeDefinition = typeDefinition.getItems().get(0);
Map<String, TypeDefinition> typeCache = new HashMap<>();
TypeDefinition typeDefinition = TypeDefinitionBuilder.build(processingEnv, field, typeCache);
String subTypeName = typeDefinition.getItems().get(0);
TypeDefinition subTypeDefinition = typeCache.get(subTypeName);
assertEquals(expectedType, typeDefinition.getType());
// assertEquals(field.getSimpleName().toString(), typeDefinition.get$ref());
assertEquals(compositeType, subTypeDefinition.getType());

View File

@ -23,10 +23,11 @@ import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import org.junit.jupiter.api.Test;
import javax.lang.model.element.TypeElement;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import static java.util.Arrays.asList;
import static org.apache.dubbo.metadata.annotation.processing.builder.TypeDefinitionBuilder.build;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -58,7 +59,8 @@ public class EnumTypeDefinitionBuilderTest extends AbstractAnnotationProcessingT
@Test
public void testBuild() {
TypeElement typeElement = getType(Color.class);
TypeDefinition typeDefinition = build(processingEnv, typeElement);
Map<String, TypeDefinition> typeCache = new HashMap<>();
TypeDefinition typeDefinition = TypeDefinitionBuilder.build(processingEnv, typeElement, typeCache);
assertEquals(Color.class.getName(), typeDefinition.getType());
assertEquals(asList("RED", "YELLOW", "BLUE"), typeDefinition.getEnums());
// assertEquals(typeDefinition.getTypeBuilderName(), builder.getClass().getName());

View File

@ -25,6 +25,8 @@ import org.junit.jupiter.api.Test;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.stream.Stream;
@ -61,11 +63,11 @@ public class MapTypeDefinitionBuilderTest extends AbstractAnnotationProcessingTe
protected void beforeEach() {
builder = new MapTypeDefinitionBuilder();
TypeElement testType = getType(MapTypeModel.class);
stringsField = findField( testType, "strings");
colorsField = findField( testType, "colors");
primitiveTypeModelsField = findField( testType, "primitiveTypeModels");
modelsField = findField( testType, "models");
modelArraysField = findField( testType, "modelArrays");
stringsField = findField(testType, "strings");
colorsField = findField(testType, "colors");
primitiveTypeModelsField = findField(testType, "primitiveTypeModels");
modelsField = findField(testType, "models");
modelArraysField = findField(testType, "modelArrays");
assertEquals("strings", stringsField.getSimpleName().toString());
assertEquals("colors", colorsField.getSimpleName().toString());
@ -119,11 +121,14 @@ public class MapTypeDefinitionBuilderTest extends AbstractAnnotationProcessingTe
static void buildAndAssertTypeDefinition(ProcessingEnvironment processingEnv, VariableElement field,
String expectedType, String keyType, String valueType,
TypeDefinitionBuilder builder,
TypeBuilder builder,
BiConsumer<TypeDefinition, TypeDefinition>... assertions) {
TypeDefinition typeDefinition = TypeDefinitionBuilder.build(processingEnv, field);
TypeDefinition keyTypeDefinition = typeDefinition.getItems().get(0);
TypeDefinition valueTypeDefinition = typeDefinition.getItems().get(1);
Map<String, TypeDefinition> typeCache = new HashMap<>();
TypeDefinition typeDefinition = TypeDefinitionBuilder.build(processingEnv, field, typeCache);
String keyTypeName = typeDefinition.getItems().get(0);
TypeDefinition keyTypeDefinition = typeCache.get(keyTypeName);
String valueTypeName = typeDefinition.getItems().get(1);
TypeDefinition valueTypeDefinition = typeCache.get(valueTypeName);
assertEquals(expectedType, typeDefinition.getType());
// assertEquals(field.getSimpleName().toString(), typeDefinition.get$ref());
assertEquals(keyType, keyTypeDefinition.getType());

View File

@ -25,6 +25,8 @@ import org.junit.jupiter.api.Test;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.findField;
@ -113,18 +115,18 @@ public class PrimitiveTypeDefinitionBuilderTest extends AbstractAnnotationProces
buildAndAssertTypeDefinition(processingEnv, dField, builder);
}
static void buildAndAssertTypeDefinition(ProcessingEnvironment processingEnv, VariableElement field, TypeDefinitionBuilder builder) {
TypeDefinition typeDefinition = TypeDefinitionBuilder.build(processingEnv, field);
static void buildAndAssertTypeDefinition(ProcessingEnvironment processingEnv, VariableElement field, TypeBuilder builder) {
Map<String, TypeDefinition> typeCache = new HashMap<>();
TypeDefinition typeDefinition = TypeDefinitionBuilder.build(processingEnv, field, typeCache);
assertBasicTypeDefinition(typeDefinition, field.asType().toString(), builder);
// assertEquals(field.getSimpleName().toString(), typeDefinition.get$ref());
}
static void assertBasicTypeDefinition(TypeDefinition typeDefinition, String type, TypeDefinitionBuilder builder) {
static void assertBasicTypeDefinition(TypeDefinition typeDefinition, String type, TypeBuilder builder) {
assertEquals(type, typeDefinition.getType());
// assertEquals(builder.getClass().getName(), typeDefinition.getTypeBuilderName());
assertTrue(typeDefinition.getProperties().isEmpty());
assertTrue(typeDefinition.getItems().isEmpty());
assertTrue(typeDefinition.getEnums().isEmpty());
assertNull(typeDefinition.getId());
}
}

View File

@ -18,10 +18,13 @@ package org.apache.dubbo.metadata.annotation.processing.builder;
import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
import org.apache.dubbo.metadata.definition.model.TypeDefinition;
import org.apache.dubbo.metadata.tools.TestServiceImpl;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import static org.apache.dubbo.metadata.annotation.processing.builder.ServiceDefinitionBuilder.build;
@ -49,16 +52,32 @@ public class ServiceDefinitionBuilderTest extends AbstractAnnotationProcessingTe
ServiceDefinition serviceDefinition = build(processingEnv, getType(TestServiceImpl.class));
assertEquals(TestServiceImpl.class.getTypeName(), serviceDefinition.getCanonicalName());
assertEquals("org/apache/dubbo/metadata/tools/TestServiceImpl.class", serviceDefinition.getCodeSource());
// types
int i = 0;
assertEquals("org.apache.dubbo.metadata.tools.TestServiceImpl", serviceDefinition.getTypes().get(i++).getType());
assertEquals("org.apache.dubbo.metadata.tools.GenericTestService", serviceDefinition.getTypes().get(i++).getType());
assertEquals("org.apache.dubbo.metadata.tools.DefaultTestService", serviceDefinition.getTypes().get(i++).getType());
assertEquals("org.apache.dubbo.metadata.tools.TestService", serviceDefinition.getTypes().get(i++).getType());
assertEquals("java.lang.AutoCloseable", serviceDefinition.getTypes().get(i++).getType());
assertEquals("java.io.Serializable", serviceDefinition.getTypes().get(i++).getType());
assertEquals("java.util.EventListener", serviceDefinition.getTypes().get(i++).getType());
List<String> typeNames = Arrays.asList(
"org.apache.dubbo.metadata.tools.TestServiceImpl",
"org.apache.dubbo.metadata.tools.GenericTestService",
"org.apache.dubbo.metadata.tools.DefaultTestService",
"org.apache.dubbo.metadata.tools.TestService",
"java.lang.AutoCloseable",
"java.io.Serializable",
"java.util.EventListener"
);
for (String typeName : typeNames) {
String gotTypeName = getTypeName(typeName, serviceDefinition.getTypes());
assertEquals(typeName, gotTypeName);
}
// methods
assertEquals(14, serviceDefinition.getMethods().size());
}
private static String getTypeName(String type, List<TypeDefinition> types) {
for (TypeDefinition typeDefinition : types) {
if (type.equals(typeDefinition.getType())) {
return typeDefinition.getType();
}
}
return type;
}
}