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