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