blob: ac91160f6f48f704ab28c7e33abf3d103fbbb3fc [file] [log] [blame]
/*
* 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<String, String> argumentNamesMap = getErasureTypesMap(
cinfo.getElementUtilities().enclosingTypeElement(targetMethod).getTypeParameters(),
declaredType.getTypeArguments());
if (sourceParam.equals(argumentNamesMap.get(targetParam))) {
return true;
}
}
}
}
return false;
}
private static HashMap<String, String> getErasureTypesMap(List<? extends TypeParameterElement> erasureArguments,
List<? extends TypeMirror> typeArguments) {
HashMap<String, String> result = new HashMap<String, String>(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<Element> types = new ArrayList<>();
Deque<TypeMirror> 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;
}
}