/** * 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.jooby.internal.spec; import java.lang.reflect.Type; import java.util.List; import java.util.stream.Collectors; import com.github.javaparser.ast.expr.BooleanLiteralExpr; import com.github.javaparser.ast.expr.CharLiteralExpr; import com.github.javaparser.ast.expr.ClassExpr; import com.github.javaparser.ast.expr.DoubleLiteralExpr; import com.github.javaparser.ast.expr.IntegerLiteralExpr; import com.github.javaparser.ast.expr.LongLiteralExpr; import com.github.javaparser.ast.expr.StringLiteralExpr; import com.github.javaparser.ast.type.ClassOrInterfaceType; import com.github.javaparser.ast.type.PrimitiveType; import com.github.javaparser.ast.type.PrimitiveType.Primitive; import com.github.javaparser.ast.type.ReferenceType; import com.github.javaparser.ast.type.VoidType; import com.github.javaparser.ast.type.WildcardType; import com.github.javaparser.ast.visitor.GenericVisitorAdapter; import com.google.inject.util.Types; public class TypeCollector extends GenericVisitorAdapter<Type, Context> { @Override public Type visit(final ClassOrInterfaceType n, final Context ctx) { String name = name(n); Type type = ctx.resolveType(n, name) .orElseThrow(() -> new IllegalArgumentException("Type not found: " + name)); List<Type> args = n.getTypeArgs().stream() .map(it -> it.accept(new TypeCollector(), ctx)) .filter(it -> it != null) .collect(Collectors.toList()); if (args.size() > 0) { type = Types.newParameterizedType(type, args.toArray(new Type[args.size()])); } return type; } @Override public Type visit(final PrimitiveType n, final Context ctx) { Primitive type = n.getType(); switch (type) { case Byte: return Byte.class; case Boolean: return boolean.class; case Char: return char.class; case Short: return short.class; case Int: return int.class; case Long: return long.class; case Float: return float.class; default: return double.class; } } @Override public Type visit(final BooleanLiteralExpr n, final Context arg) { return boolean.class; } @Override public Type visit(final StringLiteralExpr n, final Context arg) { return String.class; } @Override public Type visit(final CharLiteralExpr n, final Context arg) { return char.class; } @Override public Type visit(final DoubleLiteralExpr n, final Context arg) { return double.class; } @Override public Type visit(final IntegerLiteralExpr n, final Context arg) { return int.class; } @Override public Type visit(final LongLiteralExpr n, final Context arg) { return long.class; } @Override public Type visit(final ClassExpr n, final Context ctx) { return n.getType().accept(new TypeCollector(), ctx); } @Override public Type visit(final ReferenceType n, final Context ctx) { return n.getType().accept(new TypeCollector(), ctx); } @Override public Type visit(final VoidType n, final Context ctx) { return void.class; } @Override public Type visit(final WildcardType n, final Context ctx) { return null; } private String name(ClassOrInterfaceType n) { StringBuilder sb = new StringBuilder(); while (n != null) { String name = n.getName(); if (sb.length() == 0) { sb.append(name); } else { if (Character.isLowerCase(name.charAt(0))) { sb.insert(0, name + "."); } else { sb.insert(0, name + "$"); } } n = n.getScope(); } return sb.toString(); } }