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