Repository: incubator-juneau Updated Branches: refs/heads/master ecc843021 -> 83f2b35ba
Make fields in BeanMeta final. Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/83f2b35b Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/83f2b35b Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/83f2b35b Branch: refs/heads/master Commit: 83f2b35ba002b4d0fbefa02358476e00e332e467 Parents: ecc8430 Author: jamesbognar <[email protected]> Authored: Sun Aug 28 20:35:47 2016 -0400 Committer: jamesbognar <[email protected]> Committed: Sun Aug 28 20:35:47 2016 -0400 ---------------------------------------------------------------------- .../main/java/org/apache/juneau/BeanMeta.java | 517 ++++++++++--------- .../org/apache/juneau/BeanMetaFiltered.java | 32 +- .../org/apache/juneau/BeanPropertyMeta.java | 6 +- .../main/java/org/apache/juneau/ClassMeta.java | 5 +- 4 files changed, 287 insertions(+), 273 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/83f2b35b/juneau-core/src/main/java/org/apache/juneau/BeanMeta.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/BeanMeta.java b/juneau-core/src/main/java/org/apache/juneau/BeanMeta.java index 1453dbb..840b68b 100644 --- a/juneau-core/src/main/java/org/apache/juneau/BeanMeta.java +++ b/juneau-core/src/main/java/org/apache/juneau/BeanMeta.java @@ -62,44 +62,43 @@ import org.apache.juneau.utils.*; public class BeanMeta<T> { /** The target class type that this meta object describes. */ - protected ClassMeta<T> classMeta; + protected final ClassMeta<T> classMeta; /** The target class that this meta object describes. */ - protected Class<T> c; + protected final Class<T> c; /** The properties on the target class. */ - protected Map<String,BeanPropertyMeta> properties; + protected final Map<String,BeanPropertyMeta> properties; /** The getter properties on the target class. */ - protected Map<Method,String> getterProps = new HashMap<Method,String>(); + protected final Map<Method,String> getterProps; /** The setter properties on the target class. */ - protected Map<Method,String> setterProps = new HashMap<Method,String>(); + protected final Map<Method,String> setterProps; /** The bean context that created this metadata object. */ - protected BeanContext ctx; + protected final BeanContext ctx; /** Optional bean filter associated with the target class. */ - protected BeanFilter<? extends T> beanFilter; + protected final BeanFilter<? extends T> beanFilter; /** Type variables implemented by this bean. */ - protected Map<Class<?>,Class<?>[]> typeVarImpls; + protected final Map<Class<?>,Class<?>[]> typeVarImpls; /** The constructor for this bean. */ - protected Constructor<T> constructor; + protected final Constructor<T> constructor; /** For beans with constructors with BeanConstructor annotation, this is the list of constructor arg properties. */ - protected String[] constructorArgs = new String[0]; + protected final String[] constructorArgs; - private MetadataMap extMeta = new MetadataMap(); // Extended metadata + private final MetadataMap extMeta; // Extended metadata // Other fields - BeanPropertyMeta uriProperty; // The property identified as the URI for this bean (annotated with @BeanProperty.beanUri). - BeanPropertyMeta subTypeIdProperty; // The property indentified as the sub type differentiator property (identified by @Bean.subTypeProperty annotation). - PropertyNamer propertyNamer; // Class used for calculating bean property names. - BeanPropertyMeta classProperty; // "_class" mock bean property. + final BeanPropertyMeta uriProperty; // The property identified as the URI for this bean (annotated with @BeanProperty.beanUri). + final BeanPropertyMeta subTypeIdProperty; // The property indentified as the sub type differentiator property (identified by @Bean.subTypeProperty annotation). + private final BeanPropertyMeta classProperty; // "_class" mock bean property. - BeanMeta() {} + final String notABeanReason; /** * Constructor. @@ -107,253 +106,315 @@ public class BeanMeta<T> { * @param classMeta The target class. * @param ctx The bean context that created this object. * @param beanFilter Optional bean filter associated with the target class. Can be <jk>null</jk>. + * @param pNames Explicit list of property names and order of properties. If <jk>null</jk>, determine automatically. */ - protected BeanMeta(final ClassMeta<T> classMeta, BeanContext ctx, BeanFilter<? extends T> beanFilter) { + protected BeanMeta(final ClassMeta<T> classMeta, BeanContext ctx, BeanFilter<? extends T> beanFilter, String[] pNames) { this.classMeta = classMeta; this.ctx = ctx; + this.c = classMeta.getInnerClass(); + + Builder<T> b = new Builder<T>(classMeta, ctx, beanFilter, pNames); + this.notABeanReason = b.init(this); + this.beanFilter = beanFilter; + this.properties = b.properties; + this.getterProps = Collections.unmodifiableMap(b.getterProps); + this.setterProps = Collections.unmodifiableMap(b.setterProps); + this.typeVarImpls = b.typeVarImpls; + this.constructor = b.constructor; + this.constructorArgs = b.constructorArgs; + this.extMeta = b.extMeta; + this.uriProperty = b.uriProperty; + this.subTypeIdProperty = b.subTypeIdProperty; this.classProperty = new BeanPropertyMeta(this, "_class", ctx.string()); - this.c = classMeta.getInnerClass(); } - /** - * Returns the {@link ClassMeta} of this bean. - * - * @return The {@link ClassMeta} of this bean. - */ - @BeanIgnore - public ClassMeta<T> getClassMeta() { - return classMeta; - } - /** - * Initializes this bean meta, and returns an error message if the specified class is not - * a bean for any reason. - * - * @return Reason why this class isn't a bean, or <jk>null</jk> if no problems detected. - * @throws BeanRuntimeException If unexpected error occurs such as invalid annotations on the bean class. - */ - @SuppressWarnings("unchecked") - protected String init() throws BeanRuntimeException { - - try { - Visibility - conVis = ctx.beanConstructorVisibility, - cVis = ctx.beanClassVisibility, - mVis = ctx.beanMethodVisibility, - fVis = ctx.beanFieldVisibility; - - // If @Bean.interfaceClass is specified on the parent class, then we want - // to use the properties defined on that class, not the subclass. - Class<?> c2 = (beanFilter != null && beanFilter.getInterfaceClass() != null ? beanFilter.getInterfaceClass() : c); - - Class<?> stopClass = (beanFilter != null ? beanFilter.getStopClass() : Object.class); - if (stopClass == null) - stopClass = Object.class; - - Map<String,BeanPropertyMeta> normalProps = new LinkedHashMap<String,BeanPropertyMeta>(); - - /// See if this class matches one the patterns in the exclude-class list. - if (ctx.isNotABean(c)) - return "Class matches exclude-class list"; - - if (! cVis.isVisible(c.getModifiers())) - return "Class is not public"; - - if (c.isAnnotationPresent(BeanIgnore.class)) - return "Class is annotated with @BeanIgnore"; - - // Make sure it's serializable. - if (beanFilter == null && ctx.beansRequireSerializable && ! isParentClass(Serializable.class, c)) - return "Class is not serializable"; - - // Look for @BeanConstructor constructor. - for (Constructor<?> x : c.getConstructors()) { - if (x.isAnnotationPresent(BeanConstructor.class)) { - if (constructor != null) - throw new BeanRuntimeException(c, "Multiple instances of '@BeanConstructor' found."); - constructor = (Constructor<T>)x; - constructorArgs = x.getAnnotation(BeanConstructor.class).properties(); - if (constructorArgs.length != x.getParameterTypes().length) - throw new BeanRuntimeException(c, "Number of properties defined in '@BeanConstructor' annotation does not match number of parameters in constructor."); - if (! setAccessible(constructor)) - throw new BeanRuntimeException(c, "Could not set accessibility to true on method with @BeanConstructor annotation. Method=''{0}''", constructor.getName()); + private static final class Builder<T> { + ClassMeta<T> classMeta; + BeanContext ctx; + BeanFilter<? extends T> beanFilter; + String[] pNames; + Map<String,BeanPropertyMeta> properties; + Map<Method,String> getterProps = new HashMap<Method,String>(); + Map<Method,String> setterProps = new HashMap<Method,String>(); + Map<Class<?>,Class<?>[]> typeVarImpls; + Constructor<T> constructor; + String[] constructorArgs = new String[0]; + MetadataMap extMeta = new MetadataMap(); + BeanPropertyMeta uriProperty; + BeanPropertyMeta subTypeIdProperty; + PropertyNamer propertyNamer; + + private Builder(ClassMeta<T> classMeta, BeanContext ctx, BeanFilter<? extends T> beanFilter, String[] pNames) { + this.classMeta = classMeta; + this.ctx = ctx; + this.beanFilter = beanFilter; + this.pNames = pNames; + } + + @SuppressWarnings("unchecked") + private String init(BeanMeta<T> beanMeta) { + Class<?> c = classMeta.getInnerClass(); + + try { + Visibility + conVis = ctx.beanConstructorVisibility, + cVis = ctx.beanClassVisibility, + mVis = ctx.beanMethodVisibility, + fVis = ctx.beanFieldVisibility; + + // If @Bean.interfaceClass is specified on the parent class, then we want + // to use the properties defined on that class, not the subclass. + Class<?> c2 = (beanFilter != null && beanFilter.getInterfaceClass() != null ? beanFilter.getInterfaceClass() : c); + + Class<?> stopClass = (beanFilter != null ? beanFilter.getStopClass() : Object.class); + if (stopClass == null) + stopClass = Object.class; + + Map<String,BeanPropertyMeta> normalProps = new LinkedHashMap<String,BeanPropertyMeta>(); + + /// See if this class matches one the patterns in the exclude-class list. + if (ctx.isNotABean(c)) + return "Class matches exclude-class list"; + + if (! cVis.isVisible(c.getModifiers())) + return "Class is not public"; + + if (c.isAnnotationPresent(BeanIgnore.class)) + return "Class is annotated with @BeanIgnore"; + + // Make sure it's serializable. + if (beanFilter == null && ctx.beansRequireSerializable && ! isParentClass(Serializable.class, c)) + return "Class is not serializable"; + + // Look for @BeanConstructor constructor. + for (Constructor<?> x : c.getConstructors()) { + if (x.isAnnotationPresent(BeanConstructor.class)) { + if (constructor != null) + throw new BeanRuntimeException(c, "Multiple instances of '@BeanConstructor' found."); + constructor = (Constructor<T>)x; + constructorArgs = x.getAnnotation(BeanConstructor.class).properties(); + if (constructorArgs.length != x.getParameterTypes().length) + throw new BeanRuntimeException(c, "Number of properties defined in '@BeanConstructor' annotation does not match number of parameters in constructor."); + if (! setAccessible(constructor)) + throw new BeanRuntimeException(c, "Could not set accessibility to true on method with @BeanConstructor annotation. Method=''{0}''", constructor.getName()); + } } - } - // If this is an interface, look for impl classes defined in the context. - if (constructor == null) - constructor = (Constructor<T>)ctx.getImplClassConstructor(c, conVis); + // If this is an interface, look for impl classes defined in the context. + if (constructor == null) + constructor = (Constructor<T>)ctx.getImplClassConstructor(c, conVis); - if (constructor == null) - constructor = (Constructor<T>)ClassMeta.findNoArgConstructor(c, conVis); + if (constructor == null) + constructor = (Constructor<T>)ClassMeta.findNoArgConstructor(c, conVis); - if (constructor == null && beanFilter == null && ctx.beansRequireDefaultConstructor) - return "Class does not have the required no-arg constructor"; + if (constructor == null && beanFilter == null && ctx.beansRequireDefaultConstructor) + return "Class does not have the required no-arg constructor"; - if (! setAccessible(constructor)) - throw new BeanRuntimeException(c, "Could not set accessibility to true on no-arg constructor"); + if (! setAccessible(constructor)) + throw new BeanRuntimeException(c, "Could not set accessibility to true on no-arg constructor"); - // Explicitly defined property names in @Bean annotation. - Set<String> fixedBeanProps = new LinkedHashSet<String>(); + // Explicitly defined property names in @Bean annotation. + Set<String> fixedBeanProps = new LinkedHashSet<String>(); - if (beanFilter != null) { + if (beanFilter != null) { - // Get the 'properties' attribute if specified. - if (beanFilter.getProperties() != null) - for (String p : beanFilter.getProperties()) - fixedBeanProps.add(p); + // Get the 'properties' attribute if specified. + if (beanFilter.getProperties() != null) + for (String p : beanFilter.getProperties()) + fixedBeanProps.add(p); - if (beanFilter.getPropertyNamer() != null) - propertyNamer = beanFilter.getPropertyNamer(); - } + if (beanFilter.getPropertyNamer() != null) + propertyNamer = beanFilter.getPropertyNamer(); + } - if (propertyNamer == null) - propertyNamer = new PropertyNamerDefault(); - - // First populate the properties with those specified in the bean annotation to - // ensure that ordering first. - for (String name : fixedBeanProps) - normalProps.put(name, new BeanPropertyMeta(this, name)); - - if (ctx.useJavaBeanIntrospector) { - BeanInfo bi = null; - if (! c2.isInterface()) - bi = Introspector.getBeanInfo(c2, stopClass); - else - bi = Introspector.getBeanInfo(c2, null); - if (bi != null) { - for (PropertyDescriptor pd : bi.getPropertyDescriptors()) { - String name = pd.getName(); - if (! normalProps.containsKey(name)) - normalProps.put(name, new BeanPropertyMeta(this, name)); - normalProps.get(name).setGetter(pd.getReadMethod()).setSetter(pd.getWriteMethod()); + if (propertyNamer == null) + propertyNamer = new PropertyNamerDefault(); + + // First populate the properties with those specified in the bean annotation to + // ensure that ordering first. + for (String name : fixedBeanProps) + normalProps.put(name, new BeanPropertyMeta(beanMeta, name)); + + if (ctx.useJavaBeanIntrospector) { + BeanInfo bi = null; + if (! c2.isInterface()) + bi = Introspector.getBeanInfo(c2, stopClass); + else + bi = Introspector.getBeanInfo(c2, null); + if (bi != null) { + for (PropertyDescriptor pd : bi.getPropertyDescriptors()) { + String name = pd.getName(); + if (! normalProps.containsKey(name)) + normalProps.put(name, new BeanPropertyMeta(beanMeta, name)); + normalProps.get(name).setGetter(pd.getReadMethod()).setSetter(pd.getWriteMethod()); + } } - } - } else /* Use 'better' introspection */ { + } else /* Use 'better' introspection */ { - for (Field f : findBeanFields(c2, stopClass, fVis)) { - String name = findPropertyName(f, fixedBeanProps); - if (name != null) { - if (! normalProps.containsKey(name)) - normalProps.put(name, new BeanPropertyMeta(this, name)); - normalProps.get(name).setField(f); + for (Field f : findBeanFields(c2, stopClass, fVis)) { + String name = findPropertyName(f, fixedBeanProps); + if (name != null) { + if (! normalProps.containsKey(name)) + normalProps.put(name, new BeanPropertyMeta(beanMeta, name)); + normalProps.get(name).setField(f); + } } - } - List<BeanMethod> bms = findBeanMethods(c2, stopClass, mVis, fixedBeanProps, propertyNamer); - - // Iterate through all the getters. - for (BeanMethod bm : bms) { - String pn = bm.propertyName; - Method m = bm.method; - if (! normalProps.containsKey(pn)) - normalProps.put(pn, new BeanPropertyMeta(this, pn)); - BeanPropertyMeta bpm = normalProps.get(pn); - if (! bm.isSetter) - bpm.setGetter(m); - } + List<BeanMethod> bms = findBeanMethods(c2, stopClass, mVis, fixedBeanProps, propertyNamer); + + // Iterate through all the getters. + for (BeanMethod bm : bms) { + String pn = bm.propertyName; + Method m = bm.method; + if (! normalProps.containsKey(pn)) + normalProps.put(pn, new BeanPropertyMeta(beanMeta, pn)); + BeanPropertyMeta bpm = normalProps.get(pn); + if (! bm.isSetter) + bpm.setGetter(m); + } - // Now iterate through all the setters. - for (BeanMethod bm : bms) { - if (bm.isSetter) { - BeanPropertyMeta bpm = normalProps.get(bm.propertyName); - if (bm.matchesPropertyType(bpm)) - bpm.setSetter(bm.method); + // Now iterate through all the setters. + for (BeanMethod bm : bms) { + if (bm.isSetter) { + BeanPropertyMeta bpm = normalProps.get(bm.propertyName); + if (bm.matchesPropertyType(bpm)) + bpm.setSetter(bm.method); + } } } - } - typeVarImpls = new HashMap<Class<?>,Class<?>[]>(); - findTypeVarImpls(c, typeVarImpls); - if (typeVarImpls.isEmpty()) - typeVarImpls = null; + typeVarImpls = new HashMap<Class<?>,Class<?>[]>(); + findTypeVarImpls(c, typeVarImpls); + if (typeVarImpls.isEmpty()) + typeVarImpls = null; - // Eliminate invalid properties, and set the contents of getterProps and setterProps. - for (Iterator<BeanPropertyMeta> i = normalProps.values().iterator(); i.hasNext();) { - BeanPropertyMeta p = i.next(); - try { - if (p.validate()) { + // Eliminate invalid properties, and set the contents of getterProps and setterProps. + for (Iterator<BeanPropertyMeta> i = normalProps.values().iterator(); i.hasNext();) { + BeanPropertyMeta p = i.next(); + try { + if (p.validate(ctx, typeVarImpls)) { - if (p.getGetter() != null) - getterProps.put(p.getGetter(), p.getName()); + if (p.getGetter() != null) + getterProps.put(p.getGetter(), p.getName()); - if (p.getSetter() != null) - setterProps.put(p.getSetter(), p.getName()); + if (p.getSetter() != null) + setterProps.put(p.getSetter(), p.getName()); - if (p.isBeanUri()) - uriProperty = p; + if (p.isBeanUri()) + uriProperty = p; - } else { - i.remove(); + } else { + i.remove(); + } + } catch (ClassNotFoundException e) { + throw new BeanRuntimeException(c, e.getLocalizedMessage()); } - } catch (ClassNotFoundException e) { - throw new BeanRuntimeException(c, e.getLocalizedMessage()); } - } - - // Check for missing properties. - for (String fp : fixedBeanProps) - if (! normalProps.containsKey(fp)) - throw new BeanRuntimeException(c, "The property ''{0}'' was defined on the @Bean(properties=X) annotation but was not found on the class definition.", fp); - - // Mark constructor arg properties. - for (String fp : constructorArgs) { - BeanPropertyMeta m = normalProps.get(fp); - if (m == null) - throw new BeanRuntimeException(c, "The property ''{0}'' was defined on the @BeanConstructor(properties=X) annotation but was not found on the class definition.", fp); - m.setAsConstructorArg(); - } - - // Make sure at least one property was found. - if (beanFilter == null && ctx.beansRequireSomeProperties && normalProps.size() == 0) - return "No properties detected on bean class"; - boolean sortProperties = (ctx.sortProperties || (beanFilter != null && beanFilter.isSortProperties())) && fixedBeanProps.isEmpty(); + // Check for missing properties. + for (String fp : fixedBeanProps) + if (! normalProps.containsKey(fp)) + throw new BeanRuntimeException(c, "The property ''{0}'' was defined on the @Bean(properties=X) annotation but was not found on the class definition.", fp); + + // Mark constructor arg properties. + for (String fp : constructorArgs) { + BeanPropertyMeta m = normalProps.get(fp); + if (m == null) + throw new BeanRuntimeException(c, "The property ''{0}'' was defined on the @BeanConstructor(properties=X) annotation but was not found on the class definition.", fp); + m.setAsConstructorArg(); + } - properties = sortProperties ? new TreeMap<String,BeanPropertyMeta>() : new LinkedHashMap<String,BeanPropertyMeta>(); + // Make sure at least one property was found. + if (beanFilter == null && ctx.beansRequireSomeProperties && normalProps.size() == 0) + return "No properties detected on bean class"; - if (beanFilter != null && beanFilter.getSubTypeProperty() != null) { - String subTypeProperty = beanFilter.getSubTypeProperty(); - this.subTypeIdProperty = new SubTypePropertyMeta(subTypeProperty, beanFilter.getSubTypes(), normalProps.remove(subTypeProperty)); - properties.put(subTypeProperty, this.subTypeIdProperty); - } + boolean sortProperties = (ctx.sortProperties || (beanFilter != null && beanFilter.isSortProperties())) && fixedBeanProps.isEmpty(); - properties.putAll(normalProps); + properties = sortProperties ? new TreeMap<String,BeanPropertyMeta>() : new LinkedHashMap<String,BeanPropertyMeta>(); - // If a beanFilter is defined, look for inclusion and exclusion lists. - if (beanFilter != null) { + if (beanFilter != null && beanFilter.getSubTypeProperty() != null) { + String subTypeProperty = beanFilter.getSubTypeProperty(); + this.subTypeIdProperty = new SubTypePropertyMeta(beanMeta, subTypeProperty, beanFilter.getSubTypes(), normalProps.remove(subTypeProperty)); + properties.put(subTypeProperty, this.subTypeIdProperty); + } - // Eliminated excluded properties if BeanFilter.excludeKeys is specified. - String[] includeKeys = beanFilter.getProperties(); - String[] excludeKeys = beanFilter.getExcludeProperties(); - if (excludeKeys != null) { - for (String k : excludeKeys) - properties.remove(k); + properties.putAll(normalProps); + + // If a beanFilter is defined, look for inclusion and exclusion lists. + if (beanFilter != null) { + + // Eliminated excluded properties if BeanFilter.excludeKeys is specified. + String[] includeKeys = beanFilter.getProperties(); + String[] excludeKeys = beanFilter.getExcludeProperties(); + if (excludeKeys != null) { + for (String k : excludeKeys) + properties.remove(k); + + // Only include specified properties if BeanFilter.includeKeys is specified. + // Note that the order must match includeKeys. + } else if (includeKeys != null) { + Map<String,BeanPropertyMeta> properties2 = new LinkedHashMap<String,BeanPropertyMeta>(); + for (String k : includeKeys) { + if (properties.containsKey(k)) + properties2.put(k, properties.get(k)); + } + properties = properties2; + } + } - // Only include specified properties if BeanFilter.includeKeys is specified. - // Note that the order must match includeKeys. - } else if (includeKeys != null) { + if (pNames != null) { Map<String,BeanPropertyMeta> properties2 = new LinkedHashMap<String,BeanPropertyMeta>(); - for (String k : includeKeys) { + for (String k : pNames) { if (properties.containsKey(k)) properties2.put(k, properties.get(k)); } properties = properties2; } + + // We return this through the Bean.keySet() interface, so make sure it's not modifiable. + properties = Collections.unmodifiableMap(properties); + + } catch (BeanRuntimeException e) { + throw e; + } catch (Exception e) { + return "Exception: " + StringUtils.getStackTrace(e); } - // We return this through the Bean.keySet() interface, so make sure it's not modifiable. - properties = Collections.unmodifiableMap(properties); + return null; + } - } catch (BeanRuntimeException e) { - throw e; - } catch (Exception e) { - return "Exception: " + StringUtils.getStackTrace(e); + /* + * Returns the property name of the specified field if it's a valid property. + * Returns null if the field isn't a valid property. + */ + private String findPropertyName(Field f, Set<String> fixedBeanProps) { + BeanProperty bp = f.getAnnotation(BeanProperty.class); + if (bp != null && ! bp.name().equals("")) { + String name = bp.name(); + if (fixedBeanProps.isEmpty() || fixedBeanProps.contains(name)) + return name; + throw new BeanRuntimeException(classMeta.getInnerClass(), "Method property ''{0}'' identified in @BeanProperty, but missing from @Bean", name); + } + String name = propertyNamer.getPropertyName(f.getName()); + if (fixedBeanProps.isEmpty() || fixedBeanProps.contains(name)) + return name; + return null; } - return null; + } + + + /** + * Returns the {@link ClassMeta} of this bean. + * + * @return The {@link ClassMeta} of this bean. + */ + @BeanIgnore + public ClassMeta<T> getClassMeta() { + return classMeta; } /** @@ -621,24 +682,6 @@ public class BeanMeta<T> { return null; } - /* - * Returns the property name of the specified field if it's a valid property. - * Returns null if the field isn't a valid property. - */ - private String findPropertyName(Field f, Set<String> fixedBeanProps) { - BeanProperty bp = f.getAnnotation(BeanProperty.class); - if (bp != null && ! bp.name().equals("")) { - String name = bp.name(); - if (fixedBeanProps.isEmpty() || fixedBeanProps.contains(name)) - return name; - throw new BeanRuntimeException(c, "Method property ''{0}'' identified in @BeanProperty, but missing from @Bean", name); - } - String name = propertyNamer.getPropertyName(f.getName()); - if (fixedBeanProps.isEmpty() || fixedBeanProps.contains(name)) - return name; - return null; - } - /** * Recursively determines the classes represented by parameterized types in the class hierarchy of * the specified type, and puts the results in the specified map.<br> @@ -699,15 +742,17 @@ public class BeanMeta<T> { * Bean property for getting and setting bean subtype. */ @SuppressWarnings({"rawtypes","unchecked"}) - private class SubTypePropertyMeta extends BeanPropertyMeta { + private static class SubTypePropertyMeta extends BeanPropertyMeta { private Map<Class<?>,String> subTypes; private BeanPropertyMeta realProperty; // Bean property if bean actually has a real subtype field. + private BeanMeta<?> beanMeta; - SubTypePropertyMeta(String subTypeAttr, Map<Class<?>,String> subTypes, BeanPropertyMeta realProperty) { - super(BeanMeta.this, subTypeAttr, ctx.string()); + SubTypePropertyMeta(BeanMeta beanMeta, String subTypeAttr, Map<Class<?>,String> subTypes, BeanPropertyMeta realProperty) { + super(beanMeta, subTypeAttr, beanMeta.ctx.string()); this.subTypes = subTypes; this.realProperty = realProperty; + this.beanMeta = beanMeta; } /* @@ -721,7 +766,7 @@ public class BeanMeta<T> { for (Entry<Class<?>,String> e : subTypes.entrySet()) { if (e.getValue().equals(subTypeId)) { Class subTypeClass = e.getKey(); - m.meta = ctx.getBeanMeta(subTypeClass); + m.meta = beanMeta.ctx.getBeanMeta(subTypeClass); try { m.setBean(subTypeClass.newInstance()); if (realProperty != null) @@ -736,14 +781,14 @@ public class BeanMeta<T> { return null; } } - throw new BeanRuntimeException(c, "Unknown subtype ID ''{0}''", subTypeId); + throw new BeanRuntimeException(beanMeta.c, "Unknown subtype ID ''{0}''", subTypeId); } @Override /* BeanPropertyMeta */ public Object get(BeanMap<?> m) throws BeanRuntimeException { - String subTypeId = beanFilter.getSubTypes().get(c); + String subTypeId = beanMeta.beanFilter.getSubTypes().get(beanMeta.c); if (subTypeId == null) - throw new BeanRuntimeException(c, "Unmapped sub type class"); + throw new BeanRuntimeException(beanMeta.c, "Unmapped sub type class"); return subTypeId; } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/83f2b35b/juneau-core/src/main/java/org/apache/juneau/BeanMetaFiltered.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/BeanMetaFiltered.java b/juneau-core/src/main/java/org/apache/juneau/BeanMetaFiltered.java index b9d1d9e..f731d9d 100644 --- a/juneau-core/src/main/java/org/apache/juneau/BeanMetaFiltered.java +++ b/juneau-core/src/main/java/org/apache/juneau/BeanMetaFiltered.java @@ -25,8 +25,6 @@ import org.apache.juneau.annotation.*; */ public final class BeanMetaFiltered<T> extends BeanMeta<T> { - private final BeanMeta<T> innerMeta; - /** * Wrapper constructor. * @@ -34,10 +32,7 @@ public final class BeanMetaFiltered<T> extends BeanMeta<T> { * @param pNames The list of transformed property names. */ public BeanMetaFiltered(BeanMeta<T> innerMeta, String[] pNames) { - this.innerMeta = innerMeta; - this.properties = new LinkedHashMap<String,BeanPropertyMeta>(); - for (String p : pNames) - properties.put(p, innerMeta.getPropertyMeta(p)); + super(innerMeta.classMeta, innerMeta.ctx, innerMeta.beanFilter, pNames); } /** @@ -49,29 +44,4 @@ public final class BeanMetaFiltered<T> extends BeanMeta<T> { public BeanMetaFiltered(BeanMeta<T> innerMeta, Collection<String> pNames) { this(innerMeta, pNames.toArray(new String[pNames.size()])); } - - @Override /* Delagate */ - public ClassMeta<T> getClassMeta() { - return innerMeta.classMeta; - } - - @Override /* Delagate */ - public <M extends BeanMetaExtended> M getExtendedMeta(Class<M> m) { - return innerMeta.getExtendedMeta(m); - } - - @Override /* BeanMeta */ - public Collection<BeanPropertyMeta> getPropertyMetas() { - return properties.values(); - } - - @Override /* BeanMeta */ - public BeanPropertyMeta getPropertyMeta(String name) { - return properties.get(name); - } - - @Override /* Object */ - public String toString() { - return innerMeta.c.getName(); - } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/83f2b35b/juneau-core/src/main/java/org/apache/juneau/BeanPropertyMeta.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/BeanPropertyMeta.java b/juneau-core/src/main/java/org/apache/juneau/BeanPropertyMeta.java index b9d18b9..0d0a8b4 100644 --- a/juneau-core/src/main/java/org/apache/juneau/BeanPropertyMeta.java +++ b/juneau-core/src/main/java/org/apache/juneau/BeanPropertyMeta.java @@ -233,10 +233,7 @@ public class BeanPropertyMeta { return extMeta.get(c, this); } - boolean validate() throws Exception { - - BeanContext f = beanMeta.ctx; - Map<Class<?>,Class<?>[]> typeVarImpls = beanMeta.typeVarImpls; + boolean validate(BeanContext f, Map<Class<?>,Class<?>[]> typeVarImpls) throws Exception { if (field == null && getter == null) return false; @@ -565,6 +562,7 @@ public class BeanPropertyMeta { } catch (BeanRuntimeException e) { throw e; } catch (Exception e) { + e.printStackTrace(); if (beanMeta.ctx.ignoreInvocationExceptionsOnSetters) { if (rawTypeMeta.isPrimitive()) return rawTypeMeta.getPrimitiveDefault(); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/83f2b35b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java index 6da687c..eb60730 100644 --- a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java +++ b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java @@ -299,9 +299,10 @@ public final class ClassMeta<T> implements Type { // Note that this needs to be done after all other initialization has been done. else if (classCategory == UNKNOWN) { - BeanMeta newMeta = new BeanMeta(this, beanContext, beanFilter); + BeanMeta newMeta = null; try { - notABeanReason = newMeta.init(); + newMeta = new BeanMeta(this, beanContext, beanFilter, null); + notABeanReason = newMeta.notABeanReason; } catch (RuntimeException e) { notABeanReason = e.getMessage(); throw e;
