for (Map.Entry<String,Origin> entry : g.getSchemas().entrySet()) {
try {
Map<String,SequenceNode> map = XMLValidator.loadXMLSchema(new URL(entry.getKey()), xg);
g.getTypemap().putAll(map);
} catch (MalformedURLException ex) {
throw new XMLException("Schema URL is malformed", ex, entry.getValue());
} catch (ParseException ex) {
throw new XMLException("Could not parse schema: " + ex.getMessage(), ex, entry.getValue());
}
}
for (URL url : config.getAdditionalSchemas()) {
try {
Map<String, SequenceNode> map = XMLValidator.loadXMLSchema(url, xg);
g.getTypemap().putAll(map);
} catch (ParseException ex) {
throw new XMLException("Could not parse schema: " + ex.getMessage(), ex);
}
}
// link SchemaTypes to their nodes
final class Visitor extends BasicStatementVisitor {
Origin origin;
@Override
public void visitAnalyzeStm(AnalyzeStm s) {
if (s.getKind() != AnalyzeStm.Kind.HOTSPOT) {
linkSchemaType(s, s.getSchema());
}
}
@Override
public void visitValidateStm(ValidateStm s) {
linkSchemaType(s, s.getSchema());
}
@Override
public void visitGapifyStm(GapifyStm s) {
if (s.getSchema() != null)
linkSchemaType(s, s.getSchema());
}
@Override
public void visitConstStm(ConstStm s) {
TemplateConstant t = s.getConst();
if (t.getFragment() != null)
return;
// handle empty XML specially to avoid "" text nodes
if (t.getXML().isText() && t.getXML().asText().getString().isEmpty()) {
SequenceNode n = new SequenceNode(Collections.<Integer>emptyList(), s.getOrigin());
xg.addNode(n);
XMLGraphFragment f = new XMLGraphFragment(n, null, null, null);
t.setFragment(f);
} else {
XMLGraphFragment f = XMLGraphConverter.extend(xg, t.getXML(), XMLGraphConverter.GapConversion.CLOSED, true);
for (Map.Entry<String,String> en : f.getGapTypeMap().entrySet()) {
String gaptype = en.getValue();
// add gap types to the xml graph, and ensure that they are valid
resolveTypename(gaptype);
}
t.setFragment(f);
}
}
void linkSchemaType(Statement s, SchemaType type) {
type.setTypeNode(resolveTypename(type.getType()));
for (Map.Entry<String,String> gap : type.getGapTypes().entrySet()) {
String gapname = gap.getKey();
String gaptype = gap.getValue();
type.getGapTypeNodes().put(gapname, resolveTypename(gaptype));
}
}
Node resolveTypename(String name) {
if (g.getTypemap().containsKey(name)) {
return g.getTypemap().get(name);
}
String schemaName;
Quantifier quantifier;
if (name.endsWith("?")) {
schemaName = name.substring(0, name.length() - 1);
quantifier = Quantifier.ZeroOrOne;
} else if (name.endsWith("+")) {
schemaName = name.substring(0, name.length() - 1);
quantifier = Quantifier.OneOrMore;
} else if (name.endsWith("*")) {
schemaName = name.substring(0, name.length() - 1);
quantifier = Quantifier.ZeroOrMore;
} else {
schemaName = name;
quantifier = Quantifier.One;
}
Node base = g.getTypemap().get(schemaName);
// add datatypes on-the-fly when needed
if (base == null) {
if (XMLSchemaDatatypes.isDatatype(schemaName)) {
base = new TextNode(XMLSchemaDatatypes.getDatatype(schemaName, origin), new Origin("", -1, -1));
xg.addNode(base);
g.getTypemap().put(schemaName, base);
}
}
// if still not found, it does not exist
if (base == null) {
throw new XMLException("Could not find schema for type " + schemaName + " referred to at " + origin, origin);
}
Node result;
OneOrMoreNode on;
SequenceNode empty;