1   /*
2    * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
3    *
4    * This software is open source.
5    * See the bottom of this file for the licence.
6    */
7   
8   package org.dom4j.datatype;
9   
10  import junit.textui.TestRunner;
11  
12  import java.io.StringReader;
13  import java.text.DateFormat;
14  import java.text.SimpleDateFormat;
15  import java.util.Calendar;
16  import java.util.GregorianCalendar;
17  import java.util.SimpleTimeZone;
18  import java.util.TimeZone;
19  
20  import org.dom4j.Attribute;
21  import org.dom4j.Document;
22  import org.dom4j.Element;
23  import org.dom4j.io.SAXReader;
24  
25  /***
26   * Test harness for XML Schema Datatypes support
27   * 
28   * @author Yuxin Ruan
29   * @version $Revision: 1.3 $
30   */
31  public class Datatype2Test extends AbstractDataTypeTestCase {
32      public static final int YEAR = 2001;
33  
34      public static final int MONTH = 10;
35  
36      public static final int DATE = 31;
37  
38      public static void main(String[] args) {
39          TestRunner.run(Datatype2Test.class);
40      }
41  
42      public void testSchema() throws Exception {
43          Document schema = getSchema();
44          validateDocumentWithSchema(schema);
45      }
46  
47      public void testSchemaWithNamedComplexType() throws Exception {
48          Document schema = getSchemaWithNamedComplexType();
49          validateDocumentWithSchema(schema);
50      }
51  
52      public void testSchemaWithReference() throws Exception {
53          Document schema = getSchemaWithReference();
54          validateDocumentWithSchema(schema);
55      }
56  
57      public void testSchemaWithNamedSimpleType() throws Exception {
58          Document schema = getSchemaWithNamedSimpleType();
59          validateDocumentWithSchema(schema);
60      }
61  
62      private void validateDocumentWithSchema(Document schema) throws Exception {
63          Document doc = getSource(schema);
64          Element root = doc.getRootElement();
65          validateLongAttribute(root);
66          validateFloatElement(root);
67          validateDateElement(root);
68      }
69  
70      private void validateLongAttribute(Element root) throws Exception {
71          Attribute attr = root.attribute("longAttribute");
72          Object attrData = attr.getData();
73          validateData("testLongAttribute", attrData, new Long(123));
74          System.out.println("retrieved attribute " + attrData);
75      }
76  
77      private void validateFloatElement(Element root) throws Exception {
78          Element elem = root.element("floatElement");
79          Object elemData = elem.getData();
80          validateData("testFloatElement", elemData, new Float(1.23));
81          System.out.println("retrieved element:" + elemData);
82      }
83  
84      private void validateDateElement(Element root) throws Exception {
85          Element elem = root.element("dateElement");
86          Object elemData = elem.getData();
87          Calendar expected = getDate();
88  
89          System.out.println("retrieved element:" + elemData);
90  
91          // don't compare the Calendar instances, compare their strings instead!
92          assertTrue(elemData instanceof Calendar);
93  
94          Calendar elemCal = (Calendar) elemData;
95  
96          DateFormat format = new SimpleDateFormat("MM/dd/yyyyZ");
97          format.setTimeZone(elemCal.getTimeZone());
98  
99          String elemStr = format.format(elemCal.getTime());
100 
101         format.setTimeZone(expected.getTimeZone());
102 
103         String expectedStr = format.format(expected.getTime());
104 
105         assertEquals("testDateElement", expectedStr, elemStr);
106     }
107 
108     private void validateData(String test, Object retrieved, Object expected)
109             throws Exception {
110         Class retrievedClass = retrieved.getClass();
111         Class expectedClass = expected.getClass();
112 
113         // compare class
114         if (!expectedClass.equals(retrievedClass)) {
115             String msg = "class mismatch in " + test + ":expected "
116                     + expectedClass + ", retrieved " + retrievedClass;
117             throw new Exception(msg);
118         }
119 
120         // compare value
121         if (!expected.equals(retrieved)) {
122             String msg = "value mismatch in " + test + ":expected " + expected
123                     + ", retrieved " + retrieved;
124             throw new Exception(msg);
125         }
126     }
127 
128     private Document getSource(Document schema) throws Exception {
129         StringBuffer b = new StringBuffer();
130         b.append("<?xml version='1.0' ?>");
131         b.append("<test xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'");
132         b.append("        xsi:noNamespaceSchemaLocation='long.xsd'");
133         b.append("        longAttribute='123' >");
134         b.append("    <floatElement>1.23</floatElement>");
135         b.append("    <dateElement>" + getDateString() + "</dateElement>");
136         b.append("</test>");
137 
138         StringReader in = new StringReader(b.toString());
139         DatatypeDocumentFactory docFactory = new DatatypeDocumentFactory();
140         docFactory.loadSchema(schema);
141 
142         SAXReader parser = new SAXReader(docFactory);
143 
144         return parser.read(in);
145     }
146 
147     private Document getSchema() throws Exception {
148         StringBuffer b = new StringBuffer();
149         b.append("<?xml version='1.0' encoding='UTF-8'?>");
150         b.append("<xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'>");
151         b.append(" <xsd:element name='test'>");
152         b.append("  <xsd:complexType>");
153         b.append("   <xsd:sequence>");
154         b.append("    <xsd:element name='floatElement' type='xsd:float' />");
155         b.append("    <xsd:element name='dateElement' type='xsd:date' />");
156         b.append("   </xsd:sequence>");
157         b.append("   <xsd:attribute name='longAttribute' type='xsd:long' />");
158         b.append("  </xsd:complexType>");
159         b.append(" </xsd:element>");
160         b.append("</xsd:schema>");
161 
162         StringReader in = new StringReader(b.toString());
163         SAXReader parser = new SAXReader();
164 
165         return parser.read(in);
166     }
167 
168     private Document getSchemaWithNamedComplexType() throws Exception {
169         StringBuffer b = new StringBuffer();
170         b.append("<?xml version='1.0' encoding='UTF-8'?>");
171         b.append("<xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'>");
172         b.append(" <xsd:element name='test' type='TimePeriodType' />");
173         b.append(" <xsd:complexType name='TimePeriodType'>");
174         b.append("  <xsd:sequence>");
175         b.append("   <xsd:element name='floatElement' type='xsd:float' />");
176         b.append("   <xsd:element name='dateElement' type='xsd:date' />");
177         b.append("  </xsd:sequence>");
178         b.append("  <xsd:attribute name='longAttribute' type='xsd:long' />");
179         b.append(" </xsd:complexType>");
180         b.append("</xsd:schema>");
181 
182         StringReader in = new StringReader(b.toString());
183         SAXReader parser = new SAXReader();
184 
185         return parser.read(in);
186     }
187 
188     private Document getSchemaWithReference() throws Exception {
189         StringBuffer b = new StringBuffer();
190         b.append("<?xml version='1.0' encoding='UTF-8'?>");
191         b.append("<xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'>");
192         b.append(" <xsd:element name='test' type='TimePeriodType' />");
193         b.append(" <xsd:complexType name='TimePeriodType'>");
194         b.append("  <xsd:sequence>");
195         b.append("   <xsd:element name='floatElement' type='xsd:float' />");
196         b.append("   <xsd:element ref='dateElement' />");
197         b.append("  </xsd:sequence>");
198         b.append("  <xsd:attribute name='longAttribute' type='xsd:long' />");
199         b.append(" </xsd:complexType>");
200         b.append(" <xsd:element name='dateElement' type='xsd:date' />");
201         b.append("</xsd:schema>");
202 
203         StringReader in = new StringReader(b.toString());
204         SAXReader parser = new SAXReader();
205 
206         return parser.read(in);
207     }
208 
209     private Document getSchemaWithNamedSimpleType() throws Exception {
210         StringBuffer b = new StringBuffer();
211         b.append("<?xml version='1.0' encoding='UTF-8'?>");
212         b.append("<xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'>");
213         b.append(" <xsd:element name='test'>");
214         b.append("  <xsd:complexType>");
215         b.append("   <xsd:sequence>");
216         b.append("    <xsd:element name='floatElement' type='xsd:float' />");
217         b.append("    <xsd:element name='dateElement' type='dateType' />");
218         b.append("   </xsd:sequence>");
219         b.append("   <xsd:attribute name='longAttribute' type='xsd:long' />");
220         b.append("  </xsd:complexType>");
221         b.append(" </xsd:element>");
222         b.append(" <xsd:simpleType name='dateType'>");
223         b.append("  <xsd:restriction base='xsd:date'>");
224         b.append("  </xsd:restriction>");
225         b.append(" </xsd:simpleType>");
226         b.append("</xsd:schema>");
227 
228         StringReader in = new StringReader(b.toString());
229         SAXReader parser = new SAXReader();
230 
231         return parser.read(in);
232     }
233 
234     private static String getDateString() {
235         // return dateTime in ISO8601 format
236         String yyyy = Integer.toString(YEAR);
237         String mm = Integer.toString(MONTH);
238         String dd = Integer.toString(DATE);
239 
240         return yyyy + "-" + mm + "-" + dd + "Z";
241     }
242 
243     private static Calendar getDate() {
244         Calendar calendar = new GregorianCalendar();
245         calendar.clear();
246         calendar.set(Calendar.YEAR, YEAR);
247         calendar.set(Calendar.MONTH, MONTH - 1);
248         calendar.set(Calendar.DAY_OF_MONTH, DATE);
249         calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
250         calendar.setTimeZone(new SimpleTimeZone(0, "XSD 'Z' timezone"));
251 
252         return calendar;
253     }
254 }
255 
256 /*
257  * Redistribution and use of this software and associated documentation
258  * ("Software"), with or without modification, are permitted provided that the
259  * following conditions are met:
260  * 
261  * 1. Redistributions of source code must retain copyright statements and
262  * notices. Redistributions must also contain a copy of this document.
263  * 
264  * 2. Redistributions in binary form must reproduce the above copyright notice,
265  * this list of conditions and the following disclaimer in the documentation
266  * and/or other materials provided with the distribution.
267  * 
268  * 3. The name "DOM4J" must not be used to endorse or promote products derived
269  * from this Software without prior written permission of MetaStuff, Ltd. For
270  * written permission, please contact dom4j-info@metastuff.com.
271  * 
272  * 4. Products derived from this Software may not be called "DOM4J" nor may
273  * "DOM4J" appear in their names without prior written permission of MetaStuff,
274  * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
275  * 
276  * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
277  * 
278  * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
279  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
280  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
281  * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
282  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
283  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
284  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
285  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
286  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
287  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
288  * POSSIBILITY OF SUCH DAMAGE.
289  * 
290  * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
291  */