1b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov/**
211a89b445f3bde56bf07e6a0d04f0b0256dcb215Andrey Somov * Copyright (c) 2008, http://www.snakeyaml.org
3b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov *
4b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov * Licensed under the Apache License, Version 2.0 (the "License");
5b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov * you may not use this file except in compliance with the License.
6b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov * You may obtain a copy of the License at
7b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov *
8b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov *     http://www.apache.org/licenses/LICENSE-2.0
9b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov *
10b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov * Unless required by applicable law or agreed to in writing, software
11b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov * distributed under the License is distributed on an "AS IS" BASIS,
12b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov * See the License for the specific language governing permissions and
14b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov * limitations under the License.
15b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov */
16b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somovpackage org.yaml.snakeyaml.constructor;
17b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov
18b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somovimport java.util.List;
19b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov
20b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somovimport junit.framework.TestCase;
21b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov
22b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somovimport org.yaml.snakeyaml.Yaml;
23b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somovimport org.yaml.snakeyaml.nodes.Node;
24b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somovimport org.yaml.snakeyaml.nodes.ScalarNode;
25b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somovimport org.yaml.snakeyaml.nodes.SequenceNode;
26b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somovimport org.yaml.snakeyaml.nodes.Tag;
27b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov
28b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov/**
29b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov * Example to process a family of tags with the same prefix with one constructor
30b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov * (PrefixConstruct)
31b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov */
32b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somovpublic class PrefixConstructorTest extends TestCase {
33b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov
34b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov    @SuppressWarnings("unchecked")
35b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov    public void test1() {
36b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        Yaml yaml = new Yaml(new CustomConstructor());
37b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        String input = "- !org.yaml.Foo 123\n- !org.yaml.Bar 456\n- !org.yaml.Exact 789\n- !Immutable [aaa, bbb]";
38b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        List<Extra> list = (List<Extra>) yaml.load(input);
39b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        assertEquals(4, list.size());
40b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        Extra foo = list.get(0);
41b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        assertEquals("Foo", foo.getName());
42b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        assertEquals("123", foo.getValue());
43b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        //
44b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        Extra bar = list.get(1);
45b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        assertEquals("Bar", bar.getName());
46b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        assertEquals("456", bar.getValue());
47b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        //
48b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        Extra item = list.get(2);
49b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        assertEquals("Item", item.getName());
50b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        assertEquals("789", item.getValue());
51b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        //
52b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        Extra immut = list.get(3);
53b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        assertEquals("aaa", immut.getName());
54b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        assertEquals("bbb", immut.getValue());
55b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov    }
56b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov
57b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov    private class CustomConstructor extends SafeConstructor {
58b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        public CustomConstructor() {
59b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov            // define tags which begin with !org.yaml.
60b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov            String prefix = "!org.yaml.";
61b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov            this.yamlMultiConstructors.put(prefix, new PrefixConstruct(prefix,
62b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov                    CustomConstructor.this));
63b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov            this.yamlConstructors.put(null, new ConstructUnknown(CustomConstructor.this));
64b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov            this.yamlConstructors.put(new Tag("!org.yaml.Exact"), new ExactConstruct(
65b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov                    CustomConstructor.this));
66b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        }
67b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov    }
68b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov
69b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov    /**
70b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov     * Process tags which start with '!org.yaml.'
71b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov     */
72b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov    private class PrefixConstruct extends AbstractConstruct {
73b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        private String prefix;
74b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        private BaseConstructor con;
75b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov
76b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        public PrefixConstruct(String prefix, BaseConstructor con) {
77b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov            this.prefix = prefix;
78b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov            this.con = con;
79b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        }
80b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov
81b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        public Object construct(Node node) {
82b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov            String suffix = node.getTag().getValue().substring(prefix.length());
83b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov            return new Extra(suffix, con.constructScalar((ScalarNode) node).toString());
84b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        }
85b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov    }
86b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov
87b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov    /**
88b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov     * This has more priority then PrefixConstruct
89b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov     */
90b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov    private class ExactConstruct extends AbstractConstruct {
91b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        private BaseConstructor con;
92b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov
93b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        public ExactConstruct(BaseConstructor con) {
94b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov            this.con = con;
95b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        }
96b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov
97b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        public Object construct(Node node) {
98b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov            return new Extra("Item", con.constructScalar((ScalarNode) node).toString());
99b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        }
100b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov    }
101b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov
102b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov    /**
103b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov     * Process unrecognised tags
104b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov     */
105b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov    private class ConstructUnknown extends AbstractConstruct {
106b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        private BaseConstructor con;
107b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov
108b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        public ConstructUnknown(BaseConstructor con) {
109b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov            this.con = con;
110b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        }
111b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov
112b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        @SuppressWarnings("unchecked")
113b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        public Object construct(Node node) {
114b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov            List<String> list = (List<String>) con.constructSequence((SequenceNode) node);
115b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov            return new Extra(list.get(0), list.get(1));
116b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        }
117b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov    }
118b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov
119b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov    private class Extra {
120b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        private String name;
121b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        private String value;
122b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov
123b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        public Extra(String name, String value) {
124b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov            this.name = name;
125b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov            this.value = value;
126b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        }
127b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov
128b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        public String getValue() {
129b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov            return value;
130b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        }
131b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov
132b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        public String getName() {
133b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov            return name;
134b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov        }
135b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov    }
136b5f4ec3dfb1a49968ebcc1243da10af9a2dc54a2Andrey Somov}
137