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.ClassMeta.ClassCategory.*; 016import static org.apache.juneau.internal.ClassUtils.*; 017import static org.apache.juneau.reflect.ReflectFlags.*; 018 019import java.io.*; 020import java.lang.annotation.*; 021import java.lang.reflect.*; 022import java.lang.reflect.Proxy; 023import java.net.*; 024import java.net.URI; 025import java.util.*; 026import java.util.Date; 027import java.util.concurrent.*; 028import java.util.concurrent.locks.*; 029 030import org.apache.juneau.annotation.*; 031import org.apache.juneau.http.*; 032import org.apache.juneau.internal.*; 033import org.apache.juneau.json.*; 034import org.apache.juneau.reflect.*; 035import org.apache.juneau.transform.*; 036 037/** 038 * A wrapper class around the {@link Class} object that provides cached information about that class. 039 * 040 * <p> 041 * Instances of this class can be created through the {@link BeanContext#getClassMeta(Class)} method. 042 * 043 * <p> 044 * The {@link BeanContext} class will cache and reuse instances of this class except for the following class types: 045 * <ul> 046 * <li>Arrays 047 * <li>Maps with non-Object key/values. 048 * <li>Collections with non-Object key/values. 049 * </ul> 050 * 051 * <p> 052 * This class is tied to the {@link BeanContext} class because it's that class that makes the determination of what is 053 * a bean. 054 * 055 * @param <T> The class type of the wrapped class. 056 */ 057@Bean(bpi="innerClass,classCategory,elementType,keyType,valueType,notABeanReason,initException,beanMeta") 058public final class ClassMeta<T> implements Type { 059 060 /** Class categories. */ 061 enum ClassCategory { 062 MAP, COLLECTION, CLASS, METHOD, NUMBER, DECIMAL, BOOLEAN, CHAR, DATE, ARRAY, ENUM, OTHER, CHARSEQ, STR, OBJ, URI, BEANMAP, READER, INPUTSTREAM, VOID, ARGS, OPTIONAL 063 } 064 065 final Class<T> innerClass; // The class being wrapped. 066 final ClassInfo info; 067 068 private final Class<? extends T> implClass; // The implementation class to use if this is an interface. 069 private final ClassCategory cc; // The class category. 070 private final Method fromStringMethod; // The static valueOf(String) or fromString(String) or forString(String) method (if it has one). 071 private final ConstructorInfo 072 noArgConstructor, // The no-arg constructor for this class (if it has one). 073 stringConstructor; // The X(String) constructor (if it has one). 074 private final Method 075 exampleMethod; // The example() or @Example-annotated method (if it has one). 076 private final Field 077 exampleField; // The @Example-annotated field (if it has one). 078 private final Setter 079 namePropertyMethod, // The method to set the name on an object (if it has one). 080 parentPropertyMethod; // The method to set the parent on an object (if it has one). 081 private final boolean 082 isDelegate, // True if this class extends Delegate. 083 isAbstract, // True if this class is abstract. 084 isMemberClass; // True if this is a non-static member class. 085 private final Object primitiveDefault; // Default value for primitive type classes. 086 private final Map<String,Method> 087 publicMethods; // All public methods, including static methods. 088 private final PojoSwap<?,?>[] childPojoSwaps; // Any PojoSwaps where the normal type is a subclass of this class. 089 private final ConcurrentHashMap<Class<?>,PojoSwap<?,?>> 090 childSwapMap, // Maps normal subclasses to PojoSwaps. 091 childUnswapMap; // Maps swap subclasses to PojoSwaps. 092 private final PojoSwap<T,?>[] pojoSwaps; // The object POJO swaps associated with this bean (if it has any). 093 private final BeanFilter beanFilter; // The bean filter associated with this bean (if it has one). 094 private final BuilderSwap<T,?> builderSwap; // The builder swap associated with this bean (if it has one). 095 private final BeanContext beanContext; // The bean context that created this object. 096 private final ClassMeta<?> 097 elementType, // If ARRAY or COLLECTION, the element class type. 098 keyType, // If MAP, the key class type. 099 valueType; // If MAP, the value class type. 100 private final BeanMeta<T> beanMeta; // The bean meta for this bean class (if it's a bean). 101 private final String 102 typePropertyName, // The property name of the _type property for this class and subclasses. 103 notABeanReason, // If this isn't a bean, the reason why. 104 dictionaryName; // The dictionary name of this class if it has one. 105 private final Throwable initException; // Any exceptions thrown in the init() method. 106 private final InvocationHandler invocationHandler; // The invocation handler for this class (if it has one). 107 private final BeanRegistry beanRegistry; // The bean registry of this class meta (if it has one). 108 private final ClassMeta<?>[] args; // Arg types if this is an array of args. 109 private final Object example; // Example object. 110 private final Map<Class<?>,Mutater<?,T>> fromMutaters = new ConcurrentHashMap<>(); 111 private final Map<Class<?>,Mutater<T,?>> toMutaters = new ConcurrentHashMap<>(); 112 private final Mutater<String,T> stringMutater; 113 114 private final ReadWriteLock lock = new ReentrantReadWriteLock(false); 115 private final Lock rLock = lock.readLock(), wLock = lock.writeLock(); 116 117 /** 118 * Construct a new {@code ClassMeta} based on the specified {@link Class}. 119 * 120 * @param innerClass The class being wrapped. 121 * @param beanContext The bean context that created this object. 122 * @param implClass 123 * For interfaces and abstract classes, this represents the "real" class to instantiate. 124 * Can be <jk>null</jk>. 125 * @param beanFilter 126 * The {@link BeanFilter} programmatically associated with this class. 127 * Can be <jk>null</jk>. 128 * @param pojoSwap 129 * The {@link PojoSwap} programmatically associated with this class. 130 * Can be <jk>null</jk>. 131 * @param childPojoSwap 132 * The child {@link PojoSwap PojoSwaps} programmatically associated with this class. 133 * These are the <c>PojoSwaps</c> that have normal classes that are subclasses of this class. 134 * Can be <jk>null</jk>. 135 * @param delayedInit 136 * Don't call init() in constructor. 137 * Used for delayed initialization when the possibility of class reference loops exist. 138 */ 139 @SuppressWarnings({ "rawtypes", "unchecked" }) 140 ClassMeta(Class<T> innerClass, BeanContext beanContext, Class<? extends T> implClass, BeanFilter beanFilter, PojoSwap<T,?>[] pojoSwaps, PojoSwap<?,?>[] childPojoSwaps, Object example) { 141 this.innerClass = innerClass; 142 this.info = ClassInfo.of(innerClass); 143 this.beanContext = beanContext; 144 String notABeanReason = null; 145 146 wLock.lock(); 147 try { 148 // We always immediately add this class meta to the bean context cache so that we can resolve recursive references. 149 if (beanContext != null && beanContext.cmCache != null && isCacheable(innerClass)) 150 beanContext.cmCache.put(innerClass, this); 151 152 ClassMetaBuilder<T> builder = new ClassMetaBuilder(innerClass, beanContext, implClass, beanFilter, pojoSwaps, childPojoSwaps, example); 153 154 this.cc = builder.cc; 155 this.isDelegate = builder.isDelegate; 156 this.fromStringMethod = builder.fromStringMethod; 157 this.parentPropertyMethod = builder.parentPropertyMethod; 158 this.namePropertyMethod = builder.namePropertyMethod; 159 this.noArgConstructor = builder.noArgConstructor; 160 this.stringConstructor = builder.stringConstructor; 161 this.primitiveDefault = builder.primitiveDefault; 162 this.publicMethods = builder.publicMethods; 163 this.beanFilter = beanFilter; 164 this.pojoSwaps = builder.pojoSwaps.isEmpty() ? null : builder.pojoSwaps.toArray(new PojoSwap[builder.pojoSwaps.size()]); 165 this.builderSwap = builder.builderSwap; 166 this.keyType = builder.keyType; 167 this.valueType = builder.valueType; 168 this.elementType = builder.elementType; 169 notABeanReason = builder.notABeanReason; 170 this.beanMeta = builder.beanMeta; 171 this.initException = builder.initException; 172 this.typePropertyName = builder.typePropertyName; 173 this.dictionaryName = builder.dictionaryName; 174 this.invocationHandler = builder.invocationHandler; 175 this.beanRegistry = builder.beanRegistry; 176 this.isMemberClass = builder.isMemberClass; 177 this.isAbstract = builder.isAbstract; 178 this.implClass = builder.implClass; 179 this.childUnswapMap = builder.childUnswapMap; 180 this.childSwapMap = builder.childSwapMap; 181 this.childPojoSwaps = builder.childPojoSwaps; 182 this.exampleMethod = builder.exampleMethod; 183 this.exampleField = builder.exampleField; 184 this.example = builder.example; 185 this.args = null; 186 this.stringMutater = builder.stringMutater; 187 } catch (ClassMetaRuntimeException e) { 188 notABeanReason = e.getMessage(); 189 throw e; 190 } finally { 191 this.notABeanReason = notABeanReason; 192 wLock.unlock(); 193 } 194 } 195 196 /** 197 * Generated classes shouldn't be cacheable to prevent needlessly filling up the cache. 198 */ 199 private static boolean isCacheable(Class<?> c) { 200 String n = c.getName(); 201 char x = n.charAt(n.length()-1); // All generated classes appear to end with digits. 202 if (x >= '0' && x <= '9') { 203 if (n.indexOf("$$") != -1 || n.startsWith("sun") || n.startsWith("com.sun") || n.indexOf("$Proxy") != -1) 204 return false; 205 } 206 return true; 207 } 208 209 /** 210 * Causes thread to wait until constructor has exited. 211 */ 212 final void waitForInit() { 213 rLock.lock(); 214 rLock.unlock(); 215 } 216 217 /** 218 * Copy constructor. 219 * 220 * <p> 221 * Used for creating Map and Collection class metas that shouldn't be cached. 222 */ 223 ClassMeta(ClassMeta<T> mainType, ClassMeta<?> keyType, ClassMeta<?> valueType, ClassMeta<?> elementType) { 224 this.innerClass = mainType.innerClass; 225 this.info = mainType.info; 226 this.implClass = mainType.implClass; 227 this.childPojoSwaps = mainType.childPojoSwaps; 228 this.childSwapMap = mainType.childSwapMap; 229 this.childUnswapMap = mainType.childUnswapMap; 230 this.cc = mainType.cc; 231 this.fromStringMethod = mainType.fromStringMethod; 232 this.noArgConstructor = mainType.noArgConstructor; 233 this.stringConstructor = mainType.stringConstructor; 234 this.namePropertyMethod = mainType.namePropertyMethod; 235 this.parentPropertyMethod = mainType.parentPropertyMethod; 236 this.isDelegate = mainType.isDelegate; 237 this.isAbstract = mainType.isAbstract; 238 this.isMemberClass = mainType.isMemberClass; 239 this.primitiveDefault = mainType.primitiveDefault; 240 this.publicMethods = mainType.publicMethods; 241 this.beanContext = mainType.beanContext; 242 this.elementType = elementType; 243 this.keyType = keyType; 244 this.valueType = valueType; 245 this.invocationHandler = mainType.invocationHandler; 246 this.beanMeta = mainType.beanMeta; 247 this.typePropertyName = mainType.typePropertyName; 248 this.dictionaryName = mainType.dictionaryName; 249 this.notABeanReason = mainType.notABeanReason; 250 this.pojoSwaps = mainType.pojoSwaps; 251 this.builderSwap = mainType.builderSwap; 252 this.beanFilter = mainType.beanFilter; 253 this.initException = mainType.initException; 254 this.beanRegistry = mainType.beanRegistry; 255 this.exampleMethod = mainType.exampleMethod; 256 this.exampleField = mainType.exampleField; 257 this.example = mainType.example; 258 this.args = null; 259 this.stringMutater = mainType.stringMutater; 260 } 261 262 /** 263 * Constructor for args-arrays. 264 */ 265 @SuppressWarnings("unchecked") 266 ClassMeta(ClassMeta<?>[] args) { 267 this.innerClass = (Class<T>) Object[].class; 268 this.info = ClassInfo.of(innerClass); 269 this.args = args; 270 this.implClass = null; 271 this.childPojoSwaps = null; 272 this.childSwapMap = null; 273 this.childUnswapMap = null; 274 this.cc = ARGS; 275 this.fromStringMethod = null; 276 this.noArgConstructor = null; 277 this.stringConstructor = null; 278 this.namePropertyMethod = null; 279 this.parentPropertyMethod = null; 280 this.isDelegate = false; 281 this.isAbstract = false; 282 this.isMemberClass = false; 283 this.primitiveDefault = null; 284 this.publicMethods = null; 285 this.beanContext = null; 286 this.elementType = null; 287 this.keyType = null; 288 this.valueType = null; 289 this.invocationHandler = null; 290 this.beanMeta = null; 291 this.typePropertyName = null; 292 this.dictionaryName = null; 293 this.notABeanReason = null; 294 this.pojoSwaps = null; 295 this.builderSwap = null; 296 this.beanFilter = null; 297 this.initException = null; 298 this.beanRegistry = null; 299 this.exampleMethod = null; 300 this.exampleField = null; 301 this.example = null; 302 this.stringMutater = null; 303 } 304 305 @SuppressWarnings({"unchecked","rawtypes","hiding"}) 306 private final class ClassMetaBuilder<T> { 307 Class<T> innerClass; 308 ClassInfo ci; 309 Class<? extends T> implClass; 310 BeanContext beanContext; 311 ClassCategory cc = ClassCategory.OTHER; 312 boolean 313 isDelegate = false, 314 isMemberClass = false, 315 isAbstract = false; 316 Method 317 fromStringMethod = null; 318 Setter 319 parentPropertyMethod = null, 320 namePropertyMethod = null; 321 ConstructorInfo 322 noArgConstructor = null, 323 stringConstructor = null; 324 Object primitiveDefault = null; 325 Map<String,Method> 326 publicMethods = new LinkedHashMap<>(); 327 ClassMeta<?> 328 keyType = null, 329 valueType = null, 330 elementType = null; 331 String 332 typePropertyName = null, 333 notABeanReason = null, 334 dictionaryName = null; 335 Throwable initException = null; 336 BeanMeta beanMeta = null; 337 List<PojoSwap> pojoSwaps = new ArrayList<>(); 338 BuilderSwap builderSwap; 339 InvocationHandler invocationHandler = null; 340 BeanRegistry beanRegistry = null; 341 PojoSwap<?,?>[] childPojoSwaps; 342 ConcurrentHashMap<Class<?>,PojoSwap<?,?>> 343 childSwapMap, 344 childUnswapMap; 345 Method exampleMethod; 346 Field exampleField; 347 Object example; 348 Mutater<String,T> stringMutater; 349 350 @SuppressWarnings("deprecation") 351 ClassMetaBuilder(Class<T> innerClass, BeanContext beanContext, Class<? extends T> implClass, BeanFilter beanFilter, PojoSwap<T,?>[] pojoSwaps, PojoSwap<?,?>[] childPojoSwaps, Object example) { 352 this.innerClass = innerClass; 353 this.beanContext = beanContext; 354 BeanContext bc = beanContext; 355 356 this.implClass = implClass; 357 ClassInfo ici = ClassInfo.of(implClass); 358 this.childPojoSwaps = childPojoSwaps; 359 if (childPojoSwaps == null) { 360 this.childSwapMap = null; 361 this.childUnswapMap = null; 362 } else { 363 this.childSwapMap = new ConcurrentHashMap<>(); 364 this.childUnswapMap = new ConcurrentHashMap<>(); 365 } 366 367 Class<T> c = innerClass; 368 ci = ClassInfo.of(c); 369 370 if (c.isPrimitive()) { 371 if (c == Boolean.TYPE) 372 cc = BOOLEAN; 373 else if (c == Byte.TYPE || c == Short.TYPE || c == Integer.TYPE || c == Long.TYPE || c == Float.TYPE || c == Double.TYPE) { 374 if (c == Float.TYPE || c == Double.TYPE) 375 cc = DECIMAL; 376 else 377 cc = NUMBER; 378 } 379 else if (c == Character.TYPE) 380 cc = CHAR; 381 else if (c == void.class || c == Void.class) 382 cc = VOID; 383 } else { 384 if (ci.isChildOf(Delegate.class)) 385 isDelegate = true; 386 387 if (c == Object.class) 388 cc = OBJ; 389 else if (c.isEnum()) 390 cc = ENUM; 391 else if (c.equals(Class.class)) 392 cc = ClassCategory.CLASS; 393 else if (ci.isChildOf(Method.class)) 394 cc = METHOD; 395 else if (ci.isChildOf(CharSequence.class)) { 396 if (c.equals(String.class)) 397 cc = STR; 398 else 399 cc = CHARSEQ; 400 } 401 else if (ci.isChildOf(Number.class)) { 402 if (ci.isChildOfAny(Float.class, Double.class)) 403 cc = DECIMAL; 404 else 405 cc = NUMBER; 406 } 407 else if (ci.isChildOf(Collection.class)) 408 cc = COLLECTION; 409 else if (ci.isChildOf(Map.class)) { 410 if (ci.isChildOf(BeanMap.class)) 411 cc = BEANMAP; 412 else 413 cc = MAP; 414 } 415 else if (c == Character.class) 416 cc = CHAR; 417 else if (c == Boolean.class) 418 cc = BOOLEAN; 419 else if (ci.isChildOfAny(Date.class, Calendar.class)) 420 cc = DATE; 421 else if (c.isArray()) 422 cc = ARRAY; 423 else if (ci.isChildOfAny(URL.class, URI.class) || bc.hasAnnotation(org.apache.juneau.annotation.URI.class, c)) 424 cc = URI; 425 else if (ci.isChildOf(Reader.class)) 426 cc = READER; 427 else if (ci.isChildOf(InputStream.class)) 428 cc = INPUTSTREAM; 429 else if (ci.is(Optional.class)) 430 cc = OPTIONAL; 431 } 432 433 isMemberClass = ci.isMemberClass() && ci.isNotStatic(); 434 435 // Find static fromString(String) or equivalent method. 436 // fromString() must be checked before valueOf() so that Enum classes can create their own 437 // specialized fromString() methods to override the behavior of Enum.valueOf(String). 438 // valueOf() is used by enums. 439 // parse() is used by the java logging Level class. 440 // forName() is used by Class and Charset 441 for (String methodName : new String[]{"fromString","fromValue","valueOf","parse","parseString","forName","forString"}) { 442 if (fromStringMethod == null) { 443 for (MethodInfo m : ci.getPublicMethods()) { 444 if (m.isAll(STATIC, PUBLIC, NOT_DEPRECATED) && m.hasName(methodName) && m.hasReturnType(c) && m.hasParamTypes(String.class)) { 445 fromStringMethod = m.inner(); 446 break; 447 } 448 } 449 } 450 } 451 452 // Find example() method if present. 453 for (MethodInfo m : ci.getPublicMethods()) { 454 if (m.isAll(PUBLIC, NOT_DEPRECATED, STATIC) && m.hasName("example") && m.hasFuzzyParamTypes(BeanSession.class)) { 455 exampleMethod = m.inner(); 456 break; 457 } 458 } 459 460 for (FieldInfo f : ci.getAllFieldsParentFirst()) { 461 if (bc.hasAnnotation(ParentProperty.class, f)) { 462 if (f.isStatic()) 463 throw new ClassMetaRuntimeException(c, "@ParentProperty used on invalid field ''{0}''. Must be static.", f); 464 f.setAccessible(); 465 parentPropertyMethod = new Setter.FieldSetter(f.inner()); 466 } 467 if (bc.hasAnnotation(NameProperty.class, f)) { 468 if (f.isStatic()) 469 throw new ClassMetaRuntimeException(c, "@NameProperty used on invalid field ''{0}''. Must be static.", f); 470 f.setAccessible(); 471 namePropertyMethod = new Setter.FieldSetter(f.inner()); 472 } 473 } 474 475 for (FieldInfo f : ci.getDeclaredFields()) { 476 if (bc.hasAnnotation(Example.class, f)) { 477 if (! (f.isStatic() && ci.isParentOf(f.getType().inner()))) 478 throw new ClassMetaRuntimeException(c, "@Example used on invalid field ''{0}''. Must be static and an instance of the type.", f); 479 f.setAccessible(); 480 exampleField = f.inner(); 481 } 482 } 483 484 // Find @NameProperty and @ParentProperty methods if present. 485 for (MethodInfo m : ci.getAllMethodsParentFirst()) { 486 if (bc.hasAnnotation(ParentProperty.class, m)) { 487 if (m.isStatic() || ! m.hasNumParams(1)) 488 throw new ClassMetaRuntimeException(c, "@ParentProperty used on invalid method ''{0}''. Must not be static and have one argument.", m); 489 m.setAccessible(); 490 parentPropertyMethod = new Setter.MethodSetter(m.inner()); 491 } 492 if (bc.hasAnnotation(NameProperty.class, m)) { 493 if (m.isStatic() || ! m.hasNumParams(1)) 494 throw new ClassMetaRuntimeException(c, "@NameProperty used on invalid method ''{0}''. Must not be static and have one argument.", m); 495 m.setAccessible(); 496 namePropertyMethod = new Setter.MethodSetter(m.inner()); 497 } 498 } 499 500 for (MethodInfo m : ci.getDeclaredMethods()) { 501 if (bc.hasAnnotation(Example.class, m)) { 502 if (! (m.isStatic() && m.hasFuzzyParamTypes(BeanSession.class) && ci.isParentOf(m.getReturnType().inner()))) 503 throw new ClassMetaRuntimeException(c, "@Example used on invalid method ''{0}''. Must be static and return an instance of the declaring class.", m); 504 m.setAccessible(); 505 exampleMethod = m.inner(); 506 } 507 } 508 509 // Note: Primitive types are normally abstract. 510 isAbstract = ci.isAbstract() && ci.isNotPrimitive(); 511 512 // Find constructor(String) method if present. 513 for (ConstructorInfo cs : ci.getPublicConstructors()) { 514 if (cs.isPublic() && cs.isNotDeprecated()) { 515 List<ClassInfo> pt = cs.getParamTypes(); 516 if (pt.size() == (isMemberClass ? 1 : 0) && c != Object.class && ! isAbstract) { 517 noArgConstructor = cs; 518 } else if (pt.size() == (isMemberClass ? 2 : 1)) { 519 ClassInfo arg = pt.get(isMemberClass ? 1 : 0); 520 if (arg.is(String.class)) 521 stringConstructor = cs; 522 } 523 } 524 } 525 526 primitiveDefault = ci.getPrimitiveDefault(); 527 528 for (MethodInfo m : ci.getPublicMethods()) 529 if (m.isAll(PUBLIC, NOT_DEPRECATED)) 530 publicMethods.put(m.getSignature(), m.inner()); 531 532 if (innerClass != Object.class) { 533 ClassInfo x = implClass == null ? ci : ici; 534 noArgConstructor = x.getPublicConstructor(); 535 } 536 537 if (beanFilter == null) 538 beanFilter = findBeanFilter(bc); 539 540 if (pojoSwaps != null) 541 this.pojoSwaps.addAll(Arrays.asList(pojoSwaps)); 542 543 if (bc != null) 544 this.builderSwap = BuilderSwap.findSwapFromPojoClass(bc, c, bc.getBeanConstructorVisibility(), bc.getBeanMethodVisibility()); 545 546 findPojoSwaps(this.pojoSwaps, bc); 547 548 try { 549 550 // If this is an array, get the element type. 551 if (cc == ARRAY) 552 elementType = findClassMeta(innerClass.getComponentType()); 553 554 // If this is a MAP, see if it's parameterized (e.g. AddressBook extends HashMap<String,Person>) 555 else if (cc == MAP) { 556 ClassMeta[] parameters = findParameters(); 557 if (parameters != null && parameters.length == 2) { 558 keyType = parameters[0]; 559 valueType = parameters[1]; 560 } else { 561 keyType = findClassMeta(Object.class); 562 valueType = findClassMeta(Object.class); 563 } 564 } 565 566 // If this is a COLLECTION, see if it's parameterized (e.g. AddressBook extends LinkedList<Person>) 567 else if (cc == COLLECTION || cc == OPTIONAL) { 568 ClassMeta[] parameters = findParameters(); 569 if (parameters != null && parameters.length == 1) { 570 elementType = parameters[0]; 571 } else { 572 elementType = findClassMeta(Object.class); 573 } 574 } 575 576 // If the category is unknown, see if it's a bean. 577 // Note that this needs to be done after all other initialization has been done. 578 else if (cc == OTHER) { 579 580 BeanMeta newMeta = null; 581 try { 582 newMeta = new BeanMeta(ClassMeta.this, bc, beanFilter, null); 583 notABeanReason = newMeta.notABeanReason; 584 585 // Always get these even if it's not a bean: 586 beanRegistry = newMeta.beanRegistry; 587 typePropertyName = newMeta.typePropertyName; 588 589 } catch (RuntimeException e) { 590 notABeanReason = e.getMessage(); 591 throw e; 592 } 593 if (notABeanReason == null) 594 beanMeta = newMeta; 595 } 596 597 } catch (NoClassDefFoundError e) { 598 initException = e; 599 } catch (RuntimeException e) { 600 initException = e; 601 throw e; 602 } 603 604 if (beanMeta != null) 605 dictionaryName = beanMeta.getDictionaryName(); 606 607 if (beanMeta != null && bc != null && bc.isUseInterfaceProxies() && innerClass.isInterface()) 608 invocationHandler = new BeanProxyInvocationHandler<T>(beanMeta); 609 610 Bean b = bc == null ? null : bc.getAnnotation(Bean.class, c); 611 if (b != null) { 612 if (b.beanDictionary().length != 0) 613 beanRegistry = new BeanRegistry(bc, null, b.beanDictionary()); 614 if (b.dictionary().length != 0) 615 beanRegistry = new BeanRegistry(bc, null, b.dictionary()); 616 617 // This could be a non-bean POJO with a type name. 618 if (dictionaryName == null && ! b.typeName().isEmpty()) 619 dictionaryName = b.typeName(); 620 } 621 622 Example e = bc == null ? null : bc.getAnnotation(Example.class, c); 623 624 if (example == null && e != null && ! e.value().isEmpty()) 625 example = e.value(); 626 627 if (example == null) { 628 switch(cc) { 629 case BOOLEAN: 630 example = true; 631 break; 632 case CHAR: 633 example = 'a'; 634 break; 635 case CHARSEQ: 636 case STR: 637 example = "foo"; 638 break; 639 case DECIMAL: 640 if (isFloat()) 641 example = new Float(1f); 642 else if (isDouble()) 643 example = new Double(1d); 644 break; 645 case ENUM: 646 Iterator<? extends Enum> i = EnumSet.allOf((Class<? extends Enum>)c).iterator(); 647 if (i.hasNext()) 648 example = i.next(); 649 break; 650 case NUMBER: 651 if (isShort()) 652 example = new Short((short)1); 653 else if (isInteger()) 654 example = new Integer(1); 655 else if (isLong()) 656 example = new Long(1l); 657 break; 658 case URI: 659 case ARGS: 660 case ARRAY: 661 case BEANMAP: 662 case CLASS: 663 case COLLECTION: 664 case DATE: 665 case INPUTSTREAM: 666 case MAP: 667 case METHOD: 668 case OBJ: 669 case OTHER: 670 case READER: 671 case OPTIONAL: 672 case VOID: 673 break; 674 } 675 } 676 677 this.example = example; 678 679 this.stringMutater = Mutaters.get(String.class, c); 680 } 681 682 private BeanFilter findBeanFilter(BeanContext bc) { 683 try { 684 List<Bean> ba = info.getAnnotations(Bean.class, bc); 685 if (! ba.isEmpty()) 686 return new AnnotationBeanFilterBuilder(innerClass, ba).build(); 687 } catch (Exception e) { 688 throw new RuntimeException(e); 689 } 690 return null; 691 } 692 693 private void findPojoSwaps(List<PojoSwap> l, BeanContext bc) { 694 Swap swap = bc == null ? null : bc.getAnnotation(Swap.class, innerClass); 695 if (swap != null) 696 l.add(createPojoSwap(swap)); 697 Swaps swaps = bc == null ? null : bc.getAnnotation(Swaps.class, innerClass); 698 if (swaps != null) 699 for (Swap s : swaps.value()) 700 l.add(createPojoSwap(s)); 701 702 PojoSwap defaultSwap = DefaultSwaps.find(ci); 703 if (defaultSwap == null) 704 defaultSwap = AutoObjectSwap.find(bc, ci); 705 if (defaultSwap == null) 706 defaultSwap = AutoNumberSwap.find(bc, ci); 707 if (defaultSwap == null) 708 defaultSwap = AutoMapSwap.find(bc, ci); 709 if (defaultSwap == null) 710 defaultSwap = AutoListSwap.find(bc, ci); 711 if (defaultSwap != null) 712 l.add(defaultSwap); 713 } 714 715 private PojoSwap<T,?> createPojoSwap(Swap s) { 716 Class<?> c = s.value(); 717 if (c == Null.class) 718 c = s.impl(); 719 ClassInfo ci = ClassInfo.of(c); 720 721 if (ci.isChildOf(PojoSwap.class)) { 722 PojoSwap ps = castOrCreate(PojoSwap.class, c); 723 if (s.mediaTypes().length > 0) 724 ps.forMediaTypes(MediaType.forStrings(s.mediaTypes())); 725 if (! s.template().isEmpty()) 726 ps.withTemplate(s.template()); 727 return ps; 728 } 729 730 if (ci.isChildOf(Surrogate.class)) { 731 List<SurrogateSwap<?,?>> l = SurrogateSwap.findPojoSwaps(c, beanContext); 732 if (! l.isEmpty()) 733 return (PojoSwap<T,?>)l.iterator().next(); 734 } 735 736 throw new ClassMetaRuntimeException(c, "Invalid swap class ''{0}'' specified. Must extend from PojoSwap or Surrogate.", c); 737 } 738 739 private ClassMeta<?> findClassMeta(Class<?> c) { 740 return beanContext.getClassMeta(c, false); 741 } 742 743 private ClassMeta<?>[] findParameters() { 744 return beanContext.findParameters(innerClass, innerClass); 745 } 746 } 747 748 /** 749 * Returns the {@link ClassInfo} wrapper for the underlying class. 750 * 751 * @return The {@link ClassInfo} wrapper for the underlying class, never <jk>null</jk>. 752 */ 753 public ClassInfo getInfo() { 754 return info; 755 } 756 757 /** 758 * Returns the type property name associated with this class and subclasses. 759 * 760 * <p> 761 * If <jk>null</jk>, <js>"_type"</js> should be assumed. 762 * 763 * @return 764 * The type property name associated with this bean class, or <jk>null</jk> if there is no explicit type 765 * property name defined or this isn't a bean. 766 */ 767 public String getBeanTypePropertyName() { 768 return typePropertyName; 769 } 770 771 /** 772 * Returns the bean dictionary name associated with this class. 773 * 774 * <p> 775 * The lexical name is defined by {@link Bean#typeName() @Bean(typeName)}. 776 * 777 * @return 778 * The type name associated with this bean class, or <jk>null</jk> if there is no type name defined or this 779 * isn't a bean. 780 */ 781 public String getDictionaryName() { 782 return dictionaryName; 783 } 784 785 /** 786 * Returns the bean registry for this class. 787 * 788 * <p> 789 * This bean registry contains names specified in the {@link Bean#dictionary() @Bean(dictionary)} annotation 790 * defined on the class, regardless of whether the class is an actual bean. 791 * This allows interfaces to define subclasses with type names. 792 * 793 * @return The bean registry for this class, or <jk>null</jk> if no bean registry is associated with it. 794 */ 795 public BeanRegistry getBeanRegistry() { 796 return beanRegistry; 797 } 798 799 /** 800 * Returns the category of this class. 801 * 802 * @return The category of this class. 803 */ 804 public ClassCategory getClassCategory() { 805 return cc; 806 } 807 808 /** 809 * Returns <jk>true</jk> if this class is a superclass of or the same as the specified class. 810 * 811 * @param c The comparison class. 812 * @return <jk>true</jk> if this class is a superclass of or the same as the specified class. 813 */ 814 public boolean isAssignableFrom(Class<?> c) { 815 return info.isChildOf(c); 816 } 817 818 /** 819 * Returns <jk>true</jk> if this class is a subclass of or the same as the specified class. 820 * 821 * @param c The comparison class. 822 * @return <jk>true</jk> if this class is a subclass of or the same as the specified class. 823 */ 824 public boolean isInstanceOf(Class<?> c) { 825 return info.isParentOf(c); 826 } 827 828 /** 829 * Returns <jk>true</jk> if this class or any child classes has a {@link PojoSwap} associated with it. 830 * 831 * <p> 832 * Used when transforming bean properties to prevent having to look up transforms if we know for certain that no 833 * transforms are associated with a bean property. 834 * 835 * @return <jk>true</jk> if this class or any child classes has a {@link PojoSwap} associated with it. 836 */ 837 protected boolean hasChildPojoSwaps() { 838 return childPojoSwaps != null; 839 } 840 841 /** 842 * Returns the {@link PojoSwap} where the specified class is the same/subclass of the normal class of one of the 843 * child POJO swaps associated with this class. 844 * 845 * @param normalClass The normal class being resolved. 846 * @return The resolved {@link PojoSwap} or <jk>null</jk> if none were found. 847 */ 848 protected PojoSwap<?,?> getChildPojoSwapForSwap(Class<?> normalClass) { 849 if (childSwapMap != null) { 850 PojoSwap<?,?> s = childSwapMap.get(normalClass); 851 if (s == null) { 852 for (PojoSwap<?,?> f : childPojoSwaps) 853 if (s == null && f.getNormalClass().isParentOf(normalClass)) 854 s = f; 855 if (s == null) 856 s = PojoSwap.NULL; 857 PojoSwap<?,?> s2 = childSwapMap.putIfAbsent(normalClass, s); 858 if (s2 != null) 859 s = s2; 860 } 861 if (s == PojoSwap.NULL) 862 return null; 863 return s; 864 } 865 return null; 866 } 867 868 /** 869 * Returns the {@link PojoSwap} where the specified class is the same/subclass of the swap class of one of the child 870 * POJO swaps associated with this class. 871 * 872 * @param swapClass The swap class being resolved. 873 * @return The resolved {@link PojoSwap} or <jk>null</jk> if none were found. 874 */ 875 protected PojoSwap<?,?> getChildPojoSwapForUnswap(Class<?> swapClass) { 876 if (childUnswapMap != null) { 877 PojoSwap<?,?> s = childUnswapMap.get(swapClass); 878 if (s == null) { 879 for (PojoSwap<?,?> f : childPojoSwaps) 880 if (s == null && f.getSwapClass().isParentOf(swapClass)) 881 s = f; 882 if (s == null) 883 s = PojoSwap.NULL; 884 PojoSwap<?,?> s2 = childUnswapMap.putIfAbsent(swapClass, s); 885 if (s2 != null) 886 s = s2; 887 } 888 if (s == PojoSwap.NULL) 889 return null; 890 return s; 891 } 892 return null; 893 } 894 895 /** 896 * Locates the no-arg constructor for the specified class. 897 * 898 * <p> 899 * Constructor must match the visibility requirements specified by parameter 'v'. 900 * If class is abstract, always returns <jk>null</jk>. 901 * Note that this also returns the 1-arg constructor for non-static member classes. 902 * 903 * @param c The class from which to locate the no-arg constructor. 904 * @param v The minimum visibility. 905 * @return The constructor, or <jk>null</jk> if no no-arg constructor exists with the required visibility. 906 */ 907 @SuppressWarnings({"unchecked"}) 908 protected static <T> Constructor<? extends T> findNoArgConstructor(Class<?> c, Visibility v) { 909 ClassInfo ci = ClassInfo.of(c); 910 if (ci.isAbstract()) 911 return null; 912 boolean isMemberClass = ci.isMemberClass() && ci.isNotStatic(); 913 for (ConstructorInfo cc : ci.getPublicConstructors()) { 914 if (cc.hasNumParams(isMemberClass ? 1 : 0) && cc.isVisible(v) && cc.isNotDeprecated()) 915 return (Constructor<? extends T>) v.transform(cc.inner()); 916 } 917 return null; 918 } 919 920 /** 921 * Returns the {@link Class} object that this class type wraps. 922 * 923 * @return The wrapped class object. 924 */ 925 public Class<T> getInnerClass() { 926 return innerClass; 927 } 928 929 /** 930 * Returns the serialized (swapped) form of this class if there is an {@link PojoSwap} associated with it. 931 * 932 * @param session 933 * The bean session. 934 * <br>Required because the swap used may depend on the media type being serialized or parsed. 935 * @return The serialized class type, or this object if no swap is associated with the class. 936 */ 937 @BeanIgnore 938 public ClassMeta<?> getSerializedClassMeta(BeanSession session) { 939 PojoSwap<T,?> ps = getPojoSwap(session); 940 return (ps == null ? this : ps.getSwapClassMeta(session)); 941 } 942 943 /** 944 * Returns the example of this class. 945 * 946 * @param session 947 * The bean session. 948 * <br>Required because the example method may take it in as a parameter. 949 * @return The serialized class type, or this object if no swap is associated with the class. 950 */ 951 @SuppressWarnings({"unchecked","rawtypes"}) 952 @BeanIgnore 953 public T getExample(BeanSession session) { 954 try { 955 if (example != null) { 956 if (isInstance(example)) 957 return (T)example; 958 if (example instanceof String) { 959 if (isCharSequence()) 960 return (T)example; 961 String s = example.toString(); 962 if (isMapOrBean() && StringUtils.isObjectMap(s, false)) 963 return JsonParser.DEFAULT.parse(s, this); 964 if (isCollectionOrArray() && StringUtils.isObjectList(s, false)) 965 return JsonParser.DEFAULT.parse(s, this); 966 } 967 if (example instanceof Map && isMapOrBean()) { 968 return JsonParser.DEFAULT.parse(SimpleJsonSerializer.DEFAULT_READABLE.toString(example), this); 969 } 970 if (example instanceof Collection && isCollectionOrArray()) { 971 return JsonParser.DEFAULT.parse(SimpleJsonSerializer.DEFAULT_READABLE.serialize(example), this); 972 } 973 } 974 if (exampleMethod != null) 975 return (T)MethodInfo.of(exampleMethod).invokeFuzzy(null, session); 976 if (exampleField != null) 977 return (T)exampleField.get(null); 978 979 if (isCollection()) { 980 Object etExample = getElementType().getExample(session); 981 if (etExample != null) { 982 if (canCreateNewInstance()) { 983 Collection c = (Collection)newInstance(); 984 c.add(etExample); 985 return (T)c; 986 } 987 return (T)Collections.singleton(etExample); 988 } 989 } else if (isArray()) { 990 Object etExample = getElementType().getExample(session); 991 if (etExample != null) { 992 Object o = Array.newInstance(getElementType().innerClass, 1); 993 Array.set(o, 0, etExample); 994 return (T)o; 995 } 996 } else if (isMap()) { 997 Object vtExample = getValueType().getExample(session); 998 Object ktExample = getKeyType().getExample(session); 999 if (ktExample != null && vtExample != null) { 1000 if (canCreateNewInstance()) { 1001 Map m = (Map)newInstance(); 1002 m.put(ktExample, vtExample); 1003 return (T)m; 1004 } 1005 return (T)Collections.singletonMap(ktExample, vtExample); 1006 } 1007 } 1008 1009 return null; 1010 } catch (Exception e) { 1011 throw new ClassMetaRuntimeException(e); 1012 } 1013 } 1014 1015 /** 1016 * For array and {@code Collection} types, returns the class type of the components of the array or 1017 * {@code Collection}. 1018 * 1019 * @return The element class type, or <jk>null</jk> if this class is not an array or Collection. 1020 */ 1021 public ClassMeta<?> getElementType() { 1022 return elementType; 1023 } 1024 1025 /** 1026 * For {@code Map} types, returns the class type of the keys of the {@code Map}. 1027 * 1028 * @return The key class type, or <jk>null</jk> if this class is not a Map. 1029 */ 1030 public ClassMeta<?> getKeyType() { 1031 return keyType; 1032 } 1033 1034 /** 1035 * For {@code Map} types, returns the class type of the values of the {@code Map}. 1036 * 1037 * @return The value class type, or <jk>null</jk> if this class is not a Map. 1038 */ 1039 public ClassMeta<?> getValueType() { 1040 return valueType; 1041 } 1042 1043 /** 1044 * Returns <jk>true</jk> if this class implements {@link Delegate}, meaning it's a representation of some other 1045 * object. 1046 * 1047 * @return <jk>true</jk> if this class implements {@link Delegate}. 1048 */ 1049 public boolean isDelegate() { 1050 return isDelegate; 1051 } 1052 1053 /** 1054 * Returns <jk>true</jk> if this class is a subclass of {@link Map}. 1055 * 1056 * @return <jk>true</jk> if this class is a subclass of {@link Map}. 1057 */ 1058 public boolean isMap() { 1059 return cc == MAP || cc == BEANMAP; 1060 } 1061 1062 /** 1063 * Returns <jk>true</jk> if this class is a subclass of {@link Map} or it's a bean. 1064 * 1065 * @return <jk>true</jk> if this class is a subclass of {@link Map} or it's a bean. 1066 */ 1067 public boolean isMapOrBean() { 1068 return cc == MAP || cc == BEANMAP || beanMeta != null; 1069 } 1070 1071 /** 1072 * Returns <jk>true</jk> if this class is a subclass of {@link BeanMap}. 1073 * 1074 * @return <jk>true</jk> if this class is a subclass of {@link BeanMap}. 1075 */ 1076 public boolean isBeanMap() { 1077 return cc == BEANMAP; 1078 } 1079 1080 /** 1081 * Returns <jk>true</jk> if this class is a subclass of {@link Collection}. 1082 * 1083 * @return <jk>true</jk> if this class is a subclass of {@link Collection}. 1084 */ 1085 public boolean isCollection() { 1086 return cc == COLLECTION; 1087 } 1088 1089 /** 1090 * Returns <jk>true</jk> if this class is a subclass of {@link Optional}. 1091 * 1092 * @return <jk>true</jk> if this class is a subclass of {@link Optional}. 1093 */ 1094 public boolean isOptional() { 1095 return cc == OPTIONAL; 1096 } 1097 1098 /** 1099 * Returns <jk>true</jk> if this class is a subclass of {@link Collection} or is an array. 1100 * 1101 * @return <jk>true</jk> if this class is a subclass of {@link Collection} or is an array. 1102 */ 1103 public boolean isCollectionOrArray() { 1104 return cc == COLLECTION || cc == ARRAY; 1105 } 1106 1107 /** 1108 * Returns <jk>true</jk> if this class is a subclass of {@link Collection} or is an array or {@link Optional}. 1109 * 1110 * @return <jk>true</jk> if this class is a subclass of {@link Collection} or is an array or {@link Optional}. 1111 */ 1112 public boolean isCollectionOrArrayOrOptional() { 1113 return cc == COLLECTION || cc == ARRAY || cc == OPTIONAL; 1114 } 1115 1116 /** 1117 * Returns <jk>true</jk> if this class extends from {@link Set}. 1118 * 1119 * @return <jk>true</jk> if this class extends from {@link Set}. 1120 */ 1121 public boolean isSet() { 1122 return cc == COLLECTION && info.isChildOf(Set.class); 1123 } 1124 1125 /** 1126 * Returns <jk>true</jk> if this class extends from {@link List}. 1127 * 1128 * @return <jk>true</jk> if this class extends from {@link List}. 1129 */ 1130 public boolean isList() { 1131 return cc == COLLECTION && info.isChildOf(List.class); 1132 } 1133 1134 /** 1135 * Returns <jk>true</jk> if this class is <code><jk>byte</jk>[]</code>. 1136 * 1137 * @return <jk>true</jk> if this class is <code><jk>byte</jk>[]</code>. 1138 */ 1139 public boolean isByteArray() { 1140 return cc == ARRAY && this.innerClass == byte[].class; 1141 } 1142 1143 /** 1144 * Returns <jk>true</jk> if this class is {@link Class}. 1145 * 1146 * @return <jk>true</jk> if this class is {@link Class}. 1147 */ 1148 public boolean isClass() { 1149 return cc == ClassCategory.CLASS; 1150 } 1151 1152 /** 1153 * Returns <jk>true</jk> if this class is {@link Method}. 1154 * 1155 * @return <jk>true</jk> if this class is {@link Method}. 1156 */ 1157 public boolean isMethod() { 1158 return cc == METHOD; 1159 } 1160 1161 /** 1162 * Returns <jk>true</jk> if this class is an {@link Enum}. 1163 * 1164 * @return <jk>true</jk> if this class is an {@link Enum}. 1165 */ 1166 public boolean isEnum() { 1167 return cc == ENUM; 1168 } 1169 1170 /** 1171 * Returns <jk>true</jk> if this class is an array. 1172 * 1173 * @return <jk>true</jk> if this class is an array. 1174 */ 1175 public boolean isArray() { 1176 return cc == ARRAY; 1177 } 1178 1179 /** 1180 * Returns <jk>true</jk> if this class is a bean. 1181 * 1182 * @return <jk>true</jk> if this class is a bean. 1183 */ 1184 public boolean isBean() { 1185 return beanMeta != null; 1186 } 1187 1188 /** 1189 * Returns <jk>true</jk> if this class is {@link Object}. 1190 * 1191 * @return <jk>true</jk> if this class is {@link Object}. 1192 */ 1193 public boolean isObject() { 1194 return cc == OBJ; 1195 } 1196 1197 /** 1198 * Returns <jk>true</jk> if this class is not {@link Object}. 1199 * 1200 * @return <jk>true</jk> if this class is not {@link Object}. 1201 */ 1202 public boolean isNotObject() { 1203 return cc != OBJ; 1204 } 1205 1206 /** 1207 * Returns <jk>true</jk> if this class is a subclass of {@link Number}. 1208 * 1209 * @return <jk>true</jk> if this class is a subclass of {@link Number}. 1210 */ 1211 public boolean isNumber() { 1212 return cc == NUMBER || cc == DECIMAL; 1213 } 1214 1215 /** 1216 * Returns <jk>true</jk> if this class is a subclass of {@link Float} or {@link Double}. 1217 * 1218 * @return <jk>true</jk> if this class is a subclass of {@link Float} or {@link Double}. 1219 */ 1220 public boolean isDecimal() { 1221 return cc == DECIMAL; 1222 } 1223 1224 /** 1225 * Returns <jk>true</jk> if this class is either {@link Float} or <jk>float</jk>. 1226 * 1227 * @return <jk>true</jk> if this class is either {@link Float} or <jk>float</jk>. 1228 */ 1229 public boolean isFloat() { 1230 return innerClass == Float.class || innerClass == float.class; 1231 } 1232 1233 /** 1234 * Returns <jk>true</jk> if this class is either {@link Double} or <jk>double</jk>. 1235 * 1236 * @return <jk>true</jk> if this class is either {@link Double} or <jk>double</jk>. 1237 */ 1238 public boolean isDouble() { 1239 return innerClass == Double.class || innerClass == double.class; 1240 } 1241 1242 /** 1243 * Returns <jk>true</jk> if this class is either {@link Short} or <jk>short</jk>. 1244 * 1245 * @return <jk>true</jk> if this class is either {@link Short} or <jk>short</jk>. 1246 */ 1247 public boolean isShort() { 1248 return innerClass == Short.class || innerClass == short.class; 1249 } 1250 1251 /** 1252 * Returns <jk>true</jk> if this class is either {@link Integer} or <jk>int</jk>. 1253 * 1254 * @return <jk>true</jk> if this class is either {@link Integer} or <jk>int</jk>. 1255 */ 1256 public boolean isInteger() { 1257 return innerClass == Integer.class || innerClass == int.class; 1258 } 1259 1260 /** 1261 * Returns <jk>true</jk> if this class is either {@link Long} or <jk>long</jk>. 1262 * 1263 * @return <jk>true</jk> if this class is either {@link Long} or <jk>long</jk>. 1264 */ 1265 public boolean isLong() { 1266 return innerClass == Long.class || innerClass == long.class; 1267 } 1268 1269 /** 1270 * Returns <jk>true</jk> if this metadata represents the specified type. 1271 * 1272 * @param c The class to test against. 1273 * @return <jk>true</jk> if this metadata represents the specified type. 1274 */ 1275 public boolean isType(Class<?> c) { 1276 return info.isChildOf(c); 1277 } 1278 1279 /** 1280 * Returns <jk>true</jk> if this class is a {@link Boolean}. 1281 * 1282 * @return <jk>true</jk> if this class is a {@link Boolean}. 1283 */ 1284 public boolean isBoolean() { 1285 return cc == BOOLEAN; 1286 } 1287 1288 /** 1289 * Returns <jk>true</jk> if this class is a subclass of {@link CharSequence}. 1290 * 1291 * @return <jk>true</jk> if this class is a subclass of {@link CharSequence}. 1292 */ 1293 public boolean isCharSequence() { 1294 return cc == STR || cc == CHARSEQ; 1295 } 1296 1297 /** 1298 * Returns <jk>true</jk> if this class is a {@link String}. 1299 * 1300 * @return <jk>true</jk> if this class is a {@link String}. 1301 */ 1302 public boolean isString() { 1303 return cc == STR; 1304 } 1305 1306 /** 1307 * Returns <jk>true</jk> if this class is a {@link Character}. 1308 * 1309 * @return <jk>true</jk> if this class is a {@link Character}. 1310 */ 1311 public boolean isChar() { 1312 return cc == CHAR; 1313 } 1314 1315 /** 1316 * Returns <jk>true</jk> if this class is a primitive. 1317 * 1318 * @return <jk>true</jk> if this class is a primitive. 1319 */ 1320 public boolean isPrimitive() { 1321 return innerClass.isPrimitive(); 1322 } 1323 1324 /** 1325 * Returns <jk>true</jk> if this class is a {@link Date} or {@link Calendar}. 1326 * 1327 * @return <jk>true</jk> if this class is a {@link Date} or {@link Calendar}. 1328 */ 1329 public boolean isDateOrCalendar() { 1330 return cc == DATE; 1331 } 1332 1333 /** 1334 * Returns <jk>true</jk> if this class is a {@link Date}. 1335 * 1336 * @return <jk>true</jk> if this class is a {@link Date}. 1337 */ 1338 public boolean isDate() { 1339 return cc == DATE && info.isChildOf(Date.class); 1340 } 1341 1342 /** 1343 * Returns <jk>true</jk> if this class is a {@link Calendar}. 1344 * 1345 * @return <jk>true</jk> if this class is a {@link Calendar}. 1346 */ 1347 public boolean isCalendar() { 1348 return cc == DATE && info.isChildOf(Calendar.class); 1349 } 1350 1351 /** 1352 * Returns <jk>true</jk> if this class is a {@link URI} or {@link URL}. 1353 * 1354 * @return <jk>true</jk> if this class is a {@link URI} or {@link URL}. 1355 */ 1356 public boolean isUri() { 1357 return cc == URI; 1358 } 1359 1360 /** 1361 * Returns <jk>true</jk> if this class is a {@link Reader}. 1362 * 1363 * @return <jk>true</jk> if this class is a {@link Reader}. 1364 */ 1365 public boolean isReader() { 1366 return cc == READER; 1367 } 1368 1369 /** 1370 * Returns <jk>true</jk> if this class is an {@link InputStream}. 1371 * 1372 * @return <jk>true</jk> if this class is an {@link InputStream}. 1373 */ 1374 public boolean isInputStream() { 1375 return cc == INPUTSTREAM; 1376 } 1377 1378 /** 1379 * Returns <jk>true</jk> if this class is {@link Void} or <jk>void</jk>. 1380 * 1381 * @return <jk>true</jk> if this class is {@link Void} or <jk>void</jk>. 1382 */ 1383 public boolean isVoid() { 1384 return cc == VOID; 1385 } 1386 1387 /** 1388 * Returns <jk>true</jk> if this metadata represents an array of argument types. 1389 * 1390 * @return <jk>true</jk> if this metadata represents an array of argument types. 1391 */ 1392 public boolean isArgs() { 1393 return cc == ARGS; 1394 } 1395 1396 /** 1397 * Returns the argument types of this meta. 1398 * 1399 * @return The argument types of this meta, or <jk>null</jk> if this isn't an array of argument types. 1400 */ 1401 public ClassMeta<?>[] getArgs() { 1402 return args; 1403 } 1404 1405 /** 1406 * Returns the argument metadata at the specified index if this is an args metadata object. 1407 * 1408 * @param index The argument index. 1409 * @return The The argument metadata. Never <jk>null</jk>. 1410 * @throws BeanRuntimeException If this metadata object is not a list of arguments, or the index is out of range. 1411 */ 1412 public ClassMeta<?> getArg(int index) { 1413 if (args != null && index >= 0 && index < args.length) 1414 return args[index]; 1415 throw new BeanRuntimeException("Invalid argument index specified: {0}. Only {1} arguments are defined.", index, args == null ? 0 : args.length); 1416 } 1417 1418 /** 1419 * Returns <jk>true</jk> if instance of this object can be <jk>null</jk>. 1420 * 1421 * <p> 1422 * Objects can be <jk>null</jk>, but primitives cannot, except for chars which can be represented by 1423 * <code>(<jk>char</jk>)0</code>. 1424 * 1425 * @return <jk>true</jk> if instance of this class can be null. 1426 */ 1427 public boolean isNullable() { 1428 if (innerClass.isPrimitive()) 1429 return cc == CHAR; 1430 return true; 1431 } 1432 1433 /** 1434 * Returns <jk>true</jk> if this class is abstract. 1435 * 1436 * @return <jk>true</jk> if this class is abstract. 1437 */ 1438 public boolean isAbstract() { 1439 return isAbstract; 1440 } 1441 1442 /** 1443 * Returns <jk>true</jk> if this class is an inner class. 1444 * 1445 * @return <jk>true</jk> if this class is an inner class. 1446 */ 1447 public boolean isMemberClass() { 1448 return isMemberClass; 1449 } 1450 1451 /** 1452 * All public methods on this class including static methods. 1453 * 1454 * <p> 1455 * Keys are method signatures. 1456 * 1457 * @return The public methods on this class. 1458 */ 1459 public Map<String,Method> getPublicMethods() { 1460 return publicMethods; 1461 } 1462 1463 /** 1464 * Returns the {@link PojoSwap} associated with this class that's the best match for the specified session. 1465 * 1466 * @param session 1467 * The current bean session. 1468 * <br>If multiple swaps are associated with a class, only the first one with a matching media type will 1469 * be returned. 1470 * @return 1471 * The {@link PojoSwap} associated with this class, or <jk>null</jk> if there are no POJO swaps associated with 1472 * this class. 1473 */ 1474 public PojoSwap<T,?> getPojoSwap(BeanSession session) { 1475 if (pojoSwaps != null) { 1476 int matchQuant = 0, matchIndex = -1; 1477 1478 for (int i = 0; i < pojoSwaps.length; i++) { 1479 int q = pojoSwaps[i].match(session); 1480 if (q > matchQuant) { 1481 matchQuant = q; 1482 matchIndex = i; 1483 } 1484 } 1485 1486 if (matchIndex > -1) 1487 return pojoSwaps[matchIndex]; 1488 } 1489 return null; 1490 } 1491 1492 /** 1493 * Returns the builder swap associated with this class. 1494 * 1495 * @param session The current bean session. 1496 * @return The builder swap associated with this class, or <jk>null</jk> if it doesn't exist. 1497 */ 1498 public BuilderSwap<T,?> getBuilderSwap(BeanSession session) { 1499 return builderSwap; 1500 } 1501 1502 /** 1503 * Returns the {@link BeanMeta} associated with this class. 1504 * 1505 * @return 1506 * The {@link BeanMeta} associated with this class, or <jk>null</jk> if there is no bean meta associated with 1507 * this class. 1508 */ 1509 public BeanMeta<T> getBeanMeta() { 1510 return beanMeta; 1511 } 1512 1513 /** 1514 * Returns the no-arg constructor for this class. 1515 * 1516 * @return The no-arg constructor for this class, or <jk>null</jk> if it does not exist. 1517 */ 1518 public ConstructorInfo getConstructor() { 1519 return noArgConstructor; 1520 } 1521 1522 /** 1523 * Returns the interface proxy invocation handler for this class. 1524 * 1525 * @return The interface proxy invocation handler, or <jk>null</jk> if it does not exist. 1526 */ 1527 public InvocationHandler getProxyInvocationHandler() { 1528 return invocationHandler; 1529 } 1530 1531 /** 1532 * Returns <jk>true</jk> if this class has a no-arg constructor or invocation handler. 1533 * 1534 * @return <jk>true</jk> if a new instance of this class can be constructed. 1535 */ 1536 public boolean canCreateNewInstance() { 1537 if (isMemberClass) 1538 return false; 1539 if (noArgConstructor != null) 1540 return true; 1541 if (getProxyInvocationHandler() != null) 1542 return true; 1543 if (isArray() && elementType.canCreateNewInstance()) 1544 return true; 1545 return false; 1546 } 1547 1548 /** 1549 * Returns <jk>true</jk> if this class has a no-arg constructor or invocation handler. 1550 * Returns <jk>false</jk> if this is a non-static member class and the outer object does not match the class type of 1551 * the defining class. 1552 * 1553 * @param outer 1554 * The outer class object for non-static member classes. Can be <jk>null</jk> for non-member or static classes. 1555 * @return 1556 * <jk>true</jk> if a new instance of this class can be created within the context of the specified outer object. 1557 */ 1558 public boolean canCreateNewInstance(Object outer) { 1559 if (isMemberClass) 1560 return outer != null && noArgConstructor != null && noArgConstructor.hasParamTypes(outer.getClass()); 1561 return canCreateNewInstance(); 1562 } 1563 1564 /** 1565 * Returns <jk>true</jk> if this class can be instantiated as a bean. 1566 * Returns <jk>false</jk> if this is a non-static member class and the outer object does not match the class type of 1567 * the defining class. 1568 * 1569 * @param outer 1570 * The outer class object for non-static member classes. Can be <jk>null</jk> for non-member or static classes. 1571 * @return 1572 * <jk>true</jk> if a new instance of this bean can be created within the context of the specified outer object. 1573 */ 1574 public boolean canCreateNewBean(Object outer) { 1575 if (beanMeta == null) 1576 return false; 1577 if (beanMeta.constructor == null) 1578 return false; 1579 if (isMemberClass) 1580 return outer != null && beanMeta.constructor.hasParamTypes(outer.getClass()); 1581 return true; 1582 } 1583 1584 /** 1585 * Returns <jk>true</jk> if this class can call the {@link #newInstanceFromString(Object, String)} method. 1586 * 1587 * @param outer 1588 * The outer class object for non-static member classes. 1589 * Can be <jk>null</jk> for non-member or static classes. 1590 * @return <jk>true</jk> if this class has a no-arg constructor or invocation handler. 1591 */ 1592 public boolean canCreateNewInstanceFromString(Object outer) { 1593 if (fromStringMethod != null) 1594 return true; 1595 if (stringConstructor != null) { 1596 if (isMemberClass) 1597 return outer != null && stringConstructor.hasParamTypes(outer.getClass(), String.class); 1598 return true; 1599 } 1600 return false; 1601 } 1602 1603 /** 1604 * Returns the method or field annotated with {@link NameProperty @NameProperty}. 1605 * 1606 * @return 1607 * The method or field annotated with {@link NameProperty @NameProperty} or <jk>null</jk> if method does not 1608 * exist. 1609 */ 1610 public Setter getNameProperty() { 1611 return namePropertyMethod; 1612 } 1613 1614 /** 1615 * Returns the method or field annotated with {@link ParentProperty @ParentProperty}. 1616 * 1617 * @return 1618 * The method or field annotated with {@link ParentProperty @ParentProperty} or <jk>null</jk> if method does not 1619 * exist. 1620 */ 1621 public Setter getParentProperty() { 1622 return parentPropertyMethod; 1623 } 1624 1625 /** 1626 * Returns the reason why this class is not a bean, or <jk>null</jk> if it is a bean. 1627 * 1628 * @return The reason why this class is not a bean, or <jk>null</jk> if it is a bean. 1629 */ 1630 public synchronized String getNotABeanReason() { 1631 return notABeanReason; 1632 } 1633 1634 /** 1635 * Returns any exception that was throw in the <c>init()</c> method. 1636 * 1637 * @return The cached exception. 1638 */ 1639 public Throwable getInitException() { 1640 return initException; 1641 } 1642 1643 /** 1644 * Returns the {@link BeanContext} that created this object. 1645 * 1646 * @return The bean context. 1647 */ 1648 public BeanContext getBeanContext() { 1649 return beanContext; 1650 } 1651 1652 /** 1653 * Returns the default value for primitives such as <jk>int</jk> or <jk>Integer</jk>. 1654 * 1655 * @return The default value, or <jk>null</jk> if this class type is not a primitive. 1656 */ 1657 @SuppressWarnings("unchecked") 1658 public T getPrimitiveDefault() { 1659 return (T)primitiveDefault; 1660 } 1661 1662 /** 1663 * If this is an {@link Optional}, returns an empty optional. 1664 * 1665 * <p> 1666 * Note that if this is a nested optional, will recursively create empty optionals. 1667 * 1668 * @return An empty optional, or <jk>null</jk> if this isn't an optional. 1669 */ 1670 public Optional<?> getOptionalDefault() { 1671 if (isOptional()) 1672 return Optional.ofNullable(getElementType().getOptionalDefault()); 1673 return null; 1674 } 1675 1676 /** 1677 * Converts the specified object to a string. 1678 * 1679 * @param t The object to convert. 1680 * @return The object converted to a string, or <jk>null</jk> if the object was null. 1681 */ 1682 public String toString(Object t) { 1683 if (t == null) 1684 return null; 1685 if (isEnum() && beanContext.isUseEnumNames()) 1686 return ((Enum<?>)t).name(); 1687 return t.toString(); 1688 } 1689 1690 /** 1691 * Create a new instance of the main class of this declared type from a <c>String</c> input. 1692 * 1693 * <p> 1694 * In order to use this method, the class must have one of the following methods: 1695 * <ul> 1696 * <li><code><jk>public static</jk> T valueOf(String in);</code> 1697 * <li><code><jk>public static</jk> T fromString(String in);</code> 1698 * <li><code><jk>public</jk> T(String in);</code> 1699 * </ul> 1700 * 1701 * @param outer 1702 * The outer class object for non-static member classes. Can be <jk>null</jk> for non-member or static classes. 1703 * @param arg The input argument value. 1704 * @return A new instance of the object, or <jk>null</jk> if there is no string constructor on the object. 1705 * @throws ExecutableException Exception occurred on invoked constructor/method/field. 1706 */ 1707 @SuppressWarnings({ "unchecked", "rawtypes" }) 1708 public T newInstanceFromString(Object outer, String arg) throws ExecutableException { 1709 1710 if (isEnum() && beanContext.isUseEnumNames() && fromStringMethod != null) 1711 return (T)Enum.valueOf((Class<? extends Enum>)this.innerClass, arg); 1712 1713 Method m = fromStringMethod; 1714 if (m != null) { 1715 try { 1716 return (T)m.invoke(null, arg); 1717 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { 1718 throw new ExecutableException(e); 1719 } 1720 } 1721 ConstructorInfo c = stringConstructor; 1722 if (c != null) { 1723 if (isMemberClass) 1724 return c.<T>invoke(outer, arg); 1725 return c.<T>invoke(arg); 1726 } 1727 throw new InstantiationError("No string constructor or valueOf(String) method found for class '"+getInnerClass().getName()+"'"); 1728 } 1729 1730 /** 1731 * Create a new instance of the main class of this declared type. 1732 * 1733 * @return A new instance of the object, or <jk>null</jk> if there is no no-arg constructor on the object. 1734 * @throws ExecutableException Exception occurred on invoked constructor/method/field. 1735 */ 1736 @SuppressWarnings("unchecked") 1737 public T newInstance() throws ExecutableException { 1738 if (isArray()) 1739 return (T)Array.newInstance(getInnerClass().getComponentType(), 0); 1740 ConstructorInfo c = getConstructor(); 1741 if (c != null) 1742 return c.<T>invoke((Object[])null); 1743 InvocationHandler h = getProxyInvocationHandler(); 1744 if (h != null) 1745 return (T)Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] { getInnerClass(), java.io.Serializable.class }, h); 1746 if (isArray()) 1747 return (T)Array.newInstance(this.elementType.innerClass,0); 1748 return null; 1749 } 1750 1751 /** 1752 * Same as {@link #newInstance()} except for instantiating non-static member classes. 1753 * 1754 * @param outer 1755 * The instance of the owning object of the member class instance. 1756 * Can be <jk>null</jk> if instantiating a non-member or static class. 1757 * @return A new instance of the object, or <jk>null</jk> if there is no no-arg constructor on the object. 1758 * @throws ExecutableException Exception occurred on invoked constructor/method/field. 1759 */ 1760 public T newInstance(Object outer) throws ExecutableException { 1761 if (isMemberClass) 1762 return noArgConstructor.<T>invoke(outer); 1763 return newInstance(); 1764 } 1765 1766 /** 1767 * Similar to {@link #equals(Object)} except primitive and Object types that are similar are considered the same. 1768 * (e.g. <jk>boolean</jk> == <c>Boolean</c>). 1769 * 1770 * @param cm The class meta to compare to. 1771 * @return <jk>true</jk> if the specified class-meta is equivalent to this one. 1772 */ 1773 public boolean same(ClassMeta<?> cm) { 1774 if (equals(cm)) 1775 return true; 1776 return (isPrimitive() && cc == cm.cc); 1777 } 1778 1779 @Override /* Object */ 1780 public String toString() { 1781 return toString(false); 1782 } 1783 1784 /** 1785 * Same as {@link #toString()} except use simple class names. 1786 * 1787 * @param simple Print simple class names only (no package). 1788 * @return A new string. 1789 */ 1790 public String toString(boolean simple) { 1791 return toString(new StringBuilder(), simple).toString(); 1792 } 1793 1794 /** 1795 * Appends this object as a readable string to the specified string builder. 1796 * 1797 * @param sb The string builder to append this object to. 1798 * @param simple Print simple class names only (no package). 1799 * @return The same string builder passed in (for method chaining). 1800 */ 1801 protected StringBuilder toString(StringBuilder sb, boolean simple) { 1802 String n = innerClass.getName(); 1803 if (simple) { 1804 int i = n.lastIndexOf('.'); 1805 n = n.substring(i == -1 ? 0 : i+1).replace('$', '.'); 1806 } 1807 if (cc == ARRAY) 1808 return elementType.toString(sb, simple).append('[').append(']'); 1809 if (cc == MAP) 1810 return sb.append(n).append(keyType.isObject() && valueType.isObject() ? "" : "<"+keyType.toString(simple)+","+valueType.toString(simple)+">"); 1811 if (cc == BEANMAP) 1812 return sb.append(BeanMap.class.getName()).append('<').append(n).append('>'); 1813 if (cc == COLLECTION || cc == OPTIONAL) 1814 return sb.append(n).append(elementType.isObject() ? "" : "<"+elementType.toString(simple)+">"); 1815 return sb.append(n); 1816 } 1817 1818 /** 1819 * Returns <jk>true</jk> if the specified object is an instance of this class. 1820 * 1821 * <p> 1822 * This is a simple comparison on the base class itself and not on any generic parameters. 1823 * 1824 * @param o The object to check. 1825 * @return <jk>true</jk> if the specified object is an instance of this class. 1826 */ 1827 public boolean isInstance(Object o) { 1828 if (o != null) 1829 return info.isParentOf(o.getClass()) || (isPrimitive() && info.getPrimitiveWrapper() == o.getClass()); 1830 return false; 1831 } 1832 1833 /** 1834 * Returns a readable name for this class (e.g. <js>"java.lang.String"</js>, <js>"boolean[]"</js>). 1835 * 1836 * @return The readable name for this class. 1837 */ 1838 public String getFullName() { 1839 return info.getFullName(); 1840 } 1841 1842 /** 1843 * Shortcut for calling {@link Class#getName()} on the inner class of this metadata. 1844 * 1845 * @return The name of the inner class. 1846 */ 1847 public String getName() { 1848 return innerClass.getName(); 1849 } 1850 1851 /** 1852 * Shortcut for calling {@link Class#getSimpleName()} on the inner class of this metadata. 1853 * 1854 * @return The simple name of the inner class. 1855 */ 1856 public String getSimpleName() { 1857 return innerClass.getSimpleName(); 1858 } 1859 1860 /** 1861 * Returns <jk>true</jk> if this class has a transform associated with it that allows it to be created from a Reader. 1862 * 1863 * @return <jk>true</jk> if this class has a transform associated with it that allows it to be created from a Reader. 1864 */ 1865 public boolean hasReaderMutater() { 1866 return hasMutaterFrom(Reader.class); 1867 } 1868 1869 /** 1870 * Returns the transform for this class for creating instances from a Reader. 1871 * 1872 * @return The transform, or <jk>null</jk> if no such transform exists. 1873 */ 1874 public Mutater<Reader,T> getReaderMutater() { 1875 return getFromMutater(Reader.class); 1876 } 1877 1878 /** 1879 * Returns <jk>true</jk> if this class has a transform associated with it that allows it to be created from an InputStream. 1880 * 1881 * @return <jk>true</jk> if this class has a transform associated with it that allows it to be created from an InputStream. 1882 */ 1883 public boolean hasInputStreamMutater() { 1884 return hasMutaterFrom(InputStream.class); 1885 } 1886 1887 /** 1888 * Returns the transform for this class for creating instances from an InputStream. 1889 * 1890 * @return The transform, or <jk>null</jk> if no such transform exists. 1891 */ 1892 public Mutater<InputStream,T> getInputStreamMutater() { 1893 return getFromMutater(InputStream.class); 1894 } 1895 1896 /** 1897 * Returns <jk>true</jk> if this class has a transform associated with it that allows it to be created from a String. 1898 * 1899 * @return <jk>true</jk> if this class has a transform associated with it that allows it to be created from a String. 1900 */ 1901 public boolean hasStringMutater() { 1902 return stringMutater != null; 1903 } 1904 1905 /** 1906 * Returns the transform for this class for creating instances from a String. 1907 * 1908 * @return The transform, or <jk>null</jk> if no such transform exists. 1909 */ 1910 public Mutater<String,T> getStringMutater() { 1911 return stringMutater; 1912 } 1913 1914 /** 1915 * Returns <jk>true</jk> if this class can be instantiated from the specified type. 1916 * 1917 * @param c The class type to convert from. 1918 * @return <jk>true</jk> if this class can be instantiated from the specified type. 1919 */ 1920 public boolean hasMutaterFrom(Class<?> c) { 1921 return getFromMutater(c) != null; 1922 } 1923 1924 /** 1925 * Returns <jk>true</jk> if this class can be instantiated from the specified type. 1926 * 1927 * @param c The class type to convert from. 1928 * @return <jk>true</jk> if this class can be instantiated from the specified type. 1929 */ 1930 public boolean hasMutaterFrom(ClassMeta<?> c) { 1931 return getFromMutater(c.getInnerClass()) != null; 1932 } 1933 1934 /** 1935 * Returns <jk>true</jk> if this class can be transformed to the specified type. 1936 * 1937 * @param c The class type to convert from. 1938 * @return <jk>true</jk> if this class can be transformed to the specified type. 1939 */ 1940 public boolean hasMutaterTo(Class<?> c) { 1941 return getToMutater(c) != null; 1942 } 1943 1944 /** 1945 * Returns <jk>true</jk> if this class can be transformed to the specified type. 1946 * 1947 * @param c The class type to convert from. 1948 * @return <jk>true</jk> if this class can be transformed to the specified type. 1949 */ 1950 public boolean hasMutaterTo(ClassMeta<?> c) { 1951 return getToMutater(c.getInnerClass()) != null; 1952 } 1953 1954 /** 1955 * Transforms the specified object into an instance of this class. 1956 * 1957 * @param o The object to transform. 1958 * @return The transformed object. 1959 */ 1960 @SuppressWarnings({"unchecked","rawtypes"}) 1961 public T mutateFrom(Object o) { 1962 Mutater t = getFromMutater(o.getClass()); 1963 return (T)(t == null ? null : t.mutate(o)); 1964 } 1965 1966 /** 1967 * Transforms the specified object into an instance of this class. 1968 * 1969 * @param o The object to transform. 1970 * @param c The class 1971 * @return The transformed object. 1972 */ 1973 @SuppressWarnings({"unchecked","rawtypes"}) 1974 public <O> O mutateTo(Object o, Class<O> c) { 1975 Mutater t = getToMutater(c); 1976 return (O)(t == null ? null : t.mutate(o)); 1977 } 1978 1979 /** 1980 * Transforms the specified object into an instance of this class. 1981 * 1982 * @param o The object to transform. 1983 * @param c The class 1984 * @return The transformed object. 1985 */ 1986 public <O> O mutateTo(Object o, ClassMeta<O> c) { 1987 return mutateTo(o, c.getInnerClass()); 1988 } 1989 1990 /** 1991 * Returns the transform for this class for creating instances from other object types. 1992 * 1993 * @param c The transform-from class. 1994 * @return The transform, or <jk>null</jk> if no such transform exists. 1995 */ 1996 @SuppressWarnings({ "rawtypes", "unchecked" }) 1997 public <I> Mutater<I,T> getFromMutater(Class<I> c) { 1998 Mutater t = fromMutaters.get(c); 1999 if (t == Mutaters.NULL) 2000 return null; 2001 if (t == null) { 2002 t = Mutaters.get(c, innerClass); 2003 if (t == null) 2004 t = Mutaters.NULL; 2005 fromMutaters.put(c, t); 2006 } 2007 return t == Mutaters.NULL ? null : t; 2008 } 2009 2010 /** 2011 * Returns the transform for this class for creating instances from other object types. 2012 * 2013 * @param c The transform-from class. 2014 * @return The transform, or <jk>null</jk> if no such transform exists. 2015 */ 2016 @SuppressWarnings({ "rawtypes", "unchecked" }) 2017 public <O> Mutater<T,O> getToMutater(Class<O> c) { 2018 Mutater t = toMutaters.get(c); 2019 if (t == Mutaters.NULL) 2020 return null; 2021 if (t == null) { 2022 t = Mutaters.get(innerClass, c); 2023 if (t == null) 2024 t = Mutaters.NULL; 2025 toMutaters.put(c, t); 2026 } 2027 return t == Mutaters.NULL ? null : t; 2028 } 2029 2030 /** 2031 * Shortcut for calling <code>getInnerClass().getAnnotation(a) != <jk>null</jk></code>. 2032 * 2033 * @param a The annotation to check for. 2034 * @return <jk>true</jk> if the inner class has the annotation. 2035 */ 2036 public boolean hasAnnotation(Class<? extends Annotation> a) { 2037 return getAnnotation(a) != null; 2038 } 2039 2040 /** 2041 * Shortcut for calling <c>getInnerClass().getAnnotation(a)</c>. 2042 * 2043 * @param a The annotation to retrieve. 2044 * @return The specified annotation, or <jk>null</jk> if the class does not have the specified annotation. 2045 */ 2046 public <A extends Annotation> A getAnnotation(Class<A> a) { 2047 return info.getAnnotation(a, beanContext == null ? BeanContext.DEFAULT : beanContext); 2048 } 2049 2050 /** 2051 * Returns the declared annotation defined on this class. 2052 * 2053 * @param a The annotation to retrieve. 2054 * @return The specified annotation, or <jk>null</jk> if the class does not have the specified annotation. 2055 */ 2056 public <A extends Annotation> A getDeclaredAnnotation(Class<A> a) { 2057 return info.getDeclaredAnnotation(a, beanContext == null ? BeanContext.DEFAULT : beanContext); 2058 } 2059 2060 /** 2061 * Returns all annotations of the specified type defined on the specified class or parent classes/interfaces. 2062 * 2063 * @param a 2064 * The annotation to search for. 2065 * @return 2066 * A list of all matching annotations found in child-to-parent order, or an empty list if none found. 2067 */ 2068 public <A extends Annotation> List<A> getAnnotations(Class<A> a) { 2069 return info.getAnnotations(a, beanContext == null ? BeanContext.DEFAULT : beanContext); 2070 } 2071 2072 /** 2073 * Identical to {@link #getAnnotations(Class)} but optionally returns the list in reverse (parent-to-child) order. 2074 * 2075 * @param a 2076 * The annotation to search for. 2077 * @return 2078 * A list of all matching annotations found or an empty list if none found. 2079 */ 2080 public <A extends Annotation> List<A> getAnnotationsParentFirst(Class<A> a) { 2081 return info.getAnnotationsParentFirst(a, beanContext == null ? BeanContext.DEFAULT : beanContext); 2082 } 2083 2084 @Override /* Object */ 2085 public int hashCode() { 2086 return innerClass.hashCode(); 2087 } 2088 2089 @Override /* Object */ 2090 public boolean equals(Object o) { 2091 if (o == null || ! (o instanceof ClassMeta)) 2092 return false; 2093 ClassMeta<?> o2 = (ClassMeta<?>)o; 2094 return o2.innerClass.equals(innerClass); 2095 } 2096}