package com.xmlit.project.engine.xsd;
import java.io.Reader;
import java.io.StringReader;
import java.lang.reflect.Field;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.ws.jaxme.xs.XSAnnotation;
import org.apache.ws.jaxme.xs.XSAppinfo;
import org.apache.ws.jaxme.xs.XSElement;
import org.apache.ws.jaxme.xs.XSEnumeration;
import org.apache.ws.jaxme.xs.XSGroup;
import org.apache.ws.jaxme.xs.XSParser;
import org.apache.ws.jaxme.xs.XSParticle;
import org.apache.ws.jaxme.xs.XSSchema;
import org.apache.ws.jaxme.xs.impl.XSObjectImpl;
import org.apache.ws.jaxme.xs.xml.XsTElement;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import com.xmlit.project.engine.struct.Struct;
import com.xmlit.project.engine.struct.StructSequence;
import com.xmlit.project.engine.struct.StructSimple;
import com.xmlit.project.engine.struct.impl.StructChoiceImpl;
import com.xmlit.project.engine.struct.impl.StructSequenceImpl;
import com.xmlit.project.engine.struct.impl.StructSimpleImpl;
public class XSD2Struct {
public static Struct xsd2Struct(String schemaString) throws Exception,
SAXException, ParserConfigurationException {
StringReader schema = new StringReader(schemaString);
return xsd2Struct(schema);
}
public static Struct xsd2Struct(Reader schema) throws Exception,
SAXException, ParserConfigurationException {
InputSource source = new InputSource(schema);
XSParser xsParser = new XSParser();
xsParser.setValidating(false);
XSSchema xsSchema = null;
try {
xsSchema = xsParser.parse(source);
} catch (Exception e) {
throw new RuntimeException(e);
}
XSElement root = xsSchema.getElements()[0];
return readElement(root);
}
public static Struct readElement(XSElement element) throws Exception {
Struct current = null;
if (element.getType().isSimple()) {
current = new StructSimpleImpl(element.getName().getLocalName());
if (element.getType().getSimpleType().getPattern() != null) {
String pattern = element.getType().getSimpleType().getPattern()[0][0];
((StructSimple) current)
.setSimplePattern(handleUnEscape(pattern));
} else {
StringBuffer sb = new StringBuffer();
for (XSEnumeration enu:element.getType().getSimpleType().getEnumerations()) {
sb.append(enu.getValue() + "\n");
}
((StructSimple) current).setAllowedValues(sb.toString());
}
} else {
XSGroup group = element.getType().getComplexType().getParticle()
.getGroup();
if ("sequence".equals("" + group.getCompositor())) {
current = new StructSequenceImpl(element.getName()
.getLocalName());
} else if ("choice".equals("" + group.getCompositor())) {
current = new StructChoiceImpl(element.getName().getLocalName());
} else if ("all".equals("" + group.getCompositor())) {
throw new RuntimeException("'all' is not supported yet");
}
for (XSParticle child : group.getParticles()) {
if (child.isElement())
current.addChild(readElement(child.getElement()));
}
}
XsTElement xele = getXsTElement(element);
current.setMinOccurrences(xele.getMinOccurs());
if (xele.getMaxOccurs() == -1) {
current.setMaxOccurrences(100);
} else {
current.setMaxOccurrences(xele.getMaxOccurs());
}
handleAnnotation(current, element);
return current;
}
private static boolean handleAnnotation(Struct current, XSElement element) {
Document annotation = getAnnotationDocuments(element);
if (annotation != null) {
String prefix = annotation.getDocumentElement().getAttribute(
"prefix");
current.setPrefix(handleUnEscape(prefix));
String suffix = annotation.getDocumentElement().getAttribute(
"suffix");
current.setSuffix(handleUnEscape(suffix));
if (current instanceof StructSequence) {
String delimiter = annotation.getDocumentElement()
.getAttribute("delimiter");
((StructSequence) current)
.setDelimiter(handleUnEscape(delimiter));
String lookahead = annotation.getDocumentElement()
.getAttribute("lookahead");
((StructSequence) current)
.setLookahead(handleUnEscape(lookahead));
String not = annotation.getDocumentElement()
.getAttribute("not");
((StructSequence) current).setNegative("true".equals(not));
} else if (current instanceof StructSimple) {
((StructSimple) current).setAllowedChars(annotation
.getDocumentElement().getAttribute("allowedChars"));
((StructSimple) current).setMinLength(Integer
.parseInt(annotation.getDocumentElement().getAttribute(
"minLength")));
((StructSimple) current).setMaxLength(Integer
.parseInt(annotation.getDocumentElement().getAttribute(
"maxLength")));
if (annotation.getDocumentElement()
.getAttribute("allowedChars") != null
&& !"".equals(annotation.getDocumentElement()
.getAttribute("allowedChars"))) {
((StructSimple) current).setSimplePattern(null);
}
}
}
return true;
}
private static Document getAnnotationDocuments(XSElement element) {
if (element.getAnnotations().length > 0) {
XSAnnotation xsAnnotation = element.getAnnotations()[0];
XSAppinfo[] xsAppinfos = xsAnnotation.getAppinfos();
XSAppinfo xsAppinfo = xsAppinfos[0];
for (int i = 0; i < xsAppinfo.getChilds().length; i++) {
if (xsAppinfo.getChilds()[i] instanceof Document)
return (Document) xsAppinfo.getChilds()[i];
}
}
return null;
}
private static XsTElement getXsTElement(XSElement element) {
XsTElement base = null;
try {
Field field = XSObjectImpl.class.getDeclaredField("baseObject");
field.setAccessible(true);
base = (XsTElement) field.get(element);
} catch (Exception e) {
throw new RuntimeException(e);
}
return base;
}
private static String handleUnEscape(String attribute) {
if (attribute == null) {
return null;
}
String result = attribute.replace("\r", "\\r");
result = result.replace("\n", "\\n");
return result;
// return attribute;
}
}