Skip to content

Commit e828564

Browse files
committed
Add return types
1 parent b2621d6 commit e828564

File tree

7 files changed

+479
-67
lines changed

7 files changed

+479
-67
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.github.kklisura.cdt.protocol.support.annotations;
2+
3+
/*-
4+
* #%L
5+
* cdt-java-client
6+
* %%
7+
* Copyright (C) 2018 - 2019 Kenan Klisura
8+
* %%
9+
* Licensed under the Apache License, Version 2.0 (the "License");
10+
* you may not use this file except in compliance with the License.
11+
* You may obtain a copy of the License at
12+
*
13+
* http://www.apache.org/licenses/LICENSE-2.0
14+
*
15+
* Unless required by applicable law or agreed to in writing, software
16+
* distributed under the License is distributed on an "AS IS" BASIS,
17+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
* See the License for the specific language governing permissions and
19+
* limitations under the License.
20+
* #L%
21+
*/
22+
23+
import static java.lang.annotation.ElementType.METHOD;
24+
25+
import java.lang.annotation.Retention;
26+
import java.lang.annotation.RetentionPolicy;
27+
import java.lang.annotation.Target;
28+
29+
/**
30+
* This describes a type parameter for generics return types, if for return type of List<Metrics>
31+
* this will contain Metrics class. If the type parameter is Object or is of primitive type, this
32+
* annotation will not be present.
33+
*
34+
* @author Kenan Klisura
35+
*/
36+
@Retention(RetentionPolicy.RUNTIME)
37+
@Target(value = {METHOD})
38+
public @interface ReturnTypeParameter {
39+
Class<?>[] value();
40+
}

cdt-java-protocol-builder/src/main/java/com/github/kklisura/cdt/definition/builder/support/java/builder/impl/JavaInterfaceBuilderImpl.java

Lines changed: 89 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,26 @@
2424
import static com.github.kklisura.cdt.definition.builder.support.java.builder.utils.JavadocUtils.INDENTATION_TAB;
2525

2626
import com.github.javaparser.ast.ImportDeclaration;
27+
import com.github.javaparser.ast.NodeList;
2728
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
2829
import com.github.javaparser.ast.body.MethodDeclaration;
2930
import com.github.javaparser.ast.body.Parameter;
30-
import com.github.javaparser.ast.expr.AnnotationExpr;
31-
import com.github.javaparser.ast.expr.MarkerAnnotationExpr;
32-
import com.github.javaparser.ast.expr.Name;
33-
import com.github.javaparser.ast.expr.StringLiteralExpr;
31+
import com.github.javaparser.ast.expr.*;
32+
import com.github.javaparser.ast.type.ClassOrInterfaceType;
3433
import com.github.kklisura.cdt.definition.builder.support.java.builder.JavaInterfaceBuilder;
3534
import com.github.kklisura.cdt.definition.builder.support.java.builder.impl.utils.CompilationUnitUtils;
3635
import com.github.kklisura.cdt.definition.builder.support.java.builder.support.MethodParam;
3736
import com.github.kklisura.cdt.definition.builder.support.java.builder.utils.JavadocUtils;
37+
import java.util.ArrayList;
3838
import java.util.List;
3939
import java.util.Optional;
40+
import java.util.regex.Matcher;
41+
import java.util.regex.Pattern;
42+
import java.util.stream.Collectors;
4043
import org.apache.commons.collections4.CollectionUtils;
4144
import org.apache.commons.lang3.StringUtils;
45+
import org.slf4j.Logger;
46+
import org.slf4j.LoggerFactory;
4247

