• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2008, http://www.snakeyaml.org
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
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.introspector.PropertyUtils;
28 import org.yaml.snakeyaml.nodes.AnchorNode;
29 import org.yaml.snakeyaml.nodes.MappingNode;
30 import org.yaml.snakeyaml.nodes.Node;
31 import org.yaml.snakeyaml.nodes.NodeTuple;
32 import org.yaml.snakeyaml.nodes.ScalarNode;
33 import org.yaml.snakeyaml.nodes.SequenceNode;
34 import org.yaml.snakeyaml.nodes.Tag;
35 
36 /**
37  * Represent basic YAML structures: scalar, sequence, mapping
38  */
39 public abstract class BaseRepresenter {
40     protected final Map<Class<?>, Represent> representers = new HashMap<Class<?>, Represent>();
41     /**
42      * in Java 'null' is not a type. So we have to keep the null representer
43      * separately otherwise it will coincide with the default representer which
44      * is stored with the key null.
45      */
46     protected Represent nullRepresenter;
47     // the order is important (map can be also a sequence of key-values)
48     protected final Map<Class<?>, Represent> multiRepresenters = new LinkedHashMap<Class<?>, Represent>();
49     protected Character defaultScalarStyle;
50     protected FlowStyle defaultFlowStyle = FlowStyle.AUTO;
51     protected final Map<Object, Node> representedObjects = new IdentityHashMap<Object, Node>() {
52         private static final long serialVersionUID = -5576159264232131854L;
53 
54         public Node put(Object key, Node value) {
55             return super.put(key, new AnchorNode(value));
56         }
57     };
58 
59     protected Object objectToRepresent;
60     private PropertyUtils propertyUtils;
61     private boolean explicitPropertyUtils = false;
62 
represent(Object data)63     public Node represent(Object data) {
64         Node node = representData(data);
65         representedObjects.clear();
66         objectToRepresent = null;
67         return node;
68     }
69 
representData(Object data)70     protected final Node representData(Object data) {
71         objectToRepresent = data;
72         // check for identity
73         if (representedObjects.containsKey(objectToRepresent)) {
74             Node node = representedObjects.get(objectToRepresent);
75             return node;
76         }
77         // }
78         // check for null first
79         if (data == null) {
80             Node node = nullRepresenter.representData(null);
81             return node;
82         }
83         // check the same class
84         Node node;
85         Class<?> clazz = data.getClass();
86         if (representers.containsKey(clazz)) {
87             Represent representer = representers.get(clazz);
88             node = representer.representData(data);
89         } else {
90             // check the parents
91             for (Class<?> repr : multiRepresenters.keySet()) {
92                 if (repr.isInstance(data)) {
93                     Represent representer = multiRepresenters.get(repr);
94                     node = representer.representData(data);
95                     return node;
96                 }
97             }
98 
99             // check defaults
100             if (multiRepresenters.containsKey(null)) {
101                 Represent representer = multiRepresenters.get(null);
102                 node = representer.representData(data);
103             } else {
104                 Represent representer = representers.get(null);
105                 node = representer.representData(data);
106             }
107         }
108         return node;
109     }
110 
representScalar(Tag tag, String value, Character style)111     protected Node representScalar(Tag tag, String value, Character style) {
112         if (style == null) {
113             style = this.defaultScalarStyle;
114         }
115         Node node = new ScalarNode(tag, value, null, null, style);
116         return node;
117     }
118 
representScalar(Tag tag, String value)119     protected Node representScalar(Tag tag, String value) {
120         return representScalar(tag, value, null);
121     }
122 
representSequence(Tag tag, Iterable<?> sequence, Boolean flowStyle)123     protected Node representSequence(Tag tag, Iterable<?> sequence, Boolean flowStyle) {
124         int size = 10;// default for ArrayList
125         if (sequence instanceof List<?>) {
126             size = ((List<?>) sequence).size();
127         }
128         List<Node> value = new ArrayList<Node>(size);
129         SequenceNode node = new SequenceNode(tag, value, flowStyle);
130         representedObjects.put(objectToRepresent, node);
131         boolean bestStyle = true;
132         for (Object item : sequence) {
133             Node nodeItem = representData(item);
134             if (!(nodeItem instanceof ScalarNode && ((ScalarNode) nodeItem).getStyle() == null)) {
135                 bestStyle = false;
136             }
137             value.add(nodeItem);
138         }
139         if (flowStyle == null) {
140             if (defaultFlowStyle != FlowStyle.AUTO) {
141                 node.setFlowStyle(defaultFlowStyle.getStyleBoolean());
142             } else {
143                 node.setFlowStyle(bestStyle);
144             }
145         }
146         return node;
147     }
148 
representMapping(Tag tag, Map<?, ?> mapping, Boolean flowStyle)149     protected Node representMapping(Tag tag, Map<?, ?> mapping, Boolean flowStyle) {
150         List<NodeTuple> value = new ArrayList<NodeTuple>(mapping.size());
151         MappingNode node = new MappingNode(tag, value, flowStyle);
152         representedObjects.put(objectToRepresent, node);
153         boolean bestStyle = true;
154         for (Map.Entry<?, ?> entry : mapping.entrySet()) {
155             Node nodeKey = representData(entry.getKey());
156             Node nodeValue = representData(entry.getValue());
157             if (!(nodeKey instanceof ScalarNode && ((ScalarNode) nodeKey).getStyle() == null)) {
158                 bestStyle = false;
159             }
160             if (!(nodeValue instanceof ScalarNode && ((ScalarNode) nodeValue).getStyle() == null)) {
161                 bestStyle = false;
162             }
163             value.add(new NodeTuple(nodeKey, nodeValue));
164         }
165         if (flowStyle == null) {
166             if (defaultFlowStyle != FlowStyle.AUTO) {
167                 node.setFlowStyle(defaultFlowStyle.getStyleBoolean());
168             } else {
169                 node.setFlowStyle(bestStyle);
170             }
171         }
172         return node;
173     }
174 
setDefaultScalarStyle(ScalarStyle defaultStyle)175     public void setDefaultScalarStyle(ScalarStyle defaultStyle) {
176         this.defaultScalarStyle = defaultStyle.getChar();
177     }
178 
setDefaultFlowStyle(FlowStyle defaultFlowStyle)179     public void setDefaultFlowStyle(FlowStyle defaultFlowStyle) {
180         this.defaultFlowStyle = defaultFlowStyle;
181     }
182 
getDefaultFlowStyle()183     public FlowStyle getDefaultFlowStyle() {
184         return this.defaultFlowStyle;
185     }
186 
setPropertyUtils(PropertyUtils propertyUtils)187     public void setPropertyUtils(PropertyUtils propertyUtils) {
188         this.propertyUtils = propertyUtils;
189         this.explicitPropertyUtils = true;
190     }
191 
getPropertyUtils()192     public final PropertyUtils getPropertyUtils() {
193         if (propertyUtils == null) {
194             propertyUtils = new PropertyUtils();
195         }
196         return propertyUtils;
197     }
198 
isExplicitPropertyUtils()199     public final boolean isExplicitPropertyUtils() {
200         return explicitPropertyUtils;
201     }
202 }
203