#705: HibernateCollectionsMapper.java

projectforge-business/src/main/java/org/projectforge/framework/persistence/xstream/HibernateCollectionsMapper.java XStream mapper — replaces Hibernate collection type names with JDK equivalents in XML output, projectforge-business/src/main/java/org/projectforge/framework/persistence/xstream/HibernateCollectionsMapper.java 114 lines · 49 code · 51 comments · 14 blank
Extends XStream's XmlFriendlyMapper to intercept type-to-name and class-to-name lookups during serialization. When XStream needs to write a class name as an XML element or attribute, this mapper substitutes Hibernate-specific collection classes (PersistentList, PersistentSet, etc.) with their standard JDK counterparts (ArrayList, HashSet, etc.). This ensures the generated XML contains readable, framework-agnostic type names. This operates at the name mapping layer — the HibernateCollectionConverter handles the actual collection data conversion.

Architecture

Class Hierarchy

HibernateCollectionsMapper extends com.thoughtworks.xstream.mapper.XmlFriendlyMapper, which itself extends MapperWrapper. The XStream mapper chain follows the Decorator pattern — each mapper wraps another mapper, and calls are forwarded through the chain. This mapper intercepts three specific methods to apply Hibernate→JDK collection class substitutions.

Mapping Tables

The class uses three parallel arrays indexed identically:

IndexHibernate Class (hbClasses)Hibernate Name (hbClassNames)JDK Replacement (jdkClasses/jdkClassNames)
0PersistentListorg.hibernate.collection.spi.PersistentListjava.util.ArrayList
1PersistentSetorg.hibernate.collection.spi.PersistentSetjava.util.HashSet
2PersistentMaporg.hibernate.collection.spi.PersistentMapjava.util.HashMap
3PersistentSortedSetorg.hibernate.collection.spi.PersistentSortedSetjava.util.TreeSet
4PersistentSortedMaporg.hibernate.collection.spi.PersistentSortedMapjava.util.TreeMap

Overridden Methods

MethodInputAction
mapNameToXML(String javaName)Fully-qualified Java class nameApplies string replacement via replaceClasses(String), then delegates to super for XML-friendly encoding (e.g. replacing $ in inner class names).
serializedClass(Class type)Class objectApplies class replacement via replaceClasses(Class), then delegates to super.
serializedMember(Class type, String fieldName)Declaring class + field nameApplies class replacement to type before delegating to super, ensuring field declarations within Hibernate collections are serialized with JDK type context.

Directionality

This mapper is write-only (serialization/deflating direction). It does not implement the reverse mapping for realClass() or deserialization. The source explicitly notes: "This mapper takes care only of the writing to the XML (deflating) not the other way around (inflating) because there is no need." When XML is deserialized, XStream creates standard JDK collections, and Hibernate's ORM layer wraps them into PersistentCollection subclasses when the entity is later attached to a session.

Integration Points

Design Decisions & Gotchas

Git History

868d6abb7 2025 -> 2026
63081666f Source file headers: 2024-> 2025.
c1d14ecdb Migration stuff in progress...
b6092df09 Copyright 2023 -> 2024
ab45d51fa Copyright 2001-2022 -> 2001-2023.
5f7ef41b8 Copyright 2021 -> 2022
ceb63e8a1 Source code header: (C) 2001-2021.
7c79f1922 Copyright of source header -> 2020.
32f634b88 Optimize imports
dd5ca38ac CopyRight of all java file-header updated or created.
9ebb88522 Initial commit