qwickie.util.TypeHelper.java Source code

Java tutorial

Introduction

Here is the source code for qwickie.util.TypeHelper.java

Source

/*
 * 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 qwickie.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.internal.core.JavaElement;
import org.eclipse.jdt.internal.core.NamedMember;
import org.eclipse.jdt.internal.core.ResolvedBinaryMethod;
import org.eclipse.jdt.internal.core.ResolvedBinaryType;
import org.eclipse.jdt.internal.core.ResolvedSourceMethod;

/**
 * @author count.negative
 * 
 */
@SuppressWarnings("restriction")
public final class TypeHelper {
    private static final String PACKAGE_MARKUP = "org.apache.wicket.markup";
    private static final String PACKAGE_MODEL = "org.apache.wicket.model";
    public static final String COMPONENT = "org.apache.wicket.Component";

    private TypeHelper() {
    }

    public static List<Object> getSupertypes(final IFile javaFile) {
        final List<Object> list = new ArrayList<Object>();
        if (javaFile != null) {
            final ICompilationUnit icu = JavaCore.createCompilationUnitFrom(javaFile);
            try {
                final IType[] allTypes = icu.getAllTypes();
                for (final IType type : allTypes) {
                    final ITypeHierarchy sth = type.newTypeHierarchy(null);
                    final IType[] supertypes = sth.getAllSupertypes(type);
                    for (final IType supertype : supertypes) {
                        final IClassFile classFile = supertype.getClassFile();
                        final IResource res = supertype.getResource();
                        // only add if there's a source
                        if (classFile != null && classFile.isStructureKnown()) {
                            list.add(classFile);
                        } else if (res != null && res instanceof IFile) {
                            list.add(res);
                        }
                    }
                }
            } catch (final JavaModelException e1) {
            }
        }
        return list;
    }

    public static List<JavaElement> getWicketComponentTypes(final IFile javaFile) {
        Assert.isNotNull(javaFile);
        final Set<JavaElement> set = new HashSet<JavaElement>();

        final ASTParser parser = ASTParser.newParser(AST.JLS4);
        parser.setResolveBindings(true);
        parser.setSource(JavaCore.createCompilationUnitFrom(javaFile));
        final CompilationUnit cu = (CompilationUnit) parser.createAST(null);
        cu.accept(new ASTVisitor() {

            @Override
            public boolean visit(final ClassInstanceCreation node) {
                final ITypeBinding ntb = node.resolveTypeBinding();
                final ITypeBinding nttb = node.getType().resolveBinding();
                IJavaElement javaElement = null;
                if (ntb == null || nttb == null) {
                    return true;
                }
                if (ntb.getPackage().getName().startsWith(PACKAGE_MARKUP)) {
                    javaElement = ntb.getJavaElement();
                }
                if (nttb.getPackage().getName().startsWith(PACKAGE_MARKUP)) {
                    javaElement = nttb.getJavaElement();
                }
                if (javaElement == null) {
                    ITypeBinding superclass = ntb.getSuperclass();
                    while (superclass != null) {
                        if (PACKAGE_MARKUP.startsWith(superclass.getPackage().getName())) {
                            javaElement = ntb.getJavaElement();
                            break;
                        }
                        superclass = superclass.getSuperclass();
                    }
                }
                if (javaElement != null) {
                    set.add((JavaElement) javaElement);
                    final ResolvedBinaryType rbt = (ResolvedBinaryType) javaElement
                            .getAdapter(ResolvedBinaryType.class);
                    if (rbt != null) {
                        set.add(rbt);
                    }
                }
                return true;
            }

        });

        return new ArrayList<JavaElement>(set);
    }

    public static List<IVariableBinding> getWicketModelTypes(final IFile javaFile) {
        Assert.isNotNull(javaFile);
        final List<IVariableBinding> list = new ArrayList<IVariableBinding>();

        final ASTParser parser = ASTParser.newParser(AST.JLS4);
        parser.setResolveBindings(true);
        parser.setSource(JavaCore.createCompilationUnitFrom(javaFile));
        final CompilationUnit cu = (CompilationUnit) parser.createAST(null);
        cu.accept(new ASTVisitor() {

            @Override
            public boolean visit(final ClassInstanceCreation node) {
                ITypeBinding ntb = node.resolveTypeBinding();
                while (ntb != null) {
                    if (ntb.getPackage().getName().startsWith(PACKAGE_MODEL)) {
                        // it is a wicket model
                        final ITypeBinding[] typeArguments = ntb.getTypeArguments();
                        for (int i = 0; i < typeArguments.length; i++) {
                            ITypeBinding typeArgument = typeArguments[i];
                            if (!typeArgument.isArray() && !typeArgument.isNullType() && !typeArgument.isPrimitive()
                                    && !"java.lang.String".equals(typeArgument.getBinaryName())) {
                                list.addAll(Arrays.asList(typeArgument.getDeclaredFields()));
                                return false;
                            }
                        }
                    }
                    ntb = ntb.getSuperclass();
                }
                return true;
            }

        });

        return list;
    }

    private static boolean hierarchyContainsComponent(final IType type) throws JavaModelException {
        Assert.isNotNull(type);
        final ITypeHierarchy hierarchy = type.newSupertypeHierarchy(null);
        if (hierarchy != null) {
            final IType[] supertypes = hierarchy.getAllSupertypes(type);
            for (final IType iType : supertypes) {
                if (iType.getFullyQualifiedName().equals(TypeHelper.COMPONENT)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * checks if the JavaElement extends Component and has a String (wicketId) as the first CTOR Parameter
     * 
     * @throws JavaModelException
     */
    public static boolean isWicketComponent(final IJavaElement javaElement) throws JavaModelException {
        Assert.isNotNull(javaElement);
        if (javaElement instanceof ResolvedSourceMethod) {
            final ResolvedSourceMethod method = (ResolvedSourceMethod) javaElement;
            if ("QComponent;".equals(method.getReturnType())) {
                return true;
            }
            final IType type = method.getDeclaringType();
            if (type != null) {
                if (type.getFullyQualifiedName().equals(TypeHelper.COMPONENT)) {
                    return true;
                }
                return hierarchyContainsComponent(type);
            }
        }
        if ((javaElement instanceof ResolvedBinaryMethod)) {
            final ResolvedBinaryMethod method = (ResolvedBinaryMethod) javaElement;
            if ("V;".equals(method.getReturnType())) {
                return true;
            }
            final IType type = method.getDeclaringType();
            if (type != null) {
                if (type.getFullyQualifiedName().equals(TypeHelper.COMPONENT)) {
                    return true;
                }
                return hierarchyContainsComponent(type);
            }
        }
        if ((javaElement instanceof ResolvedBinaryType)) {
            final ResolvedBinaryType method = (ResolvedBinaryType) javaElement;
            return hierarchyContainsComponent(method);
        }
        return false;
    }

    public static boolean isWicketJavaElement(final IJavaElement javaElement) throws JavaModelException {
        Assert.isNotNull(javaElement);
        if (javaElement != null && javaElement instanceof NamedMember) {
            if (javaElement.getElementName().equals(DocumentHelper.GET_STRING)) {
                return true;
            } else if (javaElement.getElementType() == IJavaElement.TYPE) {
                final NamedMember method = (NamedMember) javaElement;
                final IType type = method.getTypeRoot().findPrimaryType();
                return hierarchyContainsComponent(type);
            } else if (javaElement.getElementType() == IJavaElement.METHOD) {
                return isWicketComponent(javaElement);
            }
            return isWicketJavaElement(javaElement.getParent());
        }
        return false;
    }

}