package com.xmlit.project.engine.kxsd;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java1.util.regex.Pattern;
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.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.StructImpl;
import com.xmlit.project.engine.struct.impl.StructSequenceImpl;
import com.xmlit.project.engine.struct.impl.StructSimpleImpl;
public class KXSDReader {
public static Struct readSchema(String schemaString) throws Exception,
SAXException, ParserConfigurationException {
StringReader schema = new StringReader(schemaString);
InputSource source = new InputSource(schema);
XSParser xsParser = new XSParser();
xsParser.setValidating(false);
XSSchema xsSchema = xsParser.parse(source);
XSElement root = xsSchema.getElements()[0];
return readElement(root);
}
public static Struct readElement(XSElement element) throws Exception {
Struct current = null;
boolean mandatory = true;
if (element.getType().isSimple()) {
current = new StructSimpleImpl(element.getName().getLocalName());
mandatory = handleSimple((StructSimple) current, element);
// System.out.println(element.getName() + " "
// +element.getType().getSimpleType().getPattern());
} else {
XSGroup group = element.getType().getComplexType().getParticle()
.getGroup();
if ("sequence".equals("" + group.getCompositor())) {
current = new StructSequenceImpl(element.getName()
.getLocalName());
mandatory = handleSequence((StructSequence) current, element);
} else if ("choice".equals("" + group.getCompositor())) {
current = new StructChoiceImpl(element.getName().getLocalName());
} else if ("all".equals("" + group.getCompositor())) {
throw new RuntimeException("Choice is not supported yet");
}
// System.out.println(element.getName());
for (XSParticle child : group.getParticles()) {
current.addChild(readElement(child.getElement()));
}
}
XsTElement xele = getXsTElement(element);
if (mandatory) {
current.setMinOccurrences(xele.getMinOccurs());
} else {
current.setMinOccurrences(0);
}
if (xele.getMaxOccurs() == -1) {
current.setMaxOccurrences(100);
} else {
current.setMaxOccurrences(xele.getMaxOccurs());
}
return current;
}
private static boolean handleSequence(StructSequence current,
XSElement element) {
Document annotation = getAnnotationDocuments(element);
if (annotation != null) {
String result = annotation.getDocumentElement().getAttribute(
"mandatory");
Element separator = null;
for (int i = 0; i < annotation.getDocumentElement().getChildNodes()
.getLength(); i++) {
if (annotation.getDocumentElement().getChildNodes().item(i) instanceof Element) {
separator = (Element) annotation.getDocumentElement()
.getChildNodes().item(i);
}
}
if (separator != null) {
String sep = separator.getAttribute("Separator");
sep = handleEscape(sep);
//sep = StructImpl.quote(sep);
//sep = sep + getRightContext(separator);
String sepReg = sep + getRightContext(separator);
if (sep != null && !"".equals(sep)) {
current.setDelimiter(sep);
if (!sepReg.equals(sep)) {
current.setDelimiterRegex(sepReg);
}
}
String after = separator.getAttribute("Also_After_Last_Child");
if (after != null && "true".equals(after)) {
current.setSuffix(sep);
}
String before = separator
.getAttribute("Also_Before_First_Child");
if (before != null && "true".equals(before)) {
current.setSuffix(sep);
}
}
return "true".equals(result);
}
return true;
}
private static String getRightContext(Element sep) {
Element rContext = (Element) sep.getElementsByTagName("right_context").item(0);
if (rContext != null) {
String constraint = rContext.getAttribute("String_Constraint");
boolean isNegative = "true".equals(rContext.getAttribute("Is_Negative_Constraint"));
if (isNegative) {
return "(?!"+constraint+")";
}
}
return "";
}
private static boolean handleSimple(StructSimple current, XSElement element)
throws Exception {
Document annotation = getAnnotationDocuments(element);
if (annotation != null) {
String result = annotation.getDocumentElement().getAttribute(
"mandatory");
String constVal = annotation.getDocumentElement().getAttribute(
"Constant_Value");
constVal = handleEscape(constVal);
if (constVal != null && !"".equals(constVal)) {
current.setSimplePattern(Pattern.quote(constVal));
return "true".equals(result);
}
String validVals = annotation.getDocumentElement().getAttribute(
"Valid_Values");
if (validVals != null && !"".equals(validVals)) {
String[] vals = validVals.split("=,");
StringBuffer res = new StringBuffer();
for (int i = 0; i < vals.length; i++) {
res.append(Pattern.quote(handleEscape(vals[i])));
if (i + 1 < vals.length)
res.append("|");
}
current.setSimplePattern(res.toString());
return "true".equals(result);
}
}
String[] pattern = element.getType().getSimpleType().getPattern()[0];
if (pattern != null) {
current.setSimplePattern(pattern[0]);
}
return true;
}
private static String handleEscape(String string) {
return string.replace("\\r\\n", "\r\n");
}
private static Document getAnnotationDocuments(XSElement element) {// to
// change
if (element.getAnnotations().length > 0) {
XSAnnotation xsAnnotation = element.getAnnotations()[0];
XSAppinfo[] xsAppinfos = xsAnnotation.getAppinfos();
XSAppinfo xsAppinfo = xsAppinfos[0];
// System.out.println(getAnnotationDocuments(xsAppinfo));
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) {// to change
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;
}
}