1 package com.fasterxml.jackson.databind.ext; 2 3 import javax.xml.datatype.*; 4 import javax.xml.namespace.QName; 5 6 import com.fasterxml.jackson.databind.*; 7 import com.fasterxml.jackson.databind.ext.CoreXMLDeserializers; 8 import com.fasterxml.jackson.databind.type.TypeFactory; 9 10 /** 11 * Core XML types (javax.xml) are considered "external" (or more precisely "optional") 12 * since some Java(-like) platforms do not include them: specifically, Google AppEngine 13 * and Android seem to skimp on their inclusion. As such, they are dynamically loaded 14 * only as needed, and need bit special handling. 15 * 16 * @author tatu 17 */ 18 public class TestCoreXMLTypes 19 extends BaseMapTest 20 { 21 /* 22 /********************************************************** 23 /* Serializer tests 24 /********************************************************** 25 */ 26 testQNameSer()27 public void testQNameSer() throws Exception 28 { 29 QName qn = new QName("http://abc", "tag", "prefix"); 30 assertEquals(quote(qn.toString()), serializeAsString(qn)); 31 } 32 testDurationSer()33 public void testDurationSer() throws Exception 34 { 35 DatatypeFactory dtf = DatatypeFactory.newInstance(); 36 // arbitrary value 37 Duration dur = dtf.newDurationDayTime(false, 15, 19, 58, 1); 38 assertEquals(quote(dur.toString()), serializeAsString(dur)); 39 } 40 testXMLGregorianCalendarSerAndDeser()41 public void testXMLGregorianCalendarSerAndDeser() throws Exception 42 { 43 DatatypeFactory dtf = DatatypeFactory.newInstance(); 44 XMLGregorianCalendar cal = dtf.newXMLGregorianCalendar 45 (1974, 10, 10, 18, 15, 17, 123, 0); 46 /* Due to [JACKSON-308], 1.6 will use configurable Date serialization; 47 * and it defaults to using timestamp. So let's try couple of combinations. 48 */ 49 ObjectMapper mapper = new ObjectMapper(); 50 long timestamp = cal.toGregorianCalendar().getTimeInMillis(); 51 String numStr = String.valueOf(timestamp); 52 assertEquals(numStr, mapper.writeValueAsString(cal)); 53 54 // [JACKSON-403] Needs to come back ok as well: 55 XMLGregorianCalendar calOut = mapper.readValue(numStr, XMLGregorianCalendar.class); 56 assertNotNull(calOut); 57 assertEquals(timestamp, calOut.toGregorianCalendar().getTimeInMillis()); 58 59 // and then textual variant 60 mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); 61 // this is ALMOST same as default for XMLGregorianCalendar... just need to unify Z/+0000 62 String exp = cal.toXMLFormat(); 63 String act = mapper.writeValueAsString(cal); 64 act = act.substring(1, act.length() - 1); // remove quotes 65 exp = removeZ(exp); 66 act = removeZ(act); 67 assertEquals(exp, act); 68 } 69 removeZ(String dateStr)70 private String removeZ(String dateStr) { 71 if (dateStr.endsWith("Z")) { 72 return dateStr.substring(0, dateStr.length()-1); 73 } 74 if (dateStr.endsWith("+0000")) { 75 return dateStr.substring(0, dateStr.length()-5); 76 } 77 if (dateStr.endsWith("+00:00")) { 78 return dateStr.substring(0, dateStr.length()-6); 79 } 80 return dateStr; 81 } 82 83 /* 84 /********************************************************** 85 /* Deserializer tests 86 /********************************************************** 87 */ 88 89 // First things first: must be able to load the deserializers... testDeserializerLoading()90 public void testDeserializerLoading() 91 { 92 CoreXMLDeserializers sers = new CoreXMLDeserializers(); 93 TypeFactory f = TypeFactory.defaultInstance(); 94 sers.findBeanDeserializer(f.constructType(Duration.class), null, null); 95 sers.findBeanDeserializer(f.constructType(XMLGregorianCalendar.class), null, null); 96 sers.findBeanDeserializer(f.constructType(QName.class), null, null); 97 } 98 testQNameDeser()99 public void testQNameDeser() throws Exception 100 { 101 QName qn = new QName("http://abc", "tag", "prefix"); 102 String qstr = qn.toString(); 103 ObjectMapper mapper = new ObjectMapper(); 104 assertEquals("Should deserialize to equal QName (exp serialization: '"+qstr+"')", 105 qn, mapper.readValue(quote(qstr), QName.class)); 106 } 107 testCalendarDeser()108 public void testCalendarDeser() throws Exception 109 { 110 DatatypeFactory dtf = DatatypeFactory.newInstance(); 111 XMLGregorianCalendar cal = dtf.newXMLGregorianCalendar 112 (1974, 10, 10, 18, 15, 17, 123, 0); 113 String exp = cal.toXMLFormat(); 114 assertEquals("Should deserialize to equal XMLGregorianCalendar ('"+exp+"')", cal, 115 new ObjectMapper().readValue(quote(exp), XMLGregorianCalendar.class)); 116 } 117 testDurationDeser()118 public void testDurationDeser() throws Exception 119 { 120 DatatypeFactory dtf = DatatypeFactory.newInstance(); 121 // arbitrary value, like... say, 27d5h15m59s 122 Duration dur = dtf.newDurationDayTime(true, 27, 5, 15, 59); 123 String exp = dur.toString(); 124 assertEquals("Should deserialize to equal Duration ('"+exp+"')", dur, 125 new ObjectMapper().readValue(quote(exp), Duration.class)); 126 } 127 } 128