diff --git a/xml/pom.xml b/xml/pom.xml index 23ecf9e9..406ce7e4 100644 --- a/xml/pom.xml +++ b/xml/pom.xml @@ -66,6 +66,10 @@ wstx-asl test + + org.apache.ws.commons.schema + XmlSchema + easymock diff --git a/xml/src/main/java/org/springframework/xml/xsd/InlineableXsdSchema.java b/xml/src/main/java/org/springframework/xml/xsd/InlineableXsdSchema.java new file mode 100644 index 00000000..d44b7321 --- /dev/null +++ b/xml/src/main/java/org/springframework/xml/xsd/InlineableXsdSchema.java @@ -0,0 +1,31 @@ +/* + * Copyright 2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.xml.xsd; + +/** + * Represents an abstraction for XSD schemas. + + * @author Arjen Poutsma + * @since 1.5.0 + */ +public interface InlineableXsdSchema extends XsdSchema { + + /** + * Inlines this schema into a set of self-contained schema's. + * */ + XsdSchema[] inline(); +} diff --git a/xml/src/main/java/org/springframework/xml/xsd/SimpleXsdSchema.java b/xml/src/main/java/org/springframework/xml/xsd/SimpleXsdSchema.java new file mode 100644 index 00000000..d8cc648c --- /dev/null +++ b/xml/src/main/java/org/springframework/xml/xsd/SimpleXsdSchema.java @@ -0,0 +1,152 @@ +/* + * Copyright 2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.xml.xsd; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.core.io.Resource; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; +import org.springframework.xml.namespace.QNameUtils; +import org.springframework.xml.sax.SaxUtils; + +/** + * The default {@link XsdSchema} implementation. + *

+ * Allows a XSD to be set by the {@link #setXsd(Resource)}, or directly in the {@link #SimpleXsdSchema(Resource) + * constructor}. + * + * @author Mark LaFond + * @author Arjen Poutsma + * @since 1.5.0 + */ +public class SimpleXsdSchema implements XsdSchema, InitializingBean { + + private static DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + + private static final String SCHEMA_NAMESPACE = "http://www.w3.org/2001/XMLSchema"; + + private static final QName SCHEMA_NAME = QNameUtils.createQName(SCHEMA_NAMESPACE, "schema", "xsd"); + + private static final QName ELEMENT_NAME = QNameUtils.createQName(SCHEMA_NAMESPACE, "element", "xsd"); + + private Resource xsdResource; + + private Element schemaElement; + + static { + documentBuilderFactory.setNamespaceAware(true); + } + + /** + * Create a new instance of the {@link SimpleXsdSchema} class. + *

+ * A subsequent call to the {@link #setXsd(Resource)} method is required. + */ + public SimpleXsdSchema() { + } + + /** + * Create a new instance of the {@link SimpleXsdSchema} class with the specified resource. + * + * @param xsdResource the XSD resource; must not be null + * @throws IllegalArgumentException if the supplied xsdResource is null + */ + public SimpleXsdSchema(Resource xsdResource) { + Assert.notNull(xsdResource, "xsdResource must not be null"); + this.xsdResource = xsdResource; + } + + /** + * Set the XSD resource to be exposed by calls to this instances' {@link #getSource()} method. + * + * @param xsdResource the XSD resource + */ + public void setXsd(Resource xsdResource) { + this.xsdResource = xsdResource; + } + + public String getTargetNamespace() { + return schemaElement.getAttribute("targetNamespace"); + } + + public Source getSource() { + return new DOMSource(schemaElement); + } + + public QName[] getElementNames() { + NodeList children = schemaElement.getChildNodes(); + List result = new ArrayList(children.getLength()); + for (int i = 0; i < children.getLength(); i++) { + if (children.item(i).getNodeType() == Node.ELEMENT_NODE) { + Element childElement = (Element) children.item(i); + QName childName = QNameUtils.getQNameForNode(childElement); + if (ELEMENT_NAME.equals(childName)) { + result.add(getElementName(childElement)); + } + } + } + return (QName[]) result.toArray(new QName[result.size()]); + } + + private QName getElementName(Element element) { + String attributeValue = element.getAttribute("name"); + return StringUtils.hasLength(attributeValue) ? new QName(getTargetNamespace(), attributeValue) : null; + } + + public void afterPropertiesSet() throws ParserConfigurationException, IOException, SAXException { + Assert.notNull(xsdResource, "'xsd' is required"); + Assert.isTrue(this.xsdResource.exists(), "xsd '" + this.xsdResource + "' does not exit"); + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + loadSchema(documentBuilder); + } + + private void loadSchema(DocumentBuilder documentBuilder) throws SAXException, IOException { + Document schemaDocument = documentBuilder.parse(SaxUtils.createInputSource(xsdResource)); + schemaElement = schemaDocument.getDocumentElement(); + Assert.isTrue(SCHEMA_NAME.getLocalPart().equals(schemaElement.getLocalName()), + xsdResource + " has invalid root element : [" + schemaElement.getLocalName() + "] instead of [schema]"); + Assert.isTrue(SCHEMA_NAME.getNamespaceURI().equals(schemaElement.getNamespaceURI()), xsdResource + + " has invalid root element: [" + schemaElement.getNamespaceURI() + "] instead of [" + + SCHEMA_NAME.getNamespaceURI() + "]"); + Assert.hasText(getTargetNamespace(), xsdResource + " has no targetNamespace"); + } + + public String toString() { + StringBuffer buffer = new StringBuffer("SimpleXsdSchema"); + buffer.append('{'); + buffer.append(getTargetNamespace()); + buffer.append('}'); + return buffer.toString(); + } + +} \ No newline at end of file diff --git a/xml/src/main/java/org/springframework/xml/xsd/XsdSchema.java b/xml/src/main/java/org/springframework/xml/xsd/XsdSchema.java new file mode 100644 index 00000000..30a8d02a --- /dev/null +++ b/xml/src/main/java/org/springframework/xml/xsd/XsdSchema.java @@ -0,0 +1,52 @@ +/* + * Copyright 2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.xml.xsd; + +import javax.xml.namespace.QName; +import javax.xml.transform.Source; + +/** + * Represents an abstraction for XSD schemas. + * + * @author Mark LaFond + * @author Arjen Poutsma + * @since 1.5.0 + */ +public interface XsdSchema { + + /** + * Returns the target namespace of theis schema. + * + * @return the target namespace + */ + String getTargetNamespace(); + + /** + * Returns the qualified names of all top-level elements declared in the schema. This excludes elements declared as child of + * another element, simplyType, or complexType. + * + * @return the top-level element names + */ + QName[] getElementNames(); + + /** + * Returns the Source of the schema. + * + * @return the Source of this XSD schema + */ + Source getSource(); +} diff --git a/xml/src/main/java/org/springframework/xml/xsd/XsdSchemaException.java b/xml/src/main/java/org/springframework/xml/xsd/XsdSchemaException.java new file mode 100644 index 00000000..af74c2e2 --- /dev/null +++ b/xml/src/main/java/org/springframework/xml/xsd/XsdSchemaException.java @@ -0,0 +1,37 @@ +/* + * Copyright 2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.xml.xsd; + +import org.springframework.xml.XmlException; + +/** + * Base class for all WSDL definition exceptions. + * + * @author Mark LaFond + * @author Arjen Poutsma + * @since 1.5.0 + */ +public class XsdSchemaException extends XmlException { + + public XsdSchemaException(String message) { + super(message); + } + + public XsdSchemaException(String message, Throwable throwable) { + super(message, throwable); + } +} diff --git a/xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchema.java b/xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchema.java new file mode 100644 index 00000000..09e01209 --- /dev/null +++ b/xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchema.java @@ -0,0 +1,192 @@ +/* + * Copyright 2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.xml.xsd.commons; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import javax.xml.namespace.QName; +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; + +import org.apache.ws.commons.schema.XmlSchema; +import org.apache.ws.commons.schema.XmlSchemaCollection; +import org.apache.ws.commons.schema.XmlSchemaInclude; +import org.apache.ws.commons.schema.XmlSchemaObject; +import org.apache.ws.commons.schema.XmlSchemaObjectCollection; +import org.xml.sax.SAXException; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.core.io.Resource; +import org.springframework.util.Assert; +import org.springframework.xml.sax.SaxUtils; +import org.springframework.xml.xsd.InlineableXsdSchema; +import org.springframework.xml.xsd.XsdSchema; + +/** + * Implementation of the {@link XsdSchema} interface that uses Apache WS-Commons XML Schema. + * + * @author Arjen Poutsma + * @see Commons XML Schema + * @since 1.5.0 + */ +public class CommonsXsdSchema implements InlineableXsdSchema, InitializingBean { + + private XmlSchema schema; + + private Resource xsdResource; + + /** + * Create a new, empty instance of the {@link CommonsXsdSchema} class. + *

+ * A subsequent call to the {@link #setXsd(Resource)} method is required. + */ + public CommonsXsdSchema() { + } + + /** + * Create a new instance of the {@link CommonsXsdSchema} class with the specified resource. + * + * @param xsdResource the XSD resource; must not be null + * @throws IllegalArgumentException if the supplied xsdResource is null + */ + public CommonsXsdSchema(Resource xsdResource) { + Assert.notNull(xsdResource, "xsdResource must not be null"); + this.xsdResource = xsdResource; + } + + /** + * Create a new instance of the {@link CommonsXsdSchema} class with the specified {@link XmlSchema} reference. + * + * @param schema the Commons XmlSchema object; must not be null + * @throws IllegalArgumentException if the supplied schema is null + */ + private CommonsXsdSchema(XmlSchema schema) { + Assert.notNull(schema, "'schema' must not be null"); + this.schema = schema; + } + + /** + * Set the XSD resource to be exposed by calls to this instances' {@link #getSource()} method. + * + * @param xsdResource the XSD resource + */ + public void setXsd(Resource xsdResource) { + this.xsdResource = xsdResource; + } + + public String getTargetNamespace() { + return schema.getTargetNamespace(); + } + + public QName[] getElementNames() { + List result = new ArrayList(); + Iterator iterator = schema.getElements().getNames(); + while (iterator.hasNext()) { + QName name = (QName) iterator.next(); + result.add(name); + } + return (QName[]) result.toArray(new QName[result.size()]); + } + + public void merge(XsdSchema o) { + Assert.isInstanceOf(CommonsXsdSchema.class, o); + XmlSchema otherSchema = ((CommonsXsdSchema) o).schema; + Assert.isTrue(this.schema.getTargetNamespace().equals(otherSchema.getTargetNamespace()), + "Schema does not have same namespace"); + XmlSchemaObjectCollection otherItems = otherSchema.getItems(); + for (int i = 0; i < otherItems.getCount(); i++) { + schema.getItems().add(otherItems.getItem(i)); + } + } + + public Source getSource() { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + schema.write(bos); + ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); + return new StreamSource(bis); + } + + /** Returns the wrapped Commons XmlSchema object. */ + public XmlSchema getSchema() { + return schema; + } + + public void afterPropertiesSet() throws IOException, SAXException { + Assert.notNull(xsdResource, "'xsd' is required"); + Assert.isTrue(this.xsdResource.exists(), "xsd '" + this.xsdResource + "' does not exit"); + loadSchema(); + } + + private void loadSchema() throws SAXException, IOException { + XmlSchemaCollection schemaCollection = new XmlSchemaCollection(); + this.schema = schemaCollection.read(SaxUtils.createInputSource(xsdResource), null); + } + + public XsdSchema[] inline() { + XmlSchema clone = cloneSchema(schema); + inlineIncludes(clone, new ArrayList()); + return new XsdSchema[]{new CommonsXsdSchema(clone)}; + } + + private static XmlSchema cloneSchema(XmlSchema schema) { + XmlSchemaCollection schemaCollection = new XmlSchemaCollection(); + XmlSchema clone = new XmlSchema(schemaCollection); + XmlSchemaObjectCollection originalItems = schema.getItems(); + XmlSchemaObjectCollection cloneItems = clone.getItems(); + for (int i = 0; i < originalItems.getCount(); i++) { + cloneItems.add(originalItems.getItem(i)); + } + return clone; + } + + private static void inlineIncludes(XmlSchema schema, List processedSchemas) { + processedSchemas.add(schema); + XmlSchemaObjectCollection includes = schema.getIncludes(); + for (int i = 0; i < includes.getCount(); i++) { + if (includes.getItem(i) instanceof XmlSchemaInclude) { + XmlSchemaInclude include = (XmlSchemaInclude) includes.getItem(i); + XmlSchema includedSchema = include.getSchema(); + XmlSchemaObjectCollection items = schema.getItems(); + if (!processedSchemas.contains(includedSchema)) { + inlineIncludes(includedSchema, processedSchemas); + XmlSchemaObjectCollection includesItems = includedSchema.getItems(); + for (int j = 0; j < includesItems.getCount(); j++) { + XmlSchemaObject includedItem = includesItems.getItem(j); + items.add(includedItem); + } + } + // remove the + items.remove(include); + } + } + } + + public String toString() { + StringBuffer buffer = new StringBuffer("CommonsXsdSchema"); + buffer.append('{'); + buffer.append(getTargetNamespace()); + buffer.append('}'); + return buffer.toString(); + } + +} diff --git a/xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaException.java b/xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaException.java new file mode 100644 index 00000000..dcf6797c --- /dev/null +++ b/xml/src/main/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaException.java @@ -0,0 +1,38 @@ +/* + * Copyright 2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.xml.xsd.commons; + +import org.apache.ws.commons.schema.XmlSchemaException; + +import org.springframework.xml.xsd.XsdSchemaException; + +/** + * Commons XmlSchema version of the {@link XsdSchemaException}. + * + * @author Arjen Poutsma + * @since 1.5.0 + */ +public class CommonsXsdSchemaException extends XsdSchemaException { + + public CommonsXsdSchemaException(String message) { + super(message); + } + + public CommonsXsdSchemaException(String message, XmlSchemaException exception) { + super(message, exception); + } +} diff --git a/xml/src/main/java/org/springframework/xml/xsd/commons/package.html b/xml/src/main/java/org/springframework/xml/xsd/commons/package.html new file mode 100644 index 00000000..55ffa82d --- /dev/null +++ b/xml/src/main/java/org/springframework/xml/xsd/commons/package.html @@ -0,0 +1,5 @@ + + +Contains a implementation of the XsdSchema interfaces that uses Apache WS-Commons XML Schema. + + diff --git a/xml/src/main/java/org/springframework/xml/xsd/package.html b/xml/src/main/java/org/springframework/xml/xsd/package.html new file mode 100644 index 00000000..7f65b3a7 --- /dev/null +++ b/xml/src/main/java/org/springframework/xml/xsd/package.html @@ -0,0 +1,5 @@ + + +Provides an abstraction over XSD XML schemas. Contains the XsdSchema and related interfaces. + + diff --git a/xml/src/test/java/org/springframework/xml/xsd/SimpleXsdSchemaTest.java b/xml/src/test/java/org/springframework/xml/xsd/SimpleXsdSchemaTest.java new file mode 100644 index 00000000..26e24e8c --- /dev/null +++ b/xml/src/test/java/org/springframework/xml/xsd/SimpleXsdSchemaTest.java @@ -0,0 +1,29 @@ +/* + * Copyright ${YEAR} the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.xml.xsd; + +import org.springframework.core.io.Resource; + +public class SimpleXsdSchemaTest extends AbstractXsdSchemaTestCase { + + protected XsdSchema createSchema(Resource resource) throws Exception { + SimpleXsdSchema schema = new SimpleXsdSchema(resource); + schema.afterPropertiesSet(); + return schema; + } + +} \ No newline at end of file diff --git a/xml/src/test/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaTest.java b/xml/src/test/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaTest.java new file mode 100644 index 00000000..52d47832 --- /dev/null +++ b/xml/src/test/java/org/springframework/xml/xsd/commons/CommonsXsdSchemaTest.java @@ -0,0 +1,63 @@ +/* + * Copyright ${YEAR} the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.xml.xsd.commons; + +import javax.xml.transform.stream.StreamSource; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.Source; + +import org.apache.ws.commons.schema.XmlSchema; +import org.apache.ws.commons.schema.XmlSchemaCollection; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +import org.springframework.core.io.Resource; +import org.springframework.core.io.ClassPathResource; +import org.springframework.xml.xsd.AbstractXsdSchemaTestCase; +import org.springframework.xml.xsd.XsdSchema; +import org.springframework.xml.transform.ResourceSource; + +public class CommonsXsdSchemaTest extends AbstractXsdSchemaTestCase { + + protected XsdSchema createSchema(Resource resource) throws Exception { + CommonsXsdSchema schema = new CommonsXsdSchema(resource); + schema.afterPropertiesSet(); + return schema; + } + + public void testInline() throws Exception { + Resource resource = new ClassPathResource("A.xsd", AbstractXsdSchemaTestCase.class); + CommonsXsdSchema schema = new CommonsXsdSchema(resource); + schema.afterPropertiesSet(); + XsdSchema[] inlined = schema.inline(); + for (int i = 0; i < inlined.length; i++) { + transformer.transform(inlined[i].getSource(), new StreamResult(System.out)); + System.out.println(); + } + } + + public void testCircular() throws Exception { + Resource resource = new ClassPathResource("circular-1.xsd", AbstractXsdSchemaTestCase.class); + CommonsXsdSchema schema = new CommonsXsdSchema(resource); + schema.afterPropertiesSet(); + XsdSchema[] inlined = schema.inline(); + for (int i = 0; i < inlined.length; i++) { + transformer.transform(inlined[i].getSource(), new StreamResult(System.out)); + System.out.println(); + } + } +} \ No newline at end of file diff --git a/xml/src/test/resources/org/springframework/xml/xsd/A.xsd b/xml/src/test/resources/org/springframework/xml/xsd/A.xsd new file mode 100644 index 00000000..dd680b01 --- /dev/null +++ b/xml/src/test/resources/org/springframework/xml/xsd/A.xsd @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/xml/src/test/resources/org/springframework/xml/xsd/AbstractXsdSchemaTestCase.java b/xml/src/test/resources/org/springframework/xml/xsd/AbstractXsdSchemaTestCase.java new file mode 100644 index 00000000..dacc087d --- /dev/null +++ b/xml/src/test/resources/org/springframework/xml/xsd/AbstractXsdSchemaTestCase.java @@ -0,0 +1,105 @@ +/* + * Copyright 2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.xml.xsd; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMResult; + +import org.custommonkey.xmlunit.XMLTestCase; +import org.custommonkey.xmlunit.XMLUnit; +import org.w3c.dom.Document; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.xml.sax.SaxUtils; + +public abstract class AbstractXsdSchemaTestCase extends XMLTestCase { + + private DocumentBuilder documentBuilder; + + protected Transformer transformer; + + protected final void setUp() throws Exception { + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setNamespaceAware(true); + documentBuilder = documentBuilderFactory.newDocumentBuilder(); + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + transformer = transformerFactory.newTransformer(); + XMLUnit.setIgnoreWhitespace(true); + } + + public void testSingle() throws Exception { + Resource resource = new ClassPathResource("single.xsd", AbstractXsdSchemaTestCase.class); + XsdSchema single = createSchema(resource); + String namespace = "http://www.springframework.org/spring-ws/single/schema"; + assertEquals("Invalid target namespace", namespace, single.getTargetNamespace()); + QName[] elementNames = single.getElementNames(); + assertQNamesEqual(new QName[]{new QName(namespace, "GetOrderRequest"), new QName(namespace, "GetOrderResponse"), + new QName(namespace, "GetOrderFault")}, elementNames); + resource = new ClassPathResource("single.xsd", AbstractXsdSchemaTestCase.class); + Document expected = documentBuilder.parse(SaxUtils.createInputSource(resource)); + DOMResult domResult = new DOMResult(); + transformer.transform(single.getSource(), domResult); + Document result = (Document) domResult.getNode(); + assertXMLEqual("Invalid Source returned", expected, result); + } + + public void testIncludes() throws Exception { + Resource resource = new ClassPathResource("including.xsd", AbstractXsdSchemaTestCase.class); + XsdSchema including = createSchema(resource); + String namespace = "http://www.springframework.org/spring-ws/include/schema"; + assertEquals("Invalid target namespace", namespace, including.getTargetNamespace()); + QName[] elementNames = including.getElementNames(); + assertQNamesEqual(new QName[]{new QName(namespace, "GetOrderRequest")}, elementNames); + resource = new ClassPathResource("including.xsd", AbstractXsdSchemaTestCase.class); + Document expected = documentBuilder.parse(SaxUtils.createInputSource(resource)); + DOMResult domResult = new DOMResult(); + transformer.transform(including.getSource(), domResult); + Document result = (Document) domResult.getNode(); + assertXMLEqual("Invalid Source returned", expected, result); + } + + public void testImports() throws Exception { + Resource resource = new ClassPathResource("importing.xsd", AbstractXsdSchemaTestCase.class); + XsdSchema importing = createSchema(resource); + String namespace = "http://www.springframework.org/spring-ws/importing/schema"; + assertEquals("Invalid target namespace", namespace, importing.getTargetNamespace()); + QName[] elementNames = importing.getElementNames(); + assertQNamesEqual(new QName[]{new QName(namespace, "GetOrderRequest")}, elementNames); + resource = new ClassPathResource("importing.xsd", AbstractXsdSchemaTestCase.class); + Document expected = documentBuilder.parse(SaxUtils.createInputSource(resource)); + DOMResult domResult = new DOMResult(); + transformer.transform(importing.getSource(), domResult); + Document result = (Document) domResult.getNode(); + assertXMLEqual("Invalid Source returned", expected, result); + } + + private void assertQNamesEqual(QName[] expected, QName[] result) { + Set expectedSet = new HashSet(Arrays.asList(expected)); + Set resultSet = new HashSet(Arrays.asList(result)); + assertEquals("Invalid QNames", expectedSet, resultSet); + } + + protected abstract XsdSchema createSchema(Resource resource) throws Exception; +} diff --git a/xml/src/test/resources/org/springframework/xml/xsd/B.xsd b/xml/src/test/resources/org/springframework/xml/xsd/B.xsd new file mode 100644 index 00000000..cb797af5 --- /dev/null +++ b/xml/src/test/resources/org/springframework/xml/xsd/B.xsd @@ -0,0 +1,14 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/xml/src/test/resources/org/springframework/xml/xsd/C.xsd b/xml/src/test/resources/org/springframework/xml/xsd/C.xsd new file mode 100644 index 00000000..932c8dcc --- /dev/null +++ b/xml/src/test/resources/org/springframework/xml/xsd/C.xsd @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/xml/src/test/resources/org/springframework/xml/xsd/D.xsd b/xml/src/test/resources/org/springframework/xml/xsd/D.xsd new file mode 100644 index 00000000..0f15daf5 --- /dev/null +++ b/xml/src/test/resources/org/springframework/xml/xsd/D.xsd @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/xml/src/test/resources/org/springframework/xml/xsd/circular-1.xsd b/xml/src/test/resources/org/springframework/xml/xsd/circular-1.xsd new file mode 100644 index 00000000..673bce49 --- /dev/null +++ b/xml/src/test/resources/org/springframework/xml/xsd/circular-1.xsd @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/xml/src/test/resources/org/springframework/xml/xsd/circular-2.xsd b/xml/src/test/resources/org/springframework/xml/xsd/circular-2.xsd new file mode 100644 index 00000000..00015897 --- /dev/null +++ b/xml/src/test/resources/org/springframework/xml/xsd/circular-2.xsd @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/xml/src/test/resources/org/springframework/xml/xsd/circular-3.xsd b/xml/src/test/resources/org/springframework/xml/xsd/circular-3.xsd new file mode 100644 index 00000000..df7a3991 --- /dev/null +++ b/xml/src/test/resources/org/springframework/xml/xsd/circular-3.xsd @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/xml/src/test/resources/org/springframework/xml/xsd/imported.xsd b/xml/src/test/resources/org/springframework/xml/xsd/imported.xsd new file mode 100644 index 00000000..22dcb834 --- /dev/null +++ b/xml/src/test/resources/org/springframework/xml/xsd/imported.xsd @@ -0,0 +1,15 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/xml/src/test/resources/org/springframework/xml/xsd/importing.xsd b/xml/src/test/resources/org/springframework/xml/xsd/importing.xsd new file mode 100644 index 00000000..421f6aa7 --- /dev/null +++ b/xml/src/test/resources/org/springframework/xml/xsd/importing.xsd @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xml/src/test/resources/org/springframework/xml/xsd/included.xsd b/xml/src/test/resources/org/springframework/xml/xsd/included.xsd new file mode 100644 index 00000000..fc508ca7 --- /dev/null +++ b/xml/src/test/resources/org/springframework/xml/xsd/included.xsd @@ -0,0 +1,15 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/xml/src/test/resources/org/springframework/xml/xsd/including.xsd b/xml/src/test/resources/org/springframework/xml/xsd/including.xsd new file mode 100644 index 00000000..78dd1daf --- /dev/null +++ b/xml/src/test/resources/org/springframework/xml/xsd/including.xsd @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xml/src/test/resources/org/springframework/xml/xsd/single.xsd b/xml/src/test/resources/org/springframework/xml/xsd/single.xsd new file mode 100644 index 00000000..df338465 --- /dev/null +++ b/xml/src/test/resources/org/springframework/xml/xsd/single.xsd @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file