All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.qt.core.AbstractIterator Maven / Gradle / Ivy

There is a newer version: 6.8.1
Show newest version
/****************************************************************************
**
** 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;

abstract class AbstractIterator extends QtObject{
	
	private final static Function, java.util.Iterator> iteratorFactory;
	private final static Function, java.util.Iterator> diteratorFactory;
	final static Function, java.util.ListIterator> mutableIteratorFactory;
	
	static {
		if(Boolean.getBoolean("io.qt.enable-concurrent-container-modification-check")) {
			@SuppressWarnings("unchecked")
			Function, java.util.Iterator> _iteratorFactory = CheckingIterator::new;
			@SuppressWarnings("unchecked")
			Function, java.util.Iterator> _diteratorFactory = CheckingDescendingIterator::new;
			iteratorFactory = _iteratorFactory;
			diteratorFactory = _diteratorFactory;
			@SuppressWarnings("unchecked")
			Function, java.util.ListIterator> _miteratorFactory = CheckingMutableIterator::new;
			mutableIteratorFactory = _miteratorFactory;
		}else {
			@SuppressWarnings("unchecked")
			Function, java.util.Iterator> _iteratorFactory = DefaultIterator::new;
			@SuppressWarnings("unchecked")
			Function, java.util.Iterator> _diteratorFactory = DefaultDescendingIterator::new;
			iteratorFactory = _iteratorFactory;
			diteratorFactory = _diteratorFactory;
			@SuppressWarnings("unchecked")
			Function, java.util.ListIterator> _miteratorFactory = MutableIterator::new;
			mutableIteratorFactory = _miteratorFactory;
		}
	}
	
	private final QtObject owner;
	private final Function> beginSupplier;
	private final Function> endSupplier;

	@SuppressWarnings({ "unchecked", "rawtypes" })
	AbstractIterator(QPrivateConstructor c, QtObject owner) {
		super(c);
		this.owner = owner;
		if(owner==null) {
			endSupplier = null;
			beginSupplier = null;			
		}else if(owner instanceof AbstractSpan) {
			AbstractSpan span = (AbstractSpan)owner;
			if(span.isConstSpan() || isConstant()) {
				endSupplier = (Function)(Function>)AbstractSpan::constEnd;
				beginSupplier = (Function)(Function>)AbstractSpan::constBegin;
			}else {
				endSupplier = (Function)(Function>)AbstractSpan::end;
				beginSupplier = (Function)(Function>)AbstractSpan::begin;
			}
		}else 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);
	}
	
    /**
     * 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 equals(QtJambi_LibraryUtilities.internal.nativeId(this), QtJambi_LibraryUtilities.internal.nativeId(iter));
        }
    	return false;
    }
    
    private static class DefaultIterator implements java.util.Iterator{
    	final AbstractIterator current;
		final AbstractIterator end;
    	private boolean hasNext;

    	DefaultIterator(AbstractIterator current) {
			super();
			this.current = current;
			end = current.end();
			hasNext = end!=null && !current.equals(end);
		}

		@Override
		public boolean hasNext() {
			return hasNext;
		}

		@Override
		public E next() {
			checkNext();
            E e = current._value();
            current.increment();
            hasNext = end!=null && !current.equals(end);
            return e;
		}
    	
		void checkNext() {
            if(!hasNext)
                throw new NoSuchElementException();
		}
    }
    
    private static class CheckingIterator extends DefaultIterator{
    	CheckingIterator(AbstractIterator nativeIterator) {
			super(nativeIterator);
		}

		void checkNext() {
    		super.checkNext();
        	if(end!=null && !end.equals(current.end()))
        		throw new ConcurrentModificationException();
		}
    }
    
    private static class DefaultDescendingIterator implements java.util.Iterator{
    	final AbstractIterator current;
    	final AbstractIterator begin;
    	private boolean hasNext;

		public DefaultDescendingIterator(AbstractIterator nativeIterator) {
			super();
			this.current = nativeIterator;
			begin = nativeIterator.begin();
			hasNext = begin!=null && !nativeIterator.equals(begin);
		}

		@Override
		public boolean hasNext() {
			return hasNext;
		}

		@Override
		public E next() {
			checkNext();
			current.decrement();
            hasNext = begin!=null && !current.equals(begin);
			E e = current._value();
            return e;
		}
    	
		void checkNext() {
            if(!hasNext)
                throw new NoSuchElementException();
		}
    }
    
    private static class CheckingDescendingIterator extends DefaultDescendingIterator{
    	public CheckingDescendingIterator(AbstractIterator nativeIterator) {
			super(nativeIterator);
		}

		void checkNext() {
    		super.checkNext();
        	if(begin!=null && !begin.equals(current.begin()))
        		throw new ConcurrentModificationException();
		}
    }
	
	private static class MutableIterator implements java.util.ListIterator{
		final AbstractIterator current;
		final AbstractIterator begin;
		final AbstractIterator end;
    	private int icursor;
    	private boolean hasNext;
    	private boolean hasPrevious;
    	
    	MutableIterator(AbstractIterator current){
    		if(current.isConstant())
    			throw new RuntimeException("Cannot produce mutable iterator from read-only iterator.");
    		this.current = current;
    		begin = current.begin();
    		end = current.end();
        	hasNext = end!=null && !current.equals(end);
        	hasPrevious = begin!=null && !current.equals(begin);
    	}
    	
        @Override
        public boolean hasNext() {
        	return hasNext;
        }

        @Override
        public T next() {
        	if(!hasNext())
                throw new NoSuchElementException();
        	checkModification();
        	T e = current._value();
        	current.increment();
        	hasNext = end!=null && !current.equals(end);
        	hasPrevious = begin!=null && !current.equals(begin);
        	icursor++;
            return e;
        }
        
        @Override
        public T previous() {
        	if(!hasPrevious())
                throw new NoSuchElementException();
        	checkModification();
        	current.decrement();
        	hasNext = end!=null && !current.equals(end);
        	hasPrevious = begin!=null && !current.equals(begin);
        	T e = current._value();
        	icursor--;
            return e;
        }
        
		@Override
        public void set(T e) {
        	checkModification();
        	if(icursor==0)
        		throw new IndexOutOfBoundsException(-1);
        	current.decrement();
        	((QSequentialIterator)current).setValue(e);
        	current.increment();
        }
        
        @Override
        public int previousIndex() {
        	return icursor-1;
        }
        
        @Override
        public int nextIndex() {
        	return icursor;
        }
        
        @Override
        public boolean hasPrevious() {
        	return hasPrevious;
        }
        
		void checkModification() {
		}

		@Override
		public void remove() {
			throw new UnsupportedOperationException("remove");
		}

		@Override
		public void add(T e) {
			throw new UnsupportedOperationException("add");
		}
	}
	
	private static class CheckingMutableIterator extends MutableIterator{

		CheckingMutableIterator(AbstractIterator current) {
			super(current);
		}
		
		void checkModification() {
			if(end!=null && !end.equals(current.end()))
        		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);
    }
	
	/**
     * Returns a java iterator over the containers entries between this and end.
     */
    @SuppressWarnings("unchecked")
	@QtUninvokable
	java.util.ListIterator toMutableJavaIterator(){
    	return (java.util.ListIterator)mutableIteratorFactory.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);
    
    @QtUninvokable
    private static native QMetaType valueType(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 value type of the iterator.
	 */
    @QtUninvokable
	public final QMetaType valueType() {
    	return valueType(QtJambi_LibraryUtilities.internal.nativeId(this));
	}
    
    /**
     * 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();
    	}
	}
    
    /**
	 * Set the value at iterator's position in the container.
	 * @param newValue the new value
	 */
    @QtUninvokable
	final boolean checkedSetValue(T newValue) {
    	if(isConstant() || !isValid())
    		return false;
    	return setValue(QtJambi_LibraryUtilities.internal.nativeId(this), newValue);
    }
    
    @QtUninvokable
    private static native  boolean setValue(long __this__nativeId, T newValue);
    
    @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 || !equals(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(QtJambi_LibraryUtilities.internal.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);
        }
    }
	
    @QtUninvokable
	private static native int hashCode(long id);
	
    @QtUninvokable
	private static native boolean equals(long id, long other);
    
    @QtUninvokable
	private static native String toString(long id);

	@Override
    @QtUninvokable
	public final int hashCode() {
		return hashCode(QtJambi_LibraryUtilities.internal.nativeId(this));
	}

	@Override
    @QtUninvokable
	public final String toString() {
		return toString(QtJambi_LibraryUtilities.internal.nativeId(this));
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy