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.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.IdentityHashMap;
22 import java.util.LinkedHashMap;
23 import java.util.List;
24 import java.util.Map;
25
26 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
27 import org.yaml.snakeyaml.DumperOptions.ScalarStyle;
28 import org.yaml.snakeyaml.error.YAMLException;
29 import org.yaml.snakeyaml.introspector.PropertyUtils;
30 import org.yaml.snakeyaml.nodes.AnchorNode;
31 import org.yaml.snakeyaml.nodes.MappingNode;
32 import org.yaml.snakeyaml.nodes.Node;
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 abstract class BaseRepresenter {
42 protected final Map<Class<?>, Represent> representers = new HashMap<Class<?>, Represent>();
43
44
45
46
47
48 protected Represent nullRepresenter;
49
50 protected final Map<Class<?>, Represent> multiRepresenters = new LinkedHashMap<Class<?>, Represent>();
51 private Character defaultStyle;
52 protected FlowStyle defaultFlowStyle = FlowStyle.AUTO;
53 protected final Map<Object, Node> representedObjects = new IdentityHashMap<Object, Node>() {
54 private static final long serialVersionUID = -5576159264232131854L;
55
56 public Node put(Object key, Node value) {
57 return super.put(key, new AnchorNode(value));
58 }
59 };
60
61 protected Object objectToRepresent;
62 private PropertyUtils propertyUtils;
63 private boolean explicitPropertyUtils = false;
64
65 public Node represent(Object data) {
66 Node node = representData(data);
67 representedObjects.clear();
68 objectToRepresent = null;
69 return node;
70 }
71
72 protected final Node representData(Object data) {
73 objectToRepresent = data;
74
75 if (representedObjects.containsKey(objectToRepresent)) {
76 Node node = representedObjects.get(objectToRepresent);
77 return node;
78 }
79
80
81 if (data == null) {
82 Node node = nullRepresenter.representData(data);
83 return node;
84 }
85
86 Node node;
87 Class<?> clazz = data.getClass();
88 if (representers.containsKey(clazz)) {
89 Represent representer = representers.get(clazz);
90 node = representer.representData(data);
91 } else {
92
93 for (Class<?> repr : multiRepresenters.keySet()) {
94 if (repr.isInstance(data)) {
95 Represent representer = multiRepresenters.get(repr);
96 node = representer.representData(data);
97 return node;
98 }
99 }
100
101 if (clazz.isArray()) {
102 throw new YAMLException("Arrays of primitives are not fully supported.");
103 }
104
105 if (multiRepresenters.containsKey(null)) {
106 Represent representer = multiRepresenters.get(null);
107 node = representer.representData(data);
108 } else {
109 Represent representer = representers.get(null);
110 node = representer.representData(data);
111 }
112 }
113 return node;
114 }
115
116 protected Node representScalar(Tag tag, String value, Character style) {
117 if (style == null) {
118 style = this.defaultStyle;
119 }
120 Node node = new ScalarNode(tag, value, null, null, style);
121
122 return node;
123 }
124
125 protected Node representScalar(Tag tag, String value) {
126 return representScalar(tag, value, null);
127 }
128
129 protected Node representSequence(Tag tag, Iterable<? extends Object> sequence, Boolean flowStyle) {
130 int size = 10;
131 if (sequence instanceof List<?>) {
132 size = ((List<?>) sequence).size();
133 }
134 List<Node> value = new ArrayList<Node>(size);
135 SequenceNode node = new SequenceNode(tag, value, flowStyle);
136 representedObjects.put(objectToRepresent, node);
137 boolean bestStyle = true;
138 for (Object item : sequence) {
139 Node nodeItem = representData(item);
140 if (!((nodeItem instanceof ScalarNode && ((ScalarNode) nodeItem).getStyle() == null))) {
141 bestStyle = false;
142 }
143 value.add(nodeItem);
144 }
145 if (flowStyle == null) {
146 if (defaultFlowStyle != FlowStyle.AUTO) {
147 node.setFlowStyle(defaultFlowStyle.getStyleBoolean());
148 } else {
149 node.setFlowStyle(bestStyle);
150 }
151 }
152 return node;
153 }
154
155 protected Node representMapping(Tag tag, Map<? extends Object, Object> mapping,
156 Boolean flowStyle) {
157 List<NodeTuple> value = new ArrayList<NodeTuple>(mapping.size());
158 MappingNode node = new MappingNode(tag, value, flowStyle);
159 representedObjects.put(objectToRepresent, node);
160 boolean bestStyle = true;
161 for (Object itemKey : mapping.keySet()) {
162 Object itemValue = mapping.get(itemKey);
163 Node nodeKey = representData(itemKey);
164 Node nodeValue = representData(itemValue);
165 if (!((nodeKey instanceof ScalarNode && ((ScalarNode) nodeKey).getStyle() == null))) {
166 bestStyle = false;
167 }
168 if (!((nodeValue instanceof ScalarNode && ((ScalarNode) nodeValue).getStyle() == null))) {
169 bestStyle = false;
170 }
171 value.add(new NodeTuple(nodeKey, nodeValue));
172 }
173 if (flowStyle == null) {
174 if (defaultFlowStyle != FlowStyle.AUTO) {
175 node.setFlowStyle(defaultFlowStyle.getStyleBoolean());
176 } else {
177 node.setFlowStyle(bestStyle);
178 }
179 }
180 return node;
181 }
182
183 public void setDefaultScalarStyle(ScalarStyle defaultStyle) {
184 this.defaultStyle = defaultStyle.getChar();
185 }
186
187 public void setDefaultFlowStyle(FlowStyle defaultFlowStyle) {
188 this.defaultFlowStyle = defaultFlowStyle;
189 }
190
191 public FlowStyle getDefaultFlowStyle() {
192 return this.defaultFlowStyle;
193 }
194
195 public void setPropertyUtils(PropertyUtils propertyUtils) {
196 this.propertyUtils = propertyUtils;
197 this.explicitPropertyUtils = true;
198 }
199
200 public final PropertyUtils getPropertyUtils() {
201 if (propertyUtils == null) {
202 propertyUtils = new PropertyUtils();
203 }
204 return propertyUtils;
205 }
206
207 public final boolean isExplicitPropertyUtils() {
208 return explicitPropertyUtils;
209 }
210 }