4348
/**
4449
* Java interface builder.
@@ -48,10 +53,25 @@
4853
public class JavaInterfaceBuilderImpl extends BaseBuilder implements JavaInterfaceBuilder {
4954
private static final String DEPRECATED_ANNOTATION = "Deprecated";
5055

56+
private static final Pattern SINGLE_CLASS = Pattern.compile("\\s*\\S+\\.class\\s*");
57+
private static final Pattern CLASS_LIST =
58+
Pattern.compile("\\{(\\s*\\S+\\.class)(\\s*,\\s*\\S+\\.class)*\\s*}");
59+
private static final Pattern CLASS_LIST_CONTENT = Pattern.compile("\\{(.*)}");
60+
5161
private String name;
5262
private ClassOrInterfaceDeclaration declaration;
5363
private String annotationsPackage;
5464

65+
private static final Logger LOGGER = LoggerFactory.getLogger("TestLogger");
66+
67+
public static void main(String[] args) {
68+
final String name = "test";
69+
final RuntimeException e = new RuntimeException("Test exception");
70+
71+
LOGGER.error("Error while processing event " + name, e);
72+
LOGGER.error("Error while processing event {}", name, e);
73+
}
74+
5575
/**
5676
* Instantiates a new class builder implementation.
5777
*
@@ -107,8 +127,28 @@ public void addParametrizedMethodAnnotation(
107127
for (MethodDeclaration methodDeclaration : methods) {
108128
Optional<AnnotationExpr> annotation = methodDeclaration.getAnnotationByName(annotationName);
109129
if (!annotation.isPresent()) {
110-
methodDeclaration.addSingleMemberAnnotation(
111-
annotationName, new StringLiteralExpr(parameter));
130+
131+
if (isClassList(parameter)) {
132+
final List<String> classList = getClassList(parameter);
133+
134+
if (classList.size() == 1) {
135+
methodDeclaration.addSingleMemberAnnotation(
136+
annotationName,
137+
new ClassExpr(new ClassOrInterfaceType(getClassName(classList.get(0)))));
138+
} else {
139+
final List<Expression> nodes =
140+
classList
141+
.stream()
142+
.map(clazz -> new ClassExpr(new ClassOrInterfaceType(getClassName(clazz))))
143+
.collect(Collectors.toList());
144+
145+
methodDeclaration.addSingleMemberAnnotation(
146+
annotationName, new ArrayInitializerExpr(new NodeList<>(nodes)));
147+
}
148+
} else {
149+
methodDeclaration.addSingleMemberAnnotation(
150+
annotationName, new StringLiteralExpr(parameter));
151+
}
112152
}
113153
}
114154

@@ -179,4 +219,47 @@ private void importAnnotation(String annotationName) {
179219
addImport(annotationsPackage, annotationName);
180220
}
181221
}
222+
223+
/**
224+
* Given a class property accessor ie TestClass.class, return a class name ie TestClass.
225+
*
226+
* @param classPropertyAccessor Class property accessor string.
227+
* @return Class name.
228+
*/
229+
private static String getClassName(String classPropertyAccessor) {
230+
final int i = classPropertyAccessor.indexOf(".class");
231+
return classPropertyAccessor.substring(0, i);
232+
}
233+
234+
static boolean isClassList(String value) {
235+
if (SINGLE_CLASS.matcher(value).matches()) {
236+
return true;
237+
}
238+
239+
return CLASS_LIST.matcher(value).matches();
240+
}
241+
242+
static List<String> getClassList(String value) {
243+
final List<String> result = new ArrayList<>();
244+
245+
if (isClassList(value)) {
246+
if (SINGLE_CLASS.matcher(value).matches()) {
247+
result.add(value.trim());
248+
return result;
249+
}
250+
251+
final Matcher matcher = CLASS_LIST_CONTENT.matcher(value);
252+
if (matcher.matches()) {
253+
final String content = matcher.group(1);
254+
255+
final String[] items = content.trim().split(",");
256+
257+
for (int i = 0; i < items.length; i++) {
258+
result.add(items[i].trim());
259+
}
260+
}
261+
}
262+
263+
return result;
264+
}
182265
}

cdt-java-protocol-builder/src/main/java/com/github/kklisura/cdt/definition/builder/support/protocol/builder/CommandBuilder.java

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@
2121
*/
2222

2323
import static com.github.kklisura.cdt.definition.builder.support.protocol.builder.TypesBuilder.LIST_CLASS_NAME;
24-
import static com.github.kklisura.cdt.definition.builder.support.utils.StringUtils.buildPackageName;
25-
import static com.github.kklisura.cdt.definition.builder.support.utils.StringUtils.getReturnTypeFromGetter;
26-
import static com.github.kklisura.cdt.definition.builder.support.utils.StringUtils.toEnumClass;
24+
import static com.github.kklisura.cdt.definition.builder.support.utils.StringUtils.*;
2725

