io.qt.core.AbstractIterator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of qtjambi Show documentation
Show all versions of qtjambi Show documentation
QtJambi base module containing QtCore, QtGui and QtWidgets.
/****************************************************************************
**
** Copyright (C) 2009-2024 Dr. Peter Droste, Omix Visualization GmbH & Co. KG. All rights reserved.
**
** This file is part of Qt Jambi.
**
** $BEGIN_LICENSE$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
** $END_LICENSE$
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
package io.qt.core;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.function.Function;
import io.qt.QtObject;
import io.qt.QtUninvokable;
import io.qt.internal.ClassAnalyzerUtility;
abstract class AbstractIterator extends QtObject{
private final static Function, java.util.Iterator>> iteratorFactory;
private final static Function, java.util.Iterator>> diteratorFactory;
static {
if(Boolean.getBoolean("io.qt.enable-concurrent-container-modification-check")) {
@SuppressWarnings("unchecked")
Function, java.util.Iterator>> _iteratorFactory = CheckingIncrementalIterator::new;
@SuppressWarnings("unchecked")
Function, java.util.Iterator>> _diteratorFactory = CheckingDecrementalIterator::new;
iteratorFactory = _iteratorFactory;
diteratorFactory = _diteratorFactory;
}else {
@SuppressWarnings("unchecked")
Function, java.util.Iterator>> _iteratorFactory = IncrementalIterator::new;
@SuppressWarnings("unchecked")
Function, java.util.Iterator>> _diteratorFactory = DecrementalIterator::new;
iteratorFactory = _iteratorFactory;
diteratorFactory = _diteratorFactory;
}
}
private final QtObject owner;
private final Function> beginSupplier;
private final Function> endSupplier;
/**
* {@inheritDoc}
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
AbstractIterator(QtObject owner) {
super((QPrivateConstructor)null);
this.owner = owner;
if(owner instanceof AbstractSequentialContainer) {
if(isConstant()) {
endSupplier = (Function)(Function>)AbstractSequentialContainer::constEnd;
beginSupplier = (Function)(Function>)AbstractSequentialContainer::constBegin;
}else if(owner instanceof AbstractList) {
endSupplier = (Function)(Function>)AbstractList::end;
beginSupplier = (Function)(Function>)AbstractList::begin;
}else {// there are no mutable iterators in QSet
endSupplier = null;
beginSupplier = null;
}
}else if(owner instanceof AbstractAssociativeContainer) {
if(isConstant()) {
endSupplier = (Function)(Function>)AbstractAssociativeContainer::constEnd;
beginSupplier = (Function)(Function>)AbstractAssociativeContainer::constBegin;
}else {
endSupplier = (Function)(Function>)AbstractAssociativeContainer::end;
beginSupplier = (Function)(Function>)AbstractAssociativeContainer::begin;
}
}else if(owner instanceof AbstractMultiAssociativeContainer) {
if(isConstant()) {
endSupplier = (Function)(Function>)AbstractMultiAssociativeContainer::constEnd;
beginSupplier = (Function)(Function>)AbstractMultiAssociativeContainer::constBegin;
}else {
endSupplier = (Function)(Function>)AbstractMultiAssociativeContainer::end;
beginSupplier = (Function)(Function>)AbstractMultiAssociativeContainer::begin;
}
}else {
BeginEndFunctions functions = findBeginEndSuppliers(owner);
beginSupplier = (Function)(isConstant() ? functions.constBegin : functions.begin);
endSupplier = (Function)(isConstant() ? functions.constEnd : functions.end);
}
}
/**
* Specifies if this type is constant iterator.
*/
boolean isConstant() {
return true;
}
/**
* Returns the container's end iterator.
*/
@QtUninvokable
final AbstractIterator end(){
return endSupplier==null ? null : endSupplier.apply(owner);
}
/**
* Returns the container's begin iterator.
*/
@QtUninvokable
final AbstractIterator begin(){
return beginSupplier==null ? null : beginSupplier.apply(owner);
}
@QtUninvokable
private static native boolean operator_equal(long __this__nativeId, long o);
/**
* Compares this iterator with other object.
*/
@Override
@QtUninvokable
public boolean equals(Object other) {
if (other instanceof AbstractIterator) {
AbstractIterator> iter = (AbstractIterator>) other;
if(owner==iter.owner)
return operator_equal(QtJambi_LibraryUtilities.internal.nativeId(this), QtJambi_LibraryUtilities.internal.nativeId(iter));
}
return false;
}
private static class IncrementalIterator implements java.util.Iterator{
final AbstractIterator nativeIterator;
final AbstractIterator end;
private boolean hasNext;
IncrementalIterator(AbstractIterator nativeIterator) {
super();
this.nativeIterator = nativeIterator;
end = nativeIterator.end();
hasNext = end!=null && !nativeIterator.equals(end);
}
@Override
public boolean hasNext() {
return hasNext;
}
@Override
public E next() {
checkNext();
E e = nativeIterator._value();
nativeIterator.increment();
hasNext = end!=null && !nativeIterator.equals(end);
return e;
}
void checkNext() {
if(!hasNext)
throw new NoSuchElementException();
}
}
private static class CheckingIncrementalIterator extends IncrementalIterator{
CheckingIncrementalIterator(AbstractIterator nativeIterator) {
super(nativeIterator);
}
void checkNext() {
super.checkNext();
if(end!=null && !end.equals(nativeIterator.end()))
throw new ConcurrentModificationException();
}
}
private static class DecrementalIterator implements java.util.Iterator{
final AbstractIterator nativeIterator;
final AbstractIterator begin;
private boolean hasNext;
public DecrementalIterator(AbstractIterator nativeIterator) {
super();
this.nativeIterator = nativeIterator;
begin = nativeIterator.begin();
hasNext = begin!=null && !nativeIterator.equals(begin);
}
@Override
public boolean hasNext() {
return hasNext;
}
@Override
public E next() {
checkNext();
nativeIterator.decrement();
hasNext = begin!=null && !nativeIterator.equals(begin);
E e = nativeIterator._value();
return e;
}
void checkNext() {
if(!hasNext)
throw new NoSuchElementException();
}
}
private static class CheckingDecrementalIterator extends DecrementalIterator{
public CheckingDecrementalIterator(AbstractIterator nativeIterator) {
super(nativeIterator);
}
void checkNext() {
super.checkNext();
if(begin!=null && !begin.equals(nativeIterator.begin()))
throw new ConcurrentModificationException();
}
}
/**
* Returns a java iterator over the containers entries between this and end.
*/
@SuppressWarnings("unchecked")
@QtUninvokable
final java.util.Iterator toJavaIterator(){
return (java.util.Iterator)iteratorFactory.apply(this);
}
/**
* Returns a descending java iterator over the containers entries between this and end.
*/
@SuppressWarnings("unchecked")
@QtUninvokable
final java.util.Iterator toJavaDescendingIterator(){
return (java.util.Iterator)diteratorFactory.apply(this);
}
/**
* Advances the iterator to the next item in the container.
*/
@QtUninvokable
final void increment() {
increment(QtJambi_LibraryUtilities.internal.nativeId(this));
}
@QtUninvokable
static native void increment(long __this__nativeId);
/**
* Advances the iterator to the previous item in the container.
*/
@QtUninvokable
final void decrement() {
decrement(QtJambi_LibraryUtilities.internal.nativeId(this));
}
@QtUninvokable
static native void decrement(long __this__nativeId);
/**
* Returns the current item's value.
*/
@QtUninvokable
final T _value() {
return value(QtJambi_LibraryUtilities.internal.nativeId(this));
}
@QtUninvokable
static native T value(long __this__nativeId);
/**
* Returns the value at iterator's position in the container or emptiness in case of end
.
*/
@QtUninvokable
public final Optional value() {
return !isValid() ? Optional.empty() : Optional.ofNullable(_value());
}
/**
* Returns the current item's value if item is valid
* or throws NoSuchElementException otherwise.
*/
@QtUninvokable
final T checkedValue() throws NoSuchElementException {
if(isValid()) {
return _value();
}else {
throw new NoSuchElementException();
}
}
@QtUninvokable
private static native boolean canLess(long __this__nativeId);
@QtUninvokable
private static native boolean lessThan(long __this__nativeId, long other);
/**
* Returns {@code true} if iterator is valid, i.e. it is less end.
*/
@QtUninvokable
final boolean isValid() {
long nativeId = QtJambi_LibraryUtilities.internal.nativeId(this);
if(nativeId==0)
return false;
AbstractIterator> end = end();
if(canLess(nativeId)) {
try {
return lessThan(nativeId, QtJambi_LibraryUtilities.internal.nativeId(end));
} catch (Exception e) {
}
}
return owner!=end.owner || !operator_equal(nativeId, QtJambi_LibraryUtilities.internal.nativeId(end));
}
private static class BeginEndFunctions{
BeginEndFunctions(
Function> constBegin,
Function> constEnd,
Function> begin,
Function> end) {
super();
this.begin = begin;
this.end = end;
this.constBegin = constBegin;
this.constEnd = constEnd;
}
final Function> begin;
final Function> end;
final Function> constBegin;
final Function> constEnd;
}
private static final Map, BeginEndFunctions> endMethodHandles = Collections.synchronizedMap(new HashMap<>());
private static BeginEndFunctions findBeginEndSuppliers(QtObject beginOwner) {
return endMethodHandles.computeIfAbsent(ClassAnalyzerUtility.getClass(beginOwner), cls -> {
Method beginMethod = null;
Method constBeginMethod = null;
Method endMethod = null;
Method constEndMethod = null;
while ((endMethod == null && constEndMethod == null
&& beginMethod == null && constBeginMethod == null)
&& cls!=null && cls != QtObject.class) {
Method methods[] = cls.getDeclaredMethods();
for (Method method : methods) {
if (method.getParameterCount() == 0
&& AbstractIterator.class.isAssignableFrom(method.getReturnType())) {
if(method.getName().equals("begin")) {
beginMethod = method;
}else if(method.getName().equals("end")) {
endMethod = method;
}else if(method.getName().equals("constEnd")) {
constEndMethod = method;
}else if(method.getName().equals("constBegin")) {
constBeginMethod = method;
}
}
if(endMethod != null && constEndMethod != null
&& beginMethod != null && constBeginMethod != null) {
break;
}
}
cls = cls.getSuperclass();
}
if(constBeginMethod==null && beginMethod!=null) {
if(beginMethod.getReturnType()!=QSequentialIterator.class
&& beginMethod.getReturnType()!=QAssociativeIterator.class) {
constBeginMethod = beginMethod;
beginMethod = null;
}
}
if(constEndMethod==null && endMethod!=null) {
if(endMethod.getReturnType()!=QSequentialIterator.class
&& endMethod.getReturnType()!=QAssociativeIterator.class) {
constEndMethod = endMethod;
endMethod = null;
}
}
if (endMethod != null || constEndMethod != null)
return new BeginEndFunctions(CoreUtility.functionFromMethod(constBeginMethod),
CoreUtility.functionFromMethod(constEndMethod),
CoreUtility.functionFromMethod(beginMethod),
CoreUtility.functionFromMethod(endMethod));
else return new BeginEndFunctions(null,null,null,null);
});
}
private static class CoreUtility extends io.qt.internal.CoreUtility{
protected static Function functionFromMethod(Method method){
return io.qt.internal.CoreUtility.functionFromMethod(method);
}
}
}