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;
014
015import static org.apache.juneau.internal.ClassUtils.*;
016
017import java.lang.reflect.*;
018
019/**
020 * Defines class/field/method visibilities.
021 *
022 * <p>
023 * Used to specify minimum levels of visibility when detecting bean classes, methods, and fields.
024 *
025 * <p>
026 * Used in conjunction with the following bean context properties:
027 * <ul class='javatree'>
028 *    <li class='jm'>{@link BeanContext.Builder#beanConstructorVisibility(Visibility)}
029 *    <li class='jm'>{@link BeanContext.Builder#beanClassVisibility(Visibility)}
030 *    <li class='jm'>{@link BeanContext.Builder#beanFieldVisibility(Visibility)}
031 *    <li class='jm'>{@link BeanContext.Builder#beanMethodVisibility(Visibility)}
032 * </ul>
033 *
034 * <h5 class='section'>See Also:</h5><ul>
035
036 * </ul>
037 */
038public enum Visibility {
039
040   /** Ignore all */
041   NONE,
042
043   /** Include only <jk>public</jk> classes/fields/methods. */
044   PUBLIC,
045
046   /** Include only <jk>public</jk> or <jk>protected</jk> classes/fields/methods. */
047   PROTECTED,
048
049   /** Include all but <jk>private</jk> classes/fields/methods. */
050   DEFAULT,
051
052   /** Include all classes/fields/methods. */
053   PRIVATE;
054
055   /**
056    * Identifies if the specified mod matches this visibility.
057    *
058    * <h5 class='section'>Example:</h5>
059    * <p class='bjava'>
060    *    <jsf>PUBLIC</jsf>.isVisible(MyPublicClass.<jk>class</jk>.getModifiers()); <jc>//true</jc>
061    *    <jsf>PUBLIC</jsf>.isVisible(MyPrivateClass.<jk>class</jk>.getModifiers()); <jc>//false</jc>
062    *    <jsf>PRIVATE</jsf>.isVisible(MyPrivateClass.<jk>class</jk>.getModifiers()); <jc>//true</jc>
063    *    <jsf>NONE</jsf>.isVisible(MyPublicClass.<jk>class</jk>.getModifiers()); <jc>//false</jc>
064    * </p>
065    *
066    * @param mod The modifier from the object being tested (e.g. results from {@link Class#getModifiers()}.
067    * @return <jk>true</jk> if this visibility matches the specified modifier attribute.
068    */
069   public boolean isVisible(int mod) {
070      switch(this) {
071         case NONE: return false;
072         case PRIVATE: return true;
073         case DEFAULT: return ! Modifier.isPrivate(mod);
074         case PROTECTED: return Modifier.isProtected(mod) || Modifier.isPublic(mod);
075         default: return Modifier.isPublic(mod);
076      }
077   }
078
079   /**
080    * Shortcut for <c>isVisible(x.getModifiers());</c>
081    *
082    * @param x The class to check.
083    * @return <jk>true</jk> if the class is at least as visible as this object.
084    */
085   public boolean isVisible(Class<?> x) {
086      return isVisible(x.getModifiers());
087   }
088
089   /**
090    * Shortcut for <c>isVisible(x.getModifiers());</c>
091    *
092    * @param x The constructor to check.
093    * @return <jk>true</jk> if the constructor is at least as visible as this object.
094    */
095   public boolean isVisible(Executable x) {
096      return isVisible(x.getModifiers());
097   }
098
099   /**
100    * Shortcut for <c>isVisible(x.getModifiers());</c>
101    *
102    * @param x The field to check.
103    * @return <jk>true</jk> if the field is at least as visible as this object.
104    */
105   public boolean isVisible(Field x) {
106      return isVisible(x.getModifiers());
107   }
108
109   /**
110    * Makes constructor accessible if it matches the visibility requirements, or returns <jk>null</jk> if it doesn't.
111    *
112    * <p>
113    * Security exceptions thrown on the call to {@link Constructor#setAccessible(boolean)} are quietly ignored.
114    *
115    * @param <T> The class type.
116    * @param x The constructor.
117    * @return
118    *    The same constructor if visibility requirements met, or <jk>null</jk> if visibility requirement not
119    *    met or call to {@link Constructor#setAccessible(boolean)} throws a security exception.
120    */
121   public <T> Constructor<T> transform(Constructor<T> x) {
122      if (x == null)
123         return null;
124      if (isVisible(x))
125         if (! setAccessible(x))
126            return null;
127      return x;
128   }
129
130   /**
131    * Makes method accessible if it matches the visibility requirements, or returns <jk>null</jk> if it doesn't.
132    *
133    * <p>
134    * Security exceptions thrown on the call to {@link Method#setAccessible(boolean)} are quietly ignored.
135    *
136    * @param x The method.
137    * @return
138    *    The same method if visibility requirements met, or <jk>null</jk> if visibility requirement not
139    *    met or call to {@link Method#setAccessible(boolean)} throws a security exception.
140    */
141   public Method transform(Method x) {
142      if (x == null)
143         return null;
144      if (isVisible(x))
145         if (! setAccessible(x))
146            return null;
147      return x;
148   }
149
150   /**
151    * Makes field accessible if it matches the visibility requirements, or returns <jk>null</jk> if it doesn't.
152    *
153    * <p>
154    * Security exceptions thrown on the call to {@link Field#setAccessible(boolean)} are quietly ignored.
155    *
156    * @param x The field.
157    * @return
158    *    The same field if visibility requirements met, or <jk>null</jk> if visibility requirement not
159    *    met or call to {@link Field#setAccessible(boolean)} throws a security exception.
160    */
161   public Field transform(Field x) {
162      if (x == null)
163         return null;
164      if (isVisible(x))
165         if (! setAccessible(x))
166            return null;
167      return x;
168   }
169}