package parsewsdl;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
enum ParseStatus {
ProcessingType, ProcessingOther
}
public class XSDTypeParser extends DefaultHandler {
public static final String typeNameMarker = "TypeName";
public static final String namespaceMarker = "Namespace";
public static final String documentMarker = "Document";
private CommonTypeProp current = null;
// contains xml header and import.
private StringBuffer commonHeader = new StringBuffer(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n");
private StringBuffer currTypeContent = new StringBuffer();
private List<CommonTypeProp> allTypes = new ArrayList<CommonTypeProp>();
private static final String COMPLEX_TYPE = "complexType";
private static final String SIMPLE_TYPE = "simpleType";
private static final String SCHEMA_NODE_NAME = "schema";
private static final String ANNOTATION_NODE_NAME = "annotation";
private static final String DOCUMENT_NODE_NAME = "documentation";
private static final String NAME_ATTR = "name";
private static final String TARGET_NAMESPACE_ATTR = "targetNamespace";
ParseStatus status = ParseStatus.ProcessingOther;
private String targetNamespace = null;
private List<String> nodePath = new ArrayList<String>();
private int documentIndex = -1;
private String prefix = "xs";
private String schemaEnd = null;
public XSDTypeParser(InputStream xsdStream) {
try {
SAXParserFactory saxfac = SAXParserFactory.newInstance();
SAXParser saxParser = saxfac.newSAXParser();
saxParser.parse(xsdStream, this);
String commonHeaderStr = commonHeader.toString();
for (CommonTypeProp type : allTypes) {
type.setSchemaTemplate(commonHeaderStr
+ type.getSchemaTemplate() + schemaEnd);
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static boolean isTypeNode(String nodeName) {
nodeName = getNodeName(nodeName);
return SIMPLE_TYPE.equalsIgnoreCase(nodeName)
|| COMPLEX_TYPE.equalsIgnoreCase(nodeName);
}
private static boolean isSchemaNode(String nodeName) {
return SCHEMA_NODE_NAME.equalsIgnoreCase(getNodeName(nodeName));
}
private static String getNodeName(String qName) {
int index = qName.indexOf(':');
if (index > -1) {
qName = qName.substring(index + 1);
}
return qName;
}
private static String getPrefix(String qName) {
int index = qName.indexOf(':');
if (index > -1) {
return qName.substring(0, index);
}
return "xs";
}
private boolean isTypeDocument() {
if (nodePath.size() == 4 && isSchemaNode(nodePath.get(0))
&& isTypeNode(nodePath.get(1))) {
return ANNOTATION_NODE_NAME.equalsIgnoreCase(getNodeName(nodePath
.get(2)))
&& DOCUMENT_NODE_NAME.equalsIgnoreCase(getNodeName(nodePath
.get(3)));
}
return false;
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
String content = new String(ch, start, length);
if (isTypeDocument() == true) {
current.setDescription(content);
appendXSD("${" + documentMarker + "}");
} else {
appendXSD(content);
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
nodePath.remove(nodePath.size() - 1);
if (isSchemaNode(qName) == true) {
schemaEnd = "\r\n</" + qName + ">";
} else {
appendXSD("</" + qName + ">");
}
if ((status == ParseStatus.ProcessingType)
&& (isTypeNode(qName) == true)) {
status = ParseStatus.ProcessingOther;
if (current != null) {
current.setNamespace(targetNamespace);
if (current.getDescription() == null) {
current.setDescription("");
currTypeContent.insert(documentIndex, getDummyDocument());
}
current.setSchemaTemplate(currTypeContent.toString());
currTypeContent.delete(0, currTypeContent.length());
allTypes.add(current);
}
documentIndex = -1;
}
}
private String getDummyDocument() {
return "\r\n<" + prefix + ":annotation>" + "\r\n<" + prefix
+ ":documentation>" + "\r\n${" + documentMarker + "}"
+ "\r\n</" + prefix + ":documentation>" + "\r\n </" + prefix
+ ":annotation>";
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
nodePath.add(qName);
boolean inTypeNode = false;
boolean inSchemaNode = false;
if ((status == ParseStatus.ProcessingOther)
&& (isTypeNode(qName) == true)) {
status = ParseStatus.ProcessingType;
inTypeNode = true;
current = new CommonTypeProp();
}
inSchemaNode = isSchemaNode(qName);
if (inSchemaNode) {
prefix = getPrefix(qName);
}
appendXSD("<" + qName + "");
for (int index = 0; index < attributes.getLength(); index++) {
String localNameAttr = attributes.getLocalName(index);
String value = attributes.getValue(index);
if (inTypeNode == true && NAME_ATTR.equalsIgnoreCase(localNameAttr)) {
// replace type name with type name marker
current.setTypeName(value);
appendXSD(" " + localNameAttr + "=\"${" + typeNameMarker
+ "}\" ");
} else if (inSchemaNode == true
&& TARGET_NAMESPACE_ATTR.equalsIgnoreCase(localNameAttr)) {
targetNamespace = value;
appendXSD(" " + localNameAttr + "=\"${" + namespaceMarker
+ "}\" ");
} else {
appendXSD(" " + localNameAttr + "=\"" + value + "\" ");
}
}
appendXSD(">");
if (inTypeNode == true) {
documentIndex = currTypeContent.length();
}
}
private void appendXSD(String content) {
if (status == ParseStatus.ProcessingType) {
currTypeContent.append(content);
} else {
commonHeader.append(content);
}
}
public List<CommonTypeProp> getAllTypes() {
return allTypes;
}
public void setAllTypes(List<CommonTypeProp> allTypes) {
this.allTypes = allTypes;
}
}
class CommonTypeProp {
protected String schemaTemplate;
protected String typeName;
protected String namespace;
protected String description;
public String getTypeName() {
return typeName;
}
public void setTypeName(String typeName) {
this.typeName = typeName;
}
public String getNamespace() {
return namespace;
}
public void setNamespace(String namespace) {
this.namespace = namespace;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getSchemaTemplate() {
return schemaTemplate;
}
public void setSchemaTemplate(String schemaTemplate) {
this.schemaTemplate = schemaTemplate;
}
public void reset() {
typeName = null;
namespace = null;
description = null;
schemaTemplate = null;
}
}