handling similar bnodes
diff --git a/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlGraph.java b/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlGraph.java
index 64b6133..720f7df 100644
--- a/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlGraph.java
+++ b/impl.sparql/src/main/java/org/apache/commons/rdf/impl/sparql/SparqlGraph.java
@@ -30,12 +30,15 @@
 import java.util.logging.Logger;
 import org.apache.commons.rdf.BlankNode;
 import org.apache.commons.rdf.BlankNodeOrIri;
+import org.apache.commons.rdf.Graph;
+import org.apache.commons.rdf.ImmutableGraph;
 import org.apache.commons.rdf.Iri;
 import org.apache.commons.rdf.Literal;
 import org.apache.commons.rdf.RdfTerm;
 import org.apache.commons.rdf.Triple;
 import org.apache.commons.rdf.impl.utils.AbstractGraph;
 import org.apache.commons.rdf.impl.utils.TripleImpl;
+import org.apache.commons.rdf.impl.utils.simple.SimpleGraph;
 
 /**
  *
@@ -47,6 +50,7 @@
     private static final Logger log = Logger.getLogger(SparqlGraph.class.getName());
 
     final SparqlClient sparqlClient;
+    
 
     /**
      * Constructs a Graph representing the default graph at the specified
@@ -82,7 +86,7 @@
             queryBuilder.append(" }");
             final List<Map<String, RdfTerm>> sparqlResults = sparqlClient.queryResultSet(queryBuilder.toString());
             //first to triples without bnode-conversion
-            //rawTripkles contains the triples with the BNodes from the result set
+            //rawTriples contains the triples with the BNodes from the result set
             final Collection<Triple> rawTriples = new ArrayList<>();
             for (Map<String, RdfTerm> result : sparqlResults) {
                 rawTriples.add(new TripleImpl(filterSubject != null ? filterSubject : (BlankNodeOrIri) result.get("s"),
@@ -96,6 +100,7 @@
             return (new Callable<Iterator<Triple>>() {
 
                 final Map<BlankNode, SparqlBNode> nodeMap = new HashMap<>();
+                final Set<ImmutableGraph> usedContext = new HashSet<>();
 
                 private RdfTerm useSparqlNode(RdfTerm node) throws IOException {
                     if (node instanceof BlankNodeOrIri) {
@@ -149,7 +154,7 @@
                     }
                 }
 
-                private Collection<Triple> getContext(final BlankNode node) throws IOException {
+                private ImmutableGraph getContext(final BlankNode node) throws IOException {
                     //we need to get the cntext of the BNode
                     //if the filter was for (null, null, null) we have the whole
                     //bnode context in the reuslt set, otherwise we need to get 
@@ -159,30 +164,41 @@
                             && (filterObject == null)) {
                         return getContextInRaw(node);
                     } else {
-                        final Collection<Triple> startContext = getContextInRaw(node);
-                        final Set<Collection<Triple>> expandedContexts = expandContext(startContext);
+                        final ImmutableGraph startContext = getContextInRaw(node);
+                        final Set<ImmutableGraph> expandedContexts = expandContext(startContext);
                         //expand bnode context
                         //note that there might be different contexts for 
                         //a bnode as present in the current result set
                         //in this case we just haveto make sure we don't 
                         //pick the same context for different bnodes in the resultset
-
-                        //TODO make sure we don't take one that has already been used
-                        return expandedContexts.iterator().next();
+                        ImmutableGraph result = null;
+                        for (ImmutableGraph expandedContext : expandedContexts) {
+                            if (!usedContext.contains(expandedContext)) {
+                                result = expandedContext;
+                                break;
+                            }
+                        }
+                        if (result == null) {
+                            log.warning("he underlying sparql graph seems to contain redundant triples, this might cause unexpected results");
+                            result = expandedContexts.iterator().next();
+                        } else {
+                            usedContext.add(result);
+                        }
+                        return result;
                     }
 
                 }
 
-                private Collection<Triple> getContextInRaw(BlankNode node) {
-                    final Collection<Triple> context = new ArrayList<>();
+                private ImmutableGraph getContextInRaw(BlankNode node) {
+                    final Graph contextBuilder = new SimpleGraph();
                     for (Triple rawTriple : rawTriples) {
                         BlankNodeOrIri rawSubject = rawTriple.getSubject();
                         RdfTerm rawObject = rawTriple.getObject();
                         if (rawSubject.equals(node) || rawObject.equals(node)) {
-                            context.add(rawTriple);
+                            contextBuilder.add(rawTriple);
                         }
                     }
-                    return context;
+                    return contextBuilder.getImmutableGraph();
                 }
 
                 @Override
@@ -214,7 +230,7 @@
                  * @param startContext
                  * @return
                  */
