/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.ide.api.editor.annotation;
import java.util.Iterator;
import java.util.NoSuchElementException;
import org.eclipse.che.ide.api.editor.text.Position;
import org.eclipse.che.ide.api.editor.text.annotation.Annotation;
/** Iterator that returns the annotations for a given region. */
final class RegionIterator implements Iterator<Annotation> {
private final Iterator<Annotation> parentIterator;
private final boolean canEndAfter;
private final boolean canStartBefore;
private final AnnotationModel model;
private Annotation next;
private final Position region;
/**
* Iterator that returns all annotations from the parent iterator which
* have a position in the given model inside the given region.
*
* @param parentIterator
* iterator containing all annotations
* @param model
* the model to use to retrieve positions from for each
* annotation
* @param offset
* start position of the region
* @param length
* length of the region
* @param canStartBefore
* include annotations starting before region
* @param canEndAfter
* include annotations ending after region
*/
public RegionIterator(Iterator<Annotation> parentIterator, AnnotationModel model, int offset, int length,
boolean canStartBefore, boolean canEndAfter) {
this.parentIterator = parentIterator;
this.model = model;
this.region = new Position(offset, length);
this.canEndAfter = canEndAfter;
this.canStartBefore = canStartBefore;
next = findNext();
}
@Override
public boolean hasNext() {
return next != null;
}
@Override
public Annotation next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
final Annotation result = next;
next = findNext();
return result;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
private Annotation findNext() {
while (parentIterator.hasNext()) {
final Annotation next = parentIterator.next();
final Position position = model.getPosition(next);
if (position != null) {
final int offset = position.getOffset();
if (isWithinRegion(offset, position.getLength())) {
return next;
}
}
}
return null;
}
private boolean isWithinRegion(int start, int length) {
if (canStartBefore && canEndAfter) {
return region.overlapsWith(start, length);
} else if (canStartBefore) {
return region.includes(start + length - (length > 0 ? 1 : 0));
} else if (canEndAfter) {
return region.includes(start);
} else {
return region.includes(start) && region.includes(start + length - (length > 0 ? 1 : 0));
}
}
}