You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2018/07/09 06:46:13 UTC

[camel] 01/03: Lets make the camel-api-component-maven-plugin handle generic methods with single bounded type parameters

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

acosentino pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 41303806213d03c504b31c6ded476758b9d61ab7
Author: jpoth <po...@gmail.com>
AuthorDate: Thu May 3 18:28:29 2018 +0200

    Lets make the camel-api-component-maven-plugin handle generic methods with single bounded type parameters
---
 .../camel/util/component/ApiMethodParser.java      | 36 +++++++++++++++-------
 .../component/ArgumentSubstitutionParserTest.java  | 16 +++++++++-
 .../org/apache/camel/util/component/TestProxy.java |  8 +++++
 3 files changed, 48 insertions(+), 12 deletions(-)

diff --git a/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodParser.java b/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodParser.java
index c3ff108..70013c8 100644
--- a/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodParser.java
+++ b/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodParser.java
@@ -39,7 +39,8 @@ public abstract class ApiMethodParser<T> {
     public static final Pattern ARGS_PATTERN = Pattern.compile("\\s*([^<\\s]+)\\s*(<[^>]+>)?\\s+([^\\s,]+)\\s*,?");
 
     private static final String METHOD_PREFIX = "^(\\s*(public|final|synchronized|native)\\s+)*(\\s*<[^>]>)?\\s*(\\S+)\\s+([^\\(]+\\s*)\\(";
-    private static final Pattern METHOD_PATTERN = Pattern.compile("\\s*([^<\\s]+)\\s*(<[^>]+>)?\\s+(\\S+)\\s*\\(\\s*([\\S\\s,]*)\\)\\s*;?\\s*");
+    private static final Pattern METHOD_PATTERN = Pattern.compile("\\s*([^<\\s]+)?\\s*(<[^>]+>)?(<(?<genericTypeParameterName>\\S+)\\s+extends\\s+"
+            + "(?<genericTypeParameterUpperBound>\\S+)>\\s+\\k<genericTypeParameterName>)?\\s+(\\S+)\\s*\\(\\s*(?<signature>[\\S\\s,]*)\\)\\s*;?\\s*");
 
     private static final String JAVA_LANG = "java.lang.";
     private static final Map<String, Class<?>> PRIMITIVE_TYPES;
@@ -116,24 +117,37 @@ public abstract class ApiMethodParser<T> {
             if (!methodMatcher.matches()) {
                 throw new IllegalArgumentException("Invalid method signature " + signature);
             }
+            // handle generic methods with single bounded type parameters
+            String genericTypeParameterName = null;
+            String genericTypeParameterUpperBound = null;
+            try {
+                genericTypeParameterName = methodMatcher.group("genericTypeParameterName");
+                genericTypeParameterUpperBound = methodMatcher.group("genericTypeParameterUpperBound");
+            } catch (IllegalArgumentException e) {
+                // ignore
+            }
 
-            // ignore generic type parameters in result, if any
-            final Class<?> resultType = forName(methodMatcher.group(1));
-            final String name = methodMatcher.group(3);
-            final String argSignature = methodMatcher.group(4);
+            final Class<?> resultType = genericTypeParameterName != null ? forName(genericTypeParameterUpperBound) : forName(methodMatcher.group(1));
+            final String name = methodMatcher.group(6);
+            final String argSignature = methodMatcher.group(7);
 
             final List<ApiMethodArg> arguments = new ArrayList<>();
             final List<Class<?>> argTypes = new ArrayList<>();
 
             final Matcher argsMatcher = ARGS_PATTERN.matcher(argSignature);
             while (argsMatcher.find()) {
-
-                final Class<?> type = forName(argsMatcher.group(1));
+                String genericParameterName = argsMatcher.group(1);
+                if (genericTypeParameterName != null && genericTypeParameterName.equals(genericParameterName)) {
+                    genericParameterName = genericTypeParameterUpperBound;
+                }
+                final Class<?> type = forName(genericParameterName);
                 argTypes.add(type);
-
-                final String typeArgsGroup = argsMatcher.group(2);
-                final String typeArgs = typeArgsGroup != null
-                    ? typeArgsGroup.substring(1, typeArgsGroup.length() - 1).replaceAll(" ", "") : null;
+                String genericParameterUpperbound = argsMatcher.group(2);
+                String typeArgs = genericParameterUpperbound != null
+                    ? genericParameterUpperbound.substring(1, genericParameterUpperbound.length() - 1).replaceAll(" ", "") : null;
+                if (typeArgs != null && typeArgs.equals(genericTypeParameterName)) {
+                    typeArgs = genericTypeParameterUpperBound;
+                }
                 arguments.add(new ApiMethodArg(argsMatcher.group(3), type, typeArgs));
             }
 
diff --git a/camel-core/src/test/java/org/apache/camel/util/component/ArgumentSubstitutionParserTest.java b/camel-core/src/test/java/org/apache/camel/util/component/ArgumentSubstitutionParserTest.java
index 9ce7d40..55c3f4d 100644
--- a/camel-core/src/test/java/org/apache/camel/util/component/ArgumentSubstitutionParserTest.java
+++ b/camel-core/src/test/java/org/apache/camel/util/component/ArgumentSubstitutionParserTest.java
@@ -18,6 +18,7 @@ package org.apache.camel.util.component;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.camel.util.component.ArgumentSubstitutionParser.Substitution;
 import org.junit.Test;
@@ -49,15 +50,28 @@ public class ArgumentSubstitutionParserTest {
         signatures.add("public final java.util.Map<String, String> greetAll(java.util.Map<String> nameMap);");
         signatures.add("public final String[] greetTimes(String name, int times);");
         signatures.add("public final String greetInnerChild(org.apache.camel.util.component.TestProxy.InnerChild child);");
+        signatures.add("public final <T extends java.util.Date> T sayHiResource(java.util.Set<T> resourceType, String resourceId);");
+        signatures.add("public final <T extends java.util.Date> T with(T theDate);");
         parser.setSignatures(signatures);
 
         final List<ApiMethodParser.ApiMethodModel> methodModels = parser.parse();
-        assertEquals(9, methodModels.size());
+        assertEquals(11, methodModels.size());
 
         final ApiMethodParser.ApiMethodModel sayHi1 = methodModels.get(8);
         assertEquals(PERSON, sayHi1.getArguments().get(0).getName());
         assertEquals("SAYHI_1", sayHi1.getUniqueName());
 
+        ApiMethodParser.ApiMethodModel sayHiResource = methodModels.get(9);
+        assertEquals(java.util.Date.class, sayHiResource.getResultType());
+        assertEquals(java.util.Set.class, sayHiResource.getArguments().get(0).getType());
+        assertEquals("resourceType", sayHiResource.getArguments().get(0).getName());
+        assertEquals("resourceId", sayHiResource.getArguments().get(1).getName());
+        assertEquals(String.class, sayHiResource.getArguments().get(1).getType());
+
+        ApiMethodParser.ApiMethodModel with = methodModels.get(10);
+        assertEquals(java.util.Date.class, with.getResultType());
+        assertEquals(java.util.Date.class, with.getArguments().get(0).getType());
+
         final ApiMethodParser.ApiMethodModel greetMe = methodModels.get(4);
         assertEquals(PERSON, greetMe.getArguments().get(0).getName());
 
diff --git a/camel-core/src/test/java/org/apache/camel/util/component/TestProxy.java b/camel-core/src/test/java/org/apache/camel/util/component/TestProxy.java
index 41f9eae..00bf1c2 100644
--- a/camel-core/src/test/java/org/apache/camel/util/component/TestProxy.java
+++ b/camel-core/src/test/java/org/apache/camel/util/component/TestProxy.java
@@ -74,6 +74,14 @@ class TestProxy {
         return result;
     }
 
+    public final <T extends java.util.Date> T sayHiResource(java.util.Set<T> resourceType, String resourceId) {
+        return null;
+    }
+
+    public final <T extends java.util.Date> T with(T theDate) {
+        return null;
+    }
+
     public final String greetInnerChild(InnerChild child) {
         return sayHi(child.getName());
     }