-                private Set<Collection<Triple>> expandContext(Collection<Triple> startContext) throws IOException {
+                private Set<ImmutableGraph> expandContext(Collection<Triple> startContext) throws IOException {
                     final Collection<String> triplePatterns = new ArrayList<>();
                     int varCounter = 0;
                     final Map<BlankNode, String> bNodeVarNameMap = new HashMap<>();
@@ -292,7 +308,7 @@
                     }
                     queryBuilder.append(" }");
                     final List<Map<String, RdfTerm>> expansionQueryResults = sparqlClient.queryResultSet(queryBuilder.toString());
-                    Set<Collection<Triple>> expandedContexts = new HashSet<>();
+                    Set<ImmutableGraph> expandedContexts = new HashSet<>();
                     //the query results may or may be from disjoint supergraphs
                     //we expand them all as if they are different which may lead
                     //us to the same MSG multiple times
@@ -362,7 +378,7 @@
 
                     }
                     if (expandedContexts.isEmpty()) {
-                        expandedContexts.add(startContext);
+                        expandedContexts.add(new SimpleGraph(startContext).getImmutableGraph());
                     }
                     return expandedContexts;
                 }
diff --git a/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/SimilarBNodes.java b/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/SimilarBNodes.java
new file mode 100644
index 0000000..1f52c4b
--- /dev/null
+++ b/impl.sparql/src/test/java/org/apache/commons/rdf/impl/sparql/SimilarBNodes.java
@@ -0,0 +1,98 @@
+package org.apache.commons.rdf.impl.sparql;
+
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+
+import org.apache.commons.rdf.impl.sparql.*;
+import com.hp.hpl.jena.query.DatasetAccessor;
+import com.hp.hpl.jena.query.DatasetAccessorFactory;
+import java.io.IOException;
+import java.net.ServerSocket;
+import org.apache.jena.fuseki.EmbeddedFusekiServer;
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.ModelFactory;
+import java.io.InputStream;
+import java.util.Iterator;
+import org.apache.commons.rdf.BlankNode;
+import org.apache.commons.rdf.BlankNodeOrIri;
+import org.apache.commons.rdf.Graph;
+import org.apache.commons.rdf.Iri;
+import org.apache.commons.rdf.RdfTerm;
+import org.apache.commons.rdf.Triple;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ *
+ * @author reto
+ */
+public class SimilarBNodes {
+
+    final static int serverPort = findFreePort();
+    static EmbeddedFusekiServer server;
+
+    @BeforeClass
+    public static void prepare() throws IOException {
+        final String serviceURI = "http://localhost:" + serverPort + "/ds/data";
+        final DatasetAccessor accessor = DatasetAccessorFactory.createHTTP(serviceURI);
+        final InputStream in = SimilarBNodes.class.getResourceAsStream("similar-bnodes.ttl");
+        final Model m = ModelFactory.createDefaultModel();
+        String base = "http://example.org/";
+        m.read(in, base, "TURTLE");
+        server = EmbeddedFusekiServer.memTDB(serverPort, "/ds");//dataSet.getAbsolutePath());
+        server.start();
+        System.out.println("Started fuseki on port " + serverPort);
+        accessor.putModel(m);
+    }
+
+    @AfterClass
+    public static void cleanup() {
+        server.stop();
+    }
+
+    @Test
+    public void graphSize() {
+        final Graph graph = new SparqlGraph("http://localhost:" + serverPort + "/ds/query");
+        Assert.assertEquals("Graph not of the exepected size", 2, graph.size());
+    }
+
+    
+    
+    @Test
+    public void foafKnowsFilter() {
+        final Graph graph = new SparqlGraph("http://localhost:" + serverPort + "/ds/query");
+        
+        final Iri foafKnows = new Iri("http://xmlns.com/foaf/0.1/knows");
+
+        final Iterator<Triple> iter = graph.filter(null, foafKnows, null);
+        Assert.assertTrue(iter.hasNext());
+        final Triple triple1 = iter.next();
+        final BlankNodeOrIri subject1 = triple1.getSubject();
+        Assert.assertTrue(subject1 instanceof BlankNode);
+        Assert.assertTrue(iter.hasNext());
+        final Triple triple2 = iter.next();
+        final BlankNodeOrIri subject2 = triple2.getSubject();
+        Assert.assertTrue(subject2 instanceof BlankNode);
+        Assert.assertNotEquals(subject1, subject2);
+    }
+    
+
+    
+
+    public static int findFreePort() {
+        int port = 0;
+        try (ServerSocket server = new ServerSocket(0);) {
+            port = server.getLocalPort();
+        } catch (Exception e) {
+            throw new RuntimeException("unable to find a free port");
+        }
+        return port;
+    }
+
+}
diff --git a/impl.sparql/src/test/resources/org/apache/commons/rdf/impl/sparql/similar-bnodes.ttl b/impl.sparql/src/test/resources/org/apache/commons/rdf/impl/sparql/similar-bnodes.ttl
new file mode 100644
index 0000000..16c1ceb
--- /dev/null
+++ b/impl.sparql/src/test/resources/org/apache/commons/rdf/impl/sparql/similar-bnodes.ttl
@@ -0,0 +1,8 @@
+@base <http://example.org/> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+
+
+[] foaf:knows [ foaf:name "Alice"] .
+[] foaf:knows [ foaf:name "Bob" ] .
\ No newline at end of file