Renamed CandidateSpans to CandidateSpan.
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/AttributeSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/AttributeSpans.java
index 2127e35..3792f7e 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/AttributeSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/AttributeSpans.java
@@ -226,8 +226,8 @@
      * attributes with smaller spanIds come first on the list.
      * 
      * */
-    class CandidateAttributeSpan extends CandidateSpans implements
-            Comparable<CandidateSpans> {
+    class CandidateAttributeSpan extends CandidateSpan implements
+            Comparable<CandidateSpan> {
 
         private short spanId;
         private int elementEnd;
@@ -268,7 +268,7 @@
         }
 
         @Override
-        public int compareTo(CandidateSpans o) {
+        public int compareTo(CandidateSpan o) {
             CandidateAttributeSpan cs = (CandidateAttributeSpan) o;
             if (this.spanId == cs.spanId)
                 return 0;
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/DistanceExclusionSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/DistanceExclusionSpans.java
index cff3100..2bc0cd4 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/DistanceExclusionSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/DistanceExclusionSpans.java
@@ -10,136 +10,152 @@
 
 import de.ids_mannheim.korap.query.SpanDistanceQuery;
 
-/** Span enumeration of the first spans which do NOT occur 
- * 	together with the second spans within a range of distance.
+/**
+ * Span enumeration of spans (the firstSpans) which do <em>not</em> occur
+ * together with other spans (the secondSpans) within a range of distance.
  * 
- * 	@author margaretha
+ * @author margaretha
  * */
-public class DistanceExclusionSpans extends DistanceSpans{
-	
-	private int minDistance, maxDistance;
-	private boolean isOrdered;
-	private boolean hasMoreSecondSpans;
+public class DistanceExclusionSpans extends DistanceSpans {
 
-	public DistanceExclusionSpans(SpanDistanceQuery query,
-			AtomicReaderContext context, Bits acceptDocs,
-			Map<Term, TermContext> termContexts, boolean isOrdered) 
-			throws IOException {
-		super(query, context, acceptDocs, termContexts);
-		minDistance = query.getMinDistance();
-		maxDistance = query.getMaxDistance();		
-  		this.isOrdered = isOrdered;
-  		hasMoreSpans = firstSpans.next();
-  		hasMoreSecondSpans = secondSpans.next();
-	}
+    private int minDistance, maxDistance;
+    private boolean isOrdered;
+    private boolean hasMoreSecondSpans;
 
-	@Override
-	protected boolean advance() throws IOException {
-		
-		while(hasMoreSpans){			
-			if (hasMoreSecondSpans) forwardSecondSpans();			
-			
-			if (findMatch()){ 
-				hasMoreSpans = firstSpans.next();
-				return true;
-			}
-			hasMoreSpans = firstSpans.next();
-		}
-		return false;
-	}
+    /**
+     * Constructs DistanceExclusionSpans for the specified
+     * {@link SpanDistanceQuery}.
+     * 
+     * @param query a SpanDistanceQuery
+     * @param context
+     * @param acceptDocs
+     * @param termContexts
+     * @param isOrdered a boolean flag representing the value <code>true</code>
+     *        if the spans must occur in order, <code>false</code> otherwise.
+     * @throws IOException
+     */
+    public DistanceExclusionSpans(SpanDistanceQuery query,
+            AtomicReaderContext context, Bits acceptDocs,
+            Map<Term, TermContext> termContexts) throws IOException {
+        super(query, context, acceptDocs, termContexts);
+        minDistance = query.getMinDistance();
+        maxDistance = query.getMaxDistance();
+        this.isOrdered = query.isOrdered();
+        hasMoreSpans = firstSpans.next();
+        hasMoreSecondSpans = secondSpans.next();
+    }
 
-	private void forwardSecondSpans() throws IOException{
-		
-		if (secondSpans.doc() < firstSpans.doc()){			
-			hasMoreSecondSpans = secondSpans.skipTo(firstSpans.doc());			
-		}
-		
-		// skip the secondSpan to the right side of the firstspan
-		while (hasMoreSecondSpans && secondSpans.doc() == firstSpans.doc() &&
-				firstSpans.start() >= secondSpans.end()){
+    @Override
+    protected boolean advance() throws IOException {
 
-			// the firstspan is within maxDistance
-			if (!isOrdered && calculateActualDistance() <= maxDistance){
-				break; 
-			}		
-			hasMoreSecondSpans = secondSpans.next();
-						
-		}		
-	}
-	
-	/** Calculate the distance / difference between a firstspan and 
-	 * 	a secondspan positions.
-	 * 	
-	 * @return distance
-	 * */
-	private int calculateActualDistance(){
-		// right secondSpan
-		if (firstSpans.end() <= secondSpans.start())
-			return secondSpans.start() - firstSpans.end() +1;
-		// left secondSpan
-		return firstSpans.start() - secondSpans.end() +1; 
-	}
-	
-	/** Check the distance between the current first span and second span 
-	 * 	against the min and max distance constraints.
-	 * 	
-	 * 	@return true if the distance between the first and the second spans
-	 * 			 are smaller as the minimum distance or bigger than the max
-	 * 			 distance.   
-	 * */
-	private boolean findMatch() throws IOException {
-		if (!hasMoreSecondSpans || secondSpans.doc() > firstSpans.doc()){
-			setMatchProperties();
-			return true;
-		}
-		if (minDistance == 0 &&
-				firstSpans.start() < secondSpans.end() && 
-				secondSpans.start() < firstSpans.end()){
-			return false;
-		}
-			
-		int actualDistance = calculateActualDistance();
-		if (actualDistance < minDistance || actualDistance > maxDistance){
-			setMatchProperties();
-			return true;
-		}
-		
-		return false;
-	}
-	
-	/** Set the current firstspan as the match
-	 * 
-	 * */
-	private void setMatchProperties() throws IOException{
-		matchDocNumber = firstSpans.doc();
-		matchStartPosition = firstSpans.start();
-		matchEndPosition = firstSpans.end();
-		
-  		if (collectPayloads && firstSpans.isPayloadAvailable())
-	    	matchPayload.addAll(firstSpans.getPayload());
-  		
-  		setMatchFirstSpan(new CandidateSpans(firstSpans));
-  		
-//	    log.trace("doc# {}, start {}, end {}",
-//		      matchDocNumber,
-//		      matchStartPosition,
-//		      matchEndPosition);		
-	}
+        while (hasMoreSpans) {
+            if (hasMoreSecondSpans)
+                forwardSecondSpans();
 
-	@Override
-	public boolean skipTo(int target) throws IOException {
-		if (hasMoreSpans && firstSpans.doc() < target){
-			if (!firstSpans.skipTo(target)){
-				hasMoreSpans = false;
-				return false;
-			}
-		}
-		return advance();
-	}
+            if (findMatch()) {
+                hasMoreSpans = firstSpans.next();
+                return true;
+            }
+            hasMoreSpans = firstSpans.next();
+        }
+        return false;
+    }
 
-	@Override
-	public long cost() {
-		return firstSpans.cost() + secondSpans.cost();
-	}
-	
+    /**
+     * Advance the second span until it occurs on the right side of the first
+     * span.
+     * 
+     * @throws IOException
+     */
+    private void forwardSecondSpans() throws IOException {
+
+        if (secondSpans.doc() < firstSpans.doc()) {
+            hasMoreSecondSpans = secondSpans.skipTo(firstSpans.doc());
+        }
+
+        // skip the secondSpan to the right side of the firstSpan
+        while (hasMoreSecondSpans && secondSpans.doc() == firstSpans.doc()
+                && firstSpans.start() >= secondSpans.end()) {
+
+            // the firstspan is within maxDistance
+            if (!isOrdered && calculateActualDistance() <= maxDistance) {
+                break;
+            }
+            hasMoreSecondSpans = secondSpans.next();
+        }
+    }
+
+    /**
+     * Calculate the distance / difference between a firstspan and a secondspan
+     * positions.
+     * 
+     * @return distance the difference between the positions of a firstspan and
+     *         a secondspan.
+     * */
+    private int calculateActualDistance() {
+        // right secondSpan
+        if (firstSpans.end() <= secondSpans.start())
+            return secondSpans.start() - firstSpans.end() + 1;
+        // left secondSpan
+        return firstSpans.start() - secondSpans.end() + 1;
+    }
+
+    /**
+     * Check the distance between the current first span and second span against
+     * the min and max distance constraints.
+     * 
+     * @return true if the distance between the first and the second spans are
+     *         smaller as the minimum distance or bigger than the max distance.
+     */
+    private boolean findMatch() throws IOException {
+        if (!hasMoreSecondSpans || secondSpans.doc() > firstSpans.doc()) {
+            setMatchProperties();
+            return true;
+        }
+        if (minDistance == 0 && firstSpans.start() < secondSpans.end()
+                && secondSpans.start() < firstSpans.end()) {
+            return false;
+        }
+
+        int actualDistance = calculateActualDistance();
+        if (actualDistance < minDistance || actualDistance > maxDistance) {
+            setMatchProperties();
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Set the current firstspan as the current match.
+     * 
+     * @throws IOException
+     */
+    private void setMatchProperties() throws IOException {
+        matchDocNumber = firstSpans.doc();
+        matchStartPosition = firstSpans.start();
+        matchEndPosition = firstSpans.end();
+
+        if (collectPayloads && firstSpans.isPayloadAvailable())
+            matchPayload.addAll(firstSpans.getPayload());
+
+        setMatchFirstSpan(new CandidateSpan(firstSpans));
+    }
+
+    @Override
+    public boolean skipTo(int target) throws IOException {
+        if (hasMoreSpans && firstSpans.doc() < target) {
+            if (!firstSpans.skipTo(target)) {
+                hasMoreSpans = false;
+                return false;
+            }
+        }
+        return advance();
+    }
+
+    @Override
+    public long cost() {
+        return firstSpans.cost() + secondSpans.cost();
+    }
+
 }
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/DistanceSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/DistanceSpans.java
index 2a0e447..8559405 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/DistanceSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/DistanceSpans.java
@@ -13,84 +13,130 @@
 import de.ids_mannheim.korap.query.SpanDistanceQuery;
 import de.ids_mannheim.korap.query.SpanMultipleDistanceQuery;
 
-/** DistanceSpan is a base class for enumeration of span matches, 
- * 	whose two child spans have a specific range of distance (within 
- * 	a min and a max distance). 
+/**
+ * DistanceSpan is a base class for enumeration of span matches, whose two child
+ * spans have a specific range of distance (within a min and a max distance) and
+ * other constraints (i.e. order and co-occurrence) depending on the
+ * {@link SpanDistanceQuery}. All distance related spans extends this class.
+ * 
+ * @see DistanceExclusionSpans
+ * @see ElementDistanceExclusionSpans
+ * @see OrderedDistanceSpans
+ * @see UnorderedDistanceSpans
+ * @see MultipleDistanceSpans
  * 
  * @author margaretha
  * */
-public abstract class DistanceSpans extends SimpleSpans{	
+public abstract class DistanceSpans extends SimpleSpans {
 
-	protected CandidateSpans matchFirstSpan,matchSecondSpan;	
-	protected Logger log = LoggerFactory.getLogger(DistanceSpans.class);
-	protected boolean exclusion; // because MultipleDistanceQuery doesn't have this property
-    
-	public DistanceSpans(SpanDistanceQuery query,
-			AtomicReaderContext context, Bits acceptDocs,
-			Map<Term, TermContext> termContexts) throws IOException {
-		super(query, context, acceptDocs, termContexts);
-		exclusion = query.isExclusion();
-	}
-	
-	public DistanceSpans(SpanMultipleDistanceQuery query,
-			AtomicReaderContext context, Bits acceptDocs,
-			Map<Term, TermContext> termContexts) throws IOException {
-		super(query, context, acceptDocs, termContexts);
-	}
-	
-	@Override
-	public boolean next() throws IOException {		
-		isStartEnumeration=false;
-  		matchPayload.clear();
-		return advance();
-	}	
+    protected CandidateSpan matchFirstSpan, matchSecondSpan;
+    protected Logger log = LoggerFactory.getLogger(DistanceSpans.class);
+    protected boolean exclusion; // for MultipleDistanceQuery
 
-		
-	/** Find the next span match.
-	 * @return true iff a span match is available.
-	 * */
-	protected abstract boolean advance() throws IOException; 
+    /**
+     * Constructs a DistanceSpans enumeration for the given
+     * {@link SpanDistanceQuery}.
+     * 
+     * @param query a SpanDistanceQuery
+     * @param context
+     * @param acceptDocs
+     * @param termContexts
+     * @throws IOException
+     */
+    public DistanceSpans(SpanDistanceQuery query, AtomicReaderContext context,
+            Bits acceptDocs, Map<Term, TermContext> termContexts)
+            throws IOException {
+        super(query, context, acceptDocs, termContexts);
+        exclusion = query.isExclusion();
+    }
 
-/*	*//** Find the same doc shared by element, firstspan and secondspan.
-	 *  @return true iff such a doc is found.
-	 * *//*
-	protected boolean findSameDoc(Spans x, 
-			Spans y, Spans e) throws IOException{
-		
-		while (hasMoreSpans) {
-			if (ensureSameDoc(x, y) &&
-					e.doc() == x.doc()){
-				return true;
-			}			
-			if (!ensureSameDoc(e,y)){
-				return false;
-			};
-		}		
-  		return false;
-	}*/
-	
-	public CandidateSpans getMatchFirstSpan() {
-		return matchFirstSpan;
-	}
+    /**
+     * Constructs a DistanceSpans enumeration for the given
+     * {@link SpanMultipleDistanceQuery}.
+     * 
+     * @param query a SpanMultipleDistanceQuery
+     * @param context
+     * @param acceptDocs
+     * @param termContexts
+     * @throws IOException
+     */
+    public DistanceSpans(SpanMultipleDistanceQuery query,
+            AtomicReaderContext context, Bits acceptDocs,
+            Map<Term, TermContext> termContexts) throws IOException {
+        super(query, context, acceptDocs, termContexts);
+    }
 
-	public void setMatchFirstSpan(CandidateSpans matchFirstSpan) {
-		this.matchFirstSpan = matchFirstSpan;
-	}
+    @Override
+    public boolean next() throws IOException {
+        isStartEnumeration = false;
+        matchPayload.clear();
+        return advance();
+    }
 
-	public CandidateSpans getMatchSecondSpan() {
-		return matchSecondSpan;
-	}
+    /**
+     * Advances the current span enumeration to the next span match.
+     * 
+     * @return <code>true</code> if a span match is available,
+     *         <code>false</code> otherwise.
+     * */
+    protected abstract boolean advance() throws IOException;
 
-	public void setMatchSecondSpan(CandidateSpans matchSecondSpan) {
-		this.matchSecondSpan = matchSecondSpan;
-	}
+    /**
+     * Returns the first span of the current match.
+     * 
+     * @return the first span of the current match.
+     */
+    public CandidateSpan getMatchFirstSpan() {
+        return matchFirstSpan;
+    }
 
-	public boolean isExclusion() {
-		return exclusion;
-	}
+    /**
+     * Sets the first span of the current match.
+     * 
+     * @param matchFirstSpan the first span of the current match.
+     */
+    public void setMatchFirstSpan(CandidateSpan matchFirstSpan) {
+        this.matchFirstSpan = matchFirstSpan;
+    }
 
-	public void setExclusion(boolean exclusion) {
-		this.exclusion = exclusion;
-	}
+    /**
+     * Returns the second span of the current match.
+     * 
+     * @return the second span of the current match.
+     */
+    public CandidateSpan getMatchSecondSpan() {
+        return matchSecondSpan;
+    }
+
+    /**
+     * Sets the second span of the current match.
+     * 
+     * @param matchSecondSpan the second span of the current match.
+     */
+    public void setMatchSecondSpan(CandidateSpan matchSecondSpan) {
+        this.matchSecondSpan = matchSecondSpan;
+    }
+
+    /**
+     * Tells if the second span must occur together with the first span, or not.
+     * 
+     * @return <code>true</code> if the second span must <em>not</em> occur
+     *         together with the first span, <code>false</code> otherwise.
+     */
+    public boolean isExclusion() {
+        return exclusion;
+    }
+
+    /**
+     * Sets <code>true</code> if the second span must <em>not</em> occur
+     * together with the first span, <code>false</code> otherwise.
+     * 
+     * @param exclusion a boolean with the value <code>true</code> if the second
+     *        span must <em>not</em> occur together with the first span,
+     *        <code>false</code> otherwise.
+     */
+    public void setExclusion(boolean exclusion) {
+        this.exclusion = exclusion;
+    }
 
 }
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/ElementDistanceExclusionSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/ElementDistanceExclusionSpans.java
index 24008bd..3e701b6 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/ElementDistanceExclusionSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/ElementDistanceExclusionSpans.java
@@ -14,241 +14,361 @@
 
 import de.ids_mannheim.korap.query.SpanDistanceQuery;
 
-/** Span enumeration of the first spans which do NOT occur together 
- * 	with the second spans within a range of some element-based distance 
- * 	(sentence or paragraph). Note: The element distance unit does not 
- * 	overlap to each other.
+/**
+ * Span enumeration of spans (firstSpans) which do <em>not</em> occur together
+ * with other spans (secondSpans) on the right side, within a range of an
+ * element-based distance (i.e. a sentence or a paragraph as the distance unit).
+ * If the query requires that the spans are ordered, then the firstSpans must
+ * occur before the secondSpans. In this class, firstSpans are also referred to
+ * as target spans and second spans as candidate spans.<br/>
+ * <br/>
+ * Note: The element distance unit does not overlap to each other.
  * 
- * 	@author margaretha
+ * @author margaretha
  * */
-public class ElementDistanceExclusionSpans extends DistanceSpans{
+public class ElementDistanceExclusionSpans extends DistanceSpans {
 
-	private Spans elements;
-	private boolean hasMoreElements;
-	private int elementPosition;
-	
-	private boolean isOrdered;
-	private boolean hasMoreSecondSpans;
-		
-	protected List<CandidateSpans> candidateList, targetList;	
-	private int currentDocNum;
-	
-	private int minDistance, maxDistance;
-	private int firstSpanPostion;
+    private Spans elements;
+    private boolean hasMoreElements;
+    private int elementPosition;
 
-        public static final boolean DEBUG = false;
+    private boolean isOrdered;
+    private boolean hasMoreSecondSpans;
 
-	public ElementDistanceExclusionSpans(SpanDistanceQuery query,
-			AtomicReaderContext context, Bits acceptDocs,
-			Map<Term, TermContext> termContexts, boolean isOrdered) 
-			throws IOException {
-		super(query, context, acceptDocs, termContexts);
-		
-		elements = query.getElementQuery().
-	  			getSpans(context, acceptDocs, termContexts);	  		
-  		hasMoreElements = elements.next();  		
-  		hasMoreSpans = firstSpans.next() && hasMoreElements;  		  		
-  		hasMoreSecondSpans = secondSpans.next();
-  		
-  		elementPosition=0;
-  		this.isOrdered = isOrdered;
-  		candidateList = new ArrayList<CandidateSpans>();
-  		targetList = new ArrayList<CandidateSpans>();
-  		currentDocNum = firstSpans.doc();
-  		
-  		minDistance = query.getMinDistance();
-		maxDistance = query.getMaxDistance();	
-	}
+    // other first spans occurred between the current target and the second
+    // spans
+    protected List<CandidateSpan> targetList;
+    // secondSpans occurring near the firstSpans
+    protected List<CandidateSpan> candidateList;
+    private int currentDocNum;
 
-	@Override
-	protected boolean advance() throws IOException {
-		while(!targetList.isEmpty() || (hasMoreSpans && ensureSameDoc(firstSpans, elements))){
-			if (!targetList.isEmpty()){
-				if (isTargetValid()) return true;
-				else continue;
-			}
-			if (checkFirstSpan()) return true;			
-		}
-		return false;
-	}
-	
-	private boolean isTargetValid() throws IOException{
-		CandidateSpans target = targetList.get(0);
-		targetList.remove(0);			
-		firstSpanPostion = target.getPosition();
-		filterCandidateList(firstSpanPostion);
-		collectRightCandidates();
-		
-		if (isWithinDistance()){
-			return false;
-		}		
-		setMatchProperties(target);
-		return true;
-	}
-	
-	private boolean checkFirstSpan() throws IOException{
-		if (firstSpans.doc() != currentDocNum){
-			currentDocNum = firstSpans.doc();
-			candidateList.clear();
-		}
-		
-		if (hasMoreSecondSpans) {
-			if (secondSpans.doc() == firstSpans.doc()){ 
-				return (findMatch() ? true : false);
-			}			
-			else if (secondSpans.doc() < firstSpans.doc()){
-				hasMoreSecondSpans = secondSpans.skipTo(firstSpans.doc());
-				return false;
-			}
-		}		
-		return (isFirstSpanValid() ? true : false);
-	}
-	
-	private boolean isFirstSpanValid() throws IOException{
-		if (candidateList.isEmpty()){
-			if (isFirstSpanInElement()){		
-				setMatchProperties(new CandidateSpans(firstSpans,elementPosition));
-				hasMoreSpans = firstSpans.next();
-				return true;
-			}
-			hasMoreSpans = firstSpans.next();
-			return false;		
-		}
-		return (findMatch() ? true : false);			
-	}
-	
-	private boolean advanceElementTo(Spans span) throws IOException{
-		while (hasMoreElements && 
-				elements.doc() == currentDocNum &&
-				elements.start() < span.end()){
-			
-			if (span.start() >= elements.start() &&
-					span.end() <= elements.end()){
-				return true;
-			}			
-			
-			hasMoreElements = elements.next();
-			elementPosition++;
-		}
-		return false;
-	}
+    private int minDistance, maxDistance;
+    private int firstSpanPostion;
 
-	private boolean findMatch() throws IOException {		
-		if (!isOrdered) collectLeftCandidates();
-		
-		if (isFirstSpanInElement()){
-			CandidateSpans target = new CandidateSpans(firstSpans,elementPosition);
-			hasMoreSpans = firstSpans.next();
-			// Checking the secondspans in the left side
-			if (!isOrdered && isWithinDistance()) return false;
-			// Checking the secondspans in the right side
-			collectRightCandidates();
-			if (isWithinDistance()) return false;
-			
-			setMatchProperties(target);
-			return true;
-		}
-		hasMoreSpans = firstSpans.next();
-		return false;
-	}
-	
-	private void collectRightCandidates() throws IOException{
-		while (hasMoreSecondSpans && secondSpans.doc() == currentDocNum){
-			
-			if (elementPosition > firstSpanPostion+maxDistance){
-				break;
-			}
-			if (hasMoreSpans && firstSpans.start() < secondSpans.start() &&
-					firstSpans.doc() == currentDocNum){
-				if (advanceElementTo(firstSpans)){
-					targetList.add(new CandidateSpans(firstSpans, elementPosition));
-				}
-				hasMoreSpans = firstSpans.next();
-				continue;
-			}
-			
-			if (advanceElementTo(secondSpans)){
-				candidateList.add(new CandidateSpans(secondSpans,elementPosition));
-			}
-			hasMoreSecondSpans = secondSpans.next();
-		}		
-	}
-	
-	private void collectLeftCandidates() throws IOException{
-		while(hasMoreSecondSpans && secondSpans.doc() == firstSpans.doc() &&
-				secondSpans.start() < firstSpans.end()){
-			if (advanceElementTo(secondSpans)){
-				candidateList.add(new CandidateSpans(secondSpans,elementPosition));
-				filterCandidateList(elementPosition);
-			}
-			hasMoreSecondSpans = secondSpans.next();
-		}	
-	}
-	
-	private boolean isWithinDistance(){
-		int actualDistance; 
-		for (CandidateSpans cs: candidateList){
-			actualDistance = cs.getPosition() - firstSpanPostion;
-			if (!isOrdered) actualDistance = Math.abs(actualDistance);
-			
-			if (minDistance <= actualDistance && actualDistance <= maxDistance)
-				return true;
-		}
-		return false;
-	}
-	
-	private boolean isFirstSpanInElement() throws IOException {
-		if (advanceElementTo(firstSpans)){
-			firstSpanPostion = elementPosition;
-			filterCandidateList(firstSpanPostion);
-			return true;
-		}
-		return false;
-	}
-	
-	private void filterCandidateList(int position){
-		
-		Iterator<CandidateSpans> i = candidateList.iterator();
-		CandidateSpans cs;
-		while(i.hasNext()){
-			cs = i.next();
-			if (cs.getPosition() == position || 
-					cs.getPosition()+maxDistance >= position){
-				break;
-			}			
-			i.remove();
-		}		
-	}	
-	
-	private void setMatchProperties(CandidateSpans match) throws IOException{
-		matchDocNumber = match.getDoc();
-		matchStartPosition = match.getStart();
-		matchEndPosition = match.getEnd();
-		
-  		if (collectPayloads && match.getPayloads() != null)
-	    	matchPayload.addAll(match.getPayloads());
-  		
-  		setMatchFirstSpan(match);
+    /**
+     * Constructs ElementDistanceExclusionSpans from the specified
+     * {@link SpanDistanceQuery}.
+     * 
+     * @param query a SpanDistanceQuery
+     * @param context
+     * @param acceptDocs
+     * @param termContexts
+     * @throws IOException
+     */
+    public ElementDistanceExclusionSpans(SpanDistanceQuery query,
+            AtomicReaderContext context, Bits acceptDocs,
+            Map<Term, TermContext> termContexts) throws IOException {
+        super(query, context, acceptDocs, termContexts);
 
-		if (DEBUG)
-		    log.trace("doc# {}, start {}, end {}",matchDocNumber,matchStartPosition,
-			      matchEndPosition);		
-	}
+        elements = query.getElementQuery().getSpans(context, acceptDocs,
+                termContexts);
+        hasMoreElements = elements.next();
+        hasMoreSpans = firstSpans.next() && hasMoreElements;
+        hasMoreSecondSpans = secondSpans.next();
 
-	@Override
-	public boolean skipTo(int target) throws IOException {
-		if (hasMoreSpans && firstSpans.doc() < target){
-			if (!firstSpans.skipTo(target)){
-				hasMoreSpans = false;
-				return false;
-			}
-		}
-		return advance();
-	}
+        elementPosition = 0;
+        this.isOrdered = query.isOrdered();
+        candidateList = new ArrayList<CandidateSpan>();
+        targetList = new ArrayList<CandidateSpan>();
+        currentDocNum = firstSpans.doc();
 
-	@Override
-	public long cost() {
-		return elements.cost() + firstSpans.cost() + secondSpans.cost();
-	}
+        minDistance = query.getMinDistance();
+        maxDistance = query.getMaxDistance();
+    }
+
+    @Override
+    protected boolean advance() throws IOException {
+        while (!targetList.isEmpty()
+                || (hasMoreSpans && ensureSameDoc(firstSpans, elements))) {
+            if (!targetList.isEmpty()) {
+                if (isFirstTargetValid())
+                    return true;
+                else
+                    continue;
+            }
+            if (findMatch())
+                return true;
+        }
+        return false;
+    }
+
+    /**
+     * Tells if the first target from the target list is a match.
+     * 
+     * @return <code>true</code> if the first target from the target list is a
+     *         match, <code>false</code> otherwise.
+     * @throws IOException
+     */
+    private boolean isFirstTargetValid() throws IOException {
+        CandidateSpan target = targetList.get(0);
+        targetList.remove(0);
+        firstSpanPostion = target.getPosition();
+        filterCandidateList(firstSpanPostion);
+        collectRightCandidates();
+
+        if (isWithinDistance()) {
+            return false;
+        }
+        setMatchProperties(target);
+        return true;
+    }
+
+    /**
+     * Validate if the current firstSpan is a match.
+     * 
+     * @return <code>true</code> if a match is found, <code>false</code>
+     *         otherwise.
+     * @throws IOException
+     */
+    private boolean findMatch() throws IOException {
+        if (firstSpans.doc() != currentDocNum) {
+            currentDocNum = firstSpans.doc();
+            candidateList.clear();
+        }
+
+        if (hasMoreSecondSpans) {
+            if (secondSpans.doc() == firstSpans.doc()) {
+                return (isFirstSpanValid() ? true : false);
+            } else if (secondSpans.doc() < firstSpans.doc()) {
+                hasMoreSecondSpans = secondSpans.skipTo(firstSpans.doc());
+                return false;
+            }
+        }
+
+        // return (isFirstSpanValid() ? true : false);
+
+        if (candidateList.isEmpty()) {
+            if (isFirstSpanInElement()) {
+                setMatchProperties(new CandidateSpan(firstSpans,
+                        elementPosition));
+                hasMoreSpans = firstSpans.next();
+                return true;
+            }
+            hasMoreSpans = firstSpans.next();
+            return false;
+        }
+        return (isFirstSpanValid() ? true : false);
+    }
+
+    /**
+     * Tells if the current firstSpan is a match.
+     * 
+     * @return <code>true</code> if a match is found, <code>false</code>
+     *         otherwise.
+     * @throws IOException <pre>
+     * private boolean isFirstSpanValid() throws IOException {
+     *     if (candidateList.isEmpty()) {
+     *         if (isFirstSpanInElement()) {
+     *             setMatchProperties(new CandidateSpan(firstSpans, elementPosition));
+     *             hasMoreSpans = firstSpans.next();
+     *             return true;
+     *         }
+     *         hasMoreSpans = firstSpans.next();
+     *         return false;
+     *     }
+     *     return (findMatch() ? true : false);
+     * }
+     * </pre>
+     */
+
+    /**
+     * Tells if the given span is in an element distance unit, or not, by
+     * advancing the element distance unit to the span position.
+     * 
+     * @param span a span
+     * @return <code>true</code> if the element distance unit can be advanced to
+     *         contain the given span, <code>false</code> otherwise.
+     * @throws IOException
+     */
+    private boolean advanceElementTo(Spans span) throws IOException {
+        while (hasMoreElements && elements.doc() == currentDocNum
+                && elements.start() < span.end()) {
+
+            if (span.start() >= elements.start()
+                    && span.end() <= elements.end()) {
+                return true;
+            }
+
+            hasMoreElements = elements.next();
+            elementPosition++;
+        }
+        return false;
+    }
+
+    /**
+     * Tells if the current firstSpan is a match.
+     * 
+     * @return <code>true</code> if a match is found, <code>false</code>
+     *         otherwise.
+     * @throws IOException
+     */
+    private boolean isFirstSpanValid() throws IOException {
+        if (!isOrdered)
+            collectLeftCandidates();
+
+        if (isFirstSpanInElement()) {
+            CandidateSpan target = new CandidateSpan(firstSpans,
+                    elementPosition);
+            hasMoreSpans = firstSpans.next();
+            // Checking if the secondspans in the *left* side are not within the
+            // distance range
+            if (!isOrdered && isWithinDistance())
+                return false;
+            // Checking if the secondspans in the *right* side are not within
+            // the distance range
+            collectRightCandidates();
+            if (isWithinDistance())
+                return false;
+
+            setMatchProperties(target);
+            return true;
+        }
+        hasMoreSpans = firstSpans.next();
+        return false;
+    }
+
+    /**
+     * Collects all second spans (candidates) on the right side of the current
+     * first span (target) position. At the same time, also collects all other
+     * first spans occurring before the second spans.
+     * 
+     * @throws IOException
+     */
+    private void collectRightCandidates() throws IOException {
+        while (hasMoreSecondSpans && secondSpans.doc() == currentDocNum) {
+
+            if (elementPosition > firstSpanPostion + maxDistance) {
+                break;
+            }
+            // stores all first spans occurring before the current second span
+            // in the target list.
+            if (hasMoreSpans && firstSpans.start() < secondSpans.start()
+                    && firstSpans.doc() == currentDocNum) {
+                if (advanceElementTo(firstSpans)) {
+                    targetList.add(new CandidateSpan(firstSpans,
+                            elementPosition));
+                }
+                hasMoreSpans = firstSpans.next();
+                continue;
+            }
+            // collects only second spans occurring inside an element
+            if (advanceElementTo(secondSpans)) {
+                candidateList.add(new CandidateSpan(secondSpans,
+                        elementPosition));
+            }
+            hasMoreSecondSpans = secondSpans.next();
+        }
+    }
+
+    /**
+     * Collects all the second spans (candidates) occurring before the first
+     * spans, and are within an element distance unit.
+     * 
+     * @throws IOException
+     */
+    private void collectLeftCandidates() throws IOException {
+        while (hasMoreSecondSpans && secondSpans.doc() == firstSpans.doc()
+                && secondSpans.start() < firstSpans.end()) {
+            if (advanceElementTo(secondSpans)) {
+                candidateList.add(new CandidateSpan(secondSpans,
+                        elementPosition));
+                filterCandidateList(elementPosition);
+            }
+            hasMoreSecondSpans = secondSpans.next();
+        }
+    }
+
+    /**
+     * Tells if there is a candidate span (second span) occurring together with
+     * the target span (firstspan) within the minimum and maximum distance
+     * range.
+     * 
+     * @return <code>true</code> if there is a candidate span (second span)
+     *         occurring together with the target span (firstspan) within the
+     *         minimum and maximum distance range, <code>false</code> otherwise.
+     */
+    private boolean isWithinDistance() {
+        int actualDistance;
+        for (CandidateSpan cs : candidateList) {
+            actualDistance = cs.getPosition() - firstSpanPostion;
+            if (!isOrdered)
+                actualDistance = Math.abs(actualDistance);
+
+            if (minDistance <= actualDistance && actualDistance <= maxDistance)
+                return true;
+        }
+        return false;
+    }
+
+    /**
+     * Tells if the current firstSpans is in an element.
+     * 
+     * @return <code>true</code> if the current firstSpans in is an element,
+     *         <code>false</code> otherwise.
+     * @throws IOException
+     */
+    private boolean isFirstSpanInElement() throws IOException {
+        if (advanceElementTo(firstSpans)) {
+            firstSpanPostion = elementPosition;
+            filterCandidateList(firstSpanPostion);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * From the candidateList, removes all candidate spans that are too far from
+     * the given target position, and have exactly the same position as the
+     * target position. Only candidate spans occurring within a range of
+     * distance from the target position, are retained.
+     * 
+     * @param position target/firstSpan position
+     */
+    private void filterCandidateList(int position) {
+
+        Iterator<CandidateSpan> i = candidateList.iterator();
+        CandidateSpan cs;
+        while (i.hasNext()) {
+            cs = i.next();
+            if (cs.getPosition() == position
+                    || cs.getPosition() + maxDistance >= position) {
+                break;
+            }
+            i.remove();
+        }
+    }
+
+    /**
+     * Sets the given target/match CandidateSpan as the current match.
+     * 
+     * @param match a target/firstSpan wrapped as a CandidateSpan
+     * @throws IOException
+     */
+    private void setMatchProperties(CandidateSpan match) throws IOException {
+        matchDocNumber = match.getDoc();
+        matchStartPosition = match.getStart();
+        matchEndPosition = match.getEnd();
+
+        if (collectPayloads && match.getPayloads() != null)
+            matchPayload.addAll(match.getPayloads());
+
+        setMatchFirstSpan(match);
+    }
+
+    @Override
+    public boolean skipTo(int target) throws IOException {
+        if (hasMoreSpans && firstSpans.doc() < target) {
+            if (!firstSpans.skipTo(target)) {
+                hasMoreSpans = false;
+                return false;
+            }
+        }
+        return advance();
+    }
+
+    @Override
+    public long cost() {
+        return elements.cost() + firstSpans.cost() + secondSpans.cost();
+    }
 
 }
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/ElementDistanceSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/ElementDistanceSpans.java
index 20c9691..229004e 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/ElementDistanceSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/ElementDistanceSpans.java
@@ -47,7 +47,7 @@
 
 	@Override
 	protected boolean findMatch() throws IOException {
-		CandidateSpans candidateSpan = candidateList.get(candidateListIndex);
+		CandidateSpan candidateSpan = candidateList.get(candidateListIndex);
 		int actualDistance = secondSpanPostion - candidateSpan.getPosition();
 		
 		// In the same element
@@ -91,7 +91,7 @@
 				firstSpans.start() < secondSpans.end()){
 			
 			if (advanceElementTo(firstSpans)){
-				candidateList.add(new CandidateSpans(firstSpans,elementPosition));				
+				candidateList.add(new CandidateSpan(firstSpans,elementPosition));				
 				filterCandidateList(elementPosition);
 			}
 			hasMoreFirstSpans = firstSpans.next();
@@ -124,8 +124,8 @@
 	 * */
 	private void filterCandidateList(int position){
 		
-		Iterator<CandidateSpans> i = candidateList.iterator();
-		CandidateSpans cs;
+		Iterator<CandidateSpan> i = candidateList.iterator();
+		CandidateSpan cs;
 		while(i.hasNext()){
 			cs = i.next();
 			if (cs.getPosition() == position || 
@@ -150,7 +150,7 @@
 	
 	@Override
 	public long cost() {
-		CandidateSpans candidateSpan = candidateList.get(candidateListIndex);
+		CandidateSpan candidateSpan = candidateList.get(candidateListIndex);
 		return elements.cost() + candidateSpan.getCost() + secondSpans.cost();
 	}
 }
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/ElementSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/ElementSpans.java
index 43163c8..8b8d90b 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/ElementSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/ElementSpans.java
@@ -154,7 +154,7 @@
 	
 	/** Match candidate for element spans.
 	 * */	
-	class CandidateElementSpans extends CandidateSpans {
+	class CandidateElementSpans extends CandidateSpan {
 		
 		private short elementRef;
 		
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/ExpandedExclusionSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/ExpandedExclusionSpans.java
index 5cfe210..79c6db4 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/ExpandedExclusionSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/ExpandedExclusionSpans.java
@@ -24,7 +24,7 @@
 	private int min, max;
 	private int direction;
 	private byte classNumber;
-	private List<CandidateSpans> candidateSpans;
+	private List<CandidateSpan> candidateSpans;
 	private boolean hasMoreNotClause;
 	private Spans notClause;
 	
@@ -54,7 +54,7 @@
 		this.notClause = secondSpans;
 		this.hasMoreNotClause = notClause.next();		
 		
-		candidateSpans = new ArrayList<CandidateSpans>();		
+		candidateSpans = new ArrayList<CandidateSpan>();		
 		hasMoreSpans = firstSpans.next();
 	}
 
@@ -69,7 +69,7 @@
 		while (hasMoreSpans || candidateSpans.size() > 0){
 			if (candidateSpans.size() > 0){
 				// set a candidate span as a match
-				CandidateSpans cs = candidateSpans.get(0);
+				CandidateSpan cs = candidateSpans.get(0);
 				matchDocNumber = cs.getDoc();
 				matchStartPosition = cs.getStart();
 				matchEndPosition = cs.getEnd();
@@ -103,14 +103,14 @@
 	private void expandLeft() throws IOException{
 		//int counter = max;
 		int maxPos = max;
-		CandidateSpans lastNotClause = null;
+		CandidateSpan lastNotClause = null;
 		while (hasMoreNotClause && 
 				notClause.start() < firstSpans.start()){
 			
 			// between max and firstspan.start()
 			if (notClause.start() >= firstSpans.start() - maxPos){
 				maxPos = firstSpans.start() - notClause.start() -1;
-				lastNotClause = new CandidateSpans(notClause);
+				lastNotClause = new CandidateSpan(notClause);
 				//counter--;
 			} 
 			if (!notClause.next()) hasMoreNotClause = false;
@@ -140,13 +140,13 @@
 		int maxPos = max;
 		boolean isFound = false;
 		
-		CandidateSpans firstNotClause = null;
+		CandidateSpan firstNotClause = null;
 		//System.out.println("main start:"+firstSpans.start());
 		while (hasMoreNotClause && notClause.start() < expansionEnd){
 			// between firstspan.end() and expansionEnd
 			if (!isFound && notClause.start() >= firstSpans.end()){							
 				maxPos = notClause.start() - firstSpans.end() -1;
-				firstNotClause = new CandidateSpans(notClause);
+				firstNotClause = new CandidateSpan(notClause);
 				isFound = true;
 			}						
 			if (!notClause.next()) hasMoreNotClause = false;
@@ -173,7 +173,7 @@
 			throws IOException {
 		int counter;
 		int start, end;
-		CandidateSpans cs;
+		CandidateSpan cs;
 		if (direction < 0 ) { // left
 			counter = maxPos;
 			while (counter >= min){
@@ -181,7 +181,7 @@
 				if (start > -1 ){					
 					end = firstSpans.end();
 					//System.out.println(start+","+end);
-					cs = new CandidateSpans(start, end, firstSpans.doc(),
+					cs = new CandidateSpan(start, end, firstSpans.doc(),
 							firstSpans.cost(), 
 							calculatePayload(start,firstSpans.start())
 					);
@@ -197,7 +197,7 @@
 				end = firstSpans.end() + counter;
 				//System.out.println(start+","+end);
 				
-				cs = new CandidateSpans(start, end, firstSpans.doc(), 
+				cs = new CandidateSpan(start, end, firstSpans.doc(), 
 						firstSpans.cost(), 
 						calculatePayload(firstSpans.end(), end)
 				);				
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/ExpandedSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/ExpandedSpans.java
index 3fd0afe..81032a6 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/ExpandedSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/ExpandedSpans.java
@@ -21,7 +21,7 @@
 	private int min, max;
 	private byte classNumber;
 	private int direction;	
-	private List<CandidateSpans> candidateSpans;
+	private List<CandidateSpan> candidateSpans;
 	private long matchCost;
 	
 	public ExpandedSpans(SpanExpansionQuery spanExpansionQuery,
@@ -33,7 +33,7 @@
 		this.direction = spanExpansionQuery.getDirection();
 		this.classNumber = spanExpansionQuery.getClassNumber();
 		
-		candidateSpans = new ArrayList<CandidateSpans>();		
+		candidateSpans = new ArrayList<CandidateSpan>();		
 		hasMoreSpans = true;		
 	}
 
@@ -59,14 +59,14 @@
 	}
 	
 	private void setCandidateList() throws IOException {
-		CandidateSpans cs;
+		CandidateSpan cs;
 		int counter, start, end;
 		
 		if (direction < 0 ){
 			counter = max;
 			while (counter >= min ){
 				start =  Math.max(0,firstSpans.start() - counter);			
-				cs = new CandidateSpans(
+				cs = new CandidateSpan(
 						start, 
 						firstSpans.end(), 
 						firstSpans.doc(), 
@@ -83,7 +83,7 @@
 			while (counter <= max){
 				// TODO: How do I know if the end is already too far (over the end of the doc)? 
 				end = firstSpans.end() + counter;
-				cs = new CandidateSpans(
+				cs = new CandidateSpan(
 						firstSpans.start(), 
 						end, 
 						firstSpans.doc(), 
@@ -118,7 +118,7 @@
 		return buffer.array();
 	}
 
-	private void setMatch(CandidateSpans candidateSpan) {
+	private void setMatch(CandidateSpan candidateSpan) {
 		matchDocNumber = candidateSpan.getDoc();
 		matchStartPosition = candidateSpan.getStart();
 		matchEndPosition = candidateSpan.getEnd();			
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/MultipleDistanceSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/MultipleDistanceSpans.java
index 52a0964..0dbd06e 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/MultipleDistanceSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/MultipleDistanceSpans.java
@@ -91,11 +91,11 @@
 	 * */	
 	protected boolean findMatch() throws IOException {
 		 		
-		CandidateSpans xf = x.getMatchFirstSpan();
-		CandidateSpans xs = x.getMatchSecondSpan();
+		CandidateSpan xf = x.getMatchFirstSpan();
+		CandidateSpan xs = x.getMatchSecondSpan();
 		
-		CandidateSpans yf = y.getMatchFirstSpan();
-		CandidateSpans ys = y.getMatchSecondSpan();
+		CandidateSpan yf = y.getMatchFirstSpan();
+		CandidateSpan ys = y.getMatchSecondSpan();
 		
 		if (x.isExclusion() || y.isExclusion()){			
 			if (xf.getStart() == yf.getStart() && xf.getEnd() == yf.getEnd()){
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/NextSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/NextSpans.java
index e03940a..7ebbc46 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/NextSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/NextSpans.java
@@ -24,8 +24,8 @@
  * */
 public class NextSpans extends SimpleSpans {	
 	
-	private List<CandidateSpans> matchList;
-	private List<CandidateSpans> candidateList;
+	private List<CandidateSpan> matchList;
+	private List<CandidateSpan> candidateList;
 	private int candidateListDocNum;
 	private boolean hasMoreFirstSpan;
 	
@@ -93,8 +93,8 @@
 	}
 	
 	private void searchCandidates() throws IOException {
-		Iterator<CandidateSpans> i = candidateList.iterator();
-		CandidateSpans cs;
+		Iterator<CandidateSpan> i = candidateList.iterator();
+		CandidateSpan cs;
 		while(i.hasNext()){
 			cs = i.next();
 			if (cs.getStart() == firstSpans.end()){
@@ -115,14 +115,14 @@
 				break;
 			}
 			if (secondSpans.start() == firstSpans.end()){
-				candidateList.add(new CandidateSpans(secondSpans));
-				addMatch(new CandidateSpans(secondSpans));
+				candidateList.add(new CandidateSpan(secondSpans));
+				addMatch(new CandidateSpan(secondSpans));
 			}
 			hasMoreSpans = secondSpans.next();
 		}
 	}
 	
-	private void addMatch(CandidateSpans cs) throws IOException{
+	private void addMatch(CandidateSpan cs) throws IOException{
 		
 		int start = firstSpans.start();
 		long cost = firstSpans.cost() + cs.getCost();
@@ -135,7 +135,7 @@
 				payloads.addAll(cs.getPayloads());
 		}	
 		
-		matchList.add(new CandidateSpans(start,cs.getEnd(),candidateListDocNum,cost,
+		matchList.add(new CandidateSpan(start,cs.getEnd(),candidateListDocNum,cost,
 				payloads));
 	}
 
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/OrderedDistanceSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/OrderedDistanceSpans.java
index bdf81ef..1dd1a04 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/OrderedDistanceSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/OrderedDistanceSpans.java
@@ -22,7 +22,7 @@
 	protected boolean hasMoreFirstSpans;	
 	protected int minDistance,maxDistance;
 	
-	protected List<CandidateSpans> candidateList;
+	protected List<CandidateSpan> candidateList;
 	protected int candidateListIndex;
 	protected int candidateListDocNum;
 	
@@ -84,11 +84,11 @@
 	
 	/** Define the properties of a span match.
 	 * */
-	protected void setMatchProperties(CandidateSpans candidateSpan, 
+	protected void setMatchProperties(CandidateSpan candidateSpan, 
 			boolean isDistanceZero) throws IOException{
 		
 		setMatchFirstSpan(candidateSpan);
-		setMatchSecondSpan(new CandidateSpans(secondSpans));
+		setMatchSecondSpan(new CandidateSpan(secondSpans));
 		
 		if (isDistanceZero){
 			matchStartPosition = Math.min(candidateSpan.getStart(), secondSpans.start());
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/RelationPartSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/RelationPartSpans.java
index 20fe1de..871298e 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/RelationPartSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/RelationPartSpans.java
@@ -242,7 +242,7 @@
 		return 0;
 	}
 
-	class CandidateRelationSpan extends CandidateSpans implements Comparable<CandidateSpans>{
+	class CandidateRelationSpan extends CandidateSpan implements Comparable<CandidateSpan>{
 		
 		private int rightStart, rightEnd; 
 		private short leftId, rightId;
@@ -261,7 +261,7 @@
 		}
 		
 		@Override
-		public int compareTo(CandidateSpans o) {
+		public int compareTo(CandidateSpan o) {
 			CandidateRelationSpan cs = (CandidateRelationSpan) o;
 			if (sortRight)
 				return sortByRight(cs);
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/RelationSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/RelationSpans.java
index 380e899..2c4bdb6 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/RelationSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/RelationSpans.java
@@ -197,7 +197,7 @@
 //		this.rightId = rightId;
 //	}
 
-	class CandidateRelationSpan extends CandidateSpans implements Comparable<CandidateSpans>{
+	class CandidateRelationSpan extends CandidateSpan implements Comparable<CandidateSpan>{
 		
 		private int rightStart, rightEnd;
 		private short leftId, rightId;
@@ -207,7 +207,7 @@
 		}
 
 		@Override
-		public int compareTo(CandidateSpans o) {
+		public int compareTo(CandidateSpan o) {
 
 			int sourcePositionComparison = super.compareTo(o);
 			
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/RepetitionSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/RepetitionSpans.java
index c4412d9..6019125 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/RepetitionSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/RepetitionSpans.java
@@ -25,7 +25,7 @@
 	
 	private int min,max;
 	private long matchCost;
-	private List<CandidateSpans> matchList;
+	private List<CandidateSpan> matchList;
 	private Logger log = LoggerFactory.getLogger(RepetitionSpans.class);
     // This advices the java compiler to ignore all loggings
     public static final boolean DEBUG = false;
@@ -38,7 +38,7 @@
 		super(query, context, acceptDocs, termContexts);
 		this.min = query.getMin();
 		this.max = query.getMax();
-		matchList = new ArrayList<CandidateSpans>();
+		matchList = new ArrayList<CandidateSpan>();
 		hasMoreSpans = firstSpans.next();
 	}
 
@@ -62,7 +62,7 @@
 			}			
 			matchCost = 0;
 			
-			List<CandidateSpans> adjacentSpans = collectAdjacentSpans();
+			List<CandidateSpan> adjacentSpans = collectAdjacentSpans();
 			setMatchList(adjacentSpans);
 		}	
 		return false;
@@ -71,14 +71,14 @@
 	/** Collect all adjacent spans occurring in a sequence.
 	 * 	@return a list of the adjacent spans 
 	 * */
-	private List<CandidateSpans> collectAdjacentSpans() throws IOException {
+	private List<CandidateSpan> collectAdjacentSpans() throws IOException {
 		
-		CandidateSpans startSpan = new CandidateSpans(firstSpans);
+		CandidateSpan startSpan = new CandidateSpan(firstSpans);
 		
-		List<CandidateSpans> adjacentSpans = new ArrayList<CandidateSpans>();
+		List<CandidateSpan> adjacentSpans = new ArrayList<CandidateSpan>();
 		adjacentSpans.add(startSpan);
 		
-		CandidateSpans prevSpan = startSpan;
+		CandidateSpan prevSpan = startSpan;
 		
 		while ((hasMoreSpans = firstSpans.next()) &&
 			startSpan.getDoc() == firstSpans.doc() ){
@@ -87,7 +87,7 @@
 				break;
 			}
 			else if (firstSpans.start() == prevSpan.getEnd()){
-				prevSpan = new CandidateSpans(firstSpans);
+				prevSpan = new CandidateSpan(firstSpans);
 				adjacentSpans.add(prevSpan);
 			}
 		}		
@@ -97,8 +97,8 @@
 	/** Generate all possible repetition candidate spans from the adjacent spans 
 	 * 	and add them to the match list. 
 	 * */
-	private void setMatchList(List<CandidateSpans> adjacentSpans){
-		CandidateSpans startSpan, endSpan, matchSpan;
+	private void setMatchList(List<CandidateSpan> adjacentSpans){
+		CandidateSpan startSpan, endSpan, matchSpan;
 		for (int i=min; i<max+1; i++){
 			//System.out.println("num: "+i);			
 			int j=0; 
@@ -116,7 +116,7 @@
 				}
 				else {
 					endSpan = adjacentSpans.get(endIndex);														
-					matchSpan = new CandidateSpans(
+					matchSpan = new CandidateSpan(
 							startSpan.getStart(), 
 							endSpan.getEnd(), 
 							startSpan.getDoc(), 
@@ -138,7 +138,7 @@
 	/** Add all the payloads of a candidate span
 	 * */
 	private Collection<byte[]> computeMatchPayload(
-			List<CandidateSpans> adjacentSpans, int start, int end) {
+			List<CandidateSpan> adjacentSpans, int start, int end) {
 		Collection<byte[]> payload = new ArrayList<byte[]>();
 		for (int i=start; i<= end; i++){
 			payload.addAll(adjacentSpans.get(i).getPayloads());
@@ -148,11 +148,11 @@
 
 	/** Add all the cost of a candidate span
 	 * */
-	private long computeMatchCost(List<CandidateSpans> adjacentSpans, 
+	private long computeMatchCost(List<CandidateSpan> adjacentSpans, 
 			int start, int end){		
 		long matchCost = 0;
 		for (int i=start; i<= end; i++){
-			CandidateSpans c = adjacentSpans.get(i);
+			CandidateSpan c = adjacentSpans.get(i);
 			matchCost += adjacentSpans.get(i).getCost();
 		}		
 		return matchCost;
@@ -161,7 +161,7 @@
 	
 	/** Setting match properties from the candidate span
 	 * */	
-	private void setMatchProperties(CandidateSpans candidateSpan) 
+	private void setMatchProperties(CandidateSpan candidateSpan) 
 			throws IOException {
 	    matchDocNumber = candidateSpan.getDoc();
 	    matchStartPosition = candidateSpan.getStart();
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/TokenDistanceSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/TokenDistanceSpans.java
index 3b63d88..f3c4907 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/TokenDistanceSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/TokenDistanceSpans.java
@@ -48,8 +48,8 @@
 	 * 	from the candidate list prepared for the previous second spans. 
 	 * */
 	private void copyPossibleCandidates(){
-		List<CandidateSpans> temp = new ArrayList<>();
-		for (CandidateSpans cs : candidateList){
+		List<CandidateSpan> temp = new ArrayList<>();
+		for (CandidateSpan cs : candidateList){
 			if (cs.getEnd()+maxDistance > secondSpans.start())
 				temp.add(cs);
 		}
@@ -64,7 +64,7 @@
 				firstSpans.start() < secondSpans.end()){
 			
 			if (firstSpans.end()+maxDistance > secondSpans.start())
-				candidateList.add(new CandidateSpans(firstSpans));
+				candidateList.add(new CandidateSpan(firstSpans));
 			
 			hasMoreFirstSpans = firstSpans.next();
 		}
@@ -72,7 +72,7 @@
 	
 	@Override
 	protected boolean findMatch() throws IOException {
-		CandidateSpans candidateSpan = candidateList.get(candidateListIndex);		
+		CandidateSpan candidateSpan = candidateList.get(candidateListIndex);		
 		if (minDistance == 0 &&
 				// intersection
 				candidateSpan.getStart() < secondSpans.end() && 
@@ -95,7 +95,7 @@
 	
 	@Override
 	public long cost() {
-		CandidateSpans candidateSpan = candidateList.get(candidateListIndex);
+		CandidateSpan candidateSpan = candidateList.get(candidateListIndex);
 		return candidateSpan.getCost() + secondSpans.cost();
 	}
 
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/UnorderedDistanceSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/UnorderedDistanceSpans.java
index 9d0aa65..7934f34 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/UnorderedDistanceSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/UnorderedDistanceSpans.java
@@ -24,8 +24,8 @@
 
 	protected int minDistance, maxDistance;
 	protected boolean hasMoreFirstSpans, hasMoreSecondSpans;
-	protected List<CandidateSpans> firstSpanList, secondSpanList;	
-	protected List<CandidateSpans> matchList;
+	protected List<CandidateSpan> firstSpanList, secondSpanList;	
+	protected List<CandidateSpan> matchList;
 	private long matchCost;
 	private int matchListSpanNum; 	
 	protected int currentDocNum;
@@ -40,9 +40,9 @@
 		minDistance = query.getMinDistance();
 		maxDistance =  query.getMaxDistance();
 		
-		firstSpanList = new ArrayList<CandidateSpans>();
-		secondSpanList = new ArrayList<CandidateSpans>();
-		matchList = new ArrayList<CandidateSpans>();
+		firstSpanList = new ArrayList<CandidateSpan>();
+		secondSpanList = new ArrayList<CandidateSpan>();
+		matchList = new ArrayList<CandidateSpan>();
 		
 		hasMoreFirstSpans = firstSpans.next();
 		hasMoreSecondSpans = secondSpans.next();
@@ -90,7 +90,7 @@
 //			System.out.println(cs.getStart() +" "+ cs.getEnd());
 //		}
 		
-		CandidateSpans currentFirstSpan, currentSecondSpan;
+		CandidateSpan currentFirstSpan, currentSecondSpan;
 		if (!firstSpanList.isEmpty() && !secondSpanList.isEmpty()){
 			
 			currentFirstSpan = firstSpanList.get(0)	;
@@ -140,7 +140,7 @@
 		}
 	}
 	
-	private boolean isLastCandidateSmaller(CandidateSpans currentFirstSpan, CandidateSpans 
+	private boolean isLastCandidateSmaller(CandidateSpan currentFirstSpan, CandidateSpan 
 			currentSecondSpan){
 		if (currentFirstSpan.getEnd() == currentSecondSpan.getEnd() ){
 			int secondEnd = secondSpanList.get(secondSpanList.size()-1).getEnd();
@@ -151,29 +151,29 @@
 		return false;
 	}
 	
-	protected abstract void updateList(List<CandidateSpans> candidateList);
+	protected abstract void updateList(List<CandidateSpan> candidateList);
 	
 	/** Set the candidate list for the first element in the target list.
 	 * @return true iff the spans enumeration still has a next element 
 	 * to be a candidate
 	 */
-	protected abstract boolean setCandidateList(List<CandidateSpans> 
+	protected abstract boolean setCandidateList(List<CandidateSpan> 
 			candidateList, Spans candidate, boolean hasMoreCandidates,
-			List<CandidateSpans> targetList) throws IOException;
+			List<CandidateSpan> targetList) throws IOException;
 	
 	/** Search all matches between the target span and its candidates in the candidate 
 	 * 	list.
 	 * 	@return the matches in a list 
 	 * */
-	protected abstract List<CandidateSpans> findMatches(CandidateSpans target, 
-			List<CandidateSpans> candidateList);
+	protected abstract List<CandidateSpan> findMatches(CandidateSpan target, 
+			List<CandidateSpan> candidateList);
 	
 	/** Compute match properties and create a candidate span match 
 	 * 	to be added to the match list.
 	 * 	@return a candidate span match 
 	 * */
-	protected CandidateSpans createMatchCandidate(CandidateSpans target,
-			CandidateSpans cs, boolean isDistanceZero) {
+	protected CandidateSpan createMatchCandidate(CandidateSpan target,
+			CandidateSpan cs, boolean isDistanceZero) {
 		
 		int start = Math.min(target.getStart(), cs.getStart());
 		int end = Math.max(target.getEnd(),cs.getEnd());
@@ -190,7 +190,7 @@
 			}
 		}
 		
-		CandidateSpans match = new CandidateSpans(start,end,doc,cost,payloads);
+		CandidateSpan match = new CandidateSpan(start,end,doc,cost,payloads);
 		match.setChildSpan(cs);
 		return match;
 	}
@@ -198,7 +198,7 @@
 	/** Assign the first candidate span in the match list as the current span match.
 	 * */
 	private void setMatchProperties() {
-		CandidateSpans cs = matchList.get(0);
+		CandidateSpan cs = matchList.get(0);
 		matchDocNumber = cs.getDoc();
 		matchStartPosition = cs.getStart();
 		matchEndPosition = cs.getEnd();
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/UnorderedElementDistanceSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/UnorderedElementDistanceSpans.java
index 4a90575..a0c4474 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/UnorderedElementDistanceSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/UnorderedElementDistanceSpans.java
@@ -29,7 +29,7 @@
 	
 	// contains all previous elements whose position is greater than the last 
 	// target span
-	private List<CandidateSpans> elementList;
+	private List<CandidateSpan> elementList;
 	
 	public UnorderedElementDistanceSpans(SpanDistanceQuery query,
 			AtomicReaderContext context, Bits acceptDocs,
@@ -39,7 +39,7 @@
 	  			getSpans(context, acceptDocs, termContexts);	  		
   		hasMoreElements = elements.next();  		
   		elementPosition=0;  		
-  		elementList = new ArrayList<CandidateSpans>();  		
+  		elementList = new ArrayList<CandidateSpan>();  		
 	}
 	
 	@Override
@@ -74,13 +74,13 @@
 		return true;
 	}
 	
-	private boolean addSpan(Spans span, List<CandidateSpans> list, boolean hasMoreSpan) 
+	private boolean addSpan(Spans span, List<CandidateSpan> list, boolean hasMoreSpan) 
 			throws IOException {
 		int position;
 		while (hasMoreSpan && span.doc() == currentDocNum){
 			position = findElementPosition(span);
 			if (position != -1){
-				list.add(new CandidateSpans(span,position));
+				list.add(new CandidateSpan(span,position));
 				hasMoreSpan = span.next();
 				return hasMoreSpan;
 			}
@@ -100,7 +100,7 @@
 		if (!elementList.isEmpty() && 
 				span.end() <= elementList.get(elementList.size()-1).getEnd()){
 			
-			for (CandidateSpans e : elementList)
+			for (CandidateSpan e : elementList)
 				if (e.getEnd() >= span.end() && e.getStart() <= span.start()){
 					return e.getPosition();
 				}
@@ -124,7 +124,7 @@
 					span.end() <= elements.end()){
 				return true;
 			}
-			elementList.add(new CandidateSpans(elements,elementPosition));
+			elementList.add(new CandidateSpan(elements,elementPosition));
 			hasMoreElements = elements.next();
 			elementPosition++;			
 		}
@@ -133,18 +133,18 @@
 	}
 
 	@Override
-	protected boolean setCandidateList(List<CandidateSpans> 
+	protected boolean setCandidateList(List<CandidateSpan> 
 			candidateList, Spans candidate, boolean hasMoreCandidates,
-			List<CandidateSpans> targetList) throws IOException {
+			List<CandidateSpan> targetList) throws IOException {
 		 
 		if (!targetList.isEmpty()){			
-			CandidateSpans cs;
-			CandidateSpans target = targetList.get(0);
+			CandidateSpan cs;
+			CandidateSpan target = targetList.get(0);
 			int position;
 			while (hasMoreCandidates && candidate.doc() == target.getDoc()){
 				position = findElementPosition(candidate); 
 				if (position != -1){
-					cs = new CandidateSpans(candidate,position);
+					cs = new CandidateSpan(candidate,position);
 					
 					if (isWithinMaxDistance(target, cs)){
 						candidateList.add(cs);						
@@ -162,7 +162,7 @@
 	 *  @return true iff the target and candidate spans are within the maximum
 	 *  distance
 	 * */
-	protected boolean isWithinMaxDistance(CandidateSpans target, CandidateSpans candidate) {
+	protected boolean isWithinMaxDistance(CandidateSpan target, CandidateSpan candidate) {
 		int candidatePos = candidate.getPosition();
 		int targetPos = target.getPosition();
 		
@@ -180,15 +180,15 @@
 	}
 	
 	@Override
-	protected List<CandidateSpans> findMatches(CandidateSpans target, List<CandidateSpans> 
+	protected List<CandidateSpan> findMatches(CandidateSpan target, List<CandidateSpan> 
 			candidateList) {
 		
-		List<CandidateSpans> matches = new ArrayList<>();
+		List<CandidateSpan> matches = new ArrayList<>();
 		
 		int actualDistance;
 		int targetPos = target.getPosition();		
 		
-		for (CandidateSpans cs : candidateList){						
+		for (CandidateSpan cs : candidateList){						
 			actualDistance = Math.abs( targetPos - cs.getPosition() );
 			
 			if (minDistance == 0 && actualDistance == 0){
@@ -203,7 +203,7 @@
 	}
 
 	@Override
-	protected void updateList(List<CandidateSpans> candidateList) {
+	protected void updateList(List<CandidateSpan> candidateList) {
 		updateElementList(candidateList.get(0).getPosition());
 		candidateList.remove(0);
 	}
@@ -213,8 +213,8 @@
 	 * 	span.
 	 * */
 	private void updateElementList(int position){
-		Iterator<CandidateSpans> i = elementList.iterator();
-		CandidateSpans e;
+		Iterator<CandidateSpan> i = elementList.iterator();
+		CandidateSpan e;
 		while(i.hasNext()){
 			e = i.next();			
 			if (e.getPosition() <= position) {
diff --git a/src/main/java/de/ids_mannheim/korap/query/spans/UnorderedTokenDistanceSpans.java b/src/main/java/de/ids_mannheim/korap/query/spans/UnorderedTokenDistanceSpans.java
index 91ef11a..5f1abd9 100644
--- a/src/main/java/de/ids_mannheim/korap/query/spans/UnorderedTokenDistanceSpans.java
+++ b/src/main/java/de/ids_mannheim/korap/query/spans/UnorderedTokenDistanceSpans.java
@@ -33,8 +33,8 @@
 		if (firstSpanList.isEmpty() && secondSpanList.isEmpty()){
 			if (hasMoreFirstSpans && hasMoreSecondSpans &&
 					ensureSameDoc(firstSpans, secondSpans)){			
-				firstSpanList.add(new CandidateSpans(firstSpans));
-				secondSpanList.add(new CandidateSpans(secondSpans));
+				firstSpanList.add(new CandidateSpan(firstSpans));
+				secondSpanList.add(new CandidateSpan(secondSpans));
 				currentDocNum = firstSpans.doc();
 				hasMoreFirstSpans = firstSpans.next();
 				hasMoreSecondSpans = secondSpans.next();				
@@ -46,27 +46,27 @@
 		}
 		else if (firstSpanList.isEmpty() && hasMoreFirstSpans && 
 				firstSpans.doc() == currentDocNum){
-			firstSpanList.add(new CandidateSpans(firstSpans));
+			firstSpanList.add(new CandidateSpan(firstSpans));
 			hasMoreFirstSpans = firstSpans.next();
 		}
 		else if (secondSpanList.isEmpty() && hasMoreSecondSpans && 
 				secondSpans.doc() == currentDocNum){
-			secondSpanList.add(new CandidateSpans(secondSpans));
+			secondSpanList.add(new CandidateSpan(secondSpans));
 			hasMoreSecondSpans = secondSpans.next();
 		}
 		return true;
 	}
 	
 	@Override
-	protected boolean setCandidateList(List<CandidateSpans> 
+	protected boolean setCandidateList(List<CandidateSpan> 
 			candidateList, Spans candidate, boolean hasMoreCandidates,
-			List<CandidateSpans> targetList) throws IOException {
+			List<CandidateSpan> targetList) throws IOException {
 		
 		if (!targetList.isEmpty()){
-			CandidateSpans target = targetList.get(0);
+			CandidateSpan target = targetList.get(0);
 			while (hasMoreCandidates && candidate.doc() == target.getDoc()
 					&& isWithinMaxDistance(target,candidate)){
-				candidateList.add(new CandidateSpans(candidate));
+				candidateList.add(new CandidateSpan(candidate));
 				hasMoreCandidates = candidate.next();
 			}
 		}
@@ -77,7 +77,7 @@
 	 *  @return true iff the target and candidate spans are within the maximum
 	 *  distance
 	 * */
-	protected boolean isWithinMaxDistance(CandidateSpans target, Spans candidate) {
+	protected boolean isWithinMaxDistance(CandidateSpan target, Spans candidate) {
 		// left candidate
 		if (candidate.end() < target.getStart() && 
 				candidate.end() + maxDistance <= target.getStart()){
@@ -92,12 +92,12 @@
 	}
 	
 	@Override	
-	protected List<CandidateSpans> findMatches(CandidateSpans target, List<CandidateSpans> 
+	protected List<CandidateSpan> findMatches(CandidateSpan target, List<CandidateSpan> 
 			candidateList) {
 		
-		List<CandidateSpans> matches = new ArrayList<>();		
+		List<CandidateSpan> matches = new ArrayList<>();		
 		int actualDistance;
-		for (CandidateSpans cs : candidateList){
+		for (CandidateSpan cs : candidateList){
 			if (minDistance == 0 &&
 					//intersection
 					target.getStart() < cs.getEnd() &&
@@ -119,7 +119,7 @@
 	}
 
 	@Override
-	protected void updateList(List<CandidateSpans> candidateList) {
+	protected void updateList(List<CandidateSpan> candidateList) {
 		candidateList.remove(0);		
 	}