Created
May 20, 2025 02:51
-
-
Save aaronanderson/5e3e67fb321109769c528fe5c3b6cfe5 to your computer and use it in GitHub Desktop.
Use CXF WSDL and Apache XML Schema tools (cxf-rt-wsdl) to parse WSDL port type operation input and output XML schema types for annotations
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.acme.objects.processor; | |
import java.io.InputStream; | |
import java.io.Writer; | |
import java.nio.file.Files; | |
import java.nio.file.Path; | |
import java.nio.file.Paths; | |
import java.nio.file.StandardOpenOption; | |
import java.util.Collections; | |
import java.util.HashMap; | |
import java.util.HashSet; | |
import java.util.LinkedList; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Set; | |
import javax.wsdl.Definition; | |
import javax.wsdl.Input; | |
import javax.wsdl.Message; | |
import javax.wsdl.Operation; | |
import javax.wsdl.Part; | |
import javax.wsdl.PortType; | |
import javax.wsdl.Types; | |
import javax.wsdl.factory.WSDLFactory; | |
import javax.wsdl.xml.WSDLReader; | |
import javax.xml.namespace.QName; | |
import org.apache.cxf.BusFactory; | |
import org.apache.cxf.common.xmlschema.SchemaCollection; | |
import org.apache.cxf.service.model.SchemaInfo; | |
import org.apache.cxf.wsdl11.SchemaUtil; | |
import org.apache.ws.commons.schema.XmlSchemaAnnotation; | |
import org.apache.ws.commons.schema.XmlSchemaAnnotationItem; | |
import org.apache.ws.commons.schema.XmlSchemaAny; | |
import org.apache.ws.commons.schema.XmlSchemaAppInfo; | |
import org.apache.ws.commons.schema.XmlSchemaAttribute; | |
import org.apache.ws.commons.schema.XmlSchemaAttributeOrGroupRef; | |
import org.apache.ws.commons.schema.XmlSchemaChoice; | |
import org.apache.ws.commons.schema.XmlSchemaChoiceMember; | |
import org.apache.ws.commons.schema.XmlSchemaComplexContent; | |
import org.apache.ws.commons.schema.XmlSchemaComplexType; | |
import org.apache.ws.commons.schema.XmlSchemaDocumentation; | |
import org.apache.ws.commons.schema.XmlSchemaElement; | |
import org.apache.ws.commons.schema.XmlSchemaSequence; | |
import org.apache.ws.commons.schema.XmlSchemaSequenceMember; | |
import org.apache.ws.commons.schema.XmlSchemaSimpleContent; | |
import org.apache.ws.commons.schema.XmlSchemaSimpleContentExtension; | |
import org.apache.ws.commons.schema.XmlSchemaSimpleType; | |
import org.apache.ws.commons.schema.XmlSchemaType; | |
import org.apache.ws.commons.schema.utils.XmlSchemaObjectBase; | |
import org.jboss.logging.Logger; | |
import org.w3c.dom.Element; | |
import org.w3c.dom.Node; | |
import org.w3c.dom.NodeList; | |
import org.w3c.dom.ls.DOMImplementationLS; | |
import org.w3c.dom.ls.LSSerializer; | |
import org.xml.sax.InputSource; | |
public class Generator { | |
private static final Logger LOGGER = Logger.getLogger(Generator.class); | |
public static void main(String[] args) { | |
try { | |
processWSDL("META-INF/wsdl/my.wsdl"); | |
} catch (Exception e) { | |
LOGGER.error("Generator error", e); | |
} | |
} | |
public static void processWSDL(String wsdl) { | |
try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(wsdl);) { | |
WSDLFactory factory = WSDLFactory.newInstance(); | |
WSDLReader reader = factory.newWSDLReader(); | |
// pass the URL to the reader for parsing and get back a WSDL definiton | |
Definition definition = reader.readWSDL(null, new InputSource(is)); | |
SchemaUtil schemaUtil = new SchemaUtil(BusFactory.getThreadDefaultBus(), new HashMap<String, Element>()); | |
SchemaCollection schemaCol = new SchemaCollection(); | |
List<SchemaInfo> schemaInfos = new LinkedList<>(); | |
schemaUtil.getSchemas(definition, schemaCol, schemaInfos); | |
Map<QName, PortType> portTypes = definition.getPortTypes(); | |
PortType portType = portTypes.values().iterator().next(); | |
for (Operation op : (List<Operation>) portType.getOperations()) { | |
String name = op.getName(); | |
Input input = op.getInput(); | |
Message message = input.getMessage(); | |
Part part = message.getPart("body"); | |
QName elementName = part.getElementName(); | |
XmlSchemaElement requestElement = schemaCol.getElementByQName(elementName); | |
RequestSchemaTypeVisitor requestVisitor = new RequestSchemaTypeVisitor(); | |
visitXmlSchemaObjects(requestElement, requestVisitor, new HashSet<>(), schemaCol); | |
System.out.format("Extract Op Name: %s %s %s %s %s\n", name, requestElement.getQName(), requestVisitor.supportsReferences, requestVisitor.objectType, requestVisitor.idTypes); | |
} | |
} catch (Exception e) { | |
LOGGER.error("WSDL error", e); | |
} | |
} | |
private static void visitXmlSchemaObjects(XmlSchemaObjectBase schemaObject, SchemaTypeVisitor visitor, Set<QName> visited, SchemaCollection schemaCol) { | |
if (schemaObject instanceof XmlSchemaComplexType) { | |
XmlSchemaComplexType complexType = (XmlSchemaComplexType) schemaObject; | |
//printAnnotation(complexType.getAnnotation()); | |
if (complexType.getParticle() != null) { | |
visitXmlSchemaObjects(complexType.getParticle(), visitor, visited, schemaCol); | |
} else if (complexType.getContentModel() instanceof XmlSchemaSimpleContent) { | |
XmlSchemaSimpleContent simpleContent = (XmlSchemaSimpleContent) complexType.getContentModel(); | |
if (simpleContent.getContent() instanceof XmlSchemaSimpleContentExtension) { | |
XmlSchemaSimpleContentExtension simpleExtension = (XmlSchemaSimpleContentExtension) simpleContent.getContent(); | |
for (XmlSchemaAttributeOrGroupRef attOrGroup : simpleExtension.getAttributes()) { | |
if (attOrGroup instanceof XmlSchemaAttribute) { | |
XmlSchemaAttribute attr = (XmlSchemaAttribute) attOrGroup; | |
XmlSchemaType attrSchemaType = attr.getSchemaType(); | |
if (attrSchemaType == null) { | |
attrSchemaType = schemaCol.getTypeByQName(attr.getSchemaTypeName()); | |
} | |
if (attrSchemaType instanceof XmlSchemaSimpleType) { | |
XmlSchemaSimpleType simpleAttrType = (XmlSchemaSimpleType) attrSchemaType; | |
if (!visited.contains(simpleAttrType.getQName())) { | |
visitor.visit(simpleAttrType); | |
visited.add(simpleAttrType.getQName()); | |
} | |
} | |
} | |
} | |
} else { | |
System.err.format("Unhandled simple content %s\n", simpleContent); | |
} | |
} else if (complexType.getContentModel() instanceof XmlSchemaComplexContent) { | |
XmlSchemaComplexContent complextContent = (XmlSchemaComplexContent) complexType.getContentModel(); | |
complextContent.getContent(); | |
} else if (complexType.getContentModel() != null) { | |
System.err.format("Unhandled complex type %s\n", complexType.getQName()); | |
} | |
} else if (schemaObject instanceof XmlSchemaAny) { | |
//System.out.println("Any Schema Type"); | |
} else if (schemaObject instanceof XmlSchemaElement) { | |
XmlSchemaElement element = (XmlSchemaElement) schemaObject; | |
//System.out.println("Element Schema Type " + element.getQName() + " - " + element.getSchemaType().getQName()); | |
boolean endElement = false; | |
if (!visited.contains(element.getQName())) { | |
visitor.visitStart(element); | |
visited.add(element.getQName()); | |
endElement = true; | |
} | |
if (element.getSchemaType() instanceof XmlSchemaComplexType) { | |
XmlSchemaComplexType complexType = (XmlSchemaComplexType) element.getSchemaType(); | |
if (!visited.contains(complexType.getQName())) { | |
visitor.visitStart(complexType); | |
visitXmlSchemaObjects(element.getSchemaType(), visitor, visited, schemaCol); | |
visitor.visitEnd(complexType); | |
visited.add(complexType.getQName()); | |
} | |
} | |
if (endElement) { | |
visitor.visitEnd(element); | |
} | |
} else if (schemaObject instanceof XmlSchemaSequence) { | |
//System.out.println("Sequence Schema Type"); | |
final XmlSchemaSequence xmlSchemaSequence = (XmlSchemaSequence) schemaObject; | |
final List<XmlSchemaSequenceMember> items = xmlSchemaSequence.getItems(); | |
items.forEach((item) -> { | |
visitXmlSchemaObjects(item, visitor, visited, schemaCol); | |
}); | |
} else if (schemaObject instanceof XmlSchemaChoice) { | |
//System.out.println("Choice Schema Type"); | |
final XmlSchemaChoice xmlSchemaChoice = (XmlSchemaChoice) schemaObject; | |
final List<XmlSchemaChoiceMember> items = xmlSchemaChoice.getItems(); | |
items.forEach((item) -> { | |
visitXmlSchemaObjects(item, visitor, visited, schemaCol); | |
}); | |
} else if (schemaObject instanceof XmlSchemaSimpleType) { | |
XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType) schemaObject; | |
//System.out.println("Simple Type " + simpleType.getQName()); | |
} else { | |
System.out.println("Unsupported Sequence Schema Type " + schemaObject.getClass()); | |
} | |
} | |
private static void printAnnotation(XmlSchemaAnnotation annotation) { | |
if (annotation != null) { | |
annotation.getItems().forEach(item -> { | |
if (item instanceof XmlSchemaAppInfo) { | |
XmlSchemaAppInfo appInfo = (XmlSchemaAppInfo) item; | |
System.out.format("\t app info %s\n", toString(appInfo.getMarkup())); | |
} else if (item instanceof XmlSchemaDocumentation) { | |
XmlSchemaDocumentation doc = (XmlSchemaDocumentation) item; | |
System.out.format("\t documentation %s\n", toString(doc.getMarkup())); | |
} | |
}); | |
} | |
} | |
public static String toString(NodeList nodeList) { | |
StringBuilder sb = new StringBuilder(); | |
for (int i = 0; i < nodeList.getLength(); i++) { | |
Node node = nodeList.item(i); | |
DOMImplementationLS lsImpl = (DOMImplementationLS) node.getOwnerDocument().getImplementation().getFeature("LS", "3.0"); | |
LSSerializer serializer = lsImpl.createLSSerializer(); | |
serializer.getDomConfig().setParameter("xml-declaration", false); //by default its true, so set it to false to get String without xml-declaration | |
String str = serializer.writeToString(node); | |
sb.append(str); | |
} | |
return sb.toString(); | |
} | |
private static List<String> idTypes(XmlSchemaSimpleType simpleType) { | |
List<String> idTypes = new LinkedList<>(); | |
if (simpleType.getContent().getAnnotation() != null) { | |
for (XmlSchemaAnnotationItem an : simpleType.getContent().getAnnotation().getItems()) { | |
if (an instanceof XmlSchemaAppInfo) { | |
XmlSchemaAppInfo xan = (XmlSchemaAppInfo) an; | |
for (int i = 0; i < xan.getMarkup().getLength(); i++) { | |
Element ean = (Element) xan.getMarkup().item(i); | |
if ("acme:enumeration".equals(ean.getNodeName())) { | |
idTypes.add(ean.getAttribute("value")); | |
} | |
} | |
} | |
} | |
} | |
return idTypes; | |
} | |
public static interface SchemaTypeVisitor { | |
public default void visitStart(XmlSchemaElement elementType) { | |
//System.out.println("Start Visiting Element " + elementType.getQName()); | |
} | |
public default void visitEnd(XmlSchemaElement elementType) { | |
//System.out.println("End Visiting Element " + elementType.getQName()); | |
} | |
public default void visitStart(XmlSchemaComplexType complexType) { | |
//System.out.println("Start Visiting Complex Type " + complexType.getQName()); | |
} | |
public default void visitEnd(XmlSchemaComplexType complexType) { | |
//System.out.println("End Visiting Complex Type " + complexType.getQName()); | |
} | |
public default void visit(XmlSchemaSimpleType simpleType) { | |
//System.out.println("Visiting Simple Type " + simpleType.getQName()); | |
} | |
} | |
public static class RequestSchemaTypeVisitor implements SchemaTypeVisitor { | |
boolean inRequestReferences = false; | |
boolean inObjectIDType = false; | |
boolean inRequestCriteria = false; | |
boolean supportsReferences = false; | |
boolean supportsCriteria = false; | |
QName objectType = null; | |
List<String> idTypes = null; | |
@Override | |
public void visitStart(XmlSchemaComplexType complexType) { | |
System.out.println("Start Visiting Complex Type " + complexType.getQName()); | |
if (complexType.getQName().getLocalPart().endsWith("Request_ReferencesType")) { | |
inRequestReferences = true; | |
supportsReferences = true; | |
} else if (complexType.getQName().getLocalPart().endsWith("Request_CriteriaType")) { | |
inRequestReferences = true; | |
} else if (complexType.getQName().getLocalPart().endsWith("ObjectType") && idTypes == null) { | |
objectType = complexType.getQName(); | |
} else if (complexType.getQName().getLocalPart().endsWith("ObjectIDType") && idTypes == null) { | |
inObjectIDType = true; | |
} else if (inRequestCriteria) { | |
supportsCriteria = true; | |
} | |
} | |
@Override | |
public void visitEnd(XmlSchemaComplexType complexType) { | |
System.out.println("End Visiting Complex Type " + complexType.getQName()); | |
if (complexType.getQName().getLocalPart().endsWith("Request_ReferencesType")) { | |
inRequestReferences = false; | |
} else if (complexType.getQName().getLocalPart().endsWith("ObjectIDType")) { | |
inObjectIDType = false; | |
} | |
} | |
@Override | |
public void visit(XmlSchemaSimpleType simpleType) { | |
System.out.format("Visiting Simple Type %s - %s %s\n", simpleType.getQName(), inRequestReferences, inObjectIDType); | |
if (inRequestReferences && inObjectIDType) { | |
idTypes = idTypes(simpleType); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment