blob: 446b73523bde91a8e41631531d444445a4c6ea7f [file] [log] [blame]
/*-
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sling.query.impl.iterator;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.function.Predicate;
import org.apache.sling.query.api.internal.TreeProvider;
import org.apache.sling.query.impl.util.IteratorUtils;
import org.apache.sling.query.impl.util.LazyList;
public class SiblingsIterator<T> extends AbstractIterator<T> {
private final Predicate<T> until;
private final ListIterator<T> siblings;
private final Type type;
private final TreeProvider<T> provider;
private boolean finished;
public SiblingsIterator(Predicate<T> until, T resource, Type type, TreeProvider<T> provider) {
this.provider = provider;
this.until = until;
this.siblings = getRewindedIterator(resource, type);
this.finished = false;
this.type = type;
}
@Override
protected T getElement() {
if (finished) {
return null;
}
while (type.canAdvance(siblings)) {
T resource = type.advance(siblings);
if (until != null && until.test(resource)) {
finished = true;
return null;
}
if (until == null) {
finished = true;
}
return resource;
}
return null;
}
private ListIterator<T> getRewindedIterator(T resource, Type type) {
String resourceName = provider.getName(resource);
T parent = provider.getParent(resource);
Iterator<T> iterator;
if (parent == null) {
iterator = IteratorUtils.singleElementIterator(resource);
} else {
iterator = provider.listChildren(parent);
}
ListIterator<T> listIterator = new LazyList<T>(iterator).listIterator();
while (listIterator.hasNext()) {
T sibling = listIterator.next();
if (provider.getName(sibling).equals(resourceName)) {
break;
}
}
if (type == Type.PREV) {
listIterator.previous();
}
return listIterator;
}
public enum Type {
NEXT {
@Override
public boolean canAdvance(ListIterator<?> iterator) {
return iterator.hasNext();
}
@Override
public <T> T advance(ListIterator<T> iterator) {
return iterator.next();
}
},
PREV {
@Override
public boolean canAdvance(ListIterator<?> iterator) {
return iterator.hasPrevious();
}
@Override
public <T> T advance(ListIterator<T> iterator) {
return iterator.previous();
}
};
public abstract boolean canAdvance(ListIterator<?> iterator);
public abstract <T> T advance(ListIterator<T> iterator);
}
}