1   /*
2    * Copyright 2004 The Apache Software Foundation.
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  
18  package org.apache.commons.betwixt.schema;
19  
20  import java.beans.IntrospectionException;
21  import java.beans.Introspector;
22  import java.beans.PropertyDescriptor;
23  import java.io.StringWriter;
24  
25  import org.apache.commons.betwixt.AbstractTestCase;
26  import org.apache.commons.betwixt.io.BeanWriter;
27  import org.apache.commons.betwixt.strategy.HyphenatedNameMapper;
28  
29  /***
30   * Tests for the generation of schema from the object models.
31   * @author <a href='http://jakarta.apache.org/'>Jakarta Commons Team</a>
32   * @version $Revision: 190509 $
33   */
34  public class TestSchemaGeneration extends AbstractTestCase {
35  
36      public TestSchemaGeneration(String name) {
37          super(name);        
38      }
39      
40      public void testSimplestBeanWithAttributes() throws Exception {
41          SchemaTranscriber transcriber = new SchemaTranscriber();
42          transcriber.getXMLIntrospector().getConfiguration().setAttributesForPrimitives(true);
43          Schema schema = transcriber.generate(SimplestBean.class);
44          
45          StringWriter out = new StringWriter();
46          out.write("<?xml version='1.0'?>");
47          BeanWriter writer = new BeanWriter(out);
48          writer.setBindingConfiguration(transcriber.createSchemaBindingConfiguration());
49          writer.getXMLIntrospector().setConfiguration(transcriber.createSchemaIntrospectionConfiguration());
50          writer.write(schema);
51          
52          String xsd = out.getBuffer().toString();
53          
54          String expected ="<?xml version='1.0'?><xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'>" +
55          "<xsd:element name='SimplestBean' type='org.apache.commons.betwixt.schema.SimplestBean'/>" +
56          "<xsd:complexType name='org.apache.commons.betwixt.schema.SimplestBean'>" +
57          "<xsd:sequence/>" +
58          "<xsd:attribute name='name' type='xsd:string'/>" +
59          "</xsd:complexType>" +
60          "</xsd:schema>";
61              
62          xmlAssertIsomorphicContent(parseString(expected), parseString(xsd));
63      }
64      
65      
66      public void testSimplestBeanWithElement() throws Exception {
67          SchemaTranscriber transcriber = new SchemaTranscriber();
68          transcriber.getXMLIntrospector().getConfiguration().setAttributesForPrimitives(true);
69          Schema schema = transcriber.generate(SimplestElementBean.class);
70          
71          StringWriter out = new StringWriter();
72          out.write("<?xml version='1.0'?>");
73          BeanWriter writer = new BeanWriter(out);
74          writer.setBindingConfiguration(transcriber.createSchemaBindingConfiguration());
75          writer.getXMLIntrospector().setConfiguration(transcriber.createSchemaIntrospectionConfiguration());
76          writer.write(schema);
77          
78          String xsd = out.getBuffer().toString();
79          
80          String expected ="<?xml version='1.0'?><xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'>" +
81          "<xsd:element name='SimplestBean' type='org.apache.commons.betwixt.schema.SimplestElementBean'/>" +
82          "<xsd:complexType name='org.apache.commons.betwixt.schema.SimplestElementBean'>" +
83          "<xsd:sequence>" +
84          "<xsd:element name='name' type='xsd:string' minOccurs='0' maxOccurs='1'/>" +
85          "</xsd:sequence>" +
86          "</xsd:complexType>" +
87          "</xsd:schema>";
88              
89          xmlAssertIsomorphicContent(parseString(expected), parseString(xsd));
90      }
91      
92      public void testSimpleBean() throws Exception {
93          SchemaTranscriber transcriber = new SchemaTranscriber();
94          Schema schema = transcriber.generate(SimpleBean.class);
95          
96          StringWriter out = new StringWriter();
97          out.write("<?xml version='1.0'?>");
98          BeanWriter writer = new BeanWriter(out);
99          writer.setBindingConfiguration(transcriber.createSchemaBindingConfiguration());
100         writer.getXMLIntrospector().setConfiguration(transcriber.createSchemaIntrospectionConfiguration());
101         writer.write(schema);
102         
103         String xsd = out.getBuffer().toString();
104         
105         String expected ="<?xml version='1.0'?><xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'>" +
106         "<xsd:element name='simple' type='org.apache.commons.betwixt.schema.SimpleBean'/>" +
107         "<xsd:complexType name='org.apache.commons.betwixt.schema.SimpleBean'>" +
108         "<xsd:sequence>" +
109         "<xsd:element name='three' type='xsd:string' minOccurs='0' maxOccurs='1'/>" +
110         "<xsd:element name='four' type='xsd:string' minOccurs='0' maxOccurs='1'/>" +
111         "</xsd:sequence>" +
112         "<xsd:attribute name='one' type='xsd:string'/>" +
113         "<xsd:attribute name='two' type='xsd:string'/>" +
114         "</xsd:complexType>" +
115         "</xsd:schema>";
116             
117         xmlAssertIsomorphicContent(parseString(expected), parseString(xsd));
118     }
119     
120     
121     public void testOrderLineBean() throws Exception {
122         SchemaTranscriber transcriber = new SchemaTranscriber();
123         transcriber.getXMLIntrospector().getConfiguration().setAttributesForPrimitives(true);
124         transcriber.getXMLIntrospector().getConfiguration().setAttributeNameMapper(new HyphenatedNameMapper());
125         Schema schema = transcriber.generate(OrderLineBean.class);
126         
127         StringWriter out = new StringWriter();
128         out.write("<?xml version='1.0'?>");
129         BeanWriter writer = new BeanWriter(out);
130         writer.setBindingConfiguration(transcriber.createSchemaBindingConfiguration());
131         writer.getXMLIntrospector().setConfiguration(transcriber.createSchemaIntrospectionConfiguration());
132         writer.write(schema);
133         
134         String xsd = out.getBuffer().toString();
135         
136         // different JVMs may return different orders during reflection
137         StringBuffer buffer = new StringBuffer("<?xml version='1.0'?><xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'>" +
138                 "<xsd:element name='OrderLineBean' type='org.apache.commons.betwixt.schema.OrderLineBean'/>" +
139                 "<xsd:complexType name='org.apache.commons.betwixt.schema.OrderLineBean'>" +
140                 "<xsd:sequence>" +
141                 "<xsd:element name='product' type='org.apache.commons.betwixt.schema.ProductBean' minOccurs='0' maxOccurs='1'/>" +
142                 "</xsd:sequence>" +
143                 "<xsd:attribute name='quantity' type='xsd:string'/>" +
144                 "</xsd:complexType>" +
145                 "<xsd:complexType name='org.apache.commons.betwixt.schema.ProductBean'>" +
146                 "<xsd:sequence/>");
147         
148         PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(ProductBean.class).getPropertyDescriptors();
149         for (int i=0; i<propertyDescriptors.length; i++)
150         {
151             PropertyDescriptor propertyDescriptor = propertyDescriptors[i];
152             if ("barcode".equals(propertyDescriptor.getName()))
153             {
154                 buffer.append("<xsd:attribute name='barcode' type='xsd:string'/>");
155             }
156             else if ("code".equals(propertyDescriptor.getName()))
157             {
158                 buffer.append("<xsd:attribute name='code' type='xsd:string'/>");
159             }
160             else if ("displayName".equals(propertyDescriptor.getName()))
161             {
162                 buffer.append("<xsd:attribute name='display-name' type='xsd:string'/>");
163             }
164             else if ("name".equals(propertyDescriptor.getName()))
165             {
166                 buffer.append("<xsd:attribute name='name' type='xsd:string'/>");
167             }
168         }
169         buffer.append("</xsd:complexType>" +
170                 "</xsd:schema>");
171         
172         String expected = buffer.toString();
173 
174         xmlAssertIsomorphicContent(parseString(expected), parseString(xsd), true);
175     }
176     
177     public void testOrder() throws Exception {
178         SchemaTranscriber transcriber = new SchemaTranscriber();
179         transcriber.getXMLIntrospector().getConfiguration()
180                 .setElementNameMapper(new HyphenatedNameMapper());
181         transcriber.getXMLIntrospector().getConfiguration()
182                 .setAttributeNameMapper(new HyphenatedNameMapper());
183         transcriber.getXMLIntrospector().getConfiguration()
184                 .setAttributesForPrimitives(true);
185         transcriber.getXMLIntrospector().getConfiguration()
186                 .setWrapCollectionsInElement(false);
187         Schema schema = transcriber.generate(OrderBean.class);
188 
189         StringWriter out = new StringWriter();
190         out.write("<?xml version='1.0'?>");
191         BeanWriter writer = new BeanWriter(out);
192         writer.setBindingConfiguration(transcriber
193                 .createSchemaBindingConfiguration());
194         writer.getXMLIntrospector().setConfiguration(
195                 transcriber.createSchemaIntrospectionConfiguration());
196         writer.write(schema);
197 
198         String xsd = out.getBuffer().toString();
199 
200         PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(
201                 OrderBean.class).getPropertyDescriptors();
202         boolean linesFirst = false;
203         for (int i = 0; i < propertyDescriptors.length; i++) {
204             PropertyDescriptor propertyDescriptor = propertyDescriptors[i];
205             if ("lines".equals(propertyDescriptor.getName())) {
206                 linesFirst = true;
207                 break;
208             } else if ("customer".equals(propertyDescriptor.getName())) {
209                 linesFirst = false;
210                 break;
211             }
212         }
213 
214         
215         StringBuffer buffer = new StringBuffer(
216                 "<?xml version='1.0'?><xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'>"
217                         + "<xsd:element name='order-bean' type='org.apache.commons.betwixt.schema.OrderBean'/>"
218                         + ""
219                         + "<xsd:complexType name='org.apache.commons.betwixt.schema.OrderBean'>"
220                         + "	<xsd:sequence>");
221 
222         if (linesFirst) {
223             buffer.append("     <xsd:element name='line' type='org.apache.commons.betwixt.schema.OrderLineBean' minOccurs='0' maxOccurs='unbounded'/>");
224             buffer.append("        <xsd:element name='customer' type='org.apache.commons.betwixt.schema.CustomerBean' minOccurs='0' maxOccurs='1'/>");
225         } else {
226             buffer.append("        <xsd:element name='customer' type='org.apache.commons.betwixt.schema.CustomerBean' minOccurs='0' maxOccurs='1'/>");
227             buffer.append("     <xsd:element name='line' type='org.apache.commons.betwixt.schema.OrderLineBean' minOccurs='0' maxOccurs='unbounded'/>");
228         }
229 
230         buffer.append("	</xsd:sequence>"
231                         + "	<xsd:attribute name='code' type='xsd:string'/>"
232                         + "</xsd:complexType>"
233                         + "");
234                         
235         if (linesFirst) {
236             writeExpectedOrderLineBeanType(buffer);
237             writeExpectedCustomerBeanType(buffer);            
238         } else {
239             writeExpectedCustomerBeanType(buffer);            
240             writeExpectedOrderLineBeanType(buffer);
241         }
242                 
243         buffer.append("</xsd:schema>");
244 
245         String expected = buffer.toString();
246 
247          xmlAssertIsomorphicContent(parseString(xsd), parseString(expected), true);
248     }
249 
250     /***
251      * @param buffer
252      * @throws IntrospectionException
253      */
254     private void writeExpectedOrderLineBeanType(StringBuffer buffer) throws IntrospectionException {
255         PropertyDescriptor[] propertyDescriptors;
256         buffer.append("<xsd:complexType name='org.apache.commons.betwixt.schema.OrderLineBean'>"
257                         + "	<xsd:sequence>"
258                         + "		<xsd:element name='product' type='org.apache.commons.betwixt.schema.ProductBean' minOccurs='0' maxOccurs='1'/>"
259                         + "	</xsd:sequence>"
260                         + "	<xsd:attribute name='quantity' type='xsd:string'/>"
261                         + "</xsd:complexType>"
262                         + ""
263                         + "<xsd:complexType name='org.apache.commons.betwixt.schema.ProductBean'>"
264                         + "	<xsd:sequence/>");
265 
266         propertyDescriptors = Introspector.getBeanInfo(ProductBean.class)
267                 .getPropertyDescriptors();
268         for (int i = 0; i < propertyDescriptors.length; i++) {
269             PropertyDescriptor propertyDescriptor = propertyDescriptors[i];
270             if ("barcode".equals(propertyDescriptor.getName())) {
271                 buffer
272                         .append("<xsd:attribute name='barcode' type='xsd:string'/>");
273             } else if ("code".equals(propertyDescriptor.getName())) {
274                 buffer.append("<xsd:attribute name='code' type='xsd:string'/>");
275             } else if ("displayName".equals(propertyDescriptor.getName())) {
276                 buffer
277                         .append("<xsd:attribute name='display-name' type='xsd:string'/>");
278             } else if ("name".equals(propertyDescriptor.getName())) {
279                 buffer.append("<xsd:attribute name='name' type='xsd:string'/>");
280             }
281         }
282         buffer.append("	</xsd:complexType>");
283     }
284 
285     /***
286      * @param buffer
287      * @throws IntrospectionException
288      */
289     private void writeExpectedCustomerBeanType(StringBuffer buffer) throws IntrospectionException {
290         PropertyDescriptor[] propertyDescriptors;
291         buffer.append("<xsd:complexType name='org.apache.commons.betwixt.schema.CustomerBean'>"
292                         + "	<xsd:sequence/>");
293 
294         propertyDescriptors = Introspector.getBeanInfo(CustomerBean.class)
295                 .getPropertyDescriptors();
296         for (int i = 0; i < propertyDescriptors.length; i++) {
297             PropertyDescriptor propertyDescriptor = propertyDescriptors[i];
298             if ("code".equals(propertyDescriptor.getName())) {
299                 buffer.append("<xsd:attribute name='code' type='xsd:string'/>");
300             } else if ("country".equals(propertyDescriptor.getName())) {
301                 buffer
302                         .append("<xsd:attribute name='country' type='xsd:string'/>");
303             } else if ("name".equals(propertyDescriptor.getName())) {
304                 buffer.append("<xsd:attribute name='name' type='xsd:string'/>");
305             } else if ("postcode".equals(propertyDescriptor.getName())) {
306                 buffer
307                         .append("<xsd:attribute name='postcode' type='xsd:string'/>");
308             } else if ("street".equals(propertyDescriptor.getName())) {
309                 buffer
310                         .append("<xsd:attribute name='street' type='xsd:string'/>");
311             } else if ("town".equals(propertyDescriptor.getName())) {
312                 buffer.append("<xsd:attribute name='town' type='xsd:string'/>");
313             }
314         }
315 
316         buffer.append("</xsd:complexType>"
317                         + "");
318     }
319     
320 }