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

org.apache.jackrabbit.jcr2spi.LazyItemIterator Maven / Gradle / Ivy

/*
 * 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.jackrabbit.jcr2spi;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

import javax.jcr.Item;
import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.PropertyIterator;
import javax.jcr.RangeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.version.Version;
import javax.jcr.version.VersionIterator;

import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyEntry;
import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyManager;
import org.apache.jackrabbit.spi.ItemId;
import org.apache.jackrabbit.spi.NodeId;
import org.apache.jackrabbit.spi.PropertyId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * LazyItemIterator is an id-based iterator that instantiates
 * the Items only when they are requested.
 * 

* Important: Items that appear to be nonexistent * for some reason (e.g. because of insufficient access rights or because they * have been removed since the iterator has been retrieved) are silently * skipped. As a result the size of the iterator as reported by * {@link #getSize()} always returns -1. */ public class LazyItemIterator implements NodeIterator, PropertyIterator, VersionIterator { /** Logger instance for this class */ private static Logger log = LoggerFactory.getLogger(LazyItemIterator.class); private static final long UNDEFINED_SIZE = -1; /** the item manager that is used to lazily fetch the items */ private final ItemManager itemMgr; /** Iterator over HierarchyEntry elements */ private final Iterator iter; /** * The number of items. * Note, that the size may change over the time due to the lazy behaviour * of this iterator that may only upon iteration found out, that a * hierarchy entry has been invalidated or removed in the mean time. */ private long size; /** the position of the next item */ private int pos; /** prefetched item to be returned on {@link #next()} */ private Item next; /** * Creates a new LazyItemIterator instance. * * @param itemMgr item manager * @param hierarchyEntryIterator Iterator over HierarchyEntries */ public LazyItemIterator(ItemManager itemMgr, Iterator hierarchyEntryIterator) { this.itemMgr = itemMgr; this.iter = hierarchyEntryIterator; if (hierarchyEntryIterator instanceof RangeIterator) { size = ((RangeIterator) hierarchyEntryIterator).getSize(); } else { size = UNDEFINED_SIZE; } pos = 0; // fetch first item next = prefetchNext(); } /** * Creates a new LazyItemIterator instance. * * @param itemMgr * @param hierarchyMgr * @param itemIds */ public LazyItemIterator(ItemManager itemMgr, HierarchyManager hierarchyMgr, Iterator itemIds) throws ItemNotFoundException, RepositoryException { this.itemMgr = itemMgr; List entries = new ArrayList(); while (itemIds.hasNext()) { ItemId id = itemIds.next(); HierarchyEntry entry; if (id.denotesNode()) { entry = hierarchyMgr.getNodeEntry((NodeId) id); } else { entry = hierarchyMgr.getPropertyEntry((PropertyId) id); } entries.add(entry); } iter = entries.iterator(); size = entries.size(); pos = 0; // fetch first item next = prefetchNext(); } /** * Prefetches next item. *

* {@link #next} is set to the next available item in this iterator or to * null in case there are no more items. */ private Item prefetchNext() { Item nextItem = null; while (nextItem == null && iter.hasNext()) { HierarchyEntry entry = iter.next(); try { nextItem = itemMgr.getItem(entry); } catch (RepositoryException e) { log.warn("Failed to fetch item " + entry.getName() + ", skipping.", e.getMessage()); // reduce the size... and try the next one size--; } } return nextItem; } //-------------------------------------------------------< NodeIterator >--- /** * {@inheritDoc} * @see NodeIterator#nextNode() */ public Node nextNode() { return (Node) next(); } //---------------------------------------------------< PropertyIterator >--- /** * {@inheritDoc} * @see PropertyIterator#nextProperty() */ public Property nextProperty() { return (Property) next(); } //----------------------------------------------------< VersionIterator >--- /** * {@inheritDoc} * @see VersionIterator#nextVersion() */ public Version nextVersion() { return (Version) next(); } //------------------------------------------------------< RangeIterator >--- /** * {@inheritDoc} * @see javax.jcr.RangeIterator#getPosition() */ public long getPosition() { return pos; } /** * Returns the number of Items in this iterator or -1 if the * size is unknown. *

* Note: The number returned by this method may differ from the number * of Items actually returned by calls to hasNext() / getNextNode(). * This is caused by the lazy instantiation behaviour of this iterator, * that may detect only upon iteration that an Item has been invalidated * or removed in the mean time. As soon as an invalid Item is * detected, the size of this iterator is adjusted. * * @return the number of Items in this iterator. * @see RangeIterator#getSize() */ public long getSize() { return size; } /** * {@inheritDoc} * @see RangeIterator#skip(long) */ public void skip(long skipNum) { if (skipNum < 0) { throw new IllegalArgumentException("skipNum must not be negative"); } if (skipNum == 0) { return; } if (next == null) { throw new NoSuchElementException(); } // skip the first (skipNum - 1) items without actually retrieving them while (--skipNum > 0) { pos++; HierarchyEntry entry = iter.next(); // check if item exists but don't build Item instance. boolean itemExists = false; while(!itemExists){ try{ itemExists = itemMgr.itemExists(entry); }catch(RepositoryException e){ log.warn("Failed to check that item {} exists",entry,e); } if(!itemExists){ log.debug("Ignoring nonexistent item {}", entry); entry = iter.next(); } } } // fetch final item (the one to be returned on next()) pos++; next = prefetchNext(); } //-----------------------------------------------------------< Iterator >--- /** * {@inheritDoc} * @see java.util.Iterator#hasNext() */ public boolean hasNext() { return next != null; } /** * {@inheritDoc} * @see Iterator#next() */ public Object next() { if (next == null) { throw new NoSuchElementException(); } Item item = next; pos++; next = prefetchNext(); return item; } /** * {@inheritDoc} * @see Iterator#remove() * * @throws UnsupportedOperationException always since removal is not implemented. */ public void remove() { throw new UnsupportedOperationException("remove"); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy