XmlObjectReader.javaElement trees) back into Java objects with populated fields. 514 lines. This is the largest file in the XmlStream framework. Javadoc: "Parses objects serialized by the XmlObjectWriter. Uses the dom4j." Works in pair with XmlObjectWriter — Writer serializes objects to XML, Reader deserializes XML back to objects.
Reader is a stateful object (unlike the stateless Writer). It holds state during a single read session:
processedElements (Set<Element>) — which XML elements were successfully read. After completion, elements NOT in this set are considered "ignored" and appear in warningsprocessedAttributes (Map<Element, Set<String>>) — which attributes per element were read. Same purpose for warningsreferenceObjects (Map<String, Object>) — cache of deserialized objects keyed by o-id. Used for deduplication: if two XML elements reference the same object, it's deserialized once and returned from cache the second timewarnings (String) — accumulated warnings about ignored elements/attributesread() Methodsread(String xml) — public APITakes a raw XML string. Parses it via XmlHelper.fromString() → dom4j Element. Clears state (processedElements, processedAttributes, warnings). Calls internal read(Element). After reading, runs checkForIgnoredElements() — if any XML tags/attributes weren't processed, they appear in warnings. Returns the root deserialized object.
read(Element el) — internal APITakes a dom4j Element, finds the class by tag name (via getClass()), and calls recursive read(Class, Element, ...). If class not found — returns null.
getClass(String elementName)When encountering an XML tag, Reader searches for the corresponding Java class in three places (in priority order):
this.aliasMap.getClassForAlias(name) — if explicitly set via setAliasMap()xmlRegistry.getClassForAlias(name) — classes registered at startupimplementationMapping. If not found, logs error and returns null (element will be ignored)This three-level system allows flexible mapping management: AliasMap for local overrides, XmlRegistry for global rules, Class.forName for backward compatibility with old XML files where tags were FQCNs.
read(Class, Element, attrName, attrValue)The heart of Reader. Takes a field type, XML element, and optional attribute name/value. Logic is a chain of type checks:
o-ref-id — it's a reference to an already-deserialized object. Looks up in referenceObjects and returns cached object (deduplication). If ref-id not found — logs errorIConverter (via xmlRegistry.getConverter(clazz)) — calls converter.fromString(). For simple types: String, Integer, Date, BigDecimal, BooleanenumFromString(). Tries Enum.valueOf(clazz, val). On IllegalArgumentException, does a second attempt with toUpperCase() — backward compatibility with old XML where enums were lowercase. Value "null" is treated as nullignoreEmptyCollections=true and collection is empty — leaves field null@XmlObject) — creates instance via BeanHelper.newInstance(), checks o-id attribute (saves in referenceObjects for future ref-id lookups), and calls read(obj, el) for recursive field populationread(Object obj, Element el)Iterates all fields of the object (via BeanHelper.getAllDeclaredFields() — including inherited), makes them accessible (reflection), and for each XML attribute and child element finds the corresponding field:
@XmlOmitField — if present, field is skipped@XmlField annotation. Compares tag/attribute name with field name (case-sensitive) and with alias from annotationread(field.getType(), element, key, attrValue) for deserialization, then field.set(obj, value) for assignment"Field '...' not found." Element remains unmarked in processedElements and will appear in warningsImportant: the o-id and ref-id fields (Writer's XML attributes) are explicitly skipped — they are not searched among object fields.
checkForIgnoredElements()After reading all XML, Reader checks: were all elements from the source XML tree marked as processed? If not — the XML contains tags for which no fields were found in the Java class. This may indicate:
All unmarked elements and attributes are collected into a warnings string. If the string exceeds 500 characters — truncated (ABBREVIATE_WARNING=500) to avoid spamming logs.
Three protected methods can be overridden in subclasses:
newInstance(Class, Element, String, String) — intercepts object creation. If returns Status.IGNORE, the object is skipped. Default returns null (standard creation)addCollectionEntry(Collection, Object, Element) — intercepts collection addition. If returns true, object is NOT auto-added. Default is falsesetField(Field, Object, Object, Element, String, String) — intercepts field assignment. Default calls field.set(obj, value)These hooks allow subclasses to modify behavior without rewriting the entire logic — e.g., skip certain fields, filter collections, or post-process objects.
initialize(Class) — Pre-scanningCan be called before reading to pre-register all @XmlObject classes in AliasMap. Recursively walks the type tree: for a class with @XmlObject, registers the alias, then for each non-primitive field recursively calls initialize(). Uses a processed Set to prevent infinite recursion on circular references. This allows passing just the root class — Reader itself finds all nested types.
868d6abb7 2025 → 2026 (copyright year update) 63081666f Source file headers: 2024→2025 a72903e36 *.java, *.kt: StringBuffer → StringBuilder b6092df09 Copyright 2023 → 2024 ab45d51fa Copyright 2001-2022 → 2001-2023 73b0be50b org.apache.commons.collections → org.apache.commons.collections4 5f7ef41b8 Copyright 2021 → 2022 cd27dd997 package xstream → xmlstream ceb63e8a1 Source code header: (C) 2001-2021 7c79f1922 Copyright of source header → 2020 73a9755df More code cleanup (StringBuffer→StringBuilder, diamond operator, etc.) 32f634b88 Optimize imports 000ca723d Remove pointless boolean expressions (business) dd5ca38ac CopyRight of all java file-header updated or created a5bbdca6a Change logger to slf4j f979e8a42 MGC-UPDATE: Update auf Version 3.0.0-SNAPSHOT 9ebb88522 Initial commit
73b0be50b migrated from commons-collections 3 to commons-collections4 — affecting CollectionUtils usage. a72903e36 and 73a9755df both replaced StringBuffer with StringBuilder (non-thread-safe but faster, since Reader is single-threaded per session). a5bbdca6a switched to SLF4J logging.