📄 rdflistimpl.java
字号:
checkValid();
}
checkNotNil( "Tried to replace a value in the empty list" );
return findElement( false, i ).setHead( value );
}
/**
* <p>
* Answer true if the given node appears as the value of a value of any
* of the cells of this list.
* </p>
*
* @param value A value to test for
* @return True if the list contains value.
*/
public boolean contains( RDFNode value ) {
return indexOf( value, 0 ) >= 0;
}
/**
* <p>
* Answer the index of the first occurrence of the given value in the list,
* or -1 if the value is not in the list.
* </p>
*
* @param value The value to search for
* @return The index of the first occurrence of value in the list, or
* <code>-1</code> if not found.
*/
public int indexOf( RDFNode value ) {
return indexOf( value, 0 );
}
/**
* <p>
* Answer the index of the first occurrence of the given value in the list
* after index <code>start</code>, or -1 if the value is not in the list
* after the given start point.
* </p>
*
* @param value The value to search for
* @param start The index into the list to start searching from
* @return The index (from zero, the front of the list) of the first
* occurrence of <code>value</code> in the list not less than
* <code>start</code>, or <code>-1</code> if not found.
* @exception ListIndexException if <code>start</code> is greater than the
* length of the list.
*/
public int indexOf( RDFNode value, int start ) {
if (s_checkValid) {
checkValid();
}
// first get to where we start
Resource l = findElement( false, start );
int index = start;
Property head = listFirst();
Property tail = listRest();
Resource nil = listNil();
boolean found = l.hasProperty( head, value );
// search for the element whose value is, er, value
while (!found && !l.equals( nil )) {
l = l.getRequiredProperty( tail ).getResource();
index++;
found = l.hasProperty( head, value );
}
return found ? index : -1;
}
/**
* <p>
* Answer a new list that is formed by adding each element of this list to
* the head of the the list formed from the
* given <code>nodes</code>. This is a non side-effecting
* operation on either this list or the given list, but generates a copy
* of this list. For a more storage efficient alternative, see {@link
* #concatenate concatenate}.
* </p>
*
* @param nodes An iterator whose range is RDFNode
* @return A new RDFList that contains all of this elements of this list,
* followed by all of the elements of the given iterator.
*/
public RDFList append( Iterator nodes ) {
return append( copy( nodes) );
}
/**
* <p>
* Answer a new list that is formed by adding each element of this list to
* the head of the given <code>list</code>. This is a non side-effecting
* operation on either this list or the given list, but generates a copy
* of this list. For a more storage efficient alternative, see {@link
* #concatenate concatenate}.
* </p>
*
* @param list The argument list
* @return A new RDFList that contains all of this elements of this list,
* followed by all of the elements of the given list.
*/
public RDFList append( RDFList list ) {
if (s_checkValid) {
checkValid();
}
if (isEmpty()) {
// special case
return list;
}
else {
// could do this recursively, but for long lists it's better to iterate
// do the copy, then change the last tail pointer to point to the arg
RDFList copy = copy( iterator() );
copy.concatenate( list );
return copy;
}
}
/**
* <p>
* Change the tail of this list to point to the given list, so that this
* list becomes the list of the concatenation of the elements of both lists.
* This is a side-effecting operation on this list; for a non side-effecting
* alternative, see {@link #append}. Due to the problem of maintaining
* the URI invariant on a node, this operation will throw an exception if an
* attempt is made to concatenate onto an empty list. To avoid this, test for
* an empty list: if true replace the empty list with the argument list, otherwise
* proceed with the concatenate as usual. An alternative solution is to use
* {@link #append} and replace the original list with the return value.
* </p>
*
* @param list The argument list to concatenate to this list
* @exception EmptyListUpdateException if this list is the nil list
*/
public void concatenate( RDFList list ) {
if (s_checkValid) {
checkValid();
}
if (isEmpty()) {
// concatenating list onto the empty list is an error
throw new EmptyListUpdateException( "Tried to concatenate onto the empty list" );
}
else {
// find the end of this list and link it to the argument list
findElement( true, 0 ).setTail( list );
}
}
/**
* <p>
* Add the nodes returned by the given iterator to the end of this list.
* </p>
*
* @param nodes An iterator whose range is RDFNode
* @exception EmptyListUpdateException if this list is the nil list
* @see #concatenate(RDFList) for details on avoiding the empty list update exception.
*/
public void concatenate( Iterator nodes ) {
// make a list of the nodes and add to the end of this
concatenate( copy( nodes ) );
}
/**
* <p>
* Answer a list that contains all of the elements of this list in the same
* order, but is a duplicate copy in the underlying model.
* </p>
*
* @return A copy of the current list
*/
public RDFList copy() {
if (s_checkValid) {
checkValid();
}
return copy( iterator() );
}
/**
* <p>
* Apply a function to each value in the list in turn.
* </p>
*
* @param fn The function to apply to each list node.
*/
public void apply( ApplyFn fn ) {
if (s_checkValid) {
checkValid();
}
for (Iterator i = iterator(); i.hasNext(); ) {
fn.apply( (RDFNode) i.next() );
}
}
/**
* <p>
* Apply a function to each value in the list in turn, accumulating the
* results in an accumulator. The final value of the accumulator is returned
* as the value of <code>reduce()</code>.
* </p>
*
* @param fn The reduction function to apply
* @param initial The initial value for the accumulator
* @return The final value of the accumulator.
*/
public Object reduce( ReduceFn fn, Object initial ) {
if (s_checkValid) {
checkValid();
}
Object acc = initial;
for (Iterator i = iterator(); i.hasNext(); ) {
acc = fn.reduce( (RDFNode) i.next(), acc );
}
return acc;
}
/**
* <p>Answer an iterator of the elements of this list, to each of which
* the given map function has been applied.</p>
* @param fn A Map function
* @return The iterator of the elements of this list mapped with the given map function.
*/
public ExtendedIterator mapWith( Map1 fn ) {
return iterator().mapWith( fn );
}
/**
* <p>
* Remove the value from the head of the list. The tail of the list remains
* in the model. Note that no changes are made to list cells that point to
* this list cell as their tail. Immediately following a
* <code>removeHead</code> operation, such lists will be in a non-valid
* state.
* </p>
*
* @return The remainder of the list after the head is removed (i.e. the
* pre-removal list tail)
*/
public RDFList removeHead() {
if (s_checkValid) {
checkValid();
}
checkNotNil( "Attempted to delete the head of a nil list" );
RDFList tail = getTail();
removeProperties();
return tail;
}
/**
* <p>Remove the given value from this list. If <code>val</code> does not occur in
* the list, no action is taken. Since removing the head of the list will invalidate
* the list head cell, in general the list must return the list that results from this
* operation. However, in many cases the return value will be the same as the object
* that this method is invoked on</p>
*
* @param val The value to be removed from the list
* @return The resulting list, which will be the same as the current list in most
* cases, except when <code>val</code> occurs at the head of the list.
*/
public RDFList remove( RDFNode val ) {
if (s_checkValid) {
checkValid();
}
RDFList prev = null;
RDFList cell = this;
boolean searching = true;
while (searching && !cell.isEmpty()) {
if (cell.getHead().equals( val )) {
// found the value to be removed
RDFList tail = cell.getTail();
if (prev != null) {
prev.setTail( tail );
}
cell.removeProperties();
// return this unless we have removed the head element
return (prev == null) ? tail : this;
}
else {
// not found yet
prev = cell;
cell = cell.getTail();
}
}
// not found
return this;
}
/**
* <p>Deprecated. Since an <code>RDFList</code> does not behave like a Java container, it is not
* the case that the contents of the list can be removed and the container filled with values
* again. Therefore, this method name has been deprecated in favour of {@link #removeList}</p>
* @deprecated Replaced by {@link #removeList}
*/
public void removeAll() {
removeList();
}
/**
* <p>Remove all of the components of this list from the model. Once this operation
* has completed, the {@link RDFList} resource on which it was called will no
* longer be a resource in the model, so further methods calls on the list object
* (for example, {@link #size} will fail. Due to restrictions on the encoding
* of lists in RDF, it is not possible to perform an operation which empties a list
* and then adds further values to that list. Client code wishing to perform
* such an operation should do so in two steps: first remove the old list, then
* create a new list with the new contents. It is important that RDF statements
* that reference the old list (in the object position) be updated to point
* to the newly created list.
* Note that this
* is operation is only removing the list cells themselves, not the resources
* referenced by the list - unless being the object of an <code>rdf:first</code>
* statement is the only mention of that resource in the model.</p>
*/
public void removeList() {
for (Iterator i = collectStatements().iterator(); i.hasNext(); ) {
((Statement) i.next()).remove();
}
}
/**
* <p>Answer a set of all of the RDF statements whose subject is one of the cells
* of this list.</p>
* @return A list of the statements that form the encoding of this list.
*/
public Set collectStatements() {
Set stmts = new HashSet();
RDFList l = this;
do {
// collect all statements of this list cell
for (Iterator i = l.listProperties(); i.hasNext(); ) {
stmts.add( i.next() );
}
// move on to next cell
l = l.getTail();
} while (!l.isEmpty());
return stmts;
}
/**
* <p>
* Answer an iterator over the elements of the list. Note that this iterator
* does not take a snapshot of the list, so changes to the list statements
* in the model while iterating will affect the behaviour of the iterator.
* To get an iterator that is not affected by model changes, use {@link
* #asJavaList}.
* </p>
*
* @return A closable iterator over the elements of the list.
*/
public ExtendedIterator iterator() {
return new RDFListIterator( this );
}
/**
* <p>
* Answer the contents of this RDF list as a Java list of RDFNode values.
* </p>
*
* @return The contents of this list as a Java List.
*/
public List asJavaList() {
List l = new ArrayList();
for (Iterator i = iterator(); i.hasNext(); ) {
l.add( i.next() );
}
return l;
}
/**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -