aboutsummaryrefslogtreecommitdiff
path: root/src/test/java/examples/jodatime/JodaTimeFlowStylesTest.java
blob: ce7ab2ecf232f21d69f9733f9266d5133ebed195 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/**
 * Copyright (c) 2008, SnakeYAML
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package examples.jodatime;

import java.util.Date;
import java.util.List;
import junit.framework.TestCase;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.DumperOptions.FlowStyle;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Construct;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.events.Event;
import org.yaml.snakeyaml.events.ScalarEvent;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeId;
import org.yaml.snakeyaml.nodes.Tag;

public class JodaTimeFlowStylesTest extends TestCase {

  private static final long timestamp = 1000000000000L;

  /**
   * @see <a href="http://code.google.com/p/snakeyaml/issues/detail?id=128">issue 128</a>
   */
  public void testLoadBeanWithBlockFlow() {
    MyBean bean = new MyBean();
    bean.setId("id123");
    DateTime etalon = new DateTime(timestamp, DateTimeZone.UTC);
    bean.setDate(etalon);
    DumperOptions options = new DumperOptions();
    options.setDefaultFlowStyle(FlowStyle.BLOCK);
    Yaml dumper = new Yaml(new JodaTimeRepresenter(), options);
    // compare Nodes with flow style AUTO and flow style BLOCK
    Node node1 = dumper.represent(bean);
    DumperOptions options2 = new DumperOptions();
    options2.setDefaultFlowStyle(FlowStyle.AUTO);
    Yaml dumper2 = new Yaml(new JodaTimeRepresenter(), options2);
    Node node2 = dumper2.represent(bean);
    assertEquals(node2.toString(), node1.toString());
    // compare Events with flow style AUTO and flow style BLOCK
    List<Event> events1 = dumper.serialize(node1);
    List<Event> events2 = dumper2.serialize(node2);
    assertEquals(events2.size(), events1.size());
    int i = 0;
    for (Event etalonEvent : events2) {
      assertEquals(etalonEvent, events1.get(i++));
      if (etalonEvent instanceof ScalarEvent) {
        ScalarEvent scalar = (ScalarEvent) etalonEvent;
        if (scalar.getValue().equals("2001-09-09T01:46:40Z")) {
          assertTrue(scalar.getImplicit().canOmitTagInPlainScalar());
          assertFalse(scalar.getImplicit().canOmitTagInNonPlainScalar());
        }
      }
    }
    // Nodes and Events are the same. Only emitter may influence the output.
    String doc1 = dumper.dump(bean);
    // System.out.println(doc1);
    /*
     * 'date' must be used only with the explicit '!!timestamp' tag. Implicit tag will not work
     * because 'date' is the JavaBean property and in this case the empty constructor of the class
     * will be used. Since this constructor does not exist for JodaTime an exception will be thrown.
     */
    assertEquals("!!examples.jodatime.MyBean\ndate: 2001-09-09T01:46:40Z\nid: id123\n", doc1);
    /*
     * provided JodaTimeContructor will be ignored because 'date' is a JavaBean property and its
     * class gets more priority then the implicit '!!timestamp' tag.
     */
    Yaml loader = new Yaml(new JodaTimeImplicitContructor());
    try {
      loader.load(doc1);
    } catch (Exception e) {
      assertTrue("The error must indicate that JodaTime cannot be created from the scalar value.",
          e.getMessage().contains(
              "No String constructor found. Exception=org.joda.time.DateTime.<init>(java.lang.String)"));
    }
    // we have to provide a special way to create JodaTime instances from
    // scalars
    Yaml loader2 = new Yaml(new JodaPropertyConstructor());
    MyBean parsed = loader2.load(doc1);
    assertEquals(etalon, parsed.getDate());
  }

  /**
   * !!timestamp must be used, without it the implicit tag will be ignored because 'date' is the
   * JavaBean property.
   *
   * Since the timestamp contains ':' character it cannot use plain scalar style in the FLOW mapping
   * style. Emitter suggests single quoted scalar style and that is why the explicit '!!timestamp'
   * is present in the YAML document.
   *
   * @see <a href="http://code.google.com/p/snakeyaml/issues/detail?id=128">issue 128</a>
   *
   */
  public void testLoadBeanWithAutoFlow() {
    MyBean bean = new MyBean();
    bean.setId("id123");
    DateTime etalon = new DateTime(timestamp, DateTimeZone.UTC);
    bean.setDate(etalon);
    DumperOptions options = new DumperOptions();
    options.setDefaultFlowStyle(FlowStyle.AUTO);
    Yaml dumper = new Yaml(new JodaTimeRepresenter(), options);
    String doc = dumper.dump(bean);
    // System.out.println(doc);
    assertEquals(
        "!!examples.jodatime.MyBean {date: !!timestamp '2001-09-09T01:46:40Z', id: id123}\n", doc);
    Yaml loader = new Yaml(new JodaTimeImplicitContructor());
    MyBean parsed = loader.load(doc);
    assertEquals(etalon, parsed.getDate());
  }

  private class JodaPropertyConstructor extends Constructor {

    public JodaPropertyConstructor() {
      yamlClassConstructors.put(NodeId.scalar, new TimeStampConstruct());
    }

    class TimeStampConstruct extends Constructor.ConstructScalar {

      @Override
      public Object construct(Node nnode) {
        if (nnode.getTag().equals(new Tag("tag:yaml.org,2002:timestamp"))) {
          Construct dateConstructor = yamlConstructors.get(Tag.TIMESTAMP);
          Date date = (Date) dateConstructor.construct(nnode);
          return new DateTime(date, DateTimeZone.UTC);
        } else {
          return super.construct(nnode);
        }
      }

    }
  }
}