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    */
038   protected ConstructorInfo(ClassInfo declaringClass, Constructor<?> c) {
039      super(declaringClass, c);
040      this.c = c;
041   }
042
043   /**
044    * Convenience method for instantiating a {@link ConstructorInfo};
045    *
046    * @param declaringClass The class that declares this method.
047    * @param c The constructor being wrapped.
048    * @return A new {@link ConstructorInfo} object, or <jk>null</jk> if the method was null;
049    */
050   public static ConstructorInfo of(ClassInfo declaringClass, Constructor<?> c) {
051      if (c == null)
052         return null;
053      return new ConstructorInfo(declaringClass, c);
054   }
055
056   /**
057    * Convenience method for instantiating a {@link ConstructorInfo};
058    *
059    * @param c The constructor being wrapped.
060    * @return A new {@link ConstructorInfo} object, or <jk>null</jk> if the method was null;
061    */
062   public static ConstructorInfo of(Constructor<?> c) {
063      if (c == null)
064         return null;
065      return new ConstructorInfo(ClassInfo.of(c.getDeclaringClass()), c);
066   }
067
068   /**
069    * Returns the wrapped method.
070    *
071    * @return The wrapped method.
072    */
073   @SuppressWarnings("unchecked")
074   public <T> Constructor<T> inner() {
075      return (Constructor<T>)c;
076   }
077
078   //-----------------------------------------------------------------------------------------------------------------
079   // Other methods
080   //-----------------------------------------------------------------------------------------------------------------
081
082   /**
083    * Shortcut for calling the new-instance method on the underlying constructor.
084    *
085    * @param args the arguments used for the method call
086    * @return The object returned from the constructor.
087    * @throws ExecutableException Exception occurred on invoked constructor/method/field.
088    */
089   @SuppressWarnings("unchecked")
090   public <T> T invoke(Object...args) throws ExecutableException {
091      try {
092         return (T)c.newInstance(args);
093      } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
094         throw new ExecutableException(e);
095      }
096   }
097
098   /**
099    * Makes constructor accessible if it matches the visibility requirements, or returns <jk>null</jk> if it doesn't.
100    *
101    * <p>
102    * Security exceptions thrown on the call to {@link Constructor#setAccessible(boolean)} are quietly ignored.
103    *
104    * @param v The minimum visibility.
105    * @return
106    *    The same constructor if visibility requirements met, or <jk>null</jk> if visibility requirement not
107    *    met or call to {@link Constructor#setAccessible(boolean)} throws a security exception.
108    */
109   public ConstructorInfo makeAccessible(Visibility v) {
110      if (v.transform(c) == null)
111         return null;
112      return this;
113   }
114
115   @Override
116   public int compareTo(ConstructorInfo o) {
117      int i = getSimpleName().compareTo(o.getSimpleName());
118      if (i == 0) {
119         i = getParamCount() - o.getParamCount();
120         if (i == 0) {
121            for (int j = 0; j < getParamCount() && i == 0; j++) {
122               Class<?>[] tpt = rawParamTypes(), opt = o.rawParamTypes();
123               i = tpt[j].getName().compareTo(opt[j].getName());
124            }
125         }
126      }
127      return i;
128   }
129}