in xstream/src/java/com/thoughtworks/xstream/converters/extended/ToAttributedValueConverter.java [134:218]
public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
final Class<?> sourceType = source.getClass();
final Map<String, Field> defaultFieldDefinition = new HashMap<>();
final String[] tagValue = new String[1];
final Object[] realValue = new Object[1];
final Class<?>[] fieldType = new Class[1];
final Class<?>[] definingType = new Class[1];
reflectionProvider.visitSerializableFields(source, new ReflectionProvider.Visitor() {
@Override
public void visit(final String fieldName, final Class<?> type, final Class<?> definedIn, final Object value) {
if (!mapper.shouldSerializeMember(definedIn, fieldName)) {
return;
}
final FastField field = new FastField(definedIn, fieldName);
final String alias = mapper.serializedMember(definedIn, fieldName);
if (!defaultFieldDefinition.containsKey(alias)) {
final Class<?> lookupType = sourceType;
defaultFieldDefinition.put(alias, reflectionProvider.getField(lookupType, fieldName));
} else if (!fieldIsEqual(field)) {
final ConversionException exception = new ConversionException(
"Cannot write attribute twice for object");
exception.add("alias", alias);
exception.add("type", sourceType.getName());
throw exception;
}
ConverterMatcher converter = Enum.class.isAssignableFrom(type) ? (ConverterMatcher)enumMapper
.getConverterFromItemType(null, type, null) : (ConverterMatcher)mapper.getLocalConverter(definedIn,
fieldName);
if (converter == null) {
converter = lookup.lookupConverterForType(type);
}
if (value != null) {
final boolean isValueField = valueField != null && fieldIsEqual(field);
if (isValueField) {
definingType[0] = definedIn;
fieldType[0] = type;
realValue[0] = value;
tagValue[0] = STRUCTURE_MARKER;
}
if (converter instanceof SingleValueConverter) {
final String str = ((SingleValueConverter)converter).toString(value);
if (isValueField) {
tagValue[0] = str;
} else {
if (str != null) {
writer.addAttribute(alias, str);
}
}
} else {
if (!isValueField) {
final ConversionException exception = new ConversionException(
"Cannot write element as attribute");
exception.add("alias", alias);
exception.add("type", sourceType.getName());
throw exception;
}
}
}
}
});
if (tagValue[0] != null) {
final Class<?> actualType = realValue[0].getClass();
final Class<?> defaultType = mapper.defaultImplementationOf(fieldType[0]);
if (!actualType.equals(defaultType)) {
final String serializedClassName = mapper.serializedClass(actualType);
if (!serializedClassName.equals(mapper.serializedClass(defaultType))) {
final String attributeName = mapper.aliasForSystemAttribute("class");
if (attributeName != null) {
writer.addAttribute(attributeName, serializedClassName);
}
}
}
if (tagValue[0] == STRUCTURE_MARKER) {
context.convertAnother(realValue[0]);
} else {
writer.setValue(tagValue[0]);
}
}
}