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.issues.issue29;
17
18import java.beans.IntrospectionException;
19import java.util.ArrayList;
20import java.util.Arrays;
21import java.util.Comparator;
22import java.util.HashMap;
23import java.util.List;
24import java.util.Map;
25import java.util.Set;
26import java.util.TreeSet;
27
28import junit.framework.TestCase;
29
30import org.yaml.snakeyaml.Yaml;
31import org.yaml.snakeyaml.introspector.BeanAccess;
32import org.yaml.snakeyaml.introspector.Property;
33import org.yaml.snakeyaml.nodes.NodeTuple;
34import org.yaml.snakeyaml.nodes.ScalarNode;
35import org.yaml.snakeyaml.nodes.SequenceNode;
36import org.yaml.snakeyaml.nodes.Tag;
37import org.yaml.snakeyaml.representer.Representer;
38
39public class FlexibleScalarStylesInJavaBeanTest extends TestCase {
40    public void testDifferentStyles() {
41        BigJavaBean bean1 = new BigJavaBean(1, "simple", "line 1\nline2\nzipcode", "short text1");
42        List<Integer> numbers1 = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
43        bean1.setNumbers(numbers1);
44        Map<String, String> data1 = new HashMap<String, String>();
45        data1.put("key1", "value1");
46        data1.put("key2", "value2");
47        bean1.setData(data1);
48        //
49        BigJavaBean bean2 = new BigJavaBean(1, "second", "line 111\nline 222\nzipcode 12345\n\n",
50                "info: semicolon is used");
51        List<Integer> numbers2 = new ArrayList<Integer>(Arrays.asList(4, 5, 6, 777, 888, 999, 1000));
52        bean2.setNumbers(numbers2);
53        Map<String, String> data2 = new HashMap<String, String>();
54        data2.put("key21", "value12");
55        data2.put("key22", "value with\ntwo lines");
56        bean2.setData(data2);
57        //
58        List<BigJavaBean> list = new ArrayList<BigJavaBean>();
59        list.add(bean1);
60        list.add(bean2);
61        Yaml yaml = new Yaml(new MyRepresenter());
62        yaml.setBeanAccess(BeanAccess.FIELD);
63        String output = yaml.dump(list);
64        // System.out.println(output);
65        // parse back
66        @SuppressWarnings("unchecked")
67        List<BigJavaBean> parsed = (List<BigJavaBean>) yaml.load(output);
68        assertEquals(2, parsed.size());
69        assertEquals(bean1, parsed.get(0));
70        assertEquals(bean2, parsed.get(1));
71
72    }
73
74    private class MyRepresenter extends Representer {
75        /*
76         * Change the default order. Important data goes first.
77         */
78        @Override
79        protected Set<Property> getProperties(Class<? extends Object> type)
80                throws IntrospectionException {
81            if (type.isAssignableFrom(BigJavaBean.class)) {
82                Set<Property> standard = super.getProperties(type);
83                Set<Property> sorted = new TreeSet<Property>(new PropertyComparator());
84                sorted.addAll(standard);
85                return sorted;
86            } else {
87                return super.getProperties(type);
88            }
89        }
90
91        private class PropertyComparator implements Comparator<Property> {
92            public int compare(Property o1, Property o2) {
93                // important go first
94                List<String> order = new ArrayList<String>(Arrays.asList("id", "name",
95                        "description", "address"));
96                for (String name : order) {
97                    int c = compareByName(o1, o2, name);
98                    if (c != 0) {
99                        return c;
100                    }
101                }
102                // all the rest
103                return o1.compareTo(o2);
104            }
105
106            private int compareByName(Property o1, Property o2, String name) {
107                if (o1.getName().equals(name)) {
108                    return -1;
109                } else if (o2.getName().equals(name)) {
110                    return 1;
111                }
112                return 0;// compare further
113            }
114        }
115
116        @Override
117        protected NodeTuple representJavaBeanProperty(Object javaBean, Property property,
118                Object propertyValue, Tag customTag) {
119            if (javaBean instanceof BigJavaBean) {
120                BigJavaBean bean = (BigJavaBean) javaBean;
121                NodeTuple standard = super.representJavaBeanProperty(javaBean, property,
122                        propertyValue, customTag);
123                if (property.getName().equals("numbers")) {
124                    // when the list is small, make it block collection style
125                    if (bean.getNumbers().size() < 5) {
126                        SequenceNode n = (SequenceNode) standard.getValueNode();
127                        return new NodeTuple(standard.getKeyNode(), new SequenceNode(n.getTag(),
128                                true, n.getValue(), n.getStartMark(), n.getEndMark(), false));
129                    }
130                }
131                if (property.getName().equals("description")) {
132                    // if description contains ':' use folded scalar style and
133                    // not single quoted scalar style
134                    if (bean.getDescription().indexOf(':') > 0) {
135                        ScalarNode n = (ScalarNode) standard.getValueNode();
136                        return new NodeTuple(standard.getKeyNode(), new ScalarNode(n.getTag(),
137                                n.getValue(), n.getStartMark(), n.getEndMark(), '>'));
138                    }
139                }
140                return standard;
141            } else {
142                return super
143                        .representJavaBeanProperty(javaBean, property, propertyValue, customTag);
144            }
145        }
146    }
147}
148