1 package com.fasterxml.jackson.dataformat.xml.ser;
2
3 import javax.xml.namespace.QName;
4
5 import com.fasterxml.jackson.core.JsonGenerator;
6 import com.fasterxml.jackson.databind.*;
7 import com.fasterxml.jackson.databind.ser.*;
8 import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap;
9
10 /**
11  * Property writer sub-class used for handling element wrapping needed for serializing
12  * collection (array, Collection; possibly Map) types.
13  */

14 public class XmlBeanPropertyWriter
15     extends BeanPropertyWriter
16 {
17     private static final long serialVersionUID = 1L;
18
19     /*
20     /**********************************************************
21     /* Config settings
22     /**********************************************************
23      */

24
25     /**
26      * Element name used as wrapper for collection.
27      */

28     protected final QName _wrapperQName;
29
30     /**
31      * Element name used for items in the collection
32      */

33     protected final QName _wrappedQName;
34
35     /*
36     /**********************************************************
37     /* Life-cycle: construction, configuration
38     /**********************************************************
39      */

40
41     public XmlBeanPropertyWriter(BeanPropertyWriter wrapped,
42             PropertyName wrapperName, PropertyName wrappedName) {
43         this(wrapped, wrapperName, wrappedName, null);
44     }
45
46     public XmlBeanPropertyWriter(BeanPropertyWriter wrapped,
47             PropertyName wrapperName, PropertyName wrappedName,
48             JsonSerializer<Object> serializer)
49     {
50         super(wrapped);
51         _wrapperQName = _qname(wrapperName);
52         _wrappedQName = _qname(wrappedName);
53
54         if (serializer != null) {
55             assignSerializer(serializer);
56         }
57     }
58
59     private QName _qname(PropertyName n)
60     {
61         String ns = n.getNamespace();
62         if (ns == null) {
63             ns = "";
64         }
65         return new QName(ns, n.getSimpleName());
66     }
67     
68     /*
69     /**********************************************************
70     /* Overridden methods
71     /**********************************************************
72      */

73
74     /**
75      * Overridden version so that we can wrap output within wrapper element if
76      * and as necessary.
77      */

78     @Override
79     public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider prov)
80         throws Exception
81     {
82         Object value = get(bean);
83
84         /* 13-Feb-2014, tatu: As per [#103], default handling does not really
85          *   work here. Rather, we need just a wrapping and should NOT call
86          *   null handler, as it does not know what to do...
87          *   
88          *   Question, however, is what should it be serialized as. We have two main
89          *   choices; equivalent empty List, and "nothing" (missing). Let's start with
90          *   empty List? But producing missing entry is non-trivial...
91          */

92         if (value == null) {
93             // if (_nullSerializer != null) { ... }
94
95             // For Empty List, we'd do this:
96             /*
97             @SuppressWarnings("resource")
98             final ToXmlGenerator xmlGen = (jgen instanceof ToXmlGenerator) ? (ToXmlGenerator) jgen : null;
99             if (xmlGen != null) {
100                 xmlGen.startWrappedValue(_wrapperQName, _wrappedQName);
101                 xmlGen.finishWrappedValue(_wrapperQName, _wrappedQName);
102             }
103             */

104             // but for missing thing, well, just output nothing
105             
106             return;
107         }
108
109         // then find serializer to use
110         JsonSerializer<Object> ser = _serializer;
111         if (ser == null) {
112             Class<?> cls = value.getClass();
113             PropertySerializerMap map = _dynamicSerializers;
114             ser = map.serializerFor(cls);
115             if (ser == null) {
116                 ser = _findAndAddDynamic(map, cls, prov);
117             }
118         }
119         // and then see if we must suppress certain values (default, empty)
120         if (_suppressableValue != null) {
121             if (MARKER_FOR_EMPTY == _suppressableValue) {
122                 if (ser.isEmpty(prov, value)) {
123                     return;
124                 }
125             } else if (_suppressableValue.equals(value)) {
126                 return;
127             }
128         }
129         // For non-nulls: simple check for direct cycles
130         if (value == bean) {
131             // NOTE: method signature here change 2.3->2.4
132             if (_handleSelfReference(bean, jgen, prov, ser)) {
133                 return;
134             }
135         }
136
137         final ToXmlGenerator xmlGen = (jgen instanceof ToXmlGenerator) ? (ToXmlGenerator) jgen : null;
138         // Ok then; addition we want to do is to add wrapper element, and that's what happens here
139         // 19-Aug-2013, tatu: ... except for those nasty 'convertValue()' calls...
140         if (xmlGen != null) {
141             xmlGen.startWrappedValue(_wrapperQName, _wrappedQName);
142         }
143         jgen.writeFieldName(_name);
144         if (_typeSerializer == null) {
145             ser.serialize(value, jgen, prov);
146         } else {
147             ser.serializeWithType(value, jgen, prov, _typeSerializer);
148         }
149         if (xmlGen != null) {
150             xmlGen.finishWrappedValue(_wrapperQName, _wrappedQName);
151         }
152     }
153 }
154