View Javadoc

1   /**
2    * Copyright (c) 2008-2011, 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  
17  package examples.jodatime;
18  
19  import java.util.Date;
20  import java.util.List;
21  
22  import junit.framework.TestCase;
23  
24  import org.joda.time.DateMidnight;
25  import org.joda.time.DateTime;
26  import org.joda.time.DateTimeZone;
27  import org.yaml.snakeyaml.DumperOptions;
28  import org.yaml.snakeyaml.DumperOptions.FlowStyle;
29  import org.yaml.snakeyaml.Yaml;
30  import org.yaml.snakeyaml.constructor.Construct;
31  import org.yaml.snakeyaml.constructor.Constructor;
32  import org.yaml.snakeyaml.events.Event;
33  import org.yaml.snakeyaml.events.ScalarEvent;
34  import org.yaml.snakeyaml.nodes.Node;
35  import org.yaml.snakeyaml.nodes.NodeId;
36  import org.yaml.snakeyaml.nodes.Tag;
37  
38  public class JodaTimeExampleTest extends TestCase {
39      private static final long timestamp = 1000000000000L;
40  
41      public void testDump() {
42          DateTime time = new DateTime(timestamp, DateTimeZone.UTC);
43          Yaml yaml = new Yaml(new JodaTimeRepresenter());
44          String joda = yaml.dump(time);
45          String date = new Yaml().dump(new Date(timestamp));
46          assertEquals(date, joda);
47          assertEquals("2001-09-09T01:46:40Z\n", joda);
48      }
49  
50      public void testLoad() {
51          Yaml yaml = new Yaml(new JodaTimeContructor());
52          DateTime time = (DateTime) yaml.load("2001-09-09T01:46:40Z");
53          assertEquals(new DateTime(timestamp, DateTimeZone.UTC), time);
54      }
55  
56      /**
57       * @see http://code.google.com/p/snakeyaml/issues/detail?id=128
58       */
59      public void testLoadBeanWithBlockFlow() {
60          MyBean bean = new MyBean();
61          bean.setId("id123");
62          DateTime etalon = new DateTime(timestamp, DateTimeZone.UTC);
63          bean.setDate(etalon);
64          DumperOptions options = new DumperOptions();
65          options.setDefaultFlowStyle(FlowStyle.BLOCK);
66          Yaml dumper = new Yaml(new JodaTimeRepresenter(), options);
67          // compare Nodes with flow style AUTO and flow style BLOCK
68          Node node1 = dumper.represent(bean);
69          DumperOptions options2 = new DumperOptions();
70          options2.setDefaultFlowStyle(FlowStyle.AUTO);
71          Yaml dumper2 = new Yaml(new JodaTimeRepresenter(), options2);
72          Node node2 = dumper2.represent(bean);
73          assertEquals(node2.toString(), node1.toString());
74          // compare Events with flow style AUTO and flow style BLOCK
75          List<Event> events1 = dumper.serialize(node1);
76          List<Event> events2 = dumper2.serialize(node2);
77          assertEquals(events2.size(), events1.size());
78          int i = 0;
79          for (Event etalonEvent : events2) {
80              assertEquals(etalonEvent, events1.get(i++));
81              if (etalonEvent instanceof ScalarEvent) {
82                  ScalarEvent scalar = (ScalarEvent) etalonEvent;
83                  if (scalar.getValue().equals("2001-09-09T01:46:40Z")) {
84                      assertTrue(scalar.getImplicit().canOmitTagInPlainScalar());
85                      assertFalse(scalar.getImplicit().canOmitTagInNonPlainScalar());
86                  }
87              }
88          }
89          // Nodes and Events are the same. Only emitter may influence the output.
90          String doc1 = dumper.dump(bean);
91          // System.out.println(doc1);
92          /*
93           * 'date' must be used only with the explicit '!!timestamp' tag.
94           * Implicit tag will not work because 'date' is the JavaBean property
95           * and in this case the empty constructor of the class will be used.
96           * Since this constructor does not exist for JodaTime an exception will
97           * be thrown.
98           */
99          assertEquals("!!examples.jodatime.MyBean\ndate: 2001-09-09T01:46:40Z\nid: id123\n", doc1);
100         /*
101          * provided JodaTimeContructor will be ignored because 'date' is a
102          * JavaBean property and its class gets more priority then the implicit
103          * '!!timestamp' tag.
104          */
105         Yaml loader = new Yaml(new JodaTimeContructor());
106         try {
107             loader.load(doc1);
108         } catch (Exception e) {
109             assertTrue(
110                     "The error must indicate that JodaTime cannot be created from the scalar value.",
111                     e.getMessage()
112                             .contains(
113                                     "No String constructor found. Exception=org.joda.time.DateTime.<init>(java.lang.String)"));
114         }
115         // we have to provide a special way to create JodaTime instances from
116         // scalars
117         Yaml loader2 = new Yaml(new JodaPropertyConstructor());
118         MyBean parsed = (MyBean) loader2.load(doc1);
119         assertEquals(etalon, parsed.getDate());
120     }
121 
122     /**
123      * !!timestamp must be used, without it the implicit tag will be ignored
124      * because 'date' is the JavaBean property.
125      * 
126      * Since the timestamp contains ':' character it cannot use plain scalar
127      * style in the FLOW mapping style. Emitter suggests single quoted scalar
128      * style and that is why the explicit '!!timestamp' is present in the YAML
129      * document.
130      * 
131      * @see http://code.google.com/p/snakeyaml/issues/detail?id=128
132      * 
133      */
134     public void testLoadBeanWithAutoFlow() {
135         MyBean bean = new MyBean();
136         bean.setId("id123");
137         DateTime etalon = new DateTime(timestamp, DateTimeZone.UTC);
138         bean.setDate(etalon);
139         DumperOptions options = new DumperOptions();
140         options.setDefaultFlowStyle(FlowStyle.AUTO);
141         Yaml dumper = new Yaml(new JodaTimeRepresenter(), options);
142         String doc = dumper.dump(bean);
143         //System.out.println(doc);
144         assertEquals(
145                 "!!examples.jodatime.MyBean {date: !!timestamp '2001-09-09T01:46:40Z', id: id123}\n",
146                 doc);
147         Yaml loader = new Yaml(new JodaTimeContructor());
148         MyBean parsed = (MyBean) loader.load(doc);
149         assertEquals(etalon, parsed.getDate());
150     }
151 
152     /**
153      * test issue 109
154      */
155     public void test109() {
156         Date someDate = new DateMidnight(9, 2, 21, DateTimeZone.forID("Europe/Amsterdam")).toDate();
157         Yaml yaml = new Yaml();
158         String timestamp = yaml.dump(someDate);
159         assertEquals("0009-02-22T23:40:28Z\n", timestamp);
160         // System.out.println(timestamp);
161         Object o = yaml.load(timestamp);
162         assertEquals(someDate, o);
163     }
164 
165     class JodaPropertyConstructor extends Constructor {
166         public JodaPropertyConstructor() {
167             yamlClassConstructors.put(NodeId.scalar, new TimeStampConstruct());
168         }
169 
170         class TimeStampConstruct extends Constructor.ConstructScalar {
171             @Override
172             public Object construct(Node nnode) {
173                 if (nnode.getTag().equals("tag:yaml.org,2002:timestamp")) {
174                     Construct dateConstructor = yamlConstructors.get(Tag.TIMESTAMP);
175                     Date date = (Date) dateConstructor.construct(nnode);
176                     return new DateTime(date, DateTimeZone.UTC);
177                 } else {
178                     return super.construct(nnode);
179                 }
180             }
181 
182         }
183     }
184 }