This is an automated email from the ASF dual-hosted git repository. coheigea pushed a commit to branch coheigea/notation in repository https://gitbox.apache.org/repos/asf/ws-xmlschema.git
commit 24d7414265b81e22857e6354d640e4a832f411ad Author: Colm O hEigeartaigh <[email protected]> AuthorDate: Thu Sep 17 10:09:47 2026 +0100 Serialize notation as well and fix some NPEs --- .../ws/commons/schema/XmlSchemaCollection.java | 3 + .../ws/commons/schema/XmlSchemaSerializer.java | 41 ++++++++ .../src/test/java/tests/NotationRoundTripTest.java | 105 +++++++++++++++++++++ 3 files changed, 149 insertions(+) diff --git a/xmlschema-core/src/main/java/org/apache/ws/commons/schema/XmlSchemaCollection.java b/xmlschema-core/src/main/java/org/apache/ws/commons/schema/XmlSchemaCollection.java index 97df7772..7c78389f 100644 --- a/xmlschema-core/src/main/java/org/apache/ws/commons/schema/XmlSchemaCollection.java +++ b/xmlschema-core/src/main/java/org/apache/ws/commons/schema/XmlSchemaCollection.java @@ -294,6 +294,9 @@ public final class XmlSchemaCollection { * @return the type object, or null. */ public XmlSchemaType getTypeByQName(QName schemaTypeName) { + if (schemaTypeName == null) { + return null; + } String uri = schemaTypeName.getNamespaceURI(); for (Map.Entry<SchemaKey, XmlSchema> entry : schemas.entrySet()) { if (entry.getKey().getNamespace().equals(uri)) { diff --git a/xmlschema-core/src/main/java/org/apache/ws/commons/schema/XmlSchemaSerializer.java b/xmlschema-core/src/main/java/org/apache/ws/commons/schema/XmlSchemaSerializer.java index 26be3e2c..76f60f6b 100644 --- a/xmlschema-core/src/main/java/org/apache/ws/commons/schema/XmlSchemaSerializer.java +++ b/xmlschema-core/src/main/java/org/apache/ws/commons/schema/XmlSchemaSerializer.java @@ -510,6 +510,44 @@ public class XmlSchemaSerializer { * Return: Element of attribute group. * ********************************************************************** */ + /** + * Serializes an xs:notation declaration. + * + * @param doc the parent document. + * @param notationObj the notation to serialize. + * @param schema the owning schema. + * @return the notation element. + * @throws XmlSchemaSerializerException if the notation has no name. + */ + Element serializeNotation(Document doc, XmlSchemaNotation notationObj, XmlSchema schema) + throws XmlSchemaSerializerException { + + Element notation = createNewElement(doc, "notation", schema.getSchemaNamespacePrefix(), + XmlSchema.SCHEMA_NS); + + if (notationObj.isAnonymous()) { + throw new XmlSchemaSerializerException("Notation must have name"); + } + notation.setAttributeNS(null, "name", notationObj.getName()); + + if (notationObj.getId() != null) { + notation.setAttributeNS(null, "id", notationObj.getId()); + } + if (notationObj.getPublic() != null) { + notation.setAttributeNS(null, "public", notationObj.getPublic()); + } + if (notationObj.getSystem() != null) { + notation.setAttributeNS(null, "system", notationObj.getSystem()); + } + if (notationObj.getAnnotation() != null) { + notation.appendChild(serializeAnnotation(doc, notationObj.getAnnotation(), schema)); + } + + processExtensibilityComponents(notationObj, notation); + + return notation; + } + Element serializeAttributeGroup(Document doc, XmlSchemaAttributeGroup attributeGroupObj, XmlSchema schema) throws XmlSchemaSerializerException { @@ -2453,6 +2491,9 @@ public class XmlSchemaSerializer { } else if (obj instanceof XmlSchemaRedefine) { Element e = serializeRedefine(serializedSchemaDocs, (XmlSchemaRedefine)obj, schemaObj); serializedSchema.appendChild(e); + } else if (obj instanceof XmlSchemaNotation) { + Element e = serializeNotation(serializedSchemaDocs, (XmlSchemaNotation)obj, schemaObj); + serializedSchema.appendChild(e); } } } diff --git a/xmlschema-core/src/test/java/tests/NotationRoundTripTest.java b/xmlschema-core/src/test/java/tests/NotationRoundTripTest.java new file mode 100644 index 00000000..aa16dca0 --- /dev/null +++ b/xmlschema-core/src/test/java/tests/NotationRoundTripTest.java @@ -0,0 +1,105 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 tests; + +import java.io.StringReader; +import java.io.StringWriter; + +import javax.xml.namespace.QName; + +import org.apache.ws.commons.schema.XmlSchema; +import org.apache.ws.commons.schema.XmlSchemaCollection; +import org.apache.ws.commons.schema.XmlSchemaNotation; + +import org.junit.Assert; +import org.junit.Test; + +/** + * read() builds an xs:notation into the model, so write() has to put it back. + */ +public class NotationRoundTripTest extends Assert { + + private static final String SCHEMA = + "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" targetNamespace=\"urn:n\">" + + "<xs:notation name=\"jpeg\" public=\"image/jpeg\" system=\"viewer.exe\">" + + "<xs:annotation><xs:documentation>a picture</xs:documentation></xs:annotation>" + + "</xs:notation>" + + "<xs:element name=\"e\" type=\"xs:string\"/>" + + "</xs:schema>"; + + private static XmlSchema read(String text) { + return new XmlSchemaCollection().read(new StringReader(text)); + } + + @Test + public void testNotationSurvivesARoundTrip() throws Exception { + XmlSchema before = read(SCHEMA); + assertEquals(1, before.getNotations().size()); + + StringWriter writer = new StringWriter(); + before.write(writer); + + XmlSchema after = read(writer.toString()); + assertEquals("the notation must not be dropped by write()", + before.getNotations().size(), after.getNotations().size()); + + XmlSchemaNotation notation = + after.getNotationByName(new QName("urn:n", "jpeg")); + assertNotNull(notation); + assertEquals("image/jpeg", notation.getPublic()); + assertEquals("viewer.exe", notation.getSystem()); + assertNotNull("the notation's annotation must survive too", notation.getAnnotation()); + } + + @Test + public void testOtherTopLevelComponentsStillSurvive() throws Exception { + XmlSchema before = read( + "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" targetNamespace=\"urn:n\">" + + "<xs:element name=\"el\" type=\"xs:string\"/>" + + "<xs:attribute name=\"at\" type=\"xs:string\"/>" + + "<xs:complexType name=\"ct\"><xs:sequence/></xs:complexType>" + + "<xs:group name=\"g\"><xs:sequence>" + + "<xs:element name=\"x\" type=\"xs:string\"/></xs:sequence></xs:group>" + + "<xs:attributeGroup name=\"ag\">" + + "<xs:attribute name=\"y\" type=\"xs:string\"/></xs:attributeGroup>" + + "<xs:notation name=\"n\" public=\"urn:p\"/>" + + "</xs:schema>"); + + StringWriter writer = new StringWriter(); + before.write(writer); + XmlSchema after = read(writer.toString()); + + assertEquals(before.getElements().size(), after.getElements().size()); + assertEquals(before.getAttributes().size(), after.getAttributes().size()); + assertEquals(before.getSchemaTypes().size(), after.getSchemaTypes().size()); + assertEquals(before.getGroups().size(), after.getGroups().size()); + assertEquals(before.getAttributeGroups().size(), after.getAttributeGroups().size()); + assertEquals(before.getNotations().size(), after.getNotations().size()); + } + + /** getTypeByQName was the only QName lookup that threw on null. */ + @Test + public void testQNameLookupsTolerateNull() { + XmlSchemaCollection collection = new XmlSchemaCollection(); + assertNull(collection.getTypeByQName(null)); + assertNull(collection.getElementByQName(null)); + assertNull(collection.getAttributeByQName(null)); + } +}
