001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.reflect;
014
015import java.lang.reflect.*;
016
017import org.apache.juneau.*;
018import org.apache.juneau.annotation.*;
019
020/**
021 * Lightweight utility class for introspecting information about a constructor.
022 */
023@BeanIgnore
024public final class ConstructorInfo extends ExecutableInfo implements Comparable<ConstructorInfo> {
025
026   private final Constructor<?> c;
027
028   //-----------------------------------------------------------------------------------------------------------------
029   // Instantiation.
030   //-----------------------------------------------------------------------------------------------------------------
031
032   /**
033    * Constructor.
034    *
035    * @param declaringClass The class that declares this method.
036    * @param c The constructor being wrapped.
037    * @param rc The "real" constructor if the constructor above is defined against a CGLIB proxy.
038    */
039   protected ConstructorInfo(ClassInfo declaringClass, Constructor<?> c, Constructor<?> rc) {
040      super(declaringClass, c, rc);
041      this.c = c;
042   }
043
044   /**
045    * Convenience method for instantiating a {@link ConstructorInfo};
046    *
047    * @param declaringClass The class that declares this method.
048    * @param c The constructor being wrapped.
049    * @param rc The "real" constructor if the constructor above is defined against a CGLIB proxy.
050    * @return A new {@link ConstructorInfo} object, or <jk>null</jk> if the method was null;
051    */
052   public static ConstructorInfo of(ClassInfo declaringClass, Constructor<?> c, Constructor<?> rc) {
053      if (c == null)
054         return null;
055      return new ConstructorInfo(declaringClass, c, rc);
056   }
057
058   /**
059    * Convenience method for instantiating a {@link ConstructorInfo};
060    *
061    * @param c The constructor being wrapped.
062    * @return A new {@link ConstructorInfo} object, or <jk>null</jk> if the method was null;
063    */
064   public static ConstructorInfo of(Constructor<?> c) {
065      if (c == null)
066         return null;
067      return new ConstructorInfo(ClassInfo.of(c.getDeclaringClass()), c, c);
068   }
069
070   /**
071    * Returns the wrapped method.
072    *
073    * @return The wrapped method.
074    */
075   @SuppressWarnings("unchecked")
076   public <T> Constructor<T> inner() {
077      return (Constructor<T>)c;
078   }
079
080   //-----------------------------------------------------------------------------------------------------------------
081   // Other methods
082   //-----------------------------------------------------------------------------------------------------------------
083
084   /**
085    * Shortcut for calling the new-instance method on the underlying constructor.
086    *
087    * @param args the arguments used for the method call
088    * @return The object returned from the constructor.
089    * @throws ExecutableException Exception occurred on invoked constructor/method/field.
090    */
091   @SuppressWarnings("unchecked")
092   public <T> T invoke(Object...args) throws ExecutableException {
093      try {
094         return (T)c.newInstance(args);
095      } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
096         throw new ExecutableException(e);
097      }
098   }
099
100   /**
101    * Makes constructor accessible if it matches the visibility requirements, or returns <jk>null</jk> if it doesn't.
102    *
103    * <p>
104    * Security exceptions thrown on the call to {@link Constructor#setAccessible(boolean)} are quietly ignored.
105    *
106    * @param v The minimum visibility.
107    * @return
108    *    The same constructor if visibility requirements met, or <jk>null</jk> if visibility requirement not
109    *    met or call to {@link Constructor#setAccessible(boolean)} throws a security exception.
110    */
111   public ConstructorInfo makeAccessible(Visibility v) {
112      if (v.transform(c) == null)
113         return null;
114      return this;
115   }
116
117   @Override
118   public int compareTo(ConstructorInfo o) {
119      int i = getSimpleName().compareTo(o.getSimpleName());
120      if (i == 0) {
121         i = getParamCount() - o.getParamCount();
122         if (i == 0) {
123            for (int j = 0; j < getParamCount() && i == 0; j++) {
124               Class<?>[] tpt = rawParamTypes(), opt = o.rawParamTypes();
125               i = tpt[j].getName().compareTo(opt[j].getName());
126            }
127         }
128      }
129      return i;
130   }
131}