empty_xpath = new HashSet<Statement>();
check_fails = new HashSet<Statement>();
final StatementNodes stm_nodes = new StatementNodes();
ChoiceNode dummy_root_content = new ChoiceNode(new ArrayList<Integer>(), null);
global_xg.addNode(dummy_root_content);
ElementNode dummy_root = new ElementNode(Automaton.makeEmpty(), dummy_root_content.getIndex(), false, null);
global_xg.addNode(dummy_root);
emptySequence = new SequenceNode(new ArrayList<Integer>(), null);
global_xg.addNode(emptySequence);
stm_nodes.setEmptySequenceNode(emptySequence);
for (Statement s : fg.getNodes()) {
s.visitBy(new BasicStatementVisitor() {
@Override
public void visitSetStm(SetStm s) {
TextNode tn = new TextNode(Automaton.makeEmpty(), s.getOrigin());
global_xg.addNode(tn);
stm_nodes.setSetTextNode(s, tn);
}
@Override
public void visitInsertStm(InsertStm s) {
SequenceNode seq = new SequenceNode(new ArrayList<Integer>(), s.getOrigin());
ChoiceNode left = new ChoiceNode(new LinkedHashSet<Integer>(), s.getOrigin());
ChoiceNode right = new ChoiceNode(new LinkedHashSet<Integer>(), s.getOrigin());
TextNode tn = new TextNode(Automaton.makeEmpty(), s.getOrigin());
global_xg.addNode(seq);
global_xg.addNode(left);
global_xg.addNode(right);
global_xg.addNode(tn);
seq.addContent(left.getIndex());
seq.addContent(right.getIndex());
stm_nodes.setInsertLeftSide(s, left);
stm_nodes.setInsertRightSide(s, right);
stm_nodes.setInsertSequenceNode(s, seq);
stm_nodes.setInsertTextNode(s, tn);
}
@Override
public void visitConcatStm(ConcatStm s) {
ChoiceNode cn = new ChoiceNode(new LinkedHashSet<Integer>(), s.getOrigin());
SequenceNode sn = new SequenceNode(new ArrayList<Integer>(), s.getOrigin());
OneOrMoreNode on = new OneOrMoreNode(cn.getIndex(), s.getOrigin());
TextNode tn = new TextNode(Automaton.makeEmpty(), s.getOrigin());
global_xg.addNode(cn);
global_xg.addNode(sn);
global_xg.addNode(on);
global_xg.addNode(tn);
on.setContent(cn.getIndex());
stm_nodes.setConcatOneOrMoreNode(s, on);
stm_nodes.setConcatTextNode(s, tn);
stm_nodes.setConcatChoiceNode(s, cn);
stm_nodes.setConcatSequenceNode(s, sn);
}
@Override
public void visitConstStm(ConstStm s) {
TemplateConstant t = s.getConst();
try {
stm_nodes.setTemplateConstantXMLFragment(t, t.getFragment());
} catch (XMLTemplateException e) {
Throwable tr = e;
if (tr.getCause() != null)
tr = tr.getCause();
String msg = tr.getMessage();
if (msg.endsWith("."))
msg = msg.substring(0, msg.length() - 1);
if (System.getProperty("dk.brics.xact.analysis.tolerate-errors") != null) {
// error recovery if enabled
System.err.println("Error: " + msg + " at " + s.getOrigin());
Node empty = new ChoiceNode(new LinkedHashSet<Integer>(), s.getOrigin());
global_xg.addNode(empty);
stm_nodes.setTemplateConstantXMLFragment(t, new XMLGraphFragment(empty, new HashSet<String>(), new HashSet<String>(), new HashMap<String,String>()));
} else {
throw new XMLAnalysisException(msg, s.getOrigin());
}
}
}
@Override
public void visitGetStm(GetStm s) {
ChoiceNode cn = new ChoiceNode(new HashSet<Integer>(), s.getOrigin());
global_xg.addNode(cn);
stm_nodes.setGetChoiceNode(s, cn);
switch (s.getKind()) {
case GETNEXTATTR:
case GETNEXTATTRIBUTE:
case GETNEXTSIBLING:
case GETFIRSTELEMENT:
SequenceNode sq = new SequenceNode(new ArrayList<Integer>(), s.getOrigin());
global_xg.addNode(sq);
stm_nodes.setGetEmptySequence(s, sq);
// OneOrMoreNode on = new OneOrMoreNode(cn.getIndex(), s.getOrigin());
// global_xg.addNode(on);
// stm_nodes.setGetOneOrMoreNode(s, on);
break;
}
}
@Override
public void visitGapifyStm(GapifyStm s) {
ChoiceNode cn = new ChoiceNode(s.getGapName(), false, false, new HashSet<Integer>(), s.getOrigin());
global_xg.addNode(cn);
stm_nodes.setGapifyChoiceNode(s, cn);
}
@Override
public void visitPlugStm(PlugStm s) {
switch (s.getKind()) {
case CLOSE:
SequenceNode sn = new SequenceNode(new ArrayList<Integer>(), s.getOrigin());
global_xg.addNode(sn);
stm_nodes.setPlugSequenceNode(s, sn);
break;
case PLUGMULTI:
case PLUG: {
TextNode tn = new TextNode(Automaton.makeEmpty(), s.getOrigin());
global_xg.addNode(tn);
stm_nodes.setPlugTextNode(s, tn);
break;
}
case PLUGWRAP: {
ChoiceNode top = new ChoiceNode(new LinkedHashSet<Integer>(), s.getOrigin());
SequenceNode empty = new SequenceNode(new ArrayList<Integer>(), s.getOrigin());
OneOrMoreNode on = new OneOrMoreNode(-1, s.getOrigin());
ChoiceNode content = new ChoiceNode(new LinkedHashSet<Integer>(), s.getOrigin());
TextNode tn = new TextNode(Automaton.makeEmpty(), s.getOrigin());
global_xg.addNode(top);
global_xg.addNode(empty);
global_xg.addNode(on);
global_xg.addNode(content);
global_xg.addNode(tn);
top.getContents().add(empty.getIndex());
top.getContents().add(on.getIndex());
on.setContent(content.getIndex());
content.getContents().add(tn.getIndex());
stm_nodes.setPlugWrapTopNode(s, top);
stm_nodes.setPlugWrapContentNode(s, content);
stm_nodes.setPlugTextNode(s, tn);
break;
}
}
}
@Override
public void visitRemoveStm(RemoveStm s) {
SequenceNode sn = new SequenceNode(new ArrayList<Integer>(), s.getOrigin());
global_xg.addNode(sn);
stm_nodes.setRemoveSequenceNode(s, sn);
}
@Override
public void visitNodeStm(NodeStm s) {
switch (s.getKind()) {
case ATTRIBUTE: {
SequenceNode seq = new SequenceNode(new LinkedList<Integer>(), s.getOrigin());
ChoiceNode left = new ChoiceNode(new LinkedHashSet<Integer>(), s.getOrigin());
AttributeNode attr = new AttributeNode(s.getName(), 0, s.getOrigin());
TextNode text = new TextNode(s.getValue(), s.getOrigin());
global_xg.addNode(seq);
global_xg.addNode(left);
global_xg.addNode(text);
global_xg.addNode(attr);
seq.addContent(left.getIndex());
left.getContents().add(attr.getIndex());
attr.setContent(text.getIndex());
stm_nodes.setStmNode(s, seq);
if (s.getNextNode() != null) {
ChoiceNode next = new ChoiceNode(new LinkedHashSet<Integer>(), s.getOrigin());
global_xg.addNode(next);
seq.addContent(next.getIndex());
stm_nodes.setStmNextNode(s, next);
}
break;
}
case ELEMENT: {
SequenceNode seq = new SequenceNode(new LinkedList<Integer>(), s.getOrigin());
ChoiceNode left1 = new ChoiceNode(new LinkedHashSet<Integer>(), s.getOrigin());
ChoiceNode left2 = new ChoiceNode(new LinkedHashSet<Integer>(), s.getOrigin());
SequenceNode left3 = new SequenceNode(new LinkedList<Integer>(), s.getOrigin());
ElementNode element = new ElementNode(s.getName(), 0, false, s.getOrigin());
global_xg.addNode(seq);
global_xg.addNode(left1);
global_xg.addNode(left2);
global_xg.addNode(left3);
global_xg.addNode(element);
seq.getContents().add(left1.getIndex());
left1.getContents().add(element.getIndex());
element.setContent(left2.getIndex());
left2.getContents().add(left3.getIndex());
stm_nodes.setStmNode(s, seq);
if (s.getNextNode() != null) {
ChoiceNode next = new ChoiceNode(new LinkedHashSet<Integer>(), s.getOrigin());
global_xg.addNode(next);
seq.addContent(next.getIndex());
stm_nodes.setStmNextNode(s, next);
}
if (s.getFirstAttr() != null) {
ChoiceNode attr = new ChoiceNode(new LinkedHashSet<Integer>(), s.getOrigin());
global_xg.addNode(attr);
left3.addContent(attr.getIndex());
stm_nodes.setStmFirstAttribute(s, attr);
}
if (s.getFirstChild() != null) {
ChoiceNode child = new ChoiceNode(new LinkedHashSet<Integer>(), s.getOrigin());
global_xg.addNode(child);
left3.addContent(child.getIndex());
stm_nodes.setStmFirstChild(s, child);
}
break;
}
case TEXT: {
SequenceNode seq = new SequenceNode(new ArrayList<Integer>(), s.getOrigin());
TextNode tn = new TextNode(s.getValue(), s.getOrigin());
global_xg.addNode(seq);
global_xg.addNode(tn);
seq.addContent(tn.getIndex());
stm_nodes.setStmNode(s, seq);
if (s.getNextNode() != null) {
ChoiceNode next = new ChoiceNode(new LinkedHashSet<Integer>(), s.getOrigin());
global_xg.addNode(next);
seq.addContent(next.getIndex());
stm_nodes.setStmNextNode(s, next);
}
break;
}
case TEMPLATEGAP:
case ATTRIBUTEGAP: {
SequenceNode seq = new SequenceNode(new LinkedList<Integer>(), s.getOrigin());
ChoiceNode cn = new ChoiceNode(s.getGap(), false, false, new LinkedHashSet<Integer>(), s.getOrigin());
global_xg.addNode(seq);
global_xg.addNode(cn);
seq.addContent(cn.getIndex());
stm_nodes.setStmNode(s, seq);
stm_nodes.setStmGap(s, cn);
if (s.getNextNode() != null) {
ChoiceNode next = new ChoiceNode(new LinkedHashSet<Integer>(), s.getOrigin());
global_xg.addNode(next);
seq.addContent(next.getIndex());
stm_nodes.setStmNextNode(s, next);
}
break;
}
case COMMENT:
case PROCESSINGINSTRUCTION: {
SequenceNode sn = new SequenceNode(new LinkedList<Integer>(), s.getOrigin());
global_xg.addNode(sn);
stm_nodes.setStmNode(s, sn);
if (s.getNextNode() != null) {
ChoiceNode next = new ChoiceNode(new LinkedHashSet<Integer>(), s.getOrigin());
global_xg.addNode(next);
sn.addContent(next.getIndex());
stm_nodes.setStmNextNode(s, next);
}
break;
}
default:
throw new RuntimeException("unknown node stm kind: " + s.getKind());
}
}
@Override
public void visitCopyStm(CopyStm s) {
SequenceNode seq = new SequenceNode(new LinkedList<Integer>(), s.getOrigin());
ChoiceNode left1 = new ChoiceNode(new LinkedHashSet<Integer>(), s.getOrigin());
global_xg.addNode(seq);
global_xg.addNode(left1);
stm_nodes.setCopyTopNode(s, seq);
stm_nodes.setCopyLeftChoice(s, left1);
seq.addContent(left1.getIndex());
if (s.getNextNode() != null) {
ChoiceNode next = new ChoiceNode(new LinkedHashSet<Integer>(), s.getOrigin());
global_xg.addNode(next);
seq.addContent(next.getIndex());
stm_nodes.setCopyNextNode(s, next);
}
switch (s.getKind()) {
case ELEMENT: { // element nodes are handled specially
ChoiceNode left2 = new ChoiceNode(new LinkedHashSet<Integer>(), s.getOrigin());
SequenceNode left3 = new SequenceNode(new LinkedList<Integer>(), s.getOrigin());
ElementNode element = new ElementNode(Automaton.makeEmpty(), 0, false, s.getOrigin());
global_xg.addNode(left2);
global_xg.addNode(left3);
global_xg.addNode(element);
stm_nodes.setCopyElementNode(s, element);
left1.getContents().add(element.getIndex());
element.setContent(left2.getIndex());
left2.getContents().add(left3.getIndex());
if (s.getFirstAttr() != null) {
ChoiceNode attr = new ChoiceNode(new LinkedHashSet<Integer>(), s.getOrigin());
global_xg.addNode(attr);
left3.addContent(attr.getIndex());