org.apache.jackrabbit.jcr2spi.query.RowIteratorImpl 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.query;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.RangeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.query.Row;
import javax.jcr.query.RowIterator;
import org.apache.jackrabbit.spi.QValue;
import org.apache.jackrabbit.spi.QueryInfo;
import org.apache.jackrabbit.spi.QueryResultRow;
import org.apache.jackrabbit.spi.NodeId;
import org.apache.jackrabbit.spi.commons.conversion.NameException;
import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
import org.apache.jackrabbit.spi.commons.value.ValueFormat;
import org.apache.jackrabbit.jcr2spi.ItemManager;
import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyManager;
/**
* Implements the {@link javax.jcr.query.RowIterator} interface returned by
* a {@link javax.jcr.query.QueryResult}.
*/
class RowIteratorImpl implements RowIterator {
/**
* The result rows from the SPI implementation.
*/
private final RangeIterator rows;
/**
* The column names.
*/
private final String[] columnNames;
/**
* The NamePathResolver
of the user Session
.
*/
private final NamePathResolver resolver;
/**
* The JCR value factory.
*/
private final ValueFactory vFactory;
/**
* The item manager.
*/
private final ItemManager itemMgr;
/**
* The hierarchy manager.
*/
private final HierarchyManager hmgr;
/**
* Creates a new RowIteratorImpl
that iterates over the result
* nodes.
*
* @param queryInfo the query info.
* @param resolver NameResolver
of the user
* Session
.
* @param vFactory the JCR value factory.
* @param itemMgr the item manager.
* @param hmgr the hierarchy manager.
*/
RowIteratorImpl(QueryInfo queryInfo, NamePathResolver resolver,
ValueFactory vFactory, ItemManager itemMgr,
HierarchyManager hmgr) {
this.rows = queryInfo.getRows();
this.columnNames = queryInfo.getColumnNames();
this.resolver = resolver;
this.vFactory = vFactory;
this.itemMgr = itemMgr;
this.hmgr = hmgr;
}
//--------------------------------------------------------< RowIterator >---
/**
* Returns the next Row
in the iteration.
*
* @return the next Row
in the iteration.
* @throws NoSuchElementException if iteration has no more Row
s.
* @see RowIterator#nextRow()
*/
public Row nextRow() throws NoSuchElementException {
return new RowImpl((QueryResultRow) rows.next());
}
//------------------------------------------------------< RangeIterator >---
/**
* Skip a number of Row
s in this iterator.
*
* @param skipNum the non-negative number of Row
s to skip
* @throws NoSuchElementException if skipped past the last Row
* in this iterator.
* @see javax.jcr.RangeIterator#skip(long)
*/
public void skip(long skipNum) throws NoSuchElementException {
rows.skip(skipNum);
}
/**
* Returns the number of Row
s in this iterator.
*
* @return the number of Row
s in this iterator.
* @see RangeIterator#getSize()
*/
public long getSize() {
return rows.getSize();
}
/**
* Returns the current position within this iterator. The number
* returned is the 0-based index of the next Row
in the iterator,
* i.e. the one that will be returned on the subsequent next
call.
*
* Note that this method does not check if there is a next element,
* i.e. an empty iterator will always return 0.
*
* @return the current position withing this iterator.
* @see RangeIterator#getPosition()
*/
public long getPosition() {
return rows.getPosition();
}
/**
* @throws UnsupportedOperationException always.
* @see Iterator#remove()
*/
public void remove() {
throw new UnsupportedOperationException("remove");
}
/**
* Returns true
if the iteration has more Row
s.
* (In other words, returns true
if next
would
* return an Row
rather than throwing an exception.)
*
* @return true
if the iterator has more elements.
* @see Iterator#hasNext()
*/
public boolean hasNext() {
return rows.hasNext();
}
/**
* Returns the next Row
in the iteration.
*
* @return the next Row
in the iteration.
* @throws NoSuchElementException if iteration has no more Row
s.
* @see Iterator#next()
*/
public Object next() throws NoSuchElementException {
return nextRow();
}
//---------------------< inner class RowImpl >------------------------------
/**
* Implements the {@link javax.jcr.query.Row} interface, which represents
* a row in the query result.
*/
class RowImpl implements Row {
/**
* The underlying QueryResultRow
.
*/
private final QueryResultRow row;
/**
* Cached value array for returned by {@link #getValues()}.
*/
private Value[] values;
/**
* Map of select property names. Key: String, Value:
* Integer, which refers to the array index in {@link #values}.
*/
private Map propertyMap;
/**
* Creates a new RowImpl
instance based on a SPI result
* row.
*
* @param row the underlying query result row
*/
private RowImpl(QueryResultRow row) {
this.row = row;
}
//------------------------------------------------------------< Row >---
/**
* Returns an array of all the values in the same order as the property
* names (column names) returned by
* {@link javax.jcr.query.QueryResult#getColumnNames()}.
*
* @return a Value
array.
* @throws RepositoryException if an error occurs while retrieving the
* values from the Node
.
* @see Row#getValues()
*/
public Value[] getValues() throws RepositoryException {
if (values == null) {
QValue[] qVals = row.getValues();
Value[] tmp = new Value[qVals.length];
for (int i = 0; i < qVals.length; i++) {
if (qVals[i] == null) {
tmp[i] = null;
} else {
tmp[i] = ValueFormat.getJCRValue(
qVals[i], resolver, vFactory);
}
}
values = tmp;
}
// return a copy of the array
Value[] ret = new Value[values.length];
System.arraycopy(values, 0, ret, 0, values.length);
return ret;
}
/**
* Returns the value of the indicated property in this Row
.
*
* If propertyName
is not among the column names of the
* query result table, an ItemNotFoundException
is thrown.
*
* @return a Value
* @throws ItemNotFoundException if propertyName
is not
* among the column names of the query result table.
* @throws RepositoryException if propertyName
is not a
* valid property name.
* @see Row#getValue(String)
*/
public Value getValue(String propertyName) throws ItemNotFoundException, RepositoryException {
if (propertyMap == null) {
// create the map first
Map tmp = new HashMap();
for (int i = 0; i < columnNames.length; i++) {
tmp.put(columnNames[i], i);
}
propertyMap = tmp;
}
try {
Integer idx = propertyMap.get(propertyName);
if (idx == null) {
throw new ItemNotFoundException(propertyName);
}
// make sure values are there
if (values == null) {
getValues();
}
return values[idx];
} catch (NameException e) {
throw new RepositoryException(e.getMessage(), e);
}
}
/**
* @see Row#getNode()
*/
public Node getNode() throws RepositoryException {
return getNode(row.getNodeId(null));
}
/**
* @see Row#getNode(String)
*/
public Node getNode(String selectorName) throws RepositoryException {
return getNode(row.getNodeId(selectorName));
}
/**
* @see Row#getPath()
*/
public String getPath() throws RepositoryException {
String path = null;
Node n = getNode();
if (n != null) {
path = n.getPath();
}
return path;
}
/**
* @see Row#getPath(String)
*/
public String getPath(String selectorName) throws RepositoryException {
String path = null;
Node n = getNode(selectorName);
if (n != null) {
path = n.getPath();
}
return path;
}
/**
* @see Row#getScore()
*/
public double getScore() throws RepositoryException {
return row.getScore(null);
}
/**
* @see Row#getScore(String)
*/
public double getScore(String selectorName) throws RepositoryException {
return row.getScore(selectorName);
}
/**
* Returns the node with the given id
or null
* if id
is null
.
*
* @param id a node id or null
.
* @return the node with the given id or null
.
* @throws RepositoryException if an error occurs while retrieving the
* node.
*/
private Node getNode(NodeId id) throws RepositoryException {
Node node = null;
if (id != null) {
node = (Node) itemMgr.getItem(hmgr.getNodeEntry(id));
}
return node;
}
}
}