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

io.sirix.service.xml.xpath.AbstractAxis Maven / Gradle / Ivy

/**
 * Copyright (c) 2011, University of Konstanz, Distributed Systems Group All rights reserved.
 * 

* Redistribution and use in source and binary forms, with or without modification, are permitted * provided that the following conditions are met: * Redistributions of source code must retain the * above copyright notice, this list of conditions and the following disclaimer. * Redistributions * in binary form must reproduce the above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other materials provided with the distribution. * * Neither the name of the University of Konstanz nor the names of its contributors may be used to * endorse or promote products derived from this software without specific prior written permission. *

* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package io.sirix.service.xml.xpath; import io.sirix.api.Axis; import io.sirix.api.NodeCursor; import io.sirix.api.NodeReadOnlyTrx; import io.sirix.api.json.JsonNodeReadOnlyTrx; import io.sirix.api.visitor.XmlNodeVisitor; import io.sirix.api.xml.XmlNodeReadOnlyTrx; import io.sirix.axis.IncludeSelf; import it.unimi.dsi.fastutil.longs.LongIterator; import org.checkerframework.checker.index.qual.NonNegative; import io.sirix.index.path.summary.PathSummaryReader; import io.sirix.settings.Fixed; import java.util.NoSuchElementException; import static java.util.Objects.requireNonNull; /** * *

* Provide standard Java iterator capability compatible with the new enhanced for loop available * since Java 5. * * Override the "template method" {@code nextKey()} to implement an axis. *

*/ public abstract class AbstractAxis implements Axis { /** Iterate over transaction exclusive to this step. */ private final NodeCursor rtx; /** Key of next node. */ protected long key; /** * Make sure {@code next()} can only be called after {@code hasNext()} has been called. */ private boolean next; /** Key of node where axis started. */ private long startKey; /** Include self? */ private final IncludeSelf includeSelf; /** Determines if a next node follows or not. */ private boolean hasNext; /** * Bind axis step to transaction. * * @param rtx transaction to operate with * @throws NullPointerException if {@code rtx} is {@code null} */ public AbstractAxis(final NodeCursor rtx) { this.rtx = requireNonNull(rtx); includeSelf = IncludeSelf.NO; hasNext = true; reset(rtx.getNodeKey()); } /** * Bind axis step to transaction. * * @param pRtx transaction to operate with * @param pIncludeSelf determines if self is included */ public AbstractAxis(final NodeCursor pRtx, final IncludeSelf pIncludeSelf) { rtx = requireNonNull(pRtx); includeSelf = requireNonNull(pIncludeSelf); hasNext = true; reset(pRtx.getNodeKey()); } @Override public final LongIterator iterator() { return this; } /** * Signals that axis traversal is done, that is {@code hasNext()} must return false. Can be called * from subclasses to signal that axis is done. * * @return null node key */ protected long done() { return Fixed.NULL_NODE_KEY.getStandardProperty(); } /** * {@inheritDoc} * *

* During the last call to {@code hasNext()}, that is {@code hasNext()} returns false, the * transaction is reset to the start key. *

* *

* Implementors should implement {@code nextKey()} instead which is a template method called * from this {@code hasNext()} method. *

*/ @Override public boolean hasNext() { if (!isHasNext()) { // End of the axis reached. return false; } if (isNext()) { // hasNext() has been called before without an intermediate next()-call. return true; } // Reset to last node key. resetToLastKey(); // Template method. key = nextKey(); if (key == Fixed.NULL_NODE_KEY.getStandardProperty()) { // Reset to the start key before invoking the axis. resetToStartKey(); return false; } else { return true; } } /** * Please do not override {@code hasNext()} directly. Use this template method instead. It * determines the next node key in the axis. Override this method to simplify {@code hasNext()}. * Simply return {@code EFixed.NULL_NODE_KEY.getStandardProperty()} if no more node is following in * the axis, otherwise return the node key of the next node. * * @return next node key */ protected long nextKey() { return 0; } @Override public final long nextLong() { if (!hasNext) { throw new NoSuchElementException("No more nodes in the axis!"); } if (!next) { if (!hasNext()) { throw new NoSuchElementException("No more nodes in the axis!"); } } if (key >= 0) { if (rtx.hasNode(key)) { rtx.moveTo(key); } else { throw new IllegalStateException("Failed to move to nodeKey: " + key); } } else { rtx.moveTo(key); } next = false; return key; } @Override public final void remove() { throw new UnsupportedOperationException(); } /** * Resetting the nodekey of this axis to a given nodekey. * * @param pNodeKey the nodekey where the reset should occur to */ @Override public void reset(@NonNegative final long pNodeKey) { startKey = pNodeKey; key = pNodeKey; next = false; hasNext = true; } @Override public XmlNodeReadOnlyTrx asXmlNodeReadTrx() { if (rtx instanceof XmlNodeReadOnlyTrx rtx) { return rtx; } throw new ClassCastException("Node cursor is no XML node transaction."); } @Override public JsonNodeReadOnlyTrx asJsonNodeReadTrx() { if (rtx instanceof JsonNodeReadOnlyTrx rtx) { return rtx; } throw new ClassCastException("Node cursor is no JSON node transaction."); } @Override public NodeReadOnlyTrx getTrx() { if (rtx instanceof NodeReadOnlyTrx) { return (XmlNodeReadOnlyTrx) rtx; } throw new IllegalStateException("Node cursor is no transaction cursor."); } @Override public PathSummaryReader asPathSummary() { if (rtx instanceof PathSummaryReader) { return (PathSummaryReader) rtx; } throw new ClassCastException("Node cursor is no path summary reader."); } @Override public NodeCursor getCursor() { return rtx; } /** * Determines if axis might have more results. * * @return {@code true} if axis might have more results, {@code false} otherwise */ public boolean isHasNext() { return hasNext; } /** * Make sure the transaction points to the node it started with. This must be called just before * {@code hasNext() == false}. * * @return key of node where transaction was before the first call of {@code hasNext()} */ protected final long resetToStartKey() { // No check because of IAxis Convention 4. rtx.moveTo(startKey); next = false; hasNext = false; return startKey; } /** * Make sure the transaction points to the node after the last hasNext(). This must be called first * in hasNext(). * * @return key of node where transaction was after the last call of {@code hasNext()} */ protected final long resetToLastKey() { // No check because of IAxis Convention 4. rtx.moveTo(key); next = true; return key; } @Override public final long getStartKey() { return startKey; } @Override public final IncludeSelf includeSelf() { return includeSelf; } @Override public long peek() { return Fixed.NULL_NODE_KEY.getStandardProperty(); } /** * Get mNext which determines if {@code hasNext()} has at least been called once before the call to * {@code next()}. * * @return {@code true} if {@code hasNext()} has been called before calling {@code next()}, * {@code false} otherwise */ public final boolean isNext() { return next; } /** * Implements a simple foreach-method. * * @param pVisitor {@link XmlNodeVisitor} implementation */ @Override public final void foreach(final XmlNodeVisitor pVisitor) { requireNonNull(pVisitor); for (; hasNext(); nextLong()) { ((XmlNodeReadOnlyTrx) rtx).acceptVisitor(pVisitor); } } @Override public synchronized final long nextNode() { synchronized (rtx) { long retVal = Fixed.NULL_NODE_KEY.getStandardProperty(); if (hasNext()) { retVal = nextLong(); } return retVal; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy