All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.modules.j2ee.ejbverification.JavaUtils Maven / Gradle / Ivy

The newest version!
/*
 * 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.netbeans.modules.j2ee.ejbverification;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import org.netbeans.api.java.source.CompilationInfo;

/**
 *
 * @author Tomasz.Slota
 */
public class JavaUtils {
    public static String extractClassNameFromType(TypeMirror type){
        if (type instanceof DeclaredType){
            Element elem = ((DeclaredType)type).asElement();
            
            if (elem.getKind() == ElementKind.CLASS
                    || elem.getKind() == ElementKind.INTERFACE){
                return ((TypeElement)elem).getQualifiedName().toString();
            }
        }
        
        return null;
    }
    
    /**
     * A convenience method, returns true if findAnnotation(...) != null
     */
    public static boolean hasAnnotation(Element element, String annClass){
        AnnotationMirror annEntity = findAnnotation(element, annClass);
        return annEntity != null;
    }
    
    public static AnnotationMirror findAnnotation(Element element, String annotationClass){
        for (AnnotationMirror ann : element.getAnnotationMirrors()){
            if (annotationClass.equals(ann.getAnnotationType().toString())){
                return ann;
            }
        }
        
        return null;
    }
    
    /**
     * @return the value of annotation attribute, null if the attribute
     * was not found or when ann was null
     */
    public static AnnotationValue getAnnotationAttrValue(AnnotationMirror ann, String attrName){
        if (ann != null){
            for (ExecutableElement attr : ann.getElementValues().keySet()){
                if (attrName.equals(attr.getSimpleName().toString())){
                    return ann.getElementValues().get(attr);
                }
            }
        }
        
        return null;
    }
    
    public static String getShortClassName(String qualifiedClassName){
        return qualifiedClassName.substring(qualifiedClassName.lastIndexOf(".") + 1); //NOI18N
    }

    public static boolean isMethodSignatureSame(CompilationInfo cinfo,
            ExecutableElement method1, ExecutableElement method2){

        // check for parameters count
        int paramCount = method1.getParameters().size();
        if (paramCount != method2.getParameters().size()) {
            return false;
        }

        for (int i = 0; i < paramCount; i++) {
            TypeMirror param1 = method1.getParameters().get(i).asType();
            TypeMirror param2 = method2.getParameters().get(i).asType();

            if (!cinfo.getTypes().isSameType(param1, param2)) {
                if (isSameDeclaredType(param1, param2)) {
                    continue;
                } else if (param2.getKind() == TypeKind.TYPEVAR) {
                    // interface method contains type erasure - see issue #201543
                    if (isParamEquivalentOfErasure(cinfo, method1, method2, param1.toString(), param2.toString())) {
                        continue;
                    }
                }
                return false;
            }
        }
        return true;
    }

    private static boolean isParamEquivalentOfErasure(CompilationInfo cinfo, ExecutableElement sourceMethod,
            ExecutableElement targetMethod, String sourceParam, String targetParam) {
        TypeMirror classTypeMirror = sourceMethod.getEnclosingElement().asType();
        for (TypeMirror typeMirror : cinfo.getTypes().directSupertypes(classTypeMirror)) {
            if (typeMirror instanceof DeclaredType) {
                DeclaredType declaredType = (DeclaredType) typeMirror;
                if (declaredType.asElement().getEnclosedElements().contains(targetMethod)) {
                    HashMap argumentNamesMap = getErasureTypesMap(
                            cinfo.getElementUtilities().enclosingTypeElement(targetMethod).getTypeParameters(),
                            declaredType.getTypeArguments());

                    if (sourceParam.equals(argumentNamesMap.get(targetParam))) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    private static HashMap getErasureTypesMap(List erasureArguments,
            List typeArguments) {
        HashMap result = new HashMap(erasureArguments.size());

        for (int i = 0; i < erasureArguments.size(); i++) {
            if (erasureArguments.size() == i || typeArguments.size() == i) {
                return result;
            }
            result.put(erasureArguments.get(i).toString(), typeArguments.get(i).toString());
        }
        return result;
    }

    public static boolean isSameDeclaredType(TypeMirror param1, TypeMirror param2) {
        String classNameParam1 = extractClassNameFromType(param1);
        // classNameParam1 == null when param1 is not declared type
        if (classNameParam1 != null && classNameParam1.equals(extractClassNameFromType(param2))) {
            return true;
        }
        return false;
    }

    /**
     * Says whether given element is subtype of the entered type.
     * @param info compilation info
     * @param element element to be examined
     * @param superType type which is looking for
     * @return {@code true} is the element implements or extends the given superType, {@code false} otherwise
     */
    public static boolean isTypeOf(CompilationInfo info, Element element, String superType) {
        final TypeMirror tm = element.asType();
        List types = new ArrayList<>();

        Deque deque = new ArrayDeque<>();
        deque.add(tm);
        while (!deque.isEmpty()) {
            TypeMirror mirror = deque.pop();
            if (mirror.getKind() == TypeKind.DECLARED) {
                Element el = info.getTypes().asElement(mirror);
                types.add(el);
                if (el.getKind() == ElementKind.CLASS) {
                    TypeElement tel = (TypeElement) el;
                    deque.add(tel.getSuperclass());
                    deque.addAll(tel.getInterfaces());
                } else if (el.getKind() == ElementKind.INTERFACE) {
                    TypeElement tel = (TypeElement) el;
                    for (TypeMirror ifaceMirror : tel.getInterfaces()) {
                        deque.add(ifaceMirror);
                    }
                }
            }
        }

        for (Element type : types) {
            if (superType.equals(type.asType().toString())) {
                return true;
            }
        }
        return false;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy