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 */
16package org.yaml.snakeyaml;
17
18import java.util.List;
19import java.util.Map;
20import java.util.TreeMap;
21
22import junit.framework.TestCase;
23
24import org.yaml.snakeyaml.constructor.AbstractConstruct;
25import org.yaml.snakeyaml.constructor.Constructor;
26import org.yaml.snakeyaml.nodes.MappingNode;
27import org.yaml.snakeyaml.nodes.Node;
28import org.yaml.snakeyaml.nodes.SequenceNode;
29import org.yaml.snakeyaml.nodes.Tag;
30import org.yaml.snakeyaml.representer.Represent;
31import org.yaml.snakeyaml.representer.Representer;
32
33/**
34 * Test Example 2.24 from the YAML specification
35 *
36 * @see <a href="http://yaml.org/spec/1.1/"></a>
37 */
38public class Example2_24Test extends TestCase {
39    class MyConstructor extends Constructor {
40        public MyConstructor() {
41            this.yamlConstructors.put(new Tag("tag:clarkevans.com,2002:shape"),
42                    new ConstructShape());
43            this.yamlConstructors.put(new Tag("tag:clarkevans.com,2002:circle"),
44                    new ConstructCircle());
45            this.yamlConstructors.put(new Tag("tag:clarkevans.com,2002:line"), new ConstructLine());
46            this.yamlConstructors.put(new Tag("tag:clarkevans.com,2002:label"),
47                    new ConstructLabel());
48        }
49
50        private class ConstructShape extends AbstractConstruct {
51            @SuppressWarnings("unchecked")
52            public Object construct(Node node) {
53                SequenceNode snode = (SequenceNode) node;
54                List<Entity> values = (List<Entity>) constructSequence(snode);
55                Shape shape = new Shape(values);
56                return shape;
57            }
58        }
59
60        private class ConstructCircle extends AbstractConstruct {
61            @SuppressWarnings("unchecked")
62            public Object construct(Node node) {
63                MappingNode mnode = (MappingNode) node;
64                Map<Object, Object> values = constructMapping(mnode);
65                Circle circle = new Circle((Map<String, Integer>) values.get("center"),
66                        (Integer) values.get("radius"));
67                return circle;
68            }
69        }
70
71        private class ConstructLine extends AbstractConstruct {
72            @SuppressWarnings("unchecked")
73            public Object construct(Node node) {
74                MappingNode mnode = (MappingNode) node;
75                Map<Object, Object> values = constructMapping(mnode);
76                Line line = new Line((Map<String, Integer>) values.get("start"),
77                        (Map<String, Integer>) values.get("finish"));
78                return line;
79            }
80        }
81
82        private class ConstructLabel extends AbstractConstruct {
83            @SuppressWarnings("unchecked")
84            public Object construct(Node node) {
85                MappingNode mnode = (MappingNode) node;
86                Map<Object, Object> values = constructMapping(mnode);
87                Label label = new Label((Map<String, Integer>) values.get("start"),
88                        (Integer) values.get("color"), (String) values.get("text"));
89                return label;
90            }
91        }
92    }
93
94    class MyRepresenter extends Representer {
95        public MyRepresenter() {
96            this.representers.put(Shape.class, new RepresentShape());
97            this.representers.put(Circle.class, new RepresentCircle());
98            this.representers.put(Line.class, new RepresentLine());
99            this.representers.put(Label.class, new RepresentLabel());
100            this.representers.put(HexInteger.class, new RepresentHex());
101        }
102
103        private class RepresentShape implements Represent {
104            public Node representData(Object data) {
105                Shape shape = (Shape) data;
106                List<Entity> value = shape.getEntities();
107                return representSequence(new Tag("!shape"), value, Boolean.FALSE);
108            }
109        }
110
111        private class RepresentCircle implements Represent {
112            public Node representData(Object data) {
113                Circle circle = (Circle) data;
114                Map<String, Object> map = new TreeMap<String, Object>();
115                map.put("center", circle.getCenter());
116                map.put("radius", circle.getRadius());
117                return representMapping(new Tag("!circle"), map, Boolean.FALSE);
118            }
119        }
120
121        private class RepresentLine implements Represent {
122            public Node representData(Object data) {
123                Line line = (Line) data;
124                Map<String, Object> map = new TreeMap<String, Object>();
125                map.put("start", line.getStart());
126                map.put("finish", line.getFinish());
127                return representMapping(new Tag("!line"), map, Boolean.FALSE);
128            }
129        }
130
131        private class RepresentLabel implements Represent {
132            public Node representData(Object data) {
133                Label label = (Label) data;
134                Map<String, Object> map = new TreeMap<String, Object>();
135                map.put("start", label.getStart());
136                map.put("color", new HexInteger(label.getColor()));
137                map.put("text", label.getText());
138                return representMapping(new Tag("!label"), map, Boolean.FALSE);
139            }
140        }
141
142        private class RepresentHex implements Represent {
143            public Node representData(Object data) {
144                HexInteger hex = (HexInteger) data;
145                return representScalar(Tag.INT, "0x"
146                        + Integer.toHexString(hex.getColor()).toUpperCase(), null);
147            }
148        }
149    }
150
151    private class HexInteger {
152        private Integer color;
153
154        public HexInteger(Integer color) {
155            this.color = color;
156        }
157
158        public Integer getColor() {
159            return color;
160        }
161    }
162
163    private class Shape {
164        private List<Entity> entities;
165
166        public List<Entity> getEntities() {
167            return entities;
168        }
169
170        public Shape(List<Entity> entities) {
171            this.entities = entities;
172        }
173    }
174
175    private class Entity {
176    }
177
178    private class Circle extends Entity {
179        private Map<String, Integer> center;
180        private Integer radius;
181
182        public Circle(Map<String, Integer> center, Integer radius) {
183            this.center = center;
184            this.radius = radius;
185        }
186
187        public Map<String, Integer> getCenter() {
188            return center;
189        }
190
191        public Integer getRadius() {
192            return radius;
193        }
194    }
195
196    private class Line extends Entity {
197        private Map<String, Integer> start;
198        private Map<String, Integer> finish;
199
200        public Line(Map<String, Integer> start, Map<String, Integer> finish) {
201            this.start = start;
202            this.finish = finish;
203        }
204
205        public Map<String, Integer> getStart() {
206            return start;
207        }
208
209        public Map<String, Integer> getFinish() {
210            return finish;
211        }
212    }
213
214    private class Label extends Entity {
215        private Map<String, Integer> start;
216        private Integer color;
217        private String text;
218
219        public Label(Map<String, Integer> start, Integer color, String text) {
220            this.start = start;
221            this.color = color;
222            this.text = text;
223        }
224
225        public Map<String, Integer> getStart() {
226            return start;
227        }
228
229        public Integer getColor() {
230            return color;
231        }
232
233        public String getText() {
234            return text;
235        }
236    }
237
238    public void testExample_2_24() {
239        Yaml yaml = new Yaml(new MyConstructor());
240        Shape shape = (Shape) yaml.load(Util.getLocalResource("specification/example2_24.yaml"));
241        assertNotNull(shape);
242        yaml = new Yaml(new MyRepresenter());
243        String output = yaml.dump(shape);
244        String etalon = Util.getLocalResource("specification/example2_24_dumped.yaml");
245        assertEquals(etalon, output);
246    }
247}
248