package org.aksw.jena_sparql_api.update;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.aksw.commons.collections.CacheSet;
import com.google.common.collect.Iterators;
import com.google.common.collect.Sets;
import org.apache.jena.sparql.core.Quad;
/**
* A DatasetListener that only forwards addition/delete events if these actions
* actually need to be carried out.
*
* @author raven
*
*/
public class GraphListererUnique
implements DatasetListener
{
private Set<DatasetListener> graphListeners = new HashSet<DatasetListener>();
private Set<Quad> insertCache = new CacheSet<Quad>(10000, true);
private Set<Quad> deleteCache = new CacheSet<Quad>(10000, true);
private Set<Quad> safeInserts = new HashSet<Quad>();
private Set<Quad> safeDeletes = new HashSet<Quad>();
private Set<Quad> verifyInserts = new HashSet<Quad>();
private Set<Quad> verifyDeletes = new HashSet<Quad>();
@Override
public void onPreDelete(Iterator<Quad> it) {
}
@Override
public void onPreInsert(Iterator<Quad> it) {
int batchSize = 10;
Iterator<Quad> chunkIt = it;
while(chunkIt.hasNext()) {
chunkIt = Iterators.limit(it, batchSize);
Set<Quad> quads = Sets.newHashSet(chunkIt);
}
}
public Set<Quad> verify(Collection<Quad> quads, boolean shouldExist) {
Set<Quad> result = new HashSet<Quad>();
for(Quad quad : quads) {
String askQuery = FilterCompiler.askForQuad(quad);
System.out.println(askQuery);
boolean exists = endpoint.createQueryExecution(askQuery).execAsk();
/*
TODO Can we set the caches here? I guess not
if(exists) {
insertCache.add(quad);
} else {
deleteCache.add(quad);
}*/
if(exists == shouldExist) {
result.add(quad);
}
}
return result;
}
/*
public void doInsert() {
for(GraphListener listener : graphListeners) {
listener.onPreBatchStart();
for(Quad quad : safeInserts) {
listener.onPreInsert(quad);
}
listener.onPreBatchEnd();
}
safeInserts.clear();
}
public void doDelete() {
for(GraphListener listener : graphListeners) {
listener.onPreBatchStart();
for(Quad quad : safeDeletes) {
listener.onPreDelete(quad);
}
listener.onPreBatchEnd();
}
safeDeletes.clear();
}
*/
public void verifyInserts() {
Set<Quad> verified = verify(verifyInserts, false);
safeInserts.addAll(verified);
verifyInserts.clear();
}
public void verifyDeletes() {
Set<Quad> verified = verify(verifyDeletes, true);
safeDeletes.addAll(verified);
verifyDeletes.clear();
}
@Override
public void onPreInsert(Quad quad) {
if(insertCache.contains(quad)) {
return;
}
if(deleteCache.contains(quad)) {
safeInserts.add(quad);
deleteCache.remove(quad);
insertCache.add(quad);
} else {
verifyInserts.add(quad);
}
}
@Override
public void onPreDelete(Quad quad) {
if(deleteCache.contains(quad)) {
return;
}
if(insertCache.contains(quad)) {
safeDeletes.add(quad);
insertCache.remove(quad);
deleteCache.add(quad);
} else {
verifyDeletes.add(quad);
}
}
public Set<UpdateListenerOld> getGraphListeners()
{
return graphListeners;
}
@Override
public void onPreBatchStart() {
}
@Override
public void onPreBatchEnd() {
verifyDeletes();
verifyInserts();
for(UpdateListenerOld listener : graphListeners) {
listener.onPreBatchStart();
for(Quad item : safeDeletes) {
listener.onPreDelete(item);
}
for(Quad item : safeInserts) {
listener.onPreInsert(item);
}
listener.onPreBatchEnd();
}
}
@Override
public void onPostBatchEnd() {
for(UpdateListenerOld listener : graphListeners) {
listener.onPostBatchStart();
for(Quad item : safeDeletes) {
listener.onPostDelete(item);
}
for(Quad item : safeInserts) {
listener.onPostInsert(item);
}
listener.onPostBatchEnd();
}
safeInserts.clear();
safeDeletes.clear();
}
}