Repository: incubator-juneau Updated Branches: refs/heads/master 342ed1dcb -> 79d19494a
Simplify the way serializers iterate over bean properties. With the introduction of MsgPack, we now need to know the number of non-null bean properties before we start serializing the entries. Also, the REST Samples that serializes HttpRequest objects is broken because it's not catching exceptions. Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/79d19494 Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/79d19494 Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/79d19494 Branch: refs/heads/master Commit: 79d19494af7f3d335d2edc693d8f9bfa675a45b0 Parents: 342ed1d Author: jamesbognar <[email protected]> Authored: Wed Aug 3 16:58:39 2016 -0400 Committer: jamesbognar <[email protected]> Committed: Wed Aug 3 16:58:39 2016 -0400 ---------------------------------------------------------------------- .../main/java/org/apache/juneau/BeanMap.java | 63 ++++++++++------- .../main/java/org/apache/juneau/BeanMeta.java | 14 +++- .../org/apache/juneau/BeanPropertyMeta.java | 10 ++- .../org/apache/juneau/BeanPropertyValue.java | 72 ++++++++++++++++++++ .../org/apache/juneau/html/HtmlSerializer.java | 33 ++++----- .../apache/juneau/internal/DelegateBeanMap.java | 22 +++++- .../org/apache/juneau/jena/RdfSerializer.java | 22 +++--- .../org/apache/juneau/json/JsonSerializer.java | 28 ++------ .../juneau/msgpack/MsgPackSerializer.java | 53 +++++++------- .../juneau/urlencoding/UonSerializer.java | 27 ++------ .../urlencoding/UrlEncodingSerializer.java | 27 ++------ .../org/apache/juneau/xml/XmlSerializer.java | 58 ++++++++-------- .../test/java/org/apache/juneau/CT_BeanMap.java | 13 +++- 13 files changed, 255 insertions(+), 187 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/79d19494/org.apache.juneau/src/main/java/org/apache/juneau/BeanMap.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/BeanMap.java b/org.apache.juneau/src/main/java/org/apache/juneau/BeanMap.java index adef3ab..28bee46 100644 --- a/org.apache.juneau/src/main/java/org/apache/juneau/BeanMap.java +++ b/org.apache.juneau/src/main/java/org/apache/juneau/BeanMap.java @@ -413,20 +413,49 @@ public class BeanMap<T> extends AbstractMap<String,Object> implements Delegate<T } /** - * Returns all the properties associated with the bean. + * Invokes all the getters on this bean and return the values as a list of {@link BeanPropertyValue} objects. + * <p> + * This allows a snapshot of all values to be grabbed from a bean in one call. + * + * @param addClassAttr Add a <jk>"_class"</jk> bean property to the returned list. + * @param ignoreNulls Don't return properties whose values are null. + * @return The list of all bean property values. */ - @Override /* Map */ - public Set<Entry<String,Object>> entrySet() { - return entrySet(false); + public List<BeanPropertyValue> getValues(final boolean addClassAttr, final boolean ignoreNulls) { + Collection<BeanPropertyMeta<T>> properties = getProperties(); + int capacity = (ignoreNulls && properties.size() > 10) ? 10 : properties.size() + (addClassAttr ? 1 : 0); + List<BeanPropertyValue> l = new ArrayList<BeanPropertyValue>(capacity); + if (addClassAttr) + l.add(new BeanPropertyValue(meta.getClassProperty(), meta.c.getName(), null)); + for (BeanPropertyMeta<T> bpm : properties) { + try { + Object val = bpm.get(this); + if (val != null || ! ignoreNulls) + l.add(new BeanPropertyValue(bpm, val, null)); + } catch (Error e) { + // Errors should always be uncaught. + throw e; + } catch (Throwable t) { + l.add(new BeanPropertyValue(bpm, null, t)); + } + } + return l; + } + + /** + * Returns a simple collection of properties for this bean map. + * @return A simple collection of properties for this bean map. + */ + protected Collection<BeanPropertyMeta<T>> getProperties() { + return meta.properties.values(); } /** * Returns all the properties associated with the bean. - * @param ignoreNulls - Iterator should not return properties with null values. * @return A new set. */ - public Set<Entry<String,Object>> entrySet(final boolean ignoreNulls) { - int todo = 1; // Create a more efficient method. + @Override + public Set<Entry<String,Object>> entrySet() { // Construct our own anonymous set to implement this function. Set<Entry<String,Object>> s = new AbstractSet<Entry<String,Object>>() { @@ -435,7 +464,7 @@ public class BeanMap<T> extends AbstractMap<String,Object> implements Delegate<T // Note that the HashMap.values() method caches results, so this collection // will really only be constructed once per bean type since the underlying // map never changes. - final Collection<BeanPropertyMeta<T>> pSet = meta.properties.values(); + final Collection<BeanPropertyMeta<T>> pSet = getProperties(); @Override /* Set */ public Iterator<java.util.Map.Entry<String, Object>> iterator() { @@ -446,29 +475,15 @@ public class BeanMap<T> extends AbstractMap<String,Object> implements Delegate<T return new Iterator<Entry<String,Object>>() { final Iterator<BeanPropertyMeta<T>> pIterator = pSet.iterator(); - BeanMapEntry<T> nextEntry; @Override /* Iterator */ public boolean hasNext() { - return nextEntry() != null; + return pIterator.hasNext(); } @Override /* Iterator */ public Map.Entry<String, Object> next() { - BeanMapEntry<T> e = nextEntry(); - nextEntry = null; - return e; - } - - private BeanMapEntry<T> nextEntry() { - if (nextEntry == null) { - while (pIterator.hasNext() && nextEntry == null) { - BeanPropertyMeta<T> bpm = pIterator.next(); - if ((! ignoreNulls) || bpm.get(BeanMap.this) != null) - nextEntry = new BeanMapEntry<T>(BeanMap.this, bpm); - } - } - return nextEntry; + return new BeanMapEntry<T>(BeanMap.this, pIterator.next()); } @Override /* Iterator */ http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/79d19494/org.apache.juneau/src/main/java/org/apache/juneau/BeanMeta.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/BeanMeta.java b/org.apache.juneau/src/main/java/org/apache/juneau/BeanMeta.java index b5f4092..8d4d631 100644 --- a/org.apache.juneau/src/main/java/org/apache/juneau/BeanMeta.java +++ b/org.apache.juneau/src/main/java/org/apache/juneau/BeanMeta.java @@ -100,6 +100,7 @@ public class BeanMeta<T> { BeanPropertyMeta<T> uriProperty; // The property identified as the URI for this bean (annotated with @BeanProperty.beanUri). BeanPropertyMeta<T> 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<T> classProperty; // "_class" mock bean property. BeanMeta() {} @@ -110,10 +111,11 @@ public class BeanMeta<T> { * @param ctx The bean context that created this object. * @param transform Optional bean transform associated with the target class. Can be <jk>null</jk>. */ - protected BeanMeta(ClassMeta<T> classMeta, BeanContext ctx, org.apache.juneau.transform.BeanTransform<? extends T> transform) { + protected BeanMeta(final ClassMeta<T> classMeta, BeanContext ctx, org.apache.juneau.transform.BeanTransform<? extends T> transform) { this.classMeta = classMeta; this.ctx = ctx; this.transform = transform; + this.classProperty = new BeanPropertyMeta<T>(this, "_class", ctx.string()); this.c = classMeta.getInnerClass(); } @@ -398,6 +400,16 @@ public class BeanMeta<T> { return uriProperty; } + /** + * Returns a mock bean property that resolves to the name <js>"_class"</js> and whose value always resolves + * to the class name of the bean. + * + * @return The class name property. + */ + public BeanPropertyMeta<T> getClassProperty() { + return classProperty; + } + /* * Temporary getter/setter method struct. */ http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/79d19494/org.apache.juneau/src/main/java/org/apache/juneau/BeanPropertyMeta.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/BeanPropertyMeta.java b/org.apache.juneau/src/main/java/org/apache/juneau/BeanPropertyMeta.java index e72ff21..48332cf 100644 --- a/org.apache.juneau/src/main/java/org/apache/juneau/BeanPropertyMeta.java +++ b/org.apache.juneau/src/main/java/org/apache/juneau/BeanPropertyMeta.java @@ -69,7 +69,13 @@ public class BeanPropertyMeta<T> { /** RDF related metadata on this bean property. */ protected RdfBeanPropertyMeta<T> rdfMeta; // - BeanPropertyMeta(BeanMeta<T> beanMeta, String name) { + /** + * Constructor. + * + * @param beanMeta The metadata of the bean containing this property. + * @param name This property name. + */ + protected BeanPropertyMeta(BeanMeta<T> beanMeta, String name) { this.beanMeta = beanMeta; this.name = name; } @@ -142,7 +148,7 @@ public class BeanPropertyMeta<T> { */ public ClassMeta<?> getClassMeta() { if (typeMeta == null) - typeMeta = (transform != null ? transform.getTransformedClassMeta() : rawTypeMeta.getTransformedClassMeta()); + typeMeta = (transform != null ? transform.getTransformedClassMeta() : rawTypeMeta == null ? beanMeta.ctx.object() : rawTypeMeta.getTransformedClassMeta()); return typeMeta; } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/79d19494/org.apache.juneau/src/main/java/org/apache/juneau/BeanPropertyValue.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/BeanPropertyValue.java b/org.apache.juneau/src/main/java/org/apache/juneau/BeanPropertyValue.java new file mode 100644 index 0000000..3238474 --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/BeanPropertyValue.java @@ -0,0 +1,72 @@ +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + ***************************************************************************************************************************/ + +package org.apache.juneau; + +/** + * Represents a simple bean property value and the meta-data associated with it. + * <p> + * + * @author James Bognar ([email protected]) + */ +public class BeanPropertyValue { + + private final BeanPropertyMeta<?> pMeta; + private final Object value; + private final Throwable thrown; + + /** + * Constructor. + * + * @param pMeta The bean property metadata. + * @param value The bean property value. + * @param thrown The exception thrown by calling the property getter. + */ + protected BeanPropertyValue(BeanPropertyMeta<?> pMeta, Object value, Throwable thrown) { + this.pMeta = pMeta; + this.value = value; + this.thrown = thrown; + } + + /** + * Returns the bean property metadata. + * @return The bean property metadata. + */ + public final BeanPropertyMeta<?> getMeta() { + return pMeta; + } + + /** + * Returns the bean property name. + * @return The bean property name. + */ + public final String getName() { + return pMeta.getName(); + } + + /** + * Returns the bean property value. + * @return The bean property value. + */ + public final Object getValue() { + return value; + } + + /** + * Returns the exception thrown by calling the property getter. + * @return The exception thrown by calling the property getter. + */ + public final Throwable getThrown() { + return thrown; + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/79d19494/org.apache.juneau/src/main/java/org/apache/juneau/html/HtmlSerializer.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/html/HtmlSerializer.java b/org.apache.juneau/src/main/java/org/apache/juneau/html/HtmlSerializer.java index 6506b9c..522e06a 100644 --- a/org.apache.juneau/src/main/java/org/apache/juneau/html/HtmlSerializer.java +++ b/org.apache.juneau/src/main/java/org/apache/juneau/html/HtmlSerializer.java @@ -320,7 +320,7 @@ public class HtmlSerializer extends XmlSerializer { } @SuppressWarnings({ "rawtypes" }) - private void serializeBeanMap(HtmlSerializerSession session, HtmlWriter out, BeanMap m, String classAttr, BeanPropertyMeta<?> ppMeta) throws Exception { + private void serializeBeanMap(HtmlSerializerSession session, HtmlWriter out, BeanMap<?> m, String classAttr, BeanPropertyMeta<?> ppMeta) throws Exception { int i = session.getIndent(); Object o = m.getBean(); @@ -345,21 +345,14 @@ public class HtmlSerializer extends XmlSerializer { out.eTag(i+1, "tr").nl(); } - Iterator mapEntries = m.entrySet(session.isTrimNulls()).iterator(); - - while (mapEntries.hasNext()) { - BeanMapEntry p = (BeanMapEntry)mapEntries.next(); + for (BeanPropertyValue p : m.getValues(false, session.isTrimNulls())) { BeanPropertyMeta pMeta = p.getMeta(); - String key = p.getKey(); - Object value = null; - try { - value = p.getValue(); - } catch (StackOverflowError e) { - throw e; - } catch (Throwable t) { + String key = p.getName(); + Object value = p.getValue(); + Throwable t = p.getThrown(); + if (t != null) session.addBeanGetterWarning(pMeta, t); - } if (session.canIgnoreValue(pMeta.getClassMeta(), key, value)) continue; @@ -371,12 +364,12 @@ public class HtmlSerializer extends XmlSerializer { out.sTag(i+2, "td").nl(); try { serializeAnything(session, out, value, p.getMeta().getClassMeta(), key, 2, pMeta); - } catch (SerializeException t) { - throw t; - } catch (StackOverflowError t) { - throw t; - } catch (Throwable t) { - session.addBeanGetterWarning(pMeta, t); + } catch (SerializeException e) { + throw e; + } catch (Error e) { + throw e; + } catch (Throwable e) { + session.addBeanGetterWarning(pMeta, e); } out.eTag(i+2, "td").nl(); out.eTag(i+1, "tr").nl(); @@ -448,7 +441,7 @@ public class HtmlSerializer extends XmlSerializer { else m2 = bc.forBean(o); - Iterator mapEntries = m2.entrySet(false).iterator(); + Iterator mapEntries = m2.entrySet().iterator(); while (mapEntries.hasNext()) { BeanMapEntry p = (BeanMapEntry)mapEntries.next(); BeanPropertyMeta pMeta = p.getMeta(); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/79d19494/org.apache.juneau/src/main/java/org/apache/juneau/internal/DelegateBeanMap.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/internal/DelegateBeanMap.java b/org.apache.juneau/src/main/java/org/apache/juneau/internal/DelegateBeanMap.java index 0c67ace..4adf0cd 100644 --- a/org.apache.juneau/src/main/java/org/apache/juneau/internal/DelegateBeanMap.java +++ b/org.apache.juneau/src/main/java/org/apache/juneau/internal/DelegateBeanMap.java @@ -96,7 +96,7 @@ public class DelegateBeanMap<T> extends BeanMap<T> { } @Override /* Map */ - public Set<Entry<String,Object>> entrySet(final boolean ignoreNulls) { + public Set<Entry<String,Object>> entrySet() { Set<Entry<String,Object>> s = Collections.newSetFromMap(new LinkedHashMap<Map.Entry<String,Object>,Boolean>()); for (final String key : keys) { BeanMapEntry<T> bme; @@ -111,6 +111,26 @@ public class DelegateBeanMap<T> extends BeanMap<T> { return s; } + @Override /* BeanMap */ + public Collection<BeanPropertyMeta<T>> getProperties() { + List<BeanPropertyMeta<T>> l = new ArrayList<BeanPropertyMeta<T>>(keys.size()); + for (final String key : keys) { + BeanPropertyMeta<T> p = this.getPropertyMeta(key); + if (overrideValues.containsKey(key)) { + p = new BeanPropertyMeta<T>(this.meta, key) { + @Override /* BeanPropertyMeta */ + public Object get(BeanMap<T> m) { + return overrideValues.get(key); + } + }; + } + if (p == null) + throw new BeanRuntimeException(super.getClassMeta().getInnerClass(), "Property ''{0}'' not found on class.", key); + l.add(p); + } + return l; + } + private class BeanMapEntryOverride<T2> extends BeanMapEntry<T2> { Object value; http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/79d19494/org.apache.juneau/src/main/java/org/apache/juneau/jena/RdfSerializer.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/jena/RdfSerializer.java b/org.apache.juneau/src/main/java/org/apache/juneau/jena/RdfSerializer.java index 27620af..d5d97ee 100644 --- a/org.apache.juneau/src/main/java/org/apache/juneau/jena/RdfSerializer.java +++ b/org.apache.juneau/src/main/java/org/apache/juneau/jena/RdfSerializer.java @@ -315,30 +315,26 @@ public class RdfSerializer extends WriterSerializer { } } - private void serializeBeanMap(RdfSerializerSession session, BeanMap m, Resource r) throws SerializeException { - ArrayList<BeanMapEntry> l = new ArrayList<BeanMapEntry>(m.entrySet(session.isTrimNulls())); + private void serializeBeanMap(RdfSerializerSession session, BeanMap<?> m, Resource r) throws SerializeException { + List<BeanPropertyValue> l = m.getValues(false, session.isTrimNulls()); Collections.reverse(l); - for (BeanMapEntry bme : l) { - BeanPropertyMeta pMeta = bme.getMeta(); + for (BeanPropertyValue bpv : l) { + BeanPropertyMeta pMeta = bpv.getMeta(); ClassMeta<?> cm = pMeta.getClassMeta(); if (pMeta.isBeanUri()) continue; - String key = bme.getKey(); - Object value = null; - try { - value = bme.getValue(); - } catch (StackOverflowError e) { - throw e; - } catch (Throwable t) { + String key = bpv.getName(); + Object value = bpv.getValue(); + Throwable t = bpv.getThrown(); + if (t != null) session.addBeanGetterWarning(pMeta, t); - } if (session.canIgnoreValue(cm, key, value)) continue; - BeanPropertyMeta bpm = bme.getMeta(); + BeanPropertyMeta bpm = bpv.getMeta(); Namespace ns = bpm.getRdfMeta().getNamespace(); if (ns == null && session.isUseXmlNamespaces()) ns = bpm.getXmlMeta().getNamespace(); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/79d19494/org.apache.juneau/src/main/java/org/apache/juneau/json/JsonSerializer.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/json/JsonSerializer.java b/org.apache.juneau/src/main/java/org/apache/juneau/json/JsonSerializer.java index 8b89e87..7d431b2 100644 --- a/org.apache.juneau/src/main/java/org/apache/juneau/json/JsonSerializer.java +++ b/org.apache.juneau/src/main/java/org/apache/juneau/json/JsonSerializer.java @@ -291,35 +291,19 @@ public class JsonSerializer extends WriterSerializer { } @SuppressWarnings({ "rawtypes" }) - private SerializerWriter serializeBeanMap(JsonSerializerSession session, JsonWriter out, BeanMap m, boolean addClassAttr) throws Exception { + private SerializerWriter serializeBeanMap(JsonSerializerSession session, JsonWriter out, BeanMap<?> m, boolean addClassAttr) throws Exception { int depth = session.getIndent(); out.append('{'); - Iterator mapEntries = m.entrySet(session.isTrimNulls()).iterator(); - - // Print out "_class" attribute on this bean if required. - if (addClassAttr) { - String attr = "_class"; - out.cr(depth).attr(attr).append(':').s().q().append(m.getClassMeta().getInnerClass().getName()).q(); - if (mapEntries.hasNext()) - out.append(',').s(); - } - boolean addComma = false; - while (mapEntries.hasNext()) { - BeanMapEntry p = (BeanMapEntry)mapEntries.next(); + for (BeanPropertyValue p : m.getValues(addClassAttr, session.isTrimNulls())) { BeanPropertyMeta pMeta = p.getMeta(); - - String key = p.getKey(); - Object value = null; - try { - value = p.getValue(); - } catch (StackOverflowError e) { - throw e; - } catch (Throwable t) { + String key = p.getName(); + Object value = p.getValue(); + Throwable t = p.getThrown(); + if (t != null) session.addBeanGetterWarning(pMeta, t); - } if (session.canIgnoreValue(pMeta.getClassMeta(), key, value)) continue; http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/79d19494/org.apache.juneau/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java b/org.apache.juneau/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java index 1779d59..76aa138 100644 --- a/org.apache.juneau/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java +++ b/org.apache.juneau/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java @@ -132,9 +132,12 @@ public class MsgPackSerializer extends OutputStreamSerializer { ClassMeta<?> keyType = type.getKeyType(), valueType = type.getValueType(); m = session.sort(m); + + // The map size may change as we're iterating over it, so + // grab a snapshot of the entries in a separate list. List<SimpleMapEntry> entries = new ArrayList<SimpleMapEntry>(m.size()); for (Map.Entry e : (Set<Map.Entry>)m.entrySet()) - entries.add(new SimpleMapEntry(e.getKey(), e.getValue(), null)); + entries.add(new SimpleMapEntry(e.getKey(), e.getValue())); out.startMap(entries.size()); @@ -157,46 +160,38 @@ public class MsgPackSerializer extends OutputStreamSerializer { serializeCollection(session, out, o, type); } - @SuppressWarnings({ "rawtypes", "unchecked" }) - private void serializeBeanMap(MsgPackSerializerSession session, MsgPackOutputStream out, final BeanMap m, boolean addClassAttr) throws Exception { - - List<SimpleMapEntry> entries = new ArrayList<SimpleMapEntry>(m.getMeta().getPropertyMetas().size() + (addClassAttr ? 1 : 0)); - // Print out "_class" attribute on this bean if required. - if (addClassAttr) - entries.add(new SimpleMapEntry("_class", m.getClassMeta().getInnerClass().getName(), null)); - - for (BeanMapEntry p : (Set<BeanMapEntry>)m.entrySet(session.isTrimNulls())) { - try { - BeanPropertyMeta pMeta = p.getMeta(); - String key = p.getKey(); - Object value = p.getValue(); - if (! session.canIgnoreValue(pMeta.getClassMeta(), p.getKey(), p.getValue())) - entries.add(new SimpleMapEntry(key, value, pMeta)); - } catch (StackOverflowError e) { - throw e; - } catch (Throwable t) { - session.addBeanGetterWarning(p.getMeta(), t); - } + @SuppressWarnings({ "rawtypes" }) + private void serializeBeanMap(MsgPackSerializerSession session, MsgPackOutputStream out, final BeanMap<?> m, boolean addClassAttr) throws Exception { - } - int size = entries.size(); + List<BeanPropertyValue> values = m.getValues(addClassAttr, session.isTrimNulls()); + + int size = values.size(); + for (BeanPropertyValue p : values) + if (p.getThrown() != null) + size--; out.startMap(size); - for (SimpleMapEntry p : entries) { - serializeAnything(session, out, p.key, null, null, null); - serializeAnything(session, out, p.value, p.pMeta == null ? session.getBeanContext().string() : p.pMeta.getClassMeta(), session.toString(p.key), p.pMeta); + for (BeanPropertyValue p : values) { + BeanPropertyMeta pMeta = p.getMeta(); + String key = p.getName(); + Object value = p.getValue(); + Throwable t = p.getThrown(); + if (t != null) + session.addBeanGetterWarning(pMeta, t); + else { + serializeAnything(session, out, key, null, null, null); + serializeAnything(session, out, value, pMeta == null ? session.getBeanContext().string() : pMeta.getClassMeta(), key, pMeta); + } } } private static class SimpleMapEntry { final Object key; final Object value; - final BeanPropertyMeta<?> pMeta; - private SimpleMapEntry(Object key, Object value, BeanPropertyMeta<?> pMeta) { + private SimpleMapEntry(Object key, Object value) { this.key = key; this.value = value; - this.pMeta = pMeta; } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/79d19494/org.apache.juneau/src/main/java/org/apache/juneau/urlencoding/UonSerializer.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/urlencoding/UonSerializer.java b/org.apache.juneau/src/main/java/org/apache/juneau/urlencoding/UonSerializer.java index 61dd1d1..df94810 100644 --- a/org.apache.juneau/src/main/java/org/apache/juneau/urlencoding/UonSerializer.java +++ b/org.apache.juneau/src/main/java/org/apache/juneau/urlencoding/UonSerializer.java @@ -367,36 +367,21 @@ public class UonSerializer extends WriterSerializer { } @SuppressWarnings({ "rawtypes" }) - private SerializerWriter serializeBeanMap(UonSerializerSession session, UonWriter out, BeanMap m, boolean addClassAttr) throws Exception { + private SerializerWriter serializeBeanMap(UonSerializerSession session, UonWriter out, BeanMap<?> m, boolean addClassAttr) throws Exception { int depth = session.getIndent(); out.startFlag('o'); - Iterator mapEntries = m.entrySet(session.isTrimNulls()).iterator(); - - // Print out "_class" attribute on this bean if required. - if (addClassAttr) { - String attr = "_class"; - out.cr(depth).appendObject(attr, false, false, false).append('=').append(m.getClassMeta().getInnerClass().getName()); - if (mapEntries.hasNext()) - out.append(','); - } - boolean addComma = false; - while (mapEntries.hasNext()) { - BeanMapEntry p = (BeanMapEntry)mapEntries.next(); + for (BeanPropertyValue p : m.getValues(addClassAttr, session.isTrimNulls())) { BeanPropertyMeta pMeta = p.getMeta(); - String key = p.getKey(); - Object value = null; - try { - value = p.getValue(); - } catch (StackOverflowError e) { - throw e; - } catch (Throwable t) { + String key = p.getName(); + Object value = p.getValue(); + Throwable t = p.getThrown(); + if (t != null) session.addBeanGetterWarning(pMeta, t); - } if (session.canIgnoreValue(pMeta.getClassMeta(), key, value)) continue; http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/79d19494/org.apache.juneau/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java b/org.apache.juneau/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java index 8f68709..fd04afb 100644 --- a/org.apache.juneau/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java +++ b/org.apache.juneau/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java @@ -321,34 +321,19 @@ public class UrlEncodingSerializer extends UonSerializer { } @SuppressWarnings({ "rawtypes" }) - private SerializerWriter serializeBeanMap(UrlEncodingSerializerSession session, UonWriter out, BeanMap m, boolean addClassAttr) throws Exception { + private SerializerWriter serializeBeanMap(UrlEncodingSerializerSession session, UonWriter out, BeanMap<?> m, boolean addClassAttr) throws Exception { int depth = session.getIndent(); - Iterator mapEntries = m.entrySet(session.isTrimNulls()).iterator(); - - // Print out "_class" attribute on this bean if required. - if (addClassAttr) { - String attr = "_class"; - out.appendObject(attr, false, false, true).append('=').append(m.getClassMeta().getInnerClass().getName()); - if (mapEntries.hasNext()) - out.cr(depth).append('&'); - } - boolean addAmp = false; - while (mapEntries.hasNext()) { - BeanMapEntry p = (BeanMapEntry)mapEntries.next(); + for (BeanPropertyValue p : m.getValues(addClassAttr, session.isTrimNulls())) { BeanPropertyMeta pMeta = p.getMeta(); - String key = p.getKey(); - Object value = null; - try { - value = p.getValue(); - } catch (StackOverflowError e) { - throw e; - } catch (Throwable t) { + String key = p.getName(); + Object value = p.getValue(); + Throwable t = p.getThrown(); + if (t != null) session.addBeanGetterWarning(pMeta, t); - } if (session.canIgnoreValue(pMeta.getClassMeta(), key, value)) continue; http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/79d19494/org.apache.juneau/src/main/java/org/apache/juneau/xml/XmlSerializer.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/xml/XmlSerializer.java b/org.apache.juneau/src/main/java/org/apache/juneau/xml/XmlSerializer.java index 11ff7aa..a686412 100644 --- a/org.apache.juneau/src/main/java/org/apache/juneau/xml/XmlSerializer.java +++ b/org.apache.juneau/src/main/java/org/apache/juneau/xml/XmlSerializer.java @@ -221,7 +221,7 @@ public class XmlSerializer extends WriterSerializer { // Handle recursion if (aType != null && ! aType.isPrimitive()) { - BeanMap bm = null; + BeanMap<?> bm = null; if (aType.isBeanMap()) { bm = (BeanMap)o; } else if (aType.isBean()) { @@ -262,7 +262,7 @@ public class XmlSerializer extends WriterSerializer { findNsfMappings(session, o2); } if (bm != null) { - for (BeanMapEntry p : (Set<BeanMapEntry>)bm.entrySet(session.isTrimNulls())) { + for (BeanPropertyValue p : bm.getValues(false, session.isTrimNulls())) { Namespace ns = p.getMeta().getXmlMeta().getNamespace(); if (ns != null && ns.uri != null) @@ -526,38 +526,38 @@ public class XmlSerializer extends WriterSerializer { return hasChildren; } - private boolean serializeBeanMap(XmlSerializerSession session, XmlWriter out, BeanMap m, Namespace elementNs, boolean isCollapsed) throws Exception { + private boolean serializeBeanMap(XmlSerializerSession session, XmlWriter out, BeanMap<?> m, Namespace elementNs, boolean isCollapsed) throws Exception { boolean hasChildren = false; BeanMeta bm = m.getMeta(); + List<BeanPropertyValue> lp = m.getValues(false, session.isTrimNulls()); + Map<String,BeanPropertyMeta> xmlAttrs = bm.getXmlMeta().getXmlAttrProperties(); Object content = null; - for (BeanPropertyMeta p : xmlAttrs.values()) { - - String key = p.getName(); - Object value = null; - try { - value = p.get(m); - } catch (StackOverflowError e) { - throw e; - } catch (Throwable x) { - session.addBeanGetterWarning(p, x); - } + for (BeanPropertyValue p : lp) { + if (xmlAttrs.containsKey(p.getName())) { + BeanPropertyMeta pMeta = p.getMeta(); + String key = p.getName(); + Object value = p.getValue(); + Throwable t = p.getThrown(); + if (t != null) + session.addBeanGetterWarning(pMeta, t); - if (session.canIgnoreValue(p.getClassMeta(), key, value)) - continue; + if (session.canIgnoreValue(pMeta.getClassMeta(), key, value)) + continue; - Namespace ns = (session.isEnableNamespaces() && p.getXmlMeta().getNamespace() != elementNs ? p.getXmlMeta().getNamespace() : null); + Namespace ns = (session.isEnableNamespaces() && pMeta.getXmlMeta().getNamespace() != elementNs ? pMeta.getXmlMeta().getNamespace() : null); - if (p.isBeanUri() || p.isUri()) - out.attrUri(ns, key, value); - else - out.attr(ns, key, value); + if (pMeta.isBeanUri() || pMeta.isUri()) + out.attrUri(ns, key, value); + else + out.attr(ns, key, value); + } } boolean hasContent = false; - for (BeanMapEntry p : (Set<BeanMapEntry>)m.entrySet(session.isTrimNulls())) { + for (BeanPropertyValue p : lp) { BeanPropertyMeta pMeta = p.getMeta(); XmlFormat xf = pMeta.getXmlMeta().getXmlFormat(); @@ -567,15 +567,11 @@ public class XmlSerializer extends WriterSerializer { } else if (xf == ATTR) { // Do nothing } else { - String key = p.getKey(); - Object value = null; - try { - value = p.getValue(); - } catch (StackOverflowError e) { - throw e; - } catch (Throwable x) { - session.addWarning("Could not call getValue() on property ''{0}'', {1}", key, x.getLocalizedMessage()); - } + String key = p.getName(); + Object value = p.getValue(); + Throwable t = p.getThrown(); + if (t != null) + session.addBeanGetterWarning(pMeta, t); if (session.canIgnoreValue(pMeta.getClassMeta(), key, value)) continue; http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/79d19494/org.apache.juneau/src/test/java/org/apache/juneau/CT_BeanMap.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/CT_BeanMap.java b/org.apache.juneau/src/test/java/org/apache/juneau/CT_BeanMap.java index 2050b4d..838e05b 100755 --- a/org.apache.juneau/src/test/java/org/apache/juneau/CT_BeanMap.java +++ b/org.apache.juneau/src/test/java/org/apache/juneau/CT_BeanMap.java @@ -1895,11 +1895,20 @@ public class CT_BeanMap { Z z = new Z(); BeanMap<Z> bm = BeanContext.DEFAULT.forBean(z); - Iterator i = bm.entrySet(true).iterator(); + Iterator i = bm.getValues(false, true).iterator(); assertFalse(i.hasNext()); z.b = ""; - i = bm.entrySet(true).iterator(); + i = bm.getValues(false, true).iterator(); + assertTrue(i.hasNext()); + i.next(); + assertFalse(i.hasNext()); + + i = bm.getValues(false, false).iterator(); + assertTrue(i.hasNext()); + i.next(); + assertTrue(i.hasNext()); + i.next(); assertTrue(i.hasNext()); i.next(); assertFalse(i.hasNext());
