com.thaiopensource.relaxng.output.xsd.BasicOutput Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of trang Show documentation
Show all versions of trang Show documentation
Jing/Trang - tools for validating and translating RelaxNG
The newest version!
package com.thaiopensource.relaxng.output.xsd;
import com.thaiopensource.relaxng.output.OutputDirectory;
import com.thaiopensource.relaxng.output.common.ErrorReporter;
import com.thaiopensource.relaxng.output.common.XmlWriter;
import com.thaiopensource.relaxng.output.xsd.basic.AbstractAttributeUseVisitor;
import com.thaiopensource.relaxng.output.xsd.basic.AbstractSchemaVisitor;
import com.thaiopensource.relaxng.output.xsd.basic.Annotated;
import com.thaiopensource.relaxng.output.xsd.basic.Annotation;
import com.thaiopensource.relaxng.output.xsd.basic.Attribute;
import com.thaiopensource.relaxng.output.xsd.basic.AttributeGroup;
import com.thaiopensource.relaxng.output.xsd.basic.AttributeGroupDefinition;
import com.thaiopensource.relaxng.output.xsd.basic.AttributeGroupRef;
import com.thaiopensource.relaxng.output.xsd.basic.AttributeUse;
import com.thaiopensource.relaxng.output.xsd.basic.AttributeUseVisitor;
import com.thaiopensource.relaxng.output.xsd.basic.Comment;
import com.thaiopensource.relaxng.output.xsd.basic.ComplexType;
import com.thaiopensource.relaxng.output.xsd.basic.ComplexTypeComplexContent;
import com.thaiopensource.relaxng.output.xsd.basic.ComplexTypeNotAllowedContent;
import com.thaiopensource.relaxng.output.xsd.basic.ComplexTypeSimpleContent;
import com.thaiopensource.relaxng.output.xsd.basic.ComplexTypeVisitor;
import com.thaiopensource.relaxng.output.xsd.basic.Element;
import com.thaiopensource.relaxng.output.xsd.basic.Facet;
import com.thaiopensource.relaxng.output.xsd.basic.GroupDefinition;
import com.thaiopensource.relaxng.output.xsd.basic.GroupRef;
import com.thaiopensource.relaxng.output.xsd.basic.Occurs;
import com.thaiopensource.relaxng.output.xsd.basic.OptionalAttribute;
import com.thaiopensource.relaxng.output.xsd.basic.Particle;
import com.thaiopensource.relaxng.output.xsd.basic.ParticleAll;
import com.thaiopensource.relaxng.output.xsd.basic.ParticleChoice;
import com.thaiopensource.relaxng.output.xsd.basic.ParticleRepeat;
import com.thaiopensource.relaxng.output.xsd.basic.ParticleSequence;
import com.thaiopensource.relaxng.output.xsd.basic.ParticleVisitor;
import com.thaiopensource.relaxng.output.xsd.basic.RootDeclaration;
import com.thaiopensource.relaxng.output.xsd.basic.Schema;
import com.thaiopensource.relaxng.output.xsd.basic.SchemaVisitor;
import com.thaiopensource.relaxng.output.xsd.basic.SchemaWalker;
import com.thaiopensource.relaxng.output.xsd.basic.SimpleType;
import com.thaiopensource.relaxng.output.xsd.basic.SimpleTypeDefinition;
import com.thaiopensource.relaxng.output.xsd.basic.SimpleTypeList;
import com.thaiopensource.relaxng.output.xsd.basic.SimpleTypeRef;
import com.thaiopensource.relaxng.output.xsd.basic.SimpleTypeRestriction;
import com.thaiopensource.relaxng.output.xsd.basic.SimpleTypeUnion;
import com.thaiopensource.relaxng.output.xsd.basic.SimpleTypeVisitor;
import com.thaiopensource.relaxng.output.xsd.basic.Structure;
import com.thaiopensource.relaxng.output.xsd.basic.StructureVisitor;
import com.thaiopensource.relaxng.output.xsd.basic.Wildcard;
import com.thaiopensource.relaxng.output.xsd.basic.WildcardAttribute;
import com.thaiopensource.relaxng.output.xsd.basic.WildcardElement;
import com.thaiopensource.util.VoidValue;
import com.thaiopensource.xml.util.Name;
import com.thaiopensource.xml.util.WellKnownNamespaces;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Vector;
public class BasicOutput {
static class Options {
String anyProcessContents = "skip";
String anyAttributeProcessContents = "skip";
}
private final XmlWriter xw;
private final Schema schema;
private final SimpleTypeOutput simpleTypeOutput = new SimpleTypeOutput();
private final ComplexTypeOutput complexTypeOutput = new ComplexTypeOutput();
private final AttributeUseOutput attributeUseOutput = new AttributeUseOutput();
private final AttributeUseVisitor attributeWildcardOutput = new AttributeWildcardOutput();
private final ParticleOutput particleOutput = new ParticleOutput();
private final ParticleVisitor globalElementOutput = new GlobalElementOutput();
private final GlobalAttributeOutput globalAttributeOutput = new GlobalAttributeOutput();
private final SchemaVisitor schemaOutput = new SchemaOutput();
private final StructureVisitor movedStructureOutput = new MovedStructureOutput();
private final SimpleTypeVisitor simpleTypeNamer = new SimpleTypeNamer();
private final NamespaceManager nsm;
private final PrefixManager pm;
private final String targetNamespace;
private final OutputDirectory od;
private final String sourceUri;
private final ComplexTypeSelector complexTypeSelector;
private final AbstractElementTypeSelector abstractElementTypeSelector;
private final Set globalElementsDefined;
private final Set globalAttributesDefined;
private final String xsPrefix;
private final Options options;
class SimpleTypeOutput implements SimpleTypeVisitor {
public VoidValue visitRestriction(SimpleTypeRestriction t) {
boolean hadPatternFacet = false;
for (Facet facet : t.getFacets()) {
if (facet.getName().equals("pattern")) {
if (!hadPatternFacet)
hadPatternFacet = true;
else {
xw.startElement(xs("restriction"));
xw.startElement(xs("simpleType"));
}
}
}
xw.startElement(xs("restriction"));
xw.attribute("base", xs(t.getName()));
hadPatternFacet = false;
for (Facet facet : t.getFacets()) {
if (facet.getName().equals("pattern")) {
if (!hadPatternFacet) {
hadPatternFacet = true;
outputFacet(facet);
}
}
else
outputFacet(facet);
}
xw.endElement();
hadPatternFacet = false;
for (Facet facet : t.getFacets()) {
if (facet.getName().equals("pattern")) {
if (!hadPatternFacet)
hadPatternFacet = true;
else {
xw.endElement();
outputFacet(facet);
xw.endElement();
}
}
}
return null;
}
private void outputFacet(Facet facet) {
xw.startElement(xs(facet.getName()));
xw.attribute("value", facet.getValue());
String prefix = facet.getPrefix();
if (prefix != null && !prefix.equals(topLevelPrefix(facet.getNamespace())))
xw.attribute(prefix.equals("") ? "xmlns" : "xmlns:" + prefix, facet.getNamespace());
outputAnnotation(facet);
xw.endElement();
}
public VoidValue visitRef(SimpleTypeRef t) {
xw.startElement(xs("restriction"));
xw.attribute("base", qualifyRef(schema.getSimpleType(t.getName()).getParentSchema().getUri(),
t.getName()));
xw.endElement();
return null;
}
public VoidValue visitUnion(SimpleTypeUnion t) {
xw.startElement(xs("union"));
StringBuffer buf = new StringBuffer();
for (SimpleType child : t.getChildren()) {
String typeName = child.accept(simpleTypeNamer);
if (typeName != null) {
if (buf.length() != 0)
buf.append(' ');
buf.append(typeName);
}
}
if (buf.length() != 0)
xw.attribute("memberTypes", buf.toString());
outputAnnotation(t);
for (SimpleType child : t.getChildren()) {
if (child.accept(simpleTypeNamer) == null)
outputWrap(child, null);
}
xw.endElement();
return null;
}
public VoidValue visitList(SimpleTypeList t) {
Occurs occ = t.getOccurs();
if (!occ.equals(Occurs.ZERO_OR_MORE)) {
xw.startElement(xs("restriction"));
xw.startElement(xs("simpleType"));
}
xw.startElement(xs("list"));
outputWrap(t.getItemType(), "itemType", t);
xw.endElement();
if (!occ.equals(Occurs.ZERO_OR_MORE)) {
xw.endElement();
if (occ.getMin() == occ.getMax()) {
xw.startElement(xs("length"));
xw.attribute("value", Integer.toString(occ.getMin()));
xw.endElement();
}
else {
if (occ.getMin() != 0) {
xw.startElement(xs("minLength"));
xw.attribute("value", Integer.toString(occ.getMin()));
xw.endElement();
}
if (occ.getMax() != Occurs.UNBOUNDED) {
xw.startElement(xs("maxLength"));
xw.attribute("value", Integer.toString(occ.getMax()));
xw.endElement();
}
}
xw.endElement();
}
return null;
}
void outputWrap(SimpleType t, Annotated parent) {
outputWrap(t, "type", parent);
}
void outputWrap(SimpleType t, String attributeName, Annotated parent) {
String typeName = t.accept(simpleTypeNamer);
if (typeName != null) {
xw.attribute(attributeName, typeName);
if (parent != null)
outputAnnotation(parent);
}
else {
if (parent != null)
outputAnnotation(parent);
xw.startElement(xs("simpleType"));
t.accept(this);
xw.endElement();
}
}
}
class SimpleTypeNamer implements SimpleTypeVisitor {
public String visitRestriction(SimpleTypeRestriction t) {
if (t.getFacets().size() > 0)
return null;
if (t.getAnnotation() != null)
return null;
return xs(t.getName());
}
public String visitRef(SimpleTypeRef t) {
if (t.getAnnotation() != null)
return null;
return qualifyRef(schema.getSimpleType(t.getName()).getParentSchema().getUri(),
t.getName());
}
public String visitList(SimpleTypeList t) {
return null;
}
public String visitUnion(SimpleTypeUnion t) {
return null;
}
}
private static final int NORMAL_CONTEXT = 0;
private static final int COMPLEX_TYPE_CONTEXT = 1;
private static final int NAMED_GROUP_CONTEXT = 2;
class ParticleOutput implements ParticleVisitor {
private Occurs occ = Occurs.EXACTLY_ONE;
private int context = NORMAL_CONTEXT;
private boolean startWrapperForElement() {
boolean needWrapper = context >= COMPLEX_TYPE_CONTEXT;
context = NORMAL_CONTEXT;
if (needWrapper)
xw.startElement(xs("sequence"));
xw.startElement(xs("element"));
outputOccurAttributes();
return needWrapper;
}
private boolean startWrapperForAny() {
boolean needWrapper = context >= COMPLEX_TYPE_CONTEXT;
context = NORMAL_CONTEXT;
if (needWrapper)
xw.startElement(xs("sequence"));
xw.startElement(xs("any"));
outputOccurAttributes();
return needWrapper;
}
private boolean startWrapperForGroupRef() {
boolean needWrapper = context == NAMED_GROUP_CONTEXT;
context = NORMAL_CONTEXT;
if (needWrapper)
xw.startElement(xs("sequence"));
xw.startElement(xs("group"));
outputOccurAttributes();
return needWrapper;
}
private boolean startWrapperForGroup(String groupType) {
boolean needWrapper = context == NAMED_GROUP_CONTEXT && !occ.equals(Occurs.EXACTLY_ONE);
context = NORMAL_CONTEXT;
if (needWrapper)
xw.startElement(xs("sequence"));
xw.startElement(xs(groupType));
outputOccurAttributes();
return needWrapper;
}
private void endWrapper(boolean extra) {
xw.endElement();
if (extra)
xw.endElement();
}
public VoidValue visitElement(Element p) {
boolean usedWrapper;
if (nsm.isGlobal(p)) {
usedWrapper = startWrapperForElement();
xw.attribute("ref", qualifyName(p.getName()));
}
else if (!namespaceIsLocal(p.getName().getNamespaceUri())) {
usedWrapper = startWrapperForGroupRef();
xw.attribute("ref", qualifyName(p.getName().getNamespaceUri(),
nsm.getProxyName(p)));
}
else {
usedWrapper = startWrapperForElement();
xw.attribute("name", p.getName().getLocalName());
if (!p.getName().getNamespaceUri().equals(targetNamespace))
xw.attribute("form", "unqualified");
complexTypeOutput.parent = p;
p.getComplexType().accept(complexTypeOutput);
}
endWrapper(usedWrapper);
return null;
}
public VoidValue visitWildcardElement(WildcardElement p) {
String ns = NamespaceManager.otherNamespace(p.getWildcard());
boolean usedWrapper;
if (ns != null && !ns.equals(targetNamespace)) {
usedWrapper = startWrapperForGroupRef();
xw.attribute("ref", qualifyName(ns, nsm.getOtherElementName(ns)));
}
else {
usedWrapper = startWrapperForAny();
namespaceAttribute(p.getWildcard());
xw.attribute("processContents", options.anyProcessContents);
outputAnnotation(p);
}
endWrapper(usedWrapper);
return null;
}
public VoidValue visitRepeat(ParticleRepeat p) {
occ = Occurs.multiply(occ, p.getOccurs());
p.getChild().accept(this);
return null;
}
public VoidValue visitSequence(ParticleSequence p) {
boolean usedWrapper = startWrapperForGroup("sequence");
outputAnnotation(p);
outputParticles(p.getChildren());
endWrapper(usedWrapper);
return null;
}
public VoidValue visitChoice(ParticleChoice p) {
boolean usedWrapper = startWrapperForGroup("choice");
outputAnnotation(p);
outputParticles(p.getChildren());
endWrapper(usedWrapper);
return null;
}
public VoidValue visitAll(ParticleAll p) {
boolean usedWrapper = startWrapperForGroup("all");
outputAnnotation(p);
outputParticles(p.getChildren());
endWrapper(usedWrapper);
return null;
}
private void outputParticles(List particles) {
for (Particle particle : particles)
particle.accept(this);
}
public VoidValue visitGroupRef(GroupRef p) {
String groupName = p.getName();
GroupDefinition def = schema.getGroup(groupName);
Name elementName = nsm.getElementNameForGroupRef(def);
boolean usedWrapper;
if (elementName != null) {
usedWrapper = startWrapperForElement();
xw.attribute("ref", qualifyName(elementName));
}
else {
usedWrapper = startWrapperForGroupRef();
xw.attribute("ref", qualifyRef(def.getParentSchema().getUri(), groupName));
}
outputAnnotation(p);
endWrapper(usedWrapper);
return null;
}
void outputOccurAttributes() {
if (occ.getMin() != 1)
xw.attribute("minOccurs", Integer.toString(occ.getMin()));
if (occ.getMax() != 1)
xw.attribute("maxOccurs",
occ.getMax() == Occurs.UNBOUNDED ? "unbounded" : Integer.toString(occ.getMax()));
occ = Occurs.EXACTLY_ONE;
}
}
class ComplexTypeOutput implements ComplexTypeVisitor {
Annotated parent;
public VoidValue visitComplexContent(ComplexTypeComplexContent t) {
outputComplexTypeComplexContent(complexTypeSelector.transformComplexContent(t), null, parent);
return null;
}
public VoidValue visitSimpleContent(ComplexTypeSimpleContent t) {
outputComplexTypeSimpleContent(complexTypeSelector.transformSimpleContent(t), null, parent);
return null;
}
public VoidValue visitNotAllowedContent(ComplexTypeNotAllowedContent t) {
xw.startElement(xs("complexType"));
xw.startElement(xs("choice"));
xw.endElement();
xw.endElement();
return null;
}
}
class AttributeUseOutput extends SchemaWalker {
boolean isOptional = false;
String defaultValue = null;
public VoidValue visitOptionalAttribute(OptionalAttribute a) {
isOptional = true;
defaultValue = a.getDefaultValue();
a.getAttribute().accept(this);
isOptional = false;
defaultValue = null;
return null;
}
public VoidValue visitAttribute(Attribute a) {
if (nsm.isGlobal(a)) {
xw.startElement(xs("attribute"));
xw.attribute("ref", qualifyName(a.getName()));
if (!isOptional)
xw.attribute("use", "required");
else if (defaultValue != null)
xw.attribute("default", defaultValue);
xw.endElement();
}
else if (namespaceIsLocal(a.getName().getNamespaceUri())) {
xw.startElement(xs("attribute"));
xw.attribute("name", a.getName().getLocalName());
if (!isOptional)
xw.attribute("use", "required");
else if (defaultValue != null)
xw.attribute("default", defaultValue);
if (!a.getName().getNamespaceUri().equals(""))
xw.attribute("form", "qualified");
if (a.getType() != null)
simpleTypeOutput.outputWrap(a.getType(), a);
else
outputAnnotation(a);
xw.endElement();
}
else {
xw.startElement(xs("attributeGroup"));
xw.attribute("ref",
qualifyName(a.getName().getNamespaceUri(),
nsm.getProxyName(a)));
xw.endElement();
}
return null;
}
public VoidValue visitAttributeGroupRef(AttributeGroupRef a) {
xw.startElement(xs("attributeGroup"));
String name = a.getName();
xw.attribute("ref",
qualifyRef(schema.getAttributeGroup(name).getParentSchema().getUri(), name));
xw.endElement();
return null;
}
}
class AttributeWildcardOutput extends SchemaWalker {
public VoidValue visitWildcardAttribute(WildcardAttribute a) {
String ns = NamespaceManager.otherNamespace(a.getWildcard());
if (ns != null && !ns.equals(targetNamespace)) {
xw.startElement(xs("attributeGroup"));
xw.attribute("ref", qualifyName(ns, nsm.getOtherAttributeName(ns)));
xw.endElement();
}
else {
xw.startElement(xs("anyAttribute"));
namespaceAttribute(a.getWildcard());
xw.attribute("processContents", options.anyAttributeProcessContents);
xw.endElement();
}
return null;
}
}
class GlobalElementOutput implements ParticleVisitor, ComplexTypeVisitor {
public VoidValue visitElement(Element p) {
Name name = p.getName();
if (nsm.isGlobal(p)
&& name.getNamespaceUri().equals(targetNamespace)
&& !globalElementsDefined.contains(name)) {
globalElementsDefined.add(name);
xw.startElement(xs("element"));
xw.attribute("name", name.getLocalName());
outputComplexType(name, p.getComplexType(), p);
xw.endElement();
}
return p.getComplexType().accept(this);
}
public VoidValue visitRepeat(ParticleRepeat p) {
return p.getChild().accept(this);
}
void visitList(List list) {
for (Particle p : list)
p.accept(this);
}
public VoidValue visitSequence(ParticleSequence p) {
visitList(p.getChildren());
return null;
}
public VoidValue visitChoice(ParticleChoice p) {
visitList(p.getChildren());
return null;
}
public VoidValue visitAll(ParticleAll p) {
visitList(p.getChildren());
return null;
}
public VoidValue visitGroupRef(GroupRef p) {
return null;
}
public VoidValue visitWildcardElement(WildcardElement p) {
return null;
}
public VoidValue visitComplexContent(ComplexTypeComplexContent t) {
if (t.getParticle() == null)
return null;
return t.getParticle().accept(this);
}
public VoidValue visitSimpleContent(ComplexTypeSimpleContent t) {
return null;
}
public VoidValue visitNotAllowedContent(ComplexTypeNotAllowedContent t) {
return null;
}
}
class GlobalAttributeOutput extends AbstractAttributeUseVisitor {
public VoidValue visitAttributeGroup(AttributeGroup a) {
for (AttributeUse child : a.getChildren())
child.accept(this);
return null;
}
public VoidValue visitAttribute(Attribute a) {
Name name = a.getName();
if (nsm.isGlobal(a)
&& name.getNamespaceUri().equals(targetNamespace)
&& !globalAttributesDefined.contains(name)) {
globalAttributesDefined.add(name);
xw.startElement(xs("attribute"));
xw.attribute("name", name.getLocalName());
if (a.getType() != null)
simpleTypeOutput.outputWrap(a.getType(), a);
xw.endElement();
}
return null;
}
public VoidValue visitOptionalAttribute(OptionalAttribute a) {
return a.getAttribute().accept(this);
}
public VoidValue visitAttributeGroupRef(AttributeGroupRef a) {
return null;
}
public VoidValue visitWildcardAttribute(WildcardAttribute a) {
return null;
}
}
class SchemaOutput extends AbstractSchemaVisitor {
public void visitGroup(GroupDefinition def) {
Particle particle = def.getParticle();
ComplexTypeComplexContentExtension ct = complexTypeSelector.createComplexTypeForGroup(def.getName(), nsm);
if (ct != null) {
Annotated anno;
if (tryAbstractElement(def))
anno = null;
else
anno = def;
outputComplexTypeComplexContent(ct, def.getName(), anno);
}
else if (!nsm.isGroupDefinitionOmitted(def)
&& !tryAbstractElement(def)
&& !tryElementChoiceSameType(def)) {
xw.startElement(xs("group"));
xw.attribute("name", def.getName());
outputAnnotation(def);
particleOutput.context = NAMED_GROUP_CONTEXT;
particle.accept(particleOutput);
xw.endElement();
}
particle.accept(globalElementOutput);
}
private boolean tryAbstractElement(GroupDefinition def) {
Name name = nsm.getGroupDefinitionAbstractElementName(def);
if (name == null)
return false;
xw.startElement(xs("element"));
xw.attribute("name", name.getLocalName());
xw.attribute("abstract", "true");
outputComplexType(name, abstractElementTypeSelector.getAbstractElementType(name), def);
xw.endElement();
return true;
}
private boolean tryElementChoiceSameType(GroupDefinition def) {
Particle particle = def.getParticle();
if (!(particle instanceof ParticleChoice))
return false;
List children = ((ParticleChoice)particle).getChildren();
if (children.size() <= 1)
return false;
Iterator iter = children.iterator();
Particle first = iter.next();
if (!(first instanceof Element))
return false;
if (!((Element)first).getName().getNamespaceUri().equals(targetNamespace))
return false;
ComplexType type = ((Element)first).getComplexType();
do {
Particle tem = iter.next();
if (!(tem instanceof Element))
return false;
if (!((Element)tem).getComplexType().equals(type))
return false;
if (!((Element)tem).getName().getNamespaceUri().equals(targetNamespace))
return false;
} while (iter.hasNext());
if (type instanceof ComplexTypeComplexContent) {
ComplexTypeComplexContentExtension t = complexTypeSelector.transformComplexContent((ComplexTypeComplexContent)type);
if (t.getBase() != null && t.getParticle() == null && !t.isMixed() && t.getAttributeUses().equals(AttributeGroup.EMPTY))
return false;
outputComplexTypeComplexContent(t, def.getName(), null);
}
else {
ComplexTypeSimpleContentExtension t = complexTypeSelector.transformSimpleContent((ComplexTypeSimpleContent)type);
if (t.getAttributeUses().equals(AttributeGroup.EMPTY)
&& (t.getBase() != null || t.getSimpleType().accept(simpleTypeNamer) != null))
return false;
outputComplexTypeSimpleContent(t, def.getName(), null);
}
xw.startElement(xs("group"));
xw.attribute("name", def.getName());
outputAnnotation(def);
xw.startElement(xs("choice"));
for (iter = children.iterator(); iter.hasNext();) {
Element element = (Element)iter.next();
xw.startElement(xs("element"));
if (nsm.isGlobal(element))
xw.attribute("ref", qualifyName(element.getName()));
else {
xw.attribute("name", element.getName().getLocalName());
xw.attribute("type", def.getName());
outputAnnotation(element);
}
xw.endElement();
}
xw.endElement();
xw.endElement();
for (iter = children.iterator(); iter.hasNext();) {
Element element = (Element)iter.next();
if (nsm.isGlobal(element) && !globalElementsDefined.contains(element.getName())) {
globalElementsDefined.add(element.getName());
xw.startElement(xs("element"));
xw.attribute("name", element.getName().getLocalName());
xw.attribute("type", def.getName());
outputAnnotation(element);
xw.endElement();
}
}
return true;
}
public void visitSimpleType(SimpleTypeDefinition def) {
ComplexTypeSimpleContentExtension ct = complexTypeSelector.createComplexTypeForSimpleType(def.getName());
if (ct != null)
outputComplexTypeSimpleContent(ct, def.getName(), def);
else {
xw.startElement(xs("simpleType"));
xw.attribute("name", def.getName());
outputAnnotation(def);
def.getSimpleType().accept(simpleTypeOutput);
xw.endElement();
}
}
public void visitAttributeGroup(AttributeGroupDefinition def) {
if (complexTypeSelector.isComplexType(def.getName()))
return;
xw.startElement(xs("attributeGroup"));
xw.attribute("name", def.getName());
outputAnnotation(def);
outputAttributeUse(def.getAttributeUses());
xw.endElement();
def.getAttributeUses().accept(globalAttributeOutput);
}
public void visitRoot(RootDeclaration decl) {
decl.getParticle().accept(globalElementOutput);
}
public void visitComment(Comment comment) {
xw.comment(comment.getContent());
}
}
class MovedStructureOutput implements StructureVisitor {
public VoidValue visitElement(Element element) {
if (!nsm.isGlobal(element)) {
xw.startElement(xs("group"));
xw.attribute("name", nsm.getProxyName(element));
particleOutput.context = NAMED_GROUP_CONTEXT;
particleOutput.visitElement(element);
xw.endElement();
}
globalElementOutput.visitElement(element);
return null;
}
public VoidValue visitAttribute(Attribute attribute) {
if (!nsm.isGlobal(attribute)) {
xw.startElement(xs("attributeGroup"));
xw.attribute("name", nsm.getProxyName(attribute));
attributeUseOutput.visitAttribute(attribute);
xw.endElement();
}
globalAttributeOutput.visitAttribute(attribute);
return null;
}
}
static void output(Schema schema, Guide guide, PrefixManager pm, OutputDirectory od,
Options options, ErrorReporter er) throws IOException {
NamespaceManager nsm = new NamespaceManager(schema, guide, pm);
ComplexTypeSelector cts = new ComplexTypeSelector(schema);
AbstractElementTypeSelector aets = new AbstractElementTypeSelector(schema, nsm, cts);
Set globalElementsDefined = new HashSet();
Set globalAttributesDefined = new HashSet();
try {
for (Schema sch : schema.getSubSchemas())
new BasicOutput(sch, er, od, options, nsm, pm, cts, aets,
globalElementsDefined, globalAttributesDefined).output();
}
catch (XmlWriter.WrappedException e) {
throw e.getIOException();
}
}
private BasicOutput(Schema schema, ErrorReporter er, OutputDirectory od, Options options,
NamespaceManager nsm, PrefixManager pm, ComplexTypeSelector complexTypeSelector,
AbstractElementTypeSelector abstractElementTypeSelector,
Set globalElementsDefined, Set globalAttributesDefined) throws IOException {
this.schema = schema;
this.nsm = nsm;
this.pm = pm;
this.complexTypeSelector = complexTypeSelector;
this.abstractElementTypeSelector = abstractElementTypeSelector;
this.globalElementsDefined = globalElementsDefined;
this.globalAttributesDefined = globalAttributesDefined;
this.sourceUri = schema.getUri();
this.od = od;
this.targetNamespace = nsm.getTargetNamespace(schema.getUri());
this.xsPrefix = pm.getPrefix(WellKnownNamespaces.XML_SCHEMA);
this.options = options;
OutputDirectory.Stream stream = od.open(schema.getUri(), schema.getEncoding());
xw = new XmlWriter(stream.getWriter(),
stream.getEncoding(),
stream.getCharRepertoire(),
od.getLineSeparator(),
od.getIndent(),
new String[0]);
}
private String topLevelPrefix(String ns) {
if (!nsm.isTargetNamespace(ns))
return null;
if (ns.equals(""))
return "";
return pm.getPrefix(ns);
}
private void output() {
outputCommentList(schema.getLeadingComments());
xw.startElement(xs("schema"));
xw.attribute("xmlns:" + xsPrefix, WellKnownNamespaces.XML_SCHEMA);
xw.attribute("elementFormDefault", "qualified");
if (!targetNamespace.equals(""))
xw.attribute("targetNamespace", targetNamespace);
for (String ns : nsm.getTargetNamespaces()) {
if (!ns.equals("")) {
String prefix = pm.getPrefix(ns);
if (!prefix.equals("xml"))
xw.attribute("xmlns:" + pm.getPrefix(ns), ns);
}
}
for (String uri : nsm.effectiveIncludes(schema.getUri()))
outputInclude(uri);
List targetNamespaces = new Vector();
targetNamespaces.addAll(nsm.getTargetNamespaces());
Collections.sort(targetNamespaces);
for (String ns : targetNamespaces) {
if (!ns.equals(targetNamespace))
outputImport(ns, nsm.getRootSchema(ns));
}
schema.accept(schemaOutput);
if (nsm.getRootSchema(targetNamespace).equals(sourceUri)) {
for (Structure structure : nsm.getMovedStructures(targetNamespace))
structure.accept(movedStructureOutput);
outputOther();
}
xw.endElement();
outputCommentList(schema.getTrailingComments());
xw.close();
}
private String xs(String name) {
return xsPrefix + ":" + name;
}
private boolean namespaceIsLocal(String ns) {
return ns.equals(targetNamespace) || ns.equals("");
}
private void outputAttributeUse(AttributeUse use) {
use.accept(attributeUseOutput);
use.accept(attributeWildcardOutput);
}
private void namespaceAttribute(Wildcard wc) {
if (wc.isPositive()) {
StringBuffer buf = new StringBuffer();
List namespaces = new Vector(wc.getNamespaces());
Collections.sort(namespaces);
for (String ns : namespaces) {
if (buf.length() > 0)
buf.append(' ');
if (ns.equals(""))
buf.append("##local");
else if (ns.equals(targetNamespace))
buf.append("##targetNamespace");
else
buf.append(ns);
}
xw.attribute("namespace", buf.toString());
}
else {
if (targetNamespace.equals(NamespaceManager.otherNamespace(wc)))
xw.attribute("namespace", "##other");
}
}
private String qualifyRef(String schemaUri, String localName) {
return qualifyName(nsm.getTargetNamespace(schemaUri), localName);
}
private String qualifyName(Name name) {
return qualifyName(name.getNamespaceUri(), name.getLocalName());
}
private String qualifyName(String ns, String localName) {
if (ns.equals(""))
return localName;
return pm.getPrefix(ns) + ":" + localName;
}
private void outputOther() {
String name = nsm.getOtherElementName(targetNamespace);
if (name != null) {
xw.startElement(xs("group"));
xw.attribute("name", name);
xw.startElement(xs("sequence"));
xw.startElement(xs("any"));
xw.attribute("namespace", "##other");
xw.attribute("processContents", options.anyProcessContents);
xw.endElement();
xw.endElement();
xw.endElement();
}
name = nsm.getOtherAttributeName(targetNamespace);
if (name != null) {
xw.startElement(xs("attributeGroup"));
xw.attribute("name", name);
xw.startElement(xs("anyAttribute"));
xw.attribute("namespace", "##other");
xw.attribute("processContents", options.anyAttributeProcessContents);
xw.endElement();
xw.endElement();
}
}
private void outputInclude(String href) {
xw.startElement(xs("include"));
xw.attribute("schemaLocation", od.reference(sourceUri, href));
xw.endElement();
}
private void outputImport(String ns, String href) {
xw.startElement(xs("import"));
if (!ns.equals(""))
xw.attribute("namespace", ns);
xw.attribute("schemaLocation", od.reference(sourceUri, href));
xw.endElement();
}
private void outputComplexTypeComplexContent(ComplexTypeComplexContentExtension t, String name, Annotated parent) {
String base = t.getBase();
if (base != null) {
base = qualifyRef(schema.getGroup(base).getParentSchema().getUri(), base);
if (name == null
&& t.getParticle() == null
&& !t.isMixed()
&& t.getAttributeUses().equals(AttributeGroup.EMPTY)) {
xw.attribute("type", base);
if (parent != null)
outputAnnotation(parent);
return;
}
}
if (name == null && parent != null)
outputAnnotation(parent);
xw.startElement(xs("complexType"));
if (name != null)
xw.attribute("name", name);
if (t.isMixed())
xw.attribute("mixed", "true");
if (name != null && parent != null)
outputAnnotation(parent);
if (base != null) {
xw.startElement(xs("complexContent"));
xw.startElement(xs("extension"));
xw.attribute("base", base);
}
if (t.getParticle() != null) {
particleOutput.context = COMPLEX_TYPE_CONTEXT;
t.getParticle().accept(particleOutput);
}
outputAttributeUse(t.getAttributeUses());
if (base != null) {
xw.endElement();
xw.endElement();
}
xw.endElement();
}
private void outputComplexTypeSimpleContent(ComplexTypeSimpleContentExtension t, String name, Annotated parent) {
String base = t.getBase();
AttributeUse attributeUses = t.getAttributeUses();
if (base != null) {
base = qualifyRef(schema.getSimpleType(base).getParentSchema().getUri(), base);
if (name == null && attributeUses.equals(AttributeGroup.EMPTY)) {
xw.attribute("type", base);
if (parent != null)
outputAnnotation(parent);
return;
}
}
else if (attributeUses.equals(AttributeGroup.EMPTY)) {
simpleTypeOutput.outputWrap(t.getSimpleType(), parent);
return;
}
if (name == null && parent != null)
outputAnnotation(parent);
xw.startElement(xs("complexType"));
if (name != null)
xw.attribute("name", name);
if (name != null && parent != null)
outputAnnotation(parent);
xw.startElement(xs("simpleContent"));
if (base == null)
base = t.getSimpleType().accept(simpleTypeNamer);
if (base != null) {
xw.startElement(xs("extension"));
xw.attribute("base", base);
}
else {
xw.startElement(xs("restriction"));
xw.attribute("base", xs("anyType"));
simpleTypeOutput.outputWrap(t.getSimpleType(), null);
}
outputAttributeUse(attributeUses);
xw.endElement();
xw.endElement();
xw.endElement();
}
private void outputComplexType(Name elementName, ComplexType ct, Annotated parent) {
Name substitutionGroup = nsm.getSubstitutionGroup(elementName);
if (substitutionGroup != null) {
xw.attribute("substitutionGroup", qualifyName(substitutionGroup));
if (ct != null && ct.equals(abstractElementTypeSelector.getAbstractElementType(substitutionGroup)))
ct = null;
}
if (ct != null) {
if (ct instanceof ComplexTypeNotAllowedContent) {
xw.attribute("abstract", "true");
outputAnnotation(parent);
}
else {
complexTypeOutput.parent = parent;
ct.accept(complexTypeOutput);
}
}
else
outputAnnotation(parent);
}
private void outputAnnotation(Annotated annotated) {
Annotation annotation = annotated.getAnnotation();
if (annotation == null)
return;
xw.startElement(xs("annotation"));
String documentation = annotation.getDocumentation();
if (documentation != null) {
xw.startElement(xs("documentation"));
xw.text(documentation);
xw.endElement();
}
xw.endElement();
}
private void outputCommentList(List list) {
for (Comment comment : list)
xw.comment((comment).getContent());
}
}