package org.callimachusproject.stream;

import java.util.ArrayList;
import java.util.List;

import org.callimachusproject.rdfa.RDFEventReader;
import org.callimachusproject.rdfa.RDFParseException;
import org.callimachusproject.rdfa.events.OrderBy;
import org.callimachusproject.rdfa.events.RDFEvent;
import org.callimachusproject.rdfa.model.Var;
import org.callimachusproject.rdfa.model.VarOrTerm;

public class OrderedSparqlReader extends RDFEventReader {
	private final RDFEventReader delegate;
	private RDFEvent next;
	private List<List<Var>> parent_vars = new ArrayList<List<Var>>();
	private List<List<Var>> parent_nested = new ArrayList<List<Var>>();
	private List<Var> nested = new ArrayList<Var>();
	private List<Var> vars = new ArrayList<Var>();

	public OrderedSparqlReader(RDFEventReader delegate) {
		this.delegate = delegate;
	}

	@Override
	public void close() throws RDFParseException {
		delegate.close();
	}

	@Override
	protected RDFEvent take() throws RDFParseException {
		try {
			if (next != null)
				return next;
		} finally {
			next = null;
		}
		RDFEvent taken = delegate.next();
		if (taken == null)
			return taken;
		process(taken);
		return taken;
	}

	private void process(RDFEvent taken) {
		if (taken.isStartGroup() || taken.isStartWhere()) {
			parent_vars.add(vars);
			parent_nested.add(nested);
			vars = new ArrayList<Var>();
			nested = new ArrayList<Var>();
		} else if (taken.isEndGroup() || taken.isEndWhere()) {
			if (!nested.isEmpty()) {
				vars.addAll(nested);
			}
			nested = parent_nested.remove(parent_nested.size() - 1);
			nested.addAll(0, vars);
			vars = parent_vars.remove(parent_vars.size() - 1);
		} else if (taken.isTriplePattern()) {
			addIfVar(taken.asTriplePattern().getPartner());
		}
		if (taken.isEndWhere() && !nested.isEmpty()) {
			next = new OrderBy(nested);
		}
	}

	private void addIfVar(VarOrTerm subj) {
		if (subj.isVar()) {
			vars.add(subj.asVar());
		}
	}

}

@@ -78,19 +78,67 @@
 va.util.
-Lis
+HashSet;%0Aimport java.util.List;%0Aimport java.util.Se
 t;%0A%0Aimpo
@@ -795,16 +795,71 @@
 %3CVar%3E();
+%0A%09private Set%3CString%3E observed = new HashSet%3CString%3E();
 %0A%0A%09publi
@@ -1791,16 +1791,65 @@
 rn()) %7B%0A
+%09%09%09addIfVar(taken.asTriplePattern().getAbout());%0A
 %09%09%09addIf
@@ -2020,24 +2020,24 @@
 erm subj) %7B%0A
-
 %09%09if (subj.i
@@ -2042,16 +2042,52 @@
 .isVar()
+ && observed.add(subj.stringValue())
 ) %7B%0A%09%09%09v

Order variables in subject position along with partners