001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.commons.reflect;
018
019import static org.apache.juneau.commons.utils.ClassUtils.*;
020import static org.apache.juneau.commons.utils.Shorts.*;
021
022import java.lang.reflect.*;
023
024/**
025 * Defines class/field/method visibilities.
026 *
027 * <p>
028 * Used to specify minimum levels of visibility when detecting bean classes, methods, and fields.
029 *
030 * <p>
031 * Used in conjunction with the following bean context properties:
032 * <ul class='javatree'>
033 *    <li class='jm'>MarshallingContext.Builder.beanConstructorVisibility
034 *    <li class='jm'>MarshallingContext.Builder.beanClassVisibility
035 *    <li class='jm'>MarshallingContext.Builder.beanFieldVisibility
036 *    <li class='jm'>MarshallingContext.Builder.beanMethodVisibility
037 * </ul>
038 *
039 */
040@SuppressWarnings({
041   "java:S1192" // Duplicated literals (argument/property names) read more clearly inline than as constants
042})
043public enum Visibility {
044
045   /** Ignore all */
046   NONE,
047
048   /** Include only <jk>public</jk> classes/fields/methods. */
049   PUBLIC,
050
051   /** Include only <jk>public</jk> or <jk>protected</jk> classes/fields/methods. */
052   PROTECTED,
053
054   /** Include all but <jk>private</jk> classes/fields/methods. */
055   DEFAULT,
056
057   /** Include all classes/fields/methods. */
058   PRIVATE;
059
060   /**
061    * Shortcut for <c>isVisible(x.getModifiers());</c>
062    *
063    * @param x The class to check. Must not be <jk>null</jk>.
064    * @return <jk>true</jk> if the class is at least as visible as this object.
065    */
066   public boolean isVisible(Class<?> x) {
067      return isVisible(x.getModifiers());
068   }
069
070   /**
071    * Shortcut for <c>isVisible(x.getModifiers());</c>
072    *
073    * @param x The constructor to check. Must not be <jk>null</jk>.
074    * @return <jk>true</jk> if the constructor is at least as visible as this object.
075    */
076   public boolean isVisible(Executable x) {
077      return isVisible(x.getModifiers());
078   }
079
080   /**
081    * Shortcut for <c>isVisible(x.getModifiers());</c>
082    *
083    * @param x The field to check. Must not be <jk>null</jk>.
084    * @return <jk>true</jk> if the field is at least as visible as this object.
085    */
086   public boolean isVisible(Field x) {
087      return isVisible(x.getModifiers());
088   }
089
090   /**
091    * Identifies if the specified mod matches this visibility.
092    *
093    * <h5 class='section'>Example:</h5>
094    * <p class='bjava'>
095    *    <jsf>PUBLIC</jsf>.isVisible(MyPublicClass.<jk>class</jk>.getModifiers()); <jc>//true</jc>
096    *    <jsf>PUBLIC</jsf>.isVisible(MyPrivateClass.<jk>class</jk>.getModifiers()); <jc>//false</jc>
097    *    <jsf>PRIVATE</jsf>.isVisible(MyPrivateClass.<jk>class</jk>.getModifiers()); <jc>//true</jc>
098    *    <jsf>NONE</jsf>.isVisible(MyPublicClass.<jk>class</jk>.getModifiers()); <jc>//false</jc>
099    * </p>
100    *
101    * @param mod The modifier from the object being tested (e.g. results from {@link Class#getModifiers()}.
102    * @return <jk>true</jk> if this visibility matches the specified modifier attribute.
103    */
104   public boolean isVisible(int mod) {
105      return switch (this) {
106         case NONE -> false;
107         case PRIVATE -> true;
108         case DEFAULT -> ! Modifier.isPrivate(mod);
109         case PROTECTED -> Modifier.isProtected(mod) || Modifier.isPublic(mod);
110         default -> Modifier.isPublic(mod);
111      };
112   }
113
114   /**
115    * Makes constructor accessible if it matches the visibility requirements, or returns <jk>null</jk> if it doesn't.
116    *
117    * <p>
118    * Security exceptions thrown on the call to {@link Constructor#setAccessible(boolean)} are quietly ignored.
119    *
120    * @param <T> The class type.
121    * @param x The constructor. Must not be <jk>null</jk>.
122    * @return
123    *    The same constructor if visibility requirements met, or <jk>null</jk> if visibility requirement not
124    *    met or call to {@link Constructor#setAccessible(boolean)} throws a security exception.
125    * @throws IllegalArgumentException If <c>x</c> is <jk>null</jk>.
126    */
127   public <T> Constructor<T> transform(Constructor<T> x) {
128      reqnn("x", x);
129      if (isVisible(x) && ! setAccessible(x))
130         return null;  // HTT
131      return x;
132   }
133
134   /**
135    * Makes field accessible if it matches the visibility requirements, or returns <jk>null</jk> if it doesn't.
136    *
137    * <p>
138    * Security exceptions thrown on the call to {@link Field#setAccessible(boolean)} are quietly ignored.
139    *
140    * @param x The field. Must not be <jk>null</jk>.
141    * @return
142    *    The same field if visibility requirements met, or <jk>null</jk> if visibility requirement not
143    *    met or call to {@link Field#setAccessible(boolean)} throws a security exception.
144    * @throws IllegalArgumentException If <c>x</c> is <jk>null</jk>.
145    */
146   public Field transform(Field x) {
147      reqnn("x", x);
148      if (isVisible(x) && ! setAccessible(x))
149         return null;  // HTT
150      return x;
151   }
152
153   /**
154    * Makes method accessible if it matches the visibility requirements, or returns <jk>null</jk> if it doesn't.
155    *
156    * <p>
157    * Security exceptions thrown on the call to {@link Method#setAccessible(boolean)} are quietly ignored.
158    *
159    * @param x The method. Must not be <jk>null</jk>.
160    * @return
161    *    The same method if visibility requirements met, or <jk>null</jk> if visibility requirement not
162    *    met or call to {@link Method#setAccessible(boolean)} throws a security exception.
163    * @throws IllegalArgumentException If <c>x</c> is <jk>null</jk>.
164    */
165   public Method transform(Method x) {
166      reqnn("x", x);
167      if (isVisible(x) && ! setAccessible(x))
168         return null;  // HTT
169      return x;
170   }
171}