package ru.naumen.gintonic.project.navigate;
import java.util.List;
import ru.naumen.gintonic.project.source.references.SourceCodeReference;
/**
* A {@link NavigationCycle} can be used to jump from one {@link SourceCodeReference} to
* another.
*
* @author tmajunke
*/
public class NavigationCycle<T extends SourceCodeReference> {
private List<T> sourceCodeReferences;
/**
* The index so we know where to jump next.
*/
private int index = 0;
public void setSourceCodeReferences(List<T> sourceCodeReferences) {
this.sourceCodeReferences = sourceCodeReferences;
}
public int getIndex() {
return index;
}
/**
* Jumps to the {@link SourceCodeReference} that is the follower of the given
* {@link SourceCodeReference}. It also sets the resource pointer to the follower.
*
* To do so we must first check if the given reference is contained in this
* navigation cycle. The check compares the reference start position and
* qualified name. If the resource is not contained in this navigation cycle
* then nothing happens and the method returns false.
*
* @param sourceCodeReference the {@link IJumpable}. May not be null.
* @return true, if the resource has been contained in this navigation
* cycle. Otherwise false.
*/
public boolean jumpToFollower(T sourceCodeReference) {
Integer resourceIndex = getResourceIndexFor(sourceCodeReference);
if (resourceIndex != null) {
this.index = resourceIndex;
jumpToNext();
return true;
}
return false;
}
/**
* Jumps to the next project resource. If we are already at the last project
* resource, then we jump to the first one (in other words we cycle through
* the project resources).
*/
public void jumpToNext() {
increaseIndex();
jumpToCurrent();
}
private void jumpToCurrent() {
T jumpTarget = sourceCodeReferences.get(index);
jumpTarget.jump();
}
private void increaseIndex() {
int size = sourceCodeReferences.size();
this.index = (index + 1) % size;
}
/**
* Returns true if the given sourceCodeReference is contained in this navigation
* cycle, otherwise false.
*
* @param sourceCodeReferenceToFind the reference
* @return true if the given reference is contained in this navigation
* cycle, otherwise false.
*/
private Integer getResourceIndexFor(SourceCodeReference sourceCodeReferenceToFind) {
int i = 0;
for (T sourceCodeReference : sourceCodeReferences){
Integer startPosition = sourceCodeReference.getOffset();
Integer startPositionToFind = sourceCodeReferenceToFind.getOffset();
if (startPosition.equals(startPositionToFind)) {
String typeNameFullyQualified = sourceCodeReference.getPrimaryTypeNameFullyQualified();
String typeNameFullyQualifiedToFind = sourceCodeReferenceToFind.getPrimaryTypeNameFullyQualified();
if (typeNameFullyQualified.equals(typeNameFullyQualifiedToFind)) {
return i;
}
}
i++;
}
return null;
}
}