Skip to content

Instantly share code, notes, and snippets.

@aaronanderson
Created May 20, 2025 02:51
Show Gist options
  • Save aaronanderson/5e3e67fb321109769c528fe5c3b6cfe5 to your computer and use it in GitHub Desktop.
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
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