Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (C) 2026 Evolveum and contributors
*
* Licensed under the EUPL-1.2 or later.
*/

package com.evolveum.midpoint.prism.impl.schema;

/**
* Namespaces that can appear in generated schema annotations/customizations, but should NOT be emitted as XSD imports.
*/
enum NonImportableSchemaNamespace {

JAKARTA_JAXB("https://jakarta.ee/xml/ns/jaxb"),
LEGACY_JAXB("http://java.sun.com/xml/ns/jaxb");

private final String namespace;

NonImportableSchemaNamespace(String namespace) {
this.namespace = namespace;
}

/**
* Returns true if the namespace should be emitted as an XSD import.
*/
static boolean isImportable(String namespace) {
return !JAKARTA_JAXB.namespace.equals(namespace)
&& !LEGACY_JAXB.namespace.equals(namespace);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -588,11 +588,15 @@ private void setQNameAttribute(Element element, String attrName, QName value) {
}

/**
* Make sure that the namespace will be added to import definitions.
* Makes sure that the namespace will be added to import definitions,
* unless it is a known annotation/customization namespace that should NOT be imported as XSD.
*
* @param namespace namespace to import
*/
private void addToImports(String namespace) {
importNamespaces.add(namespace);
if (NonImportableSchemaNamespace.isImportable(namespace)) {
importNamespaces.add(namespace);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package com.evolveum.midpoint.prism;

import static com.evolveum.midpoint.prism.schema.PrismSchemaBuildingUtil.addNewComplexTypeDefinition;

import static org.testng.AssertJUnit.*;

import static com.evolveum.midpoint.prism.PrismInternalTestUtil.DEFAULT_NAMESPACE_PREFIX;
Expand All @@ -15,17 +16,21 @@
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;

import com.evolveum.midpoint.prism.ComplexTypeDefinition.ComplexTypeDefinitionMutator;
import com.evolveum.midpoint.prism.PrismPropertyDefinition.PrismPropertyDefinitionMutator;
import com.evolveum.midpoint.prism.impl.EnumerationTypeDefinitionImpl;
import com.evolveum.midpoint.prism.impl.schema.SchemaParsingUtil;
import com.evolveum.midpoint.prism.schema.PrismSchemaBuildingUtil;

import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.evolveum.midpoint.prism.impl.schema.PrismSchemaImpl;
Expand All @@ -50,6 +55,11 @@ public class TestPrismSchemaConstruction extends AbstractPrismTest {
private static final int SCHEMA_ROUNDTRIP_LOOP_ATTEMPTS = 10;
private static final String WEAPON_PASSWORD_LOCAL_NAME = "password";
private static final String WEAPON_BLADE_LOCAL_NAME = "blade";
private static final String WEAPON_RARITY_TYPE_LOCAL_NAME = "WeaponRarityType";
private static final String WEAPON_RARITY_LOCAL_NAME = "rarity";
private static final String JAKARTA_JAXB_NAMESPACE = "https://jakarta.ee/xml/ns/jaxb";
private static final String JAXB_TYPESAFE_ENUM_CLASS = "typesafeEnumClass";
private static final String JAXB_TYPESAFE_ENUM_MEMBER = "typesafeEnumMember";

@BeforeSuite
public void setupDebug() {
Expand Down Expand Up @@ -96,6 +106,26 @@ public void testSchemaRoundtripLoopNewContext() throws Exception {
}
}

/** Verifies that enum JAXB customizations do not produce a resolvable XSD import. MID-10558 */
@Test
public void testSchemaWithEnumerationDoesNotImportJaxbNamespace() throws Exception {
constructInitializedPrismContext();
PrismSchema schema = constructSchemaWithEnumeration();

Document xsdDocument = schema.serializeToXsd();
Element xsdElement = DOMUtil.getFirstChildElement(xsdDocument);

assertNoImport(xsdElement, JAKARTA_JAXB_NAMESPACE);
assertElementPresent(xsdElement, JAKARTA_JAXB_NAMESPACE, JAXB_TYPESAFE_ENUM_CLASS);
assertElementPresent(xsdElement, JAKARTA_JAXB_NAMESPACE, JAXB_TYPESAFE_ENUM_MEMBER);

PrismSchema reparsedSchema = SchemaParsingUtil.createAndParse(xsdElement, true, "serialized enumeration schema");
EnumerationTypeDefinition rarityDefinition = reparsedSchema.findTypeDefinitionByType(
new QName(NS_MY_SCHEMA, WEAPON_RARITY_TYPE_LOCAL_NAME), EnumerationTypeDefinition.class);
assertNotNull("No re-parsed enumeration definition", rarityDefinition);
assertEquals("Unexpected number of enum values", 3, rarityDefinition.getValues().size());
}

private void schemaRoundtrip() throws SchemaException {
PrismSchema schema = constructSchema();
assertSchema(schema);
Expand Down Expand Up @@ -137,6 +167,23 @@ private PrismSchema constructSchema() {
return schema;
}

private PrismSchema constructSchemaWithEnumeration() {
PrismSchemaImpl schema = new PrismSchemaImpl(NS_MY_SCHEMA);

var enumTypeName = new QName(NS_MY_SCHEMA, WEAPON_RARITY_TYPE_LOCAL_NAME);
schema.mutator().add(new EnumerationTypeDefinitionImpl(
enumTypeName,
DOMUtil.XSD_STRING,
List.of(
new EnumerationTypeDefinitionImpl.ValueDefinitionImpl("common", null, "COMMON"),
new EnumerationTypeDefinitionImpl.ValueDefinitionImpl("rare", null, "RARE"),
new EnumerationTypeDefinitionImpl.ValueDefinitionImpl("legendary", null, "LEGENDARY"))));

PrismSchemaBuildingUtil.addNewPropertyDefinition(schema, WEAPON_RARITY_LOCAL_NAME, enumTypeName);

return schema;
}

private void assertSchema(PrismSchema schema) {
assertNotNull("Schema is null", schema);
assertEquals("Wrong schema namespace", NS_MY_SCHEMA, schema.getNamespace());
Expand Down Expand Up @@ -179,4 +226,19 @@ private void assertPrefix(String expectedPrefix, Element element) {
assertEquals("Wrong prefix on element " + DOMUtil.getQName(element), expectedPrefix, element.getPrefix());
}

private void assertNoImport(Element xsdElement, String namespace) {
NodeList imports = xsdElement.getElementsByTagNameNS(XMLConstants.W3C_XML_SCHEMA_NS_URI, "import");
for (int i = 0; i < imports.getLength(); i++) {
Element importElement = (Element) imports.item(i);
assertFalse(
"Unexpected import for " + namespace,
namespace.equals(importElement.getAttribute("namespace")));
}
}

private void assertElementPresent(Element xsdElement, String namespace, String localName) {
NodeList elements = xsdElement.getElementsByTagNameNS(namespace, localName);
assertTrue("No element {" + namespace + "}" + localName, elements.getLength() > 0);
}

}