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