1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.yaml.snakeyaml.representer;
17
18 import java.beans.IntrospectionException;
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Set;
25
26 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
27 import org.yaml.snakeyaml.error.YAMLException;
28 import org.yaml.snakeyaml.introspector.Property;
29 import org.yaml.snakeyaml.nodes.MappingNode;
30 import org.yaml.snakeyaml.nodes.Node;
31 import org.yaml.snakeyaml.nodes.NodeId;
32 import org.yaml.snakeyaml.nodes.NodeTuple;
33 import org.yaml.snakeyaml.nodes.ScalarNode;
34 import org.yaml.snakeyaml.nodes.SequenceNode;
35 import org.yaml.snakeyaml.nodes.Tag;
36
37
38
39
40 public class Representer extends SafeRepresenter {
41
42 public Representer() {
43 this.representers.put(null, new RepresentJavaBean());
44 }
45
46 protected class RepresentJavaBean implements Represent {
47 public Node representData(Object data) {
48 try {
49 return representJavaBean(getProperties(data.getClass()), data);
50 } catch (IntrospectionException e) {
51 throw new YAMLException(e);
52 }
53 }
54 }
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
71 List<NodeTuple> value = new ArrayList<NodeTuple>(properties.size());
72 Tag tag;
73 Tag customTag = classTags.get(javaBean.getClass());
74 tag = customTag != null ? customTag : new Tag(javaBean.getClass());
75
76 MappingNode node = new MappingNode(tag, value, null);
77 representedObjects.put(javaBean, node);
78 boolean bestStyle = true;
79 for (Property property : properties) {
80 Object memberValue = property.get(javaBean);
81 Tag customPropertyTag = memberValue == null ? null : classTags.get(memberValue
82 .getClass());
83 NodeTuple tuple = representJavaBeanProperty(javaBean, property, memberValue,
84 customPropertyTag);
85 if (tuple == null) {
86 continue;
87 }
88 if (((ScalarNode) tuple.getKeyNode()).getStyle() != null) {
89 bestStyle = false;
90 }
91 Node nodeValue = tuple.getValueNode();
92 if (!((nodeValue instanceof ScalarNode && ((ScalarNode) nodeValue).getStyle() == null))) {
93 bestStyle = false;
94 }
95 value.add(tuple);
96 }
97 if (defaultFlowStyle != FlowStyle.AUTO) {
98 node.setFlowStyle(defaultFlowStyle.getStyleBoolean());
99 } else {
100 node.setFlowStyle(bestStyle);
101 }
102 return node;
103 }
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119 protected NodeTuple representJavaBeanProperty(Object javaBean, Property property,
120 Object propertyValue, Tag customTag) {
121 ScalarNode nodeKey = (ScalarNode) representData(property.getName());
122
123 boolean hasAlias = this.representedObjects.containsKey(propertyValue);
124
125 Node nodeValue = representData(propertyValue);
126
127 if (propertyValue != null && !hasAlias) {
128 NodeId nodeId = nodeValue.getNodeId();
129 if (customTag == null) {
130 if (nodeId == NodeId.scalar) {
131 if (propertyValue instanceof Enum<?>) {
132 nodeValue.setTag(Tag.STR);
133 }
134 } else {
135 if (nodeId == NodeId.mapping) {
136 if (property.getType() == propertyValue.getClass()) {
137 if (!(propertyValue instanceof Map<?, ?>)) {
138 if (!nodeValue.getTag().equals(Tag.SET)) {
139 nodeValue.setTag(Tag.MAP);
140 }
141 }
142 }
143 }
144 checkGlobalTag(property, nodeValue, propertyValue);
145 }
146 }
147 }
148
149 return new NodeTuple(nodeKey, nodeValue);
150 }
151
152
153
154
155
156
157
158
159
160
161
162
163 @SuppressWarnings("unchecked")
164 protected void checkGlobalTag(Property property, Node node, Object object) {
165 Class<?>[] arguments = property.getActualTypeArguments();
166 if (arguments != null) {
167 if (node.getNodeId() == NodeId.sequence) {
168
169 Class<? extends Object> t = arguments[0];
170 SequenceNode snode = (SequenceNode) node;
171 Iterable<Object> memberList;
172 if (object.getClass().isArray()) {
173 memberList = Arrays.asList((Object[]) object);
174 } else {
175
176 memberList = (Iterable<Object>) object;
177 }
178 Iterator<Object> iter = memberList.iterator();
179 for (Node childNode : snode.getValue()) {
180 Object member = iter.next();
181 if (member != null) {
182 if (t.equals(member.getClass()))
183 if (childNode.getNodeId() == NodeId.mapping) {
184 childNode.setTag(Tag.MAP);
185 }
186 }
187 }
188 } else if (object instanceof Set) {
189 Class<?> t = arguments[0];
190 MappingNode mnode = (MappingNode) node;
191 Iterator<NodeTuple> iter = mnode.getValue().iterator();
192 Set<?> set = (Set<?>) object;
193 for (Object member : set) {
194 NodeTuple tuple = iter.next();
195 Node keyNode = tuple.getKeyNode();
196 if (t.equals(member.getClass())) {
197 if (keyNode.getNodeId() == NodeId.mapping) {
198 keyNode.setTag(Tag.MAP);
199 }
200 }
201 }
202 } else if (object instanceof Map) {
203 Class<?> keyType = arguments[0];
204 Class<?> valueType = arguments[1];
205 MappingNode mnode = (MappingNode) node;
206 for (NodeTuple tuple : mnode.getValue()) {
207 resetTag(keyType, tuple.getKeyNode());
208 resetTag(valueType, tuple.getValueNode());
209 }
210 } else {
211
212
213 }
214 }
215 }
216
217 private void resetTag(Class<? extends Object> type, Node node) {
218 Tag tag = node.getTag();
219 if (tag.matches(type)) {
220 if (Enum.class.isAssignableFrom(type)) {
221 node.setTag(Tag.STR);
222 } else {
223 node.setTag(Tag.MAP);
224 }
225 }
226 }
227
228
229
230
231
232
233
234
235
236 protected Set<Property> getProperties(Class<? extends Object> type)
237 throws IntrospectionException {
238 return getPropertyUtils().getProperties(type);
239 }
240 }