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