View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.juneau.transforms;
18  
19  import static org.apache.juneau.TestUtils.*;
20  import static org.junit.jupiter.api.Assertions.*;
21  
22  import java.time.*;
23  import java.time.chrono.*;
24  import java.time.format.*;
25  import java.time.temporal.*;
26  import java.util.*;
27  
28  import javax.xml.datatype.*;
29  
30  import org.apache.juneau.*;
31  import org.apache.juneau.annotation.*;
32  import org.apache.juneau.json.*;
33  import org.apache.juneau.serializer.*;
34  import org.apache.juneau.swap.*;
35  import org.junit.jupiter.api.*;
36  
37  class DefaultSwaps_Test extends TestBase {
38  
39  	//------------------------------------------------------------------------------------------------------------------
40  	// Setup
41  	//------------------------------------------------------------------------------------------------------------------
42  
43  	@BeforeAll static void beforeClass() {
44  		setTimeZone("GMT-5");
45  	}
46  
47  	@AfterAll static void afterClass() {
48  		unsetTimeZone();
49  	}
50  
51  	private static final WriterSerializer SERIALIZER = Json5Serializer.DEFAULT;
52  
53  	private void test1(String expected, Object o) throws Exception {
54  		assertEquals(expected, SERIALIZER.serialize(o));
55  	}
56  
57  	private void test2(String expected, Object o, Class<?> configClass) throws Exception {
58  		assertEquals(expected, SERIALIZER.copy().applyAnnotations(configClass).build().serialize(o));
59  	}
60  
61  	private void test3(String expected, Object o, Class<?> swap) throws Exception {
62  		assertEquals(expected, SERIALIZER.copy().swaps(swap).build().serializeToString(o));
63  	}
64  
65  	private void test4(String expected, Object o, Class<?> swap, Class<?> configClass) throws Exception {
66  		assertEquals(expected, SERIALIZER.copy().swaps(swap).applyAnnotations(configClass).build().serializeToString(o));
67  	}
68  
69  	//------------------------------------------------------------------------------------------------------------------
70  	//	POJO_SWAPS.put(Enumeration.class, new EnumerationSwap())
71  	//------------------------------------------------------------------------------------------------------------------
72  	private static Vector<String> A = new Vector<>();
73  	static {
74  		A.add("foo");
75  		A.add("bar");
76  	}
77  
78  	public static class ASwap extends StringSwap<Enumeration<?>> {
79  		@Override /* ObjectSwap */
80  		public String swap(BeanSession session, Enumeration<?> o) throws Exception {
81  			return "FOO";
82  		}
83  	}
84  
85  	public static class ABean {
86  		public Enumeration<String> f1 = A.elements();
87  		@Swap(ASwap.class)
88  		public Enumeration<String> f2 = A.elements();
89  	}
90  
91  	@Test void a01_Enumeration() throws Exception {
92  		test1("['foo','bar']", A.elements());
93  	}
94  
95  	@Test void a02_Enumeration_overrideSwap() throws Exception {
96  		test3("'FOO'", A.elements(), ASwap.class);
97  	}
98  
99  	@Test void a03_Enumeration_overrideAnnotation() throws Exception {
100 		test1("{f1:['foo','bar'],f2:'FOO'}", new ABean());
101 	}
102 
103 	private static Vector<String> Ac = new Vector<>();
104 	static {
105 		Ac.add("foo");
106 		Ac.add("bar");
107 	}
108 
109 	public static class AcSwap extends StringSwap<Enumeration<?>> {
110 		@Override /* ObjectSwap */
111 		public String swap(BeanSession session, Enumeration<?> o) throws Exception {
112 			return "FOO";
113 		}
114 	}
115 
116 	@Swap(on="Dummy1.f2", value=AcSwap.class)
117 	@Swap(on="AcBean.f2", value=AcSwap.class)
118 	@Swap(on="Dummy2.f2", value=AcSwap.class)
119 	private static class AcBeanConfig {}
120 
121 	public static class AcBean {
122 		public Enumeration<String> f1 = A.elements();
123 
124 		public Enumeration<String> f2 = A.elements();
125 	}
126 
127 	@Test void a01c_Enumeration_usingConfig() throws Exception {
128 		test2("['foo','bar']", Ac.elements(), AcBeanConfig.class);
129 	}
130 
131 	@Test void a02c_Enumeration_overrideSwap_usingConfig() throws Exception {
132 		test4("'FOO'", Ac.elements(), AcSwap.class, AcBeanConfig.class);
133 	}
134 
135 	@Test void a03c_Enumeration_overrideAnnotation_usingConfig() throws Exception {
136 		test2("{f1:['foo','bar'],f2:'FOO'}", new AcBean(), AcBeanConfig.class);
137 	}
138 
139 	//------------------------------------------------------------------------------------------------------------------
140 	//	POJO_SWAPS.put(Iterator.class, new IteratorSwap())
141 	//------------------------------------------------------------------------------------------------------------------
142 	private static List<String> B = list("foo","bar");
143 
144 	public static class BSwap extends StringSwap<Iterator<?>> {
145 		@Override /* ObjectSwap */
146 		public String swap(BeanSession session, Iterator<?> o) throws Exception {
147 			return "FOO";
148 		}
149 	}
150 
151 	public static class BBean {
152 		public Iterator<?> f1 = B.iterator();
153 		@Swap(BSwap.class)
154 		public Iterator<?> f2 = B.iterator();
155 	}
156 
157 	@Test void b01_Iterator() throws Exception {
158 		test1("['foo','bar']", B.iterator());
159 	}
160 
161 	@Test void b02_Iterator_overrideSwap() throws Exception {
162 		test3("'FOO'", B.iterator(), BSwap.class);
163 	}
164 
165 	@Test void b03_Iterator_overrideAnnotation() throws Exception {
166 		test1("{f1:['foo','bar'],f2:'FOO'}", new BBean());
167 	}
168 
169 	private static List<String> Bc = list("foo","bar");
170 
171 	public static class BcSwap extends StringSwap<Iterator<?>> {
172 		@Override /* ObjectSwap */
173 		public String swap(BeanSession session, Iterator<?> o) throws Exception {
174 			return "FOO";
175 		}
176 	}
177 
178 	@Swap(on="Dummy1.f2", value=BcSwap.class)
179 	@Swap(on="BcBean.f2", value=BcSwap.class)
180 	@Swap(on="Dummy2.f2", value=BcSwap.class)
181 	private static class BcBeanConfig {}
182 
183 	public static class BcBean {
184 		public Iterator<?> f1 = B.iterator();
185 		public Iterator<?> f2 = B.iterator();
186 	}
187 
188 	@Test void b01c_Iterator_usingConfig() throws Exception {
189 		test2("['foo','bar']", Bc.iterator(), BcBeanConfig.class);
190 	}
191 
192 	@Test void b02c_Iterator_overrideSwap_usingConfig() throws Exception {
193 		test4("'FOO'", Bc.iterator(), BcSwap.class, BcBeanConfig.class);
194 	}
195 
196 	@Test void b03c_Iterator_overrideAnnotation_usingConfig() throws Exception {
197 		test2("{f1:['foo','bar'],f2:'FOO'}", new BcBean(), BcBeanConfig.class);
198 	}
199 
200 	//------------------------------------------------------------------------------------------------------------------
201 	//	POJO_SWAPS.put(Locale.class, new LocaleSwap())
202 	//------------------------------------------------------------------------------------------------------------------
203 	private static Locale C = Locale.JAPAN;
204 
205 	public static class CSwap extends StringSwap<Locale> {
206 		@Override /* ObjectSwap */
207 		public String swap(BeanSession session, Locale o) throws Exception {
208 			return "FOO";
209 		}
210 	}
211 
212 	public static class CBean {
213 		public Locale f1 = C;
214 		@Swap(CSwap.class)
215 		public Locale f2 = C;
216 	}
217 
218 	@Test void c01_Locale() throws Exception {
219 		test1("'ja-JP'", C);
220 	}
221 
222 	@Test void c02_Locale_overrideSwap() throws Exception {
223 		test3("'FOO'", C, CSwap.class);
224 	}
225 
226 	@Test void c03_Locale_overrideAnnotation() throws Exception {
227 		test1("{f1:'ja-JP',f2:'FOO'}", new CBean());
228 	}
229 
230 	//------------------------------------------------------------------------------------------------------------------
231 	//	POJO_SWAPS.put(Calendar.class, new TemporalCalendarSwap.IsoOffsetDateTime())
232 	//------------------------------------------------------------------------------------------------------------------
233 	private static GregorianCalendar D = GregorianCalendar.from(ZonedDateTime.from(DateTimeFormatter.ISO_ZONED_DATE_TIME.parse("2012-12-21T12:34:56Z")));
234 
235 	public static class DSwap extends StringSwap<Calendar> {
236 		@Override /* ObjectSwap */
237 		public String swap(BeanSession session, Calendar o) throws Exception {
238 			return "FOO";
239 		}
240 	}
241 
242 	public static class DBean {
243 		public GregorianCalendar f1 = D;
244 		@Swap(DSwap.class)
245 		public GregorianCalendar f2 = D;
246 	}
247 
248 	@Test void d01_Calendar() throws Exception {
249 		test1("'2012-12-21T12:34:56Z'", D);
250 	}
251 
252 	@Test void d02_Calendar_overrideSwap() throws Exception {
253 		test3("'FOO'", D, DSwap.class);
254 	}
255 
256 	@Test void d03_Calendar_overrideAnnotation() throws Exception {
257 		test1("{f1:'2012-12-21T12:34:56Z',f2:'FOO'}", new DBean());
258 	}
259 
260 	//------------------------------------------------------------------------------------------------------------------
261 	//	POJO_SWAPS.put(Date.class, new TemporalDateSwap.IsoLocalDateTime())
262 	//------------------------------------------------------------------------------------------------------------------
263 	private static Date E = Date.from(Instant.from(DateTimeFormatter.ISO_INSTANT.parse("2012-12-21T12:34:56Z")));
264 
265 	public static class ESwap extends StringSwap<Date> {
266 		@Override /* ObjectSwap */
267 		public String swap(BeanSession session, Date o) throws Exception {
268 			return "FOO";
269 		}
270 	}
271 
272 	public static class EBean {
273 		public Date f1 = E;
274 		@Swap(ESwap.class)
275 		public Date f2 = E;
276 	}
277 
278 	@Test void e01_Date() throws Exception {
279 		test1("'2012-12-21T07:34:56'", E);
280 	}
281 
282 	@Test void e02_Date_overrideSwap() throws Exception {
283 		test3("'FOO'", E, ESwap.class);
284 	}
285 
286 	@Test void e03_Date_overrideAnnotation() throws Exception {
287 		test1("{f1:'2012-12-21T07:34:56',f2:'FOO'}", new EBean());
288 	}
289 
290 	//------------------------------------------------------------------------------------------------------------------
291 	//	POJO_SWAPS.put(Instant.class, new TemporalSwap.IsoInstant())
292 	//------------------------------------------------------------------------------------------------------------------
293 	private static Instant FA = Instant.parse("2012-12-21T12:34:56Z");
294 
295 	public static class FASwap extends StringSwap<Instant> {
296 		@Override /* ObjectSwap */
297 		public String swap(BeanSession session, Instant o) throws Exception {
298 			return "FOO";
299 		}
300 	}
301 
302 	public static class FABean {
303 		public Instant f1 = FA;
304 		@Swap(FASwap.class)
305 		public Instant f2 = FA;
306 	}
307 
308 	@Test void fa01_Instant() throws Exception {
309 		test1("'2012-12-21T12:34:56Z'", FA);
310 	}
311 
312 	@Test void fa02_Instant_overrideSwap() throws Exception {
313 		test3("'FOO'", FA, FASwap.class);
314 	}
315 
316 	@Test void fa03_Instant_overrideAnnotation() throws Exception {
317 		test1("{f1:'2012-12-21T12:34:56Z',f2:'FOO'}", new FABean());
318 	}
319 
320 	//------------------------------------------------------------------------------------------------------------------
321 	//	POJO_SWAPS.put(ZonedDateTime.class, new TemporalSwap.IsoOffsetDateTime())
322 	//------------------------------------------------------------------------------------------------------------------
323 	private static ZonedDateTime FB = ZonedDateTime.parse("2012-12-21T12:34:56Z");
324 
325 	public static class FBSwap extends StringSwap<ZonedDateTime> {
326 		@Override /* ObjectSwap */
327 		public String swap(BeanSession session, ZonedDateTime o) throws Exception {
328 			return "FOO";
329 		}
330 	}
331 
332 	public static class FBBean {
333 		public ZonedDateTime f1 = FB;
334 		@Swap(FBSwap.class)
335 		public ZonedDateTime f2 = FB;
336 	}
337 
338 	@Test void fb01_ZonedDateTime() throws Exception {
339 		test1("'2012-12-21T12:34:56Z'", FB);
340 	}
341 
342 	@Test void fb02_ZonedDateTime_overrideSwap() throws Exception {
343 		test3("'FOO'", FB, FBSwap.class);
344 	}
345 
346 	@Test void fb03_ZonedDateTime_overrideAnnotation() throws Exception {
347 		test1("{f1:'2012-12-21T12:34:56Z',f2:'FOO'}", new FBBean());
348 	}
349 
350 	//------------------------------------------------------------------------------------------------------------------
351 	//	POJO_SWAPS.put(LocalDate.class, new TemporalSwap.IsoLocalDate())
352 	//------------------------------------------------------------------------------------------------------------------
353 	private static LocalDate FC = LocalDate.parse("2012-12-21");
354 
355 	public static class FCSwap extends StringSwap<LocalDate> {
356 		@Override /* ObjectSwap */
357 		public String swap(BeanSession session, LocalDate o) throws Exception {
358 			return "FOO";
359 		}
360 	}
361 
362 	public static class FCBean {
363 		public LocalDate f1 = FC;
364 		@Swap(FCSwap.class)
365 		public LocalDate f2 = FC;
366 	}
367 
368 	@Test void fc01_LocalDate() throws Exception {
369 		test1("'2012-12-21'", FC);
370 	}
371 
372 	@Test void fc02_LocalDate_overrideSwap() throws Exception {
373 		test3("'FOO'", FC, FCSwap.class);
374 	}
375 
376 	@Test void fc03_LocalDate_overrideAnnotation() throws Exception {
377 		test1("{f1:'2012-12-21',f2:'FOO'}", new FCBean());
378 	}
379 
380 	//------------------------------------------------------------------------------------------------------------------
381 	//	POJO_SWAPS.put(LocalDateTime.class, new TemporalSwap.IsoLocalDateTime())
382 	//------------------------------------------------------------------------------------------------------------------
383 	private static LocalDateTime FD = LocalDateTime.parse("2012-12-21T12:34:56");
384 
385 	public static class FDSwap extends StringSwap<LocalDateTime> {
386 		@Override /* ObjectSwap */
387 		public String swap(BeanSession session, LocalDateTime o) throws Exception {
388 			return "FOO";
389 		}
390 	}
391 
392 	public static class FDBean {
393 		public LocalDateTime f1 = FD;
394 		@Swap(FDSwap.class)
395 		public LocalDateTime f2 = FD;
396 	}
397 
398 	@Test void fd01_LocalDateTime() throws Exception {
399 		test1("'2012-12-21T12:34:56'", FD);
400 	}
401 
402 	@Test void fd02_LocalDateTime_overrideSwap() throws Exception {
403 		test3("'FOO'", FD, FDSwap.class);
404 	}
405 
406 	@Test void fd03_LocalDateTime_overrideAnnotation() throws Exception {
407 		test1("{f1:'2012-12-21T12:34:56',f2:'FOO'}", new FDBean());
408 	}
409 
410 	//------------------------------------------------------------------------------------------------------------------
411 	//	POJO_SWAPS.put(LocalTime.class, new TemporalSwap.IsoLocalTime())
412 	//------------------------------------------------------------------------------------------------------------------
413 	private static LocalTime FE = LocalTime.parse("12:34:56");
414 
415 	public static class FESwap extends StringSwap<LocalTime> {
416 		@Override /* ObjectSwap */
417 		public String swap(BeanSession session, LocalTime o) throws Exception {
418 			return "FOO";
419 		}
420 	}
421 
422 	public static class FEBean {
423 		public LocalTime f1 = FE;
424 		@Swap(FESwap.class)
425 		public LocalTime f2 = FE;
426 	}
427 
428 	@Test void fe01_LocalTime() throws Exception {
429 		test1("'12:34:56'", FE);
430 	}
431 
432 	@Test void fe02_LocalTime_overrideSwap() throws Exception {
433 		test3("'FOO'", FE, FESwap.class);
434 	}
435 
436 	@Test void fe03_LocalTime_overrideAnnotation() throws Exception {
437 		test1("{f1:'12:34:56',f2:'FOO'}", new FEBean());
438 	}
439 
440 	//------------------------------------------------------------------------------------------------------------------
441 	//	POJO_SWAPS.put(OffsetDateTime.class, new TemporalSwap.IsoOffsetDateTime())
442 	//------------------------------------------------------------------------------------------------------------------
443 	private static OffsetDateTime FF = OffsetDateTime.parse("2012-12-21T12:34:56-05:00");
444 
445 	public static class FFSwap extends StringSwap<OffsetDateTime> {
446 		@Override /* ObjectSwap */
447 		public String swap(BeanSession session, OffsetDateTime o) throws Exception {
448 			return "FOO";
449 		}
450 	}
451 
452 	public static class FFBean {
453 		public OffsetDateTime f1 = FF;
454 		@Swap(FFSwap.class)
455 		public OffsetDateTime f2 = FF;
456 	}
457 
458 	@Test void ff01_OffsetDateTime() throws Exception {
459 		test1("'2012-12-21T12:34:56-05:00'", FF);
460 	}
461 
462 	@Test void ff02_OffsetDateTime_overrideSwap() throws Exception {
463 		test3("'FOO'", FF, FFSwap.class);
464 	}
465 
466 	@Test void ff03_OffsetDateTime_overrideAnnotation() throws Exception {
467 		test1("{f1:'2012-12-21T12:34:56-05:00',f2:'FOO'}", new FFBean());
468 	}
469 
470 	//------------------------------------------------------------------------------------------------------------------
471 	//	POJO_SWAPS.put(OffsetTime.class, new TemporalSwap.IsoOffsetTime())
472 	//------------------------------------------------------------------------------------------------------------------
473 	private static OffsetTime FG = OffsetTime.parse("12:34:56-05:00");
474 
475 	public static class FGSwap extends StringSwap<OffsetTime> {
476 		@Override /* ObjectSwap */
477 		public String swap(BeanSession session, OffsetTime o) throws Exception {
478 			return "FOO";
479 		}
480 	}
481 
482 	public static class FGBean {
483 		public OffsetTime f1 = FG;
484 		@Swap(FGSwap.class)
485 		public OffsetTime f2 = FG;
486 	}
487 
488 	@Test void fg01_OffsetTime() throws Exception {
489 		test1("'12:34:56-05:00'", FG);
490 	}
491 
492 	@Test void fg02_OffsetTime_overrideSwap() throws Exception {
493 		test3("'FOO'", FG, FGSwap.class);
494 	}
495 
496 	@Test void fg03_OffsetTime_overrideAnnotation() throws Exception {
497 		test1("{f1:'12:34:56-05:00',f2:'FOO'}", new FGBean());
498 	}
499 
500 	//------------------------------------------------------------------------------------------------------------------
501 	//	POJO_SWAPS.put(Year.class, new TemporalSwap.IsoYear())
502 	//------------------------------------------------------------------------------------------------------------------
503 	private static Year FH = Year.parse("2012");
504 
505 	public static class FHSwap extends StringSwap<Year> {
506 		@Override /* ObjectSwap */
507 		public String swap(BeanSession session, Year o) throws Exception {
508 			return "FOO";
509 		}
510 	}
511 
512 	public static class FHBean {
513 		public Year f1 = FH;
514 		@Swap(FHSwap.class)
515 		public Year f2 = FH;
516 	}
517 
518 	@Test void fh01_Year() throws Exception {
519 		test1("'2012'", FH);
520 	}
521 
522 	@Test void fh02_Year_overrideSwap() throws Exception {
523 		test3("'FOO'", FH, FHSwap.class);
524 	}
525 
526 	@Test void fh03_Year_overrideAnnotation() throws Exception {
527 		test1("{f1:'2012',f2:'FOO'}", new FHBean());
528 	}
529 
530 	//------------------------------------------------------------------------------------------------------------------
531 	//	POJO_SWAPS.put(YearMonth.class, new TemporalSwap.IsoYearMonth())
532 	//------------------------------------------------------------------------------------------------------------------
533 	private static YearMonth FI = YearMonth.parse("2012-12");
534 
535 	public static class FISwap extends StringSwap<YearMonth> {
536 		@Override /* ObjectSwap */
537 		public String swap(BeanSession session, YearMonth o) throws Exception {
538 			return "FOO";
539 		}
540 	}
541 
542 	public static class FIBean {
543 		public YearMonth f1 = FI;
544 		@Swap(FISwap.class)
545 		public YearMonth f2 = FI;
546 	}
547 
548 	@Test void fi01_YearMonth() throws Exception {
549 		test1("'2012-12'", FI);
550 	}
551 
552 	@Test void fi02_YearMonth_overrideSwap() throws Exception {
553 		test3("'FOO'", FI, FISwap.class);
554 	}
555 
556 	@Test void fi03_YearMonth_overrideAnnotation() throws Exception {
557 		test1("{f1:'2012-12',f2:'FOO'}", new FIBean());
558 	}
559 
560 	//------------------------------------------------------------------------------------------------------------------
561 	//	POJO_SWAPS.put(Temporal.class, new TemporalSwap.IsoInstant())
562 	//------------------------------------------------------------------------------------------------------------------
563 	private static Temporal FJ = HijrahDate.from(FB);
564 
565 	public static class FJSwap extends StringSwap<Temporal> {
566 		@Override /* ObjectSwap */
567 		public String swap(BeanSession session, Temporal o) throws Exception {
568 			return "FOO";
569 		}
570 	}
571 
572 	public static class FJBean {
573 		public Temporal f1 = FJ;
574 		@Swap(FJSwap.class)
575 		public Temporal f2 = FJ;
576 	}
577 
578 	@Test void fj01_Temporal() throws Exception {
579 		test1("'2012-12-21T05:00:00Z'", FJ);
580 	}
581 
582 	@Test void fj02_Temporal_overrideSwap() throws Exception {
583 		test3("'FOO'", FJ, FJSwap.class);
584 	}
585 
586 	@Test void fj03_Temporal_overrideAnnotation() throws Exception {
587 		test1("{f1:'2012-12-21T05:00:00Z',f2:'FOO'}", new FJBean());
588 	}
589 
590 	//------------------------------------------------------------------------------------------------------------------
591 	//	POJO_SWAPS.put(TimeZone.class, new TimeZoneSwap())
592 	//------------------------------------------------------------------------------------------------------------------
593 	private static TimeZone G = TimeZone.getTimeZone("Z");
594 
595 	public static class GSwap extends StringSwap<TimeZone> {
596 		@Override /* ObjectSwap */
597 		public String swap(BeanSession session, TimeZone o) throws Exception {
598 			return "FOO";
599 		}
600 	}
601 
602 	public static class GBean {
603 		public TimeZone f1 = G;
604 		@Swap(GSwap.class)
605 		public TimeZone f2 = G;
606 	}
607 
608 	@Test void g01_TimeZone() throws Exception {
609 		test1("'GMT'", G);
610 	}
611 
612 	@Test void g02_TimeZone_overrideSwap() throws Exception {
613 		test3("'FOO'", G, GSwap.class);
614 	}
615 
616 	@Test void g03_TimeZone_overrideAnnotation() throws Exception {
617 		test1("{f1:'GMT',f2:'FOO'}", new GBean());
618 	}
619 
620 	//------------------------------------------------------------------------------------------------------------------
621 	//	POJO_SWAPS.put(XMLGregorianCalendar.class, new XMLGregorianCalendarSwap())
622 	//------------------------------------------------------------------------------------------------------------------
623 	private static XMLGregorianCalendar H;
624 	static {
625 		try {
626 			H = DatatypeFactory.newInstance().newXMLGregorianCalendar("2012-12-21T12:34:56.789Z");
627 		} catch (DatatypeConfigurationException e) {
628 			e.printStackTrace();
629 		}
630 	}
631 
632 	public static class HSwap extends StringSwap<XMLGregorianCalendar> {
633 		@Override /* ObjectSwap */
634 		public String swap(BeanSession session, XMLGregorianCalendar o) throws Exception {
635 			return "FOO";
636 		}
637 	}
638 
639 	public static class HBean {
640 		public XMLGregorianCalendar f1 = H;
641 		@Swap(HSwap.class)
642 		public XMLGregorianCalendar f2 = H;
643 	}
644 
645 	@Test void h01_XMLGregorianCalendar() throws Exception {
646 		test1("'2012-12-21T12:34:56.789Z'", H);
647 	}
648 
649 	@Test void h02_XMLGregorianCalendar_overrideSwap() throws Exception {
650 		test3("'FOO'", H, HSwap.class);
651 	}
652 
653 	@Test void h03_XMLGregorianCalendar_overrideAnnotation() throws Exception {
654 		test1("{f1:'2012-12-21T12:34:56.789Z',f2:'FOO'}", new HBean());
655 	}
656 
657 	//------------------------------------------------------------------------------------------------------------------
658 	//	POJO_SWAPS.put(ZoneId.class, new ZoneIdSwap())
659 	//------------------------------------------------------------------------------------------------------------------
660 	private static ZoneId I = ZoneId.of("Z");
661 
662 	public static class ISwap extends StringSwap<ZoneId> {
663 		@Override /* ObjectSwap */
664 		public String swap(BeanSession session, ZoneId o) throws Exception {
665 			return "FOO";
666 		}
667 	}
668 
669 	public static class IBean {
670 		public ZoneId f1 = I;
671 		@Swap(ISwap.class)
672 		public ZoneId f2 = I;
673 	}
674 
675 	@Test void i01_ZoneId() throws Exception {
676 		test1("'Z'", I);
677 	}
678 
679 	@Test void i02_ZoneId_overrideSwap() throws Exception {
680 		test3("'FOO'", I, ISwap.class);
681 	}
682 
683 	@Test void i03_ZoneId_overrideAnnotation() throws Exception {
684 		test1("{f1:'Z',f2:'FOO'}", new IBean());
685 	}
686 }