2826
import com.github.kklisura.cdt.definition.builder.support.java.builder.Builder;
2927
import com.github.kklisura.cdt.definition.builder.support.java.builder.JavaBuilderFactory;
@@ -62,6 +60,7 @@ public class CommandBuilder {
6260

6361
private static final String COMMENT_PARAM = "@param";
6462
private static final String EMPTY_SPACE = " ";
63+
private static final String OBJECT_CLASS_PROPERTY = ".class";
6564

6665
private String basePackageName;
6766
private String typesPackageName;
@@ -221,12 +220,12 @@ private void addCommand(
221220
List<MethodParam> methodParams =
222221
buildMethodParams(command, domain, interfaceBuilder, domainTypeResolver, builders);
223222

224-
String returnType =
223+
ReturnType returnType =
225224
buildReturnType(command, domain, interfaceBuilder, domainTypeResolver, builders);
226225
String description =
227226
buildMethodParamDescription(command.getDescription(), command.getParameters());
228227

229-
interfaceBuilder.addMethod(method, description, methodParams, returnType);
228+
interfaceBuilder.addMethod(method, description, methodParams, returnType.getType());
230229

231230
if (Boolean.TRUE.equals(command.getDeprecated())) {
232231
interfaceBuilder.addMethodAnnotation(method, TypesBuilder.DEPRECATED_ANNOTATION);
@@ -241,6 +240,13 @@ private void addCommand(
241240
if (returns.size() == 1) {
242241
interfaceBuilder.addParametrizedMethodAnnotation(
243242
method, TypesBuilder.RETURNS_ANNOTATION, returns.get(0).getName());
243+
244+
if (returnType.isTyped()) {
245+
interfaceBuilder.addParametrizedMethodAnnotation(
246+
method,
247+
TypesBuilder.RETURN_TYPE_PARAMETER_ANNOTATION,
248+
buildReturnClasses(returnType.getSubType()));
249+
}
244250
}
245251
}
246252
}
@@ -268,7 +274,37 @@ private String buildMethodParamDescription(String description, List<Property> pa
268274
return result.toString();
269275
}
270276

271-
private String buildReturnType(
277+
public static class ReturnType {
278+
private static final ReturnType VOID = new ReturnType(null);
279+
280+
private final String type;
281+
private final String subType;
282+
private final boolean typed;
283+
284+
public ReturnType(String type) {
285+
this(type, null, false);
286+
}
287+
288+
public ReturnType(String type, String subType, boolean typed) {
289+
this.type = type;
290+
this.subType = subType;
291+
this.typed = typed;
292+
}
293+
294+
public String getType() {
295+
return type;
296+
}
297+
298+
public String getSubType() {
299+
return subType;
300+
}
301+
302+
public boolean isTyped() {
303+
return typed;
304+
}
305+
}
306+
307+
private ReturnType buildReturnType(
272308
Command command,
273309
Domain domain,
274310
JavaInterfaceBuilder interfaceBuilder,
@@ -292,7 +328,7 @@ private String buildReturnType(
292328

293329
addBuilder(domain, property, result, interfaceBuilder, builders);
294330

295-
return result.getType();
331+
return new ReturnType(result.getType(), result.getSubType(), result.isTyped());
296332
} else {
297333
String name = getReturnTypeFromGetter(command.getName());
298334

@@ -311,11 +347,11 @@ private String buildReturnType(
311347
String packageName = buildPackageName(typesPackageName, domain.getDomain().toLowerCase());
312348
interfaceBuilder.addImport(packageName, name);
313349

314-
return name;
350+
return new ReturnType(name);
315351
}
316352
}
317353

318-
return null;
354+
return ReturnType.VOID;
319355
}
320356

321357
private List<MethodParam> buildMethodParams(
@@ -410,4 +446,22 @@ private String getTypeName(PropertyHandlerResult propertyHandlerResult) {
410446

411447
return type;
412448
}
449+
450+
static String buildReturnClasses(String returnType) {
451+
return "{" + buildReturnClassesRecursive(returnType) + "}";
452+
}
453+
454+
private static String buildReturnClassesRecursive(String returnType) {
455+
if (!returnType.contains("<")) {
456+
return returnType + OBJECT_CLASS_PROPERTY;
457+
}
458+
459+
final int start = returnType.indexOf("<");
460+
final int end = returnType.lastIndexOf(">");
461+
462+
final String clazz = returnType.substring(0, start);
463+
final String parameter = returnType.substring(start + 1, end);
464+
465+
return clazz + OBJECT_CLASS_PROPERTY + "," + buildReturnClassesRecursive(parameter);
466+
}
413467
}

0 commit comments

Comments
 (0)