1 package com.fasterxml.jackson.dataformat.xml.ser;
2
3 import java.util.*;
4
5 import com.fasterxml.jackson.databind.*;
6 import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
7 import com.fasterxml.jackson.databind.ser.*;
8 import com.fasterxml.jackson.databind.ser.std.BeanSerializerBase;
9 import com.fasterxml.jackson.dataformat.xml.util.AnnotationUtil;
10 import com.fasterxml.jackson.dataformat.xml.util.TypeUtil;
11 import com.fasterxml.jackson.dataformat.xml.util.XmlInfo;
12
13 /**
14  * We need a {@link BeanSerializerModifier} to replace default <code>BeanSerializer</code>
15  * with XML-specific one; mostly to ensure that attribute properties are output
16  * before element properties.
17  */

18 public class XmlBeanSerializerModifier
19     extends BeanSerializerModifier
20     implements java.io.Serializable
21 {
22     private static final long serialVersionUID = 1L;
23
24     public XmlBeanSerializerModifier() { }
25
26     /*
27     /**********************************************************
28     /* Overridden methods
29     /**********************************************************
30      */

31
32     /**
33      * First thing to do is to find annotations regarding XML serialization,
34      * and wrap collection serializers.
35      */

36     @Override
37     public List<BeanPropertyWriter> changeProperties(SerializationConfig config,
38             BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties)
39     {
40         final AnnotationIntrospector intr = config.getAnnotationIntrospector();
41         for (int i = 0, len = beanProperties.size(); i < len; ++i) {
42             BeanPropertyWriter bpw = beanProperties.get(i);
43             final AnnotatedMember member = bpw.getMember();
44             String ns = AnnotationUtil.findNamespaceAnnotation(intr, member);
45             Boolean isAttribute = AnnotationUtil.findIsAttributeAnnotation(intr, member);
46             Boolean isText = AnnotationUtil.findIsTextAnnotation(intr, member);
47             Boolean isCData = AnnotationUtil.findIsCDataAnnotation(intr, member);
48             bpw.setInternalSetting(XmlBeanSerializerBase.KEY_XML_INFO,
49                     new XmlInfo(isAttribute, ns, isText, isCData));
50
51             // Actually: if we have a Collection type, easiest place to add wrapping would be here...
52             //  or: let's also allow wrapping of "untyped" (Object): assuming it is a dynamically
53             //   typed Collection...
54             if (!TypeUtil.isIndexedType(bpw.getType())) {
55                 continue;
56             }
57             PropertyName wrappedName = PropertyName.construct(bpw.getName(), ns);
58             PropertyName wrapperName = bpw.getWrapperName();
59
60             // first things first: no wrapping?
61             if (wrapperName == null || wrapperName == PropertyName.NO_NAME) {
62                 continue;
63             }
64             // no local name? Just double the wrapped name for wrapper
65             String localName = wrapperName.getSimpleName();
66             if (localName == null || localName.length() == 0) {
67                 wrapperName = wrappedName;
68             }
69             beanProperties.set(i, new XmlBeanPropertyWriter(bpw, wrapperName, wrappedName));
70         }
71         return beanProperties;
72     }
73     
74     @Override
75     public JsonSerializer<?> modifySerializer(SerializationConfig config,
76             BeanDescription beanDesc, JsonSerializer<?> serializer)
77     {
78         /* First things first: we can only handle real BeanSerializers; question
79          * is, what to do if it's not one: throw exception or bail out?
80          * For now let's do latter.
81          */

82         if (!(serializer instanceof BeanSerializerBase)) {
83             return serializer;
84         }
85         return new XmlBeanSerializer((BeanSerializerBase) serializer);
86     }
87 }
88