001/* 002 * Copyright 2013 Chris Pheby 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.jadira.reflection.core.misc; 017 018import java.lang.reflect.Field; 019import java.lang.reflect.Method; 020import java.lang.reflect.Modifier; 021import java.math.BigDecimal; 022import java.math.BigInteger; 023import java.net.URI; 024import java.net.URL; 025import java.util.HashSet; 026import java.util.Set; 027import java.util.UUID; 028import java.util.regex.Pattern; 029 030/** 031 * Utility methods for inspecting and interpreting classes 032 */ 033public final class ClassUtils { 034 035 private ClassUtils() { 036 } 037 038 /** 039 * Indicate if the class is a known non-primitive, JDK immutable type 040 * @param type Class to test 041 * @return True if the type is an immutable from the JDK class libraries 042 */ 043 public static boolean isJdkImmutable(Class<?> type) { 044 045 if (Class.class == type) { 046 return true; 047 } 048 if (String.class == type) { 049 return true; 050 } 051 if (BigInteger.class == type) { 052 return true; 053 } 054 if (BigDecimal.class == type) { 055 return true; 056 } 057 if (URL.class == type) { 058 return true; 059 } 060 if (UUID.class == type) { 061 return true; 062 } 063 if (URI.class == type) { 064 return true; 065 } 066 if (Pattern.class == type) { 067 return true; 068 } 069 return false; 070 } 071 072 /** 073 * Indicate if the class is a known primitive wrapper type 074 * @param type Class to test 075 * @return True if the type is a primitive wrapper type 076 */ 077 public static boolean isWrapper(Class<?> type) { 078 079 if (Boolean.class == type) { 080 return true; 081 } 082 if (Byte.class == type) { 083 return true; 084 } 085 if (Character.class == type) { 086 return true; 087 } 088 if (Short.class == type) { 089 return true; 090 } 091 if (Integer.class == type) { 092 return true; 093 } 094 if (Long.class == type) { 095 return true; 096 } 097 if (Float.class == type) { 098 return true; 099 } 100 if (Double.class == type) { 101 return true; 102 } 103 return false; 104 } 105 106 /** 107 * Produces an array with all the instance fields of the specified class 108 * @param c The class specified 109 * @return The array of matched Fields 110 */ 111 public static Field[] collectDeclaredInstanceFields(Class<?> c) { 112 113 return collectInstanceFields(c, c.getSuperclass()); 114 } 115 116 /** 117 * Produces an array with all the instance fields of the specified class 118 * @param c The class specified 119 * @return The array of matched Fields 120 */ 121 public static Field[] collectInstanceFields(Class<?> c) { 122 123 return collectFields(c, 0, Modifier.STATIC); 124 } 125 126 /** 127 * Produces an array with all the instance fields of the specified class 128 * @param c The class specified 129 * @param limitExclusive Fields from this class or higher in the hierarchy will not be returned 130 * @return The array of matched Fields 131 */ 132 public static Field[] collectInstanceFields(Class<?> c, Class<?> limitExclusive) { 133 134 return collectFields(c, 0, Modifier.STATIC, limitExclusive); 135 } 136 137 138 /** 139 * Produces an array with all the instance fields of the specified class which match the supplied rules 140 * @param c The class specified 141 * @param excludePublic Exclude public fields if true 142 * @param excludeProtected Exclude protected fields if true 143 * @param excludePrivate Exclude private fields if true 144 * @return The array of matched Fields 145 */ 146 public static Field[] collectInstanceFields(Class<?> c, boolean excludePublic, boolean excludeProtected, boolean excludePrivate) { 147 148 int inclusiveModifiers = 0; 149 int exclusiveModifiers = Modifier.STATIC; 150 151 if (excludePrivate) { 152 exclusiveModifiers += Modifier.PRIVATE; 153 } 154 if (excludePublic) { 155 exclusiveModifiers += Modifier.PUBLIC; 156 } 157 if (excludeProtected) { 158 exclusiveModifiers += Modifier.PROTECTED; 159 } 160 161 return collectFields(c, inclusiveModifiers, exclusiveModifiers); 162 } 163 164 /** 165 * Produces an array with all the fields of the specified class 166 * @param c The class specified 167 * @return The array of matched Fields 168 */ 169 public static Field[] collectDeclaredFields(Class<?> c) { 170 171 return collectFields(c, c.getSuperclass()); 172 } 173 174 /** 175 * Produces an array with all the fields of the specified class 176 * @param c The class specified 177 * @return The array of matched Fields 178 */ 179 public static Field[] collectFields(Class<?> c) { 180 181 return collectFields(c, 0, 0); 182 } 183 184 /** 185 * Produces an array with all the fields of the specified class 186 * @param c The class specified 187 * @param limitExclusive Fields from this class or higher in the hierarchy will not be returned 188 * @return The array of matched Fields 189 */ 190 public static Field[] collectFields(Class<?> c, Class<?> limitExclusive) { 191 192 return collectFields(c, 0, 0, limitExclusive); 193 } 194 195 196 /** 197 * Produces an array with all the instance fields of the specified class which match the supplied rules 198 * @param c The class specified 199 * @param inclusiveModifiers An int indicating the {@link Modifier}s that may be applied 200 * @param exclusiveModifiers An int indicating the {@link Modifier}s that must be excluded 201 * @return The array of matched Fields 202 */ 203 public static Field[] collectFields(Class<?> c, int inclusiveModifiers, int exclusiveModifiers) { 204 205 return collectFields(c, inclusiveModifiers, exclusiveModifiers, Object.class); 206 } 207 208 /** 209 * Produces an array with all the instance fields of the specified class which match the supplied rules 210 * @param c The class specified 211 * @param inclusiveModifiers An int indicating the {@link Modifier}s that may be applied 212 * @param exclusiveModifiers An int indicating the {@link Modifier}s that must be excluded 213 * @param limitExclusive Fields from this class or higher in the hierarchy will not be returned 214 * @return The array of matched Fields 215 */ 216 public static Field[] collectFields(Class<?> c, int inclusiveModifiers, int exclusiveModifiers, Class<?> limitExclusive) { 217 218 Set<Field> fields = new HashSet<Field>(); 219 while (c != limitExclusive) { 220 for (Field f : c.getDeclaredFields()) { 221 if (((f.getModifiers() & exclusiveModifiers) == 0) 222 && ((f.getModifiers() & inclusiveModifiers) == inclusiveModifiers)) { 223 fields.add(f); 224 f.setAccessible(true); 225 } 226 } 227 c = c.getSuperclass(); 228 } 229 return fields.toArray(new Field[]{}); 230 } 231 232 /** 233 * Produces an array with all the methods of the specified class 234 * @param c The class specified 235 * @return The array of matched Methods 236 */ 237 public static Method[] collectDeclaredMethods(Class<?> c) { 238 return collectMethods(c, 0, 0, c.getSuperclass()); 239 } 240 241 242 /** 243 * Produces an array with all the methods of the specified class 244 * @param c The class specified 245 * @return The array of matched Methods 246 */ 247 public static Method[] collectMethods(Class<?> c) { 248 249 return collectMethods(c, 0, 0); 250 } 251 252 /** 253 * Produces an array with all the methods of the specified class 254 * @param c The class specified 255 * @param limitExclusive Methods from this class or higher in the hierarchy will not be returned 256 * @return The array of matched Methods 257 */ 258 public static Method[] collectMethods(Class<?> c, Class<?> limitExclusive) { 259 260 return collectMethods(c, 0, 0, limitExclusive); 261 } 262 263 264 /** 265 * Produces an array with all the methods of the specified class 266 * @param c The class specified 267 * @param inclusiveModifiers An int indicating the {@link Modifier}s that may be applied 268 * @param exclusiveModifiers An int indicating the {@link Modifier}s that must be excluded 269 * @return The array of matched Methods 270 */ 271 public static Method[] collectMethods(Class<?> c, int inclusiveModifiers, int exclusiveModifiers) { 272 273 return collectMethods(c, inclusiveModifiers, exclusiveModifiers, Object.class); 274 } 275 276 /** 277 * Produces an array with all the methods of the specified class 278 * @param c The class specified 279 * @param inclusiveModifiers An int indicating the {@link Modifier}s that may be applied 280 * @param exclusiveModifiers An int indicating the {@link Modifier}s that must be excluded 281 * @param limitExclusive Methods from this class or higher in the hierarchy will not be returned 282 * @return The array of matched Methods 283 */ 284 public static Method[] collectMethods(Class<?> c, int inclusiveModifiers, int exclusiveModifiers, Class<?> limitExclusive) { 285 286 Set<Method> methods = new HashSet<Method>(); 287 while (c != limitExclusive) { 288 for (Method f : c.getDeclaredMethods()) { 289 if (((f.getModifiers() & exclusiveModifiers) == 0) 290 && ((f.getModifiers() & inclusiveModifiers) == inclusiveModifiers)) { 291 methods.add(f); 292 f.setAccessible(true); 293 } 294 } 295 c = c.getSuperclass(); 296 } 297 return methods.toArray(new Method[]{}); 298 } 299}