package com.sun.xml.internal.rngom.digested;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.List;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import com.sun.xml.internal.rngom.ast.builder.BuildException;
import com.sun.xml.internal.rngom.ast.builder.SchemaBuilder;
import com.sun.xml.internal.rngom.ast.util.CheckingSchemaBuilder;
import com.sun.xml.internal.rngom.nc.NameClass;
import com.sun.xml.internal.rngom.nc.NameClassVisitor;
import com.sun.xml.internal.rngom.nc.SimpleNameClass;
import com.sun.xml.internal.rngom.parse.Parseable;
import com.sun.xml.internal.rngom.parse.compact.CompactParseable;
import com.sun.xml.internal.rngom.parse.xml.SAXParseable;
import com.sun.xml.internal.rngom.xml.util.WellKnownNamespaces;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
public class DXMLPrinter {
protected XMLStreamWriter out;
protected String indentStep = "\t";
protected String newLine = System.getProperty("line.separator");
protected int indent;
protected boolean afterEnd = false;
protected DXMLPrinterVisitor visitor;
protected NameClassXMLPrinterVisitor ncVisitor;
protected DOMPrinter domPrinter;
public DXMLPrinter(XMLStreamWriter out) {
this.out = out;
this.visitor = new DXMLPrinterVisitor();
this.ncVisitor = new NameClassXMLPrinterVisitor();
this.domPrinter = new DOMPrinter(out);
}
public void printDocument(DGrammarPattern grammar) throws XMLStreamException {
try {
visitor.startDocument();
visitor.on(grammar);
visitor.endDocument();
} catch (XMLWriterException e) {
if (e.getCause() instanceof XMLStreamException) {
throw (XMLStreamException) e.getCause();
} else {
throw new XMLStreamException(e);
}
}
}
public void print(DPattern pattern) throws XMLStreamException {
try {
pattern.accept(visitor);
} catch (XMLWriterException e) {
if (e.getCause() instanceof XMLStreamException) {
throw (XMLStreamException) e.getCause();
} else {
throw new XMLStreamException(e);
}
}
}
public void print(NameClass nc) throws XMLStreamException {
try {
nc.accept(ncVisitor);
} catch (XMLWriterException e) {
if (e.getCause() instanceof XMLStreamException) {
throw (XMLStreamException) e.getCause();
} else {
throw new XMLStreamException(e);
}
}
}
public void print(Node node) throws XMLStreamException {
domPrinter.print(node);
}
protected class XMLWriterException extends RuntimeException {
protected XMLWriterException(Throwable cause) {
super(cause);
}
}
protected class XMLWriter {
protected void newLine() {
try {
out.writeCharacters(newLine);
} catch (XMLStreamException e) {
throw new XMLWriterException(e);
}
}
protected void indent() {
try {
for (int i = 0; i < indent; i++) {
out.writeCharacters(indentStep);
}
} catch (XMLStreamException e) {
throw new XMLWriterException(e);
}
}
public void startDocument() {
try {
out.writeStartDocument();
} catch (XMLStreamException e) {
throw new XMLWriterException(e);
}
}
public void endDocument() {
try {
out.writeEndDocument();
} catch (XMLStreamException e) {
throw new XMLWriterException(e);
}
}
public final void start(String element) {
try {
newLine();
indent();
out.writeStartElement(element);
indent++;
afterEnd = false;
} catch (XMLStreamException e) {
throw new XMLWriterException(e);
}
}
public void end() {
try {
indent--;
if (afterEnd) {
newLine();
indent();
}
out.writeEndElement();
afterEnd = true;
} catch (XMLStreamException e) {
throw new XMLWriterException(e);
}
}
public void attr(String prefix, String ns, String name, String value) {
try {
out.writeAttribute(prefix, ns, name, value);
} catch (XMLStreamException e) {
throw new XMLWriterException(e);
}
}
public void attr(String name, String value) {
try {
out.writeAttribute(name, value);
} catch (XMLStreamException e) {
throw new XMLWriterException(e);
}
}
public void ns(String prefix, String uri) {
try {
out.writeNamespace(prefix, uri);
} catch (XMLStreamException e) {
throw new XMLWriterException(e);
}
}
public void body(String text) {
try {
out.writeCharacters(text);
afterEnd = false;
} catch (XMLStreamException e) {
throw new XMLWriterException(e);
}
}
}
protected class DXMLPrinterVisitor extends XMLWriter implements DPatternVisitor<Void> {
protected void on(DPattern p) {
p.accept(this);
}
protected void unwrapGroup(DPattern p) {
if (p instanceof DGroupPattern && p.getAnnotation() == DAnnotation.EMPTY) {
for (DPattern d : (DGroupPattern) p) {
on(d);
}
} else {
on(p);
}
}
protected void unwrapChoice(DPattern p) {
if (p instanceof DChoicePattern && p.getAnnotation() == DAnnotation.EMPTY) {
for (DPattern d : (DChoicePattern) p) {
on(d);
}
} else {
on(p);
}
}
protected void on(NameClass nc) {
if (nc instanceof SimpleNameClass) {
QName qname = ((SimpleNameClass) nc).name;
String name = qname.getLocalPart();
if (!qname.getPrefix().equals("")) name = qname.getPrefix() + ":";
attr("name", name);
} else {
nc.accept(ncVisitor);
}
}
protected void on(DAnnotation ann) {
if (ann == DAnnotation.EMPTY) return;
for (DAnnotation.Attribute attr : ann.getAttributes().values()) {
attr(attr.getPrefix(), attr.getNs(), attr.getLocalName(), attr.getValue());
}
for (Element elem : ann.getChildren()) {
try {
newLine();
indent();
print(elem);
}
catch (XMLStreamException e) {
throw new XMLWriterException(e);
}
}
}
public Void onAttribute(DAttributePattern p) {
start("attribute");
on(p.getName());
on(p.getAnnotation());
DPattern child = p.getChild();
if (!(child instanceof DTextPattern)) {
on(p.getChild());
}
end();
return null;
}
public Void onChoice(DChoicePattern p) {
start("choice");
on(p.getAnnotation());
for (DPattern d : p) {
on(d);
}
end();
return null;
}
public Void onData(DDataPattern p) {
List<DDataPattern.Param> params = p.getParams();
DPattern except = p.getExcept();
start("data");
attr("datatypeLibrary", p.getDatatypeLibrary());
attr("type", p.getType());
on(p.getAnnotation());
for (DDataPattern.Param param : params) {
start("param");
attr("ns", param.getNs());
attr("name", param.getName());
body(param.getValue());
end();
}
if (except != null) {
start("except");
unwrapChoice(except);
end();
}
end();
return null;
}
public Void onElement(DElementPattern p) {
start("element");
on(p.getName());
on(p.getAnnotation());
unwrapGroup(p.getChild());
end();
return null;
}
public Void onEmpty(DEmptyPattern p) {
start("empty");
on(p.getAnnotation());
end();
return null;
}
public Void onGrammar(DGrammarPattern p) {
start("grammar");
ns(null, WellKnownNamespaces.RELAX_NG);
on(p.getAnnotation());
start("start");
on(p.getStart());
end();
for (DDefine d : p) {
start("define");
attr("name", d.getName());
on(d.getAnnotation());
unwrapGroup(d.getPattern());
end();
}
end();
return null;
}
public Void onGroup(DGroupPattern p) {
start("group");
on(p.getAnnotation());
for (DPattern d : p) {
on(d);
}
end();
return null;
}
public Void onInterleave(DInterleavePattern p) {
start("interleave");
on(p.getAnnotation());
for (DPattern d : p) {
on(d);
}
end();
return null;
}
public Void onList(DListPattern p) {
start("list");
on(p.getAnnotation());
unwrapGroup(p.getChild());
end();
return null;
}
public Void onMixed(DMixedPattern p) {
start("mixed");
on(p.getAnnotation());
unwrapGroup(p.getChild());
end();
return null;
}
public Void onNotAllowed(DNotAllowedPattern p) {
start("notAllowed");
on(p.getAnnotation());
end();
return null;
}
public Void onOneOrMore(DOneOrMorePattern p) {
start("oneOrMore");
on(p.getAnnotation());
unwrapGroup(p.getChild());
end();
return null;
}
public Void onOptional(DOptionalPattern p) {
start("optional");
on(p.getAnnotation());
unwrapGroup(p.getChild());
end();
return null;
}
public Void onRef(DRefPattern p) {
start("ref");
attr("name", p.getName());
on(p.getAnnotation());
end();
return null;
}
public Void onText(DTextPattern p) {
start("text");
on(p.getAnnotation());
end();
return null;
}
public Void onValue(DValuePattern p) {
start("value");
if (!p.getNs().equals("")) attr("ns", p.getNs());
attr("datatypeLibrary", p.getDatatypeLibrary());
attr("type", p.getType());
on(p.getAnnotation());
body(p.getValue());
end();
return null;
}
public Void onZeroOrMore(DZeroOrMorePattern p) {
start("zeroOrMore");
on(p.getAnnotation());
unwrapGroup(p.getChild());
end();
return null;
}
}
protected class NameClassXMLPrinterVisitor extends XMLWriter implements NameClassVisitor<Void> {
public Void visitChoice(NameClass nc1, NameClass nc2) {
start("choice");
nc1.accept(this);
nc2.accept(this);
end();
return null;
}
public Void visitNsName(String ns) {
start("nsName");
attr("ns", ns);
end();
return null;
}
public Void visitNsNameExcept(String ns, NameClass nc) {
start("nsName");
attr("ns", ns);
start("except");
nc.accept(this);
end();
end();
return null;
}
public Void visitAnyName() {
start("anyName");
end();
return null;
}
public Void visitAnyNameExcept(NameClass nc) {
start("anyName");
start("except");
nc.accept(this);
end();
end();
return null;
}
public Void visitName(QName name) {
start("name");
if (!name.getPrefix().equals("")) {
body(name.getPrefix() + ":");
}
body(name.getLocalPart());
end();
return null;
}
public Void visitNull() {
throw new UnsupportedOperationException("visitNull");
}
}
public static void main(String[] args) throws Exception {
Parseable p;
ErrorHandler eh = new DefaultHandler() {
@Override
public void error(SAXParseException e) throws SAXException {
throw e;
}
};
String path = new File(args[0]).toURL().toString();
if (args[0].endsWith(".rng")) {
p = new SAXParseable(new InputSource(path), eh);
} else {
p = new CompactParseable(new InputSource(path), eh);
}
SchemaBuilder sb = new CheckingSchemaBuilder(new DSchemaBuilderImpl(), eh);
try {
DGrammarPattern grammar = (DGrammarPattern) p.parse(sb);
OutputStream out = new FileOutputStream(args[1]);
XMLOutputFactory factory = XMLOutputFactory.newInstance();
factory.setProperty("javax.xml.stream.isRepairingNamespaces", Boolean.TRUE);
XMLStreamWriter output = factory.createXMLStreamWriter(out);
DXMLPrinter printer = new DXMLPrinter(output);
printer.printDocument(grammar);
output.close();
out.close();
} catch (BuildException e) {
if (e.getCause() instanceof SAXParseException) {
SAXParseException se = (SAXParseException) e.getCause();
System.out.println("("
+ se.getLineNumber()
+ ","
+ se.getColumnNumber()
+ "): "
+ se.getMessage());
return;
} else
if (e.getCause() instanceof SAXException) {
SAXException se = (SAXException) e.getCause();
if (se.getException() != null)
se.getException().printStackTrace();
}
throw e;
}
}
}