| /* |
| * Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // Rick Barkhouse - 2.1 - Initial implementation |
| package org.eclipse.persistence.jaxb.javamodel.xjc; |
| |
| import java.lang.reflect.Modifier; |
| import java.lang.reflect.ParameterizedType; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.List; |
| |
| import org.eclipse.persistence.dynamic.DynamicClassLoader; |
| import org.eclipse.persistence.jaxb.javamodel.JavaAnnotation; |
| import org.eclipse.persistence.jaxb.javamodel.JavaClass; |
| import org.eclipse.persistence.jaxb.javamodel.JavaMethod; |
| |
| import com.sun.codemodel.JAnnotationUse; |
| import com.sun.codemodel.JClass; |
| import com.sun.codemodel.JClassAlreadyExistsException; |
| import com.sun.codemodel.JCodeModel; |
| import com.sun.codemodel.JDefinedClass; |
| import com.sun.codemodel.JMethod; |
| import com.sun.codemodel.JType; |
| |
| /** |
| * INTERNAL: |
| * <p> |
| * <b>Purpose:</b> <code>JavaMethod</code> implementation wrapping XJC's <code>JMethod</code>. Used when |
| * bootstrapping a <code>DynamicJAXBContext</code> from an XML Schema. |
| * </p> |
| * |
| * <p> |
| * <b>Responsibilities:</b> |
| * </p> |
| * <ul> |
| * <li>Provide <code>Method</code> information from the underlying <code>JMethod</code>.</li> |
| * </ul> |
| * |
| * @since EclipseLink 2.1 |
| * |
| * @see org.eclipse.persistence.jaxb.javamodel.JavaMethod |
| */ |
| public class XJCJavaMethodImpl implements JavaMethod { |
| |
| private JMethod xjcMethod; |
| private JCodeModel jCodeModel; |
| private DynamicClassLoader dynamicClassLoader; |
| private JavaClass owningClass; |
| |
| /** |
| * Construct a new instance of <code>XJCJavaMethodImpl</code>. |
| * |
| * @param javaMethod - the XJC <code>JMethod</code> to be wrapped. |
| * @param codeModel - the XJC <code>JCodeModel</code> this method belongs to. |
| * @param loader - the <code>ClassLoader</code> used to bootstrap the <code>DynamicJAXBContext</code>. |
| * @param owner - the <code>JavaClass</code> this method belongs to. |
| */ |
| public XJCJavaMethodImpl(JMethod javaMethod, JCodeModel codeModel, DynamicClassLoader loader, JavaClass owner) { |
| this.xjcMethod = javaMethod; |
| this.jCodeModel = codeModel; |
| this.dynamicClassLoader = loader; |
| this.owningClass = owner; |
| } |
| |
| /** |
| * If this <code>JavaMethod</code> is annotated with an <code>Annotation</code> matching <code>aClass</code>, |
| * return its <code>JavaAnnotation</code> representation. |
| * |
| * @param aClass a <code>JavaClass</code> representing the <code>Annotation</code> to look for. |
| * |
| * @return the <code>JavaAnnotation</code> represented by <code>aClass</code>, if one exists, otherwise return <code>null</code>. |
| */ |
| @Override |
| @SuppressWarnings("unchecked") |
| public JavaAnnotation getAnnotation(JavaClass aClass) { |
| if (aClass != null) { |
| Collection<JAnnotationUse> annotations = xjcMethod.annotations(); |
| for (JAnnotationUse annotationUse : annotations) { |
| XJCJavaAnnotationImpl xjcAnnotation = new XJCJavaAnnotationImpl(annotationUse, dynamicClassLoader); |
| if (xjcAnnotation.getJavaAnnotationClass().getCanonicalName().equals(aClass.getQualifiedName())) { |
| return xjcAnnotation; |
| } |
| } |
| // Didn't find annotation so return null |
| return null; |
| } |
| // aClass was null so return null |
| return null; |
| } |
| |
| /** |
| * Return all of the <code>Annotations</code> for this <code>JavaMethod</code>. |
| * |
| * @return A <code>Collection</code> containing this <code>JavaMethod's</code> <code>JavaAnnotations</code>. |
| */ |
| @Override |
| @SuppressWarnings("unchecked") |
| public Collection<JavaAnnotation> getAnnotations() { |
| ArrayList<JavaAnnotation> annotationsList = new ArrayList<>(); |
| Collection<JAnnotationUse> annotations = xjcMethod.annotations(); |
| for (JAnnotationUse annotationUse : annotations) { |
| XJCJavaAnnotationImpl xjcAnnotation = new XJCJavaAnnotationImpl(annotationUse, dynamicClassLoader); |
| annotationsList.add(xjcAnnotation); |
| } |
| return annotationsList; |
| } |
| |
| /** |
| * Returns the name of this <code>JavaMethod</code>. |
| * |
| * @return the <code>String</code> name of this <code>JavaMethod</code>. |
| */ |
| @Override |
| public String getName() { |
| return xjcMethod.name(); |
| } |
| |
| /** |
| * Returns the array of parameters for this <code>JavaMethod</code>. |
| * |
| * @return a <code>JavaClass[]</code> representing the argument types for this method. |
| */ |
| @Override |
| public JavaClass[] getParameterTypes() { |
| JType[] params = xjcMethod.listParamTypes(); |
| JavaClass[] paramArray = new JavaClass[params.length]; |
| |
| for (int i = 0; i < params.length; i++) { |
| if (((XJCJavaClassImpl) getOwningClass()).getJavaModel() != null) { |
| paramArray[i] = ((XJCJavaClassImpl) getOwningClass()).getJavaModel().getClass(params[i].fullName()); |
| } else { |
| paramArray[i] = new XJCJavaClassImpl((JDefinedClass) params[i], jCodeModel, dynamicClassLoader); |
| } |
| } |
| return paramArray; |
| } |
| |
| /** |
| * Returns this <code>JavaMethod's</code> return type. |
| * |
| * @return a <code>JavaClass</code> representing the return type of this method. |
| */ |
| public JavaClass getResolvedType() { |
| if (((XJCJavaClassImpl) getOwningClass()).getJavaModel() != null) { |
| return ((XJCJavaClassImpl) getOwningClass()).getJavaModel().getClass(xjcMethod.type().fullName()); |
| } |
| |
| try { |
| return new XJCJavaClassImpl(jCodeModel._class(xjcMethod.type().fullName()), jCodeModel, dynamicClassLoader); |
| } catch (JClassAlreadyExistsException ex) { |
| return new XJCJavaClassImpl(jCodeModel._getClass(xjcMethod.type().fullName()), jCodeModel, dynamicClassLoader); |
| } |
| } |
| |
| /** |
| * Returns this <code>JavaMethod's</code> return type. |
| * |
| * @return a <code>JavaClass</code> representing the return type of this method. |
| */ |
| @Override |
| @SuppressWarnings("unchecked") |
| public JavaClass getReturnType() { |
| JType type = xjcMethod.type(); |
| JavaClass returnClass = null; |
| |
| if (((XJCJavaClassImpl) getOwningClass()).getJavaModel() != null) { |
| returnClass = ((XJCJavaClassImpl) getOwningClass()).getJavaModel().getClass(type.fullName()); |
| } else { |
| try { |
| returnClass = new XJCJavaClassImpl(jCodeModel._class(type.fullName()), jCodeModel, dynamicClassLoader); |
| } catch (JClassAlreadyExistsException ex) { |
| returnClass = new XJCJavaClassImpl(jCodeModel._getClass(type.fullName()), jCodeModel, dynamicClassLoader); |
| } |
| } |
| if (type instanceof JClass) { |
| JClass jcl = (JClass) type; |
| if (jcl.isParameterized()) { |
| List<JClass> args = jcl.getTypeParameters(); |
| JClass arg = args.get(0); |
| JavaClass argClass = ((XJCJavaClassImpl) getOwningClass()).getJavaModel().getClass(arg.fullName()); |
| ((XJCJavaClassImpl) returnClass).setActualTypeArgument(argClass); |
| } |
| } |
| return returnClass; |
| } |
| |
| /** |
| * Indicates if this <code>JavaMethod</code> has actual type arguments, i.e. is a |
| * parameterized type (for example, <code>List<Employee</code>). |
| * |
| * @return <code>true</code> if this <code>JavaClass</code> is parameterized, otherwise <code>false</code>. |
| */ |
| public boolean hasActualTypeArguments() { |
| try { |
| JavaClass[] allParams = getParameterTypes(); |
| |
| for (JavaClass type : allParams) { |
| Class<?> paramClass = Class.forName(type.getPackageName() + "." + type.getName()); |
| if (paramClass.getConstructor().newInstance() instanceof ParameterizedType) { |
| return true; |
| } |
| } |
| return false; |
| } catch (Exception e) { |
| return false; |
| } |
| } |
| |
| /** |
| * Not supported. |
| */ |
| public Collection<Object> getActualTypeArguments() { |
| throw new UnsupportedOperationException("getActualTypeArguments"); |
| } |
| |
| /** |
| * Returns the Java language modifiers for this <code>JavaMethod</code>, encoded in an integer. |
| * |
| * @return the <code>int</code> representing the modifiers for this method. |
| * |
| * @see java.lang.reflect.Modifier |
| */ |
| @Override |
| public int getModifiers() { |
| return xjcMethod.mods().getValue(); |
| } |
| |
| /** |
| * Indicates if this <code>JavaMethod</code> is <code>abstract</code>. |
| * |
| * @return <code>true</code> if this <code>JavaMethod</code> is <code>abstract</code>, otherwise <code>false</code>. |
| */ |
| @Override |
| public boolean isAbstract() { |
| return Modifier.isAbstract(getModifiers()); |
| } |
| |
| /** |
| * Indicates if this <code>JavaMethod</code> is <code>private</code>. |
| * |
| * @return <code>true</code> if this <code>JavaMethod</code> is <code>private</code>, otherwise <code>false</code>. |
| */ |
| @Override |
| public boolean isPrivate() { |
| return Modifier.isPrivate(getModifiers()); |
| } |
| |
| /** |
| * Indicates if this <code>JavaMethod</code> is <code>protected</code>. |
| * |
| * @return <code>true</code> if this <code>JavaMethod</code> is <code>protected</code>, otherwise <code>false</code>. |
| */ |
| @Override |
| public boolean isProtected() { |
| return Modifier.isProtected(getModifiers()); |
| } |
| |
| /** |
| * Indicates if this <code>JavaMethod</code> is <code>public</code>. |
| * |
| * @return <code>true</code> if this <code>JavaMethod</code> is <code>public</code>, otherwise <code>false</code>. |
| */ |
| @Override |
| public boolean isPublic() { |
| return Modifier.isPublic(getModifiers()); |
| } |
| |
| /** |
| * Indicates if this <code>JavaMethod</code> is <code>static</code>. |
| * |
| * @return <code>true</code> if this <code>JavaMethod</code> is <code>static</code>, otherwise <code>false</code>. |
| */ |
| @Override |
| public boolean isStatic() { |
| return Modifier.isStatic(getModifiers()); |
| } |
| |
| /** |
| * Indicates if this <code>JavaMethod</code> is <code>final</code>. |
| * |
| * @return <code>true</code> if this <code>JavaMethod</code> is <code>final</code>, otherwise <code>false</code>. |
| */ |
| @Override |
| public boolean isFinal() { |
| return Modifier.isFinal(getModifiers()); |
| } |
| |
| /** |
| * Not supported. |
| */ |
| @Override |
| public boolean isSynthetic() { |
| return false; |
| } |
| |
| /** |
| * Not supported. |
| */ |
| @Override |
| public JavaAnnotation getDeclaredAnnotation(JavaClass arg0) { |
| throw new UnsupportedOperationException("getDeclaredAnnotation"); |
| } |
| |
| /** |
| * Not supported. |
| */ |
| @Override |
| public Collection<JavaAnnotation> getDeclaredAnnotations() { |
| throw new UnsupportedOperationException("getDeclaredAnnotations"); |
| } |
| |
| /** |
| * Returns the <code>JavaClass</code> which contains this method. |
| * |
| * @return <code>JavaClass</code> representing the owner of this <code>JavaMethod</code>. |
| */ |
| @Override |
| public JavaClass getOwningClass() { |
| return owningClass; |
| } |
| |
| /** |
| * Set the <code>JavaClass</code> which contains this method. |
| * |
| * @param owningClass the <code>JavaClass</code> representing the owner of this <code>JavaMethod</code>. |
| */ |
| public void setOwningClass(JavaClass owningClass) { |
| this.owningClass = owningClass; |
| } |
| |
| /** |
| * Not supported. |
| */ |
| @Override |
| public boolean isBridge() { |
| return false; |
| } |
| } |