📄 rdflistimpl.java
字号:
/*****************************************************************************
* Source code information
* -----------------------
* Original author Ian Dickinson, HP Labs Bristol
* Author email Ian.Dickinson@hp.com
* Package Jena 2
* Web http://sourceforge.net/projects/jena/
* Created 24 Jan 2003
* Filename $RCSfile: RDFListImpl.java,v $
* Revision $Revision: 1.16 $
* Release status $State: Exp $
*
* Last modified on $Date: 2007/01/02 11:48:30 $
* by $Author: andy_seaborne $
*
* (c) Copyright 2003, 2004, 2005, 2006, 2007 Hewlett-Packard Development Company, LP
* (see footer for full conditions)
*****************************************************************************/
// Package
///////////////
package com.hp.hpl.jena.rdf.model.impl;
// Imports
///////////////
import com.hp.hpl.jena.ontology.*;
import com.hp.hpl.jena.rdf.model.*;
import com.hp.hpl.jena.shared.*;
import com.hp.hpl.jena.util.iterator.*;
import com.hp.hpl.jena.enhanced.*;
import com.hp.hpl.jena.graph.*;
import com.hp.hpl.jena.vocabulary.*;
import java.util.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* <p>
* Standard implementation the list abstraction from rdf.model.
* </p>
*
* @author Ian Dickinson, HP Labs
* (<a href="mailto:Ian.Dickinson@hp.com" >email</a>)
* @version CVS $Id: RDFListImpl.java,v 1.16 2007/01/02 11:48:30 andy_seaborne Exp $
*/
public class RDFListImpl
extends ResourceImpl
implements RDFList
{
// Constants
//////////////////////////////////
// Static variables
//////////////////////////////////
/**
* A factory for generating RDFList facets from nodes in enhanced graphs.
*/
public static Implementation factory = new Implementation() {
public EnhNode wrap( Node n, EnhGraph eg ) {
if (canWrap( n, eg )) {
RDFListImpl impl = new RDFListImpl( n, eg );
// pass on the vocabulary terms, if available
if (eg instanceof OntModel) {
Profile prof = ((OntModel) eg).getProfile();
impl.m_listFirst = prof.FIRST();
impl.m_listRest = prof.REST();
impl.m_listNil = prof.NIL();
impl.m_listType = prof.LIST();
}
return impl;
}
else {
throw new JenaException( "Cannot convert node " + n + " to RDFList");
}
}
public boolean canWrap( Node node, EnhGraph eg ) {
Graph g = eg.asGraph();
// if we are using a language profile, get the first, rest and next resources from there
Resource first = RDF.first;
Resource rest = RDF.rest;
Resource nil = RDF.nil;
if (eg instanceof OntModel) {
Profile prof = ((OntModel) eg).getProfile();
first = prof.FIRST();
rest = prof.REST();
nil = prof.NIL();
}
// node will support being an RDFList facet if it has rdf:type rdf:List, is nil, or is in the domain of a list property
return
node.equals( nil.asNode() ) ||
g.contains( node, first.asNode(), Node.ANY ) ||
g.contains( node, rest.asNode(), Node.ANY ) ||
g.contains( node, RDF.type.asNode(), RDF.List.asNode() );
}
};
/** Flag to indicate whether we are checking for valid lists during list operations. Default false. */
protected static boolean s_checkValid = false;
private static final Log log = LogFactory.getLog( RDFListImpl.class );
// Instance variables
//////////////////////////////////
/** Error message if validity check fails */
protected String m_errorMsg = null;
/** Pointer to the node that is the tail of the list */
protected RDFList m_tail = null;
/** The URI for the 'first' property in this list */
protected Property m_listFirst = RDF.first;
/** The URI for the 'rest' property in this list */
protected Property m_listRest = RDF.rest;
/** The URI for the 'nil' Resource in this list */
protected Resource m_listNil = RDF.nil;
/** The URI for the rdf:type of this list */
protected Resource m_listType = RDF.List;
// Constructors
//////////////////////////////////
/**
* <p>
* Construct an implementation of RDFList in the given graph, where the
* given node is the head of the list.
* </p>
*
* @param n The node that is the head of the list, currently
* @param g The enh graph that contains n
*/
public RDFListImpl( Node n, EnhGraph g ) {
super( n, g );
}
// External signature methods
//////////////////////////////////
// vocabulary terms
public Resource listType() { return m_listType; }
public Resource listNil() { return m_listNil; }
public Property listFirst() { return m_listFirst; }
public Property listRest() { return m_listRest; }
public Class listAbstractionClass() { return RDFList.class; }
/**
* <p>
* Answer the number of elements in the list.
* </p>
*
* @return The length of the list as an integer
*/
public int size() {
if (s_checkValid) {
checkValid();
}
int size = 0;
for (Iterator i = iterator(); i.hasNext(); i.next()) {
size++;
}
return size;
}
/**
* <p>
* Answer the value that is at the head of the list.
* </p>
*
* @return The value that is associated with the head of the list.
* @exception EmptyListException if this list is the empty list
*/
public RDFNode getHead() {
if (s_checkValid) {
checkValid();
}
checkNotNil( "Tried to get the head of an empty list" );
return getRequiredProperty( listFirst() ).getObject();
}
/**
* <p>
* Update the head of the list to have the given value, and return the
* previous value.
* </p>
*
* @param value The value that will become the value of the list head
* @exception EmptyListException if this list is the empty list
*/
public RDFNode setHead( RDFNode value ) {
if (s_checkValid) {
checkValid();
}
checkNotNil( "Tried to set the head of an empty list" );
// first remove the existing head
Statement current = getRequiredProperty( listFirst() );
RDFNode n = current.getObject();
current.remove();
// now add the new head value to the graph
addProperty( listFirst(), value );
return n;
}
/**
* <p>
* Answer the list that is the tail of this list.
* </p>
*
* @return The tail of the list, as a list
* @exception EmptyListException if this list is the empty list
*/
public RDFList getTail() {
if (s_checkValid) {
checkValid();
}
checkNotNil( "Tried to get the tail of an empty list" );
Resource tail = getRequiredProperty( listRest() ).getResource();
return (RDFList) tail.as( listAbstractionClass() );
}
/**
* <p>
* Update the list cell at the front of the list to have the given list as
* tail. The old tail is returned, and remains in the model.
* </p>
*
* @param tail The new tail for this list.
* @return The old tail.
*/
public RDFList setTail( RDFList tail ) {
if (s_checkValid) {
checkValid();
}
checkNotNil( "Tried to set the tail of an empty list" );
return (RDFList) (setTailAux( this, tail, listRest() )).as( listAbstractionClass() );
}
/**
* Answer true if this list is the empty list.
*
* @return True if this is the empty (nil) list, otherwise false.
*/
public boolean isEmpty() {
if (s_checkValid) {
checkValid();
}
return equals( listNil() );
}
/**
* <p>
* Return a reference to a new list cell whose head is <code>value</code>
* and whose tail is this list.
* </p>
*
* @param value A new value to add to the head of the list
* @return The new list, whose head is <code>value</code>
*/
public RDFList cons( RDFNode value ) {
if (s_checkValid) {
checkValid();
}
// create a new, anonymous typed resource to be the list cell
// map to a list facet
return (RDFList) (newListCell( value, this )).as( listAbstractionClass() );
}
/**
* <p>
* Add the given value to the end of the list. This is a side-effecting
* operation on the underlying model that is only defined if this is not the
* empty list. If this list is the empty (nil) list, we cannot perform a
* side-effecting update without changing the URI of this node (from <code>rdf:nil</code)
* to a blank-node for the new list cell) without violating a Jena invariant.
* Therefore, this update operation will throw an exception if an attempt is
* made to add to the nil list. Safe ways to add to an empty list include
* {@link #with} and {@link #cons}.
* </p>
*
* @param value A value to add to the end of the list
* @exception EmptyListUpdateException if an attempt is made to
* <code>add</code> to the empty list.
*/
public void add( RDFNode value ) {
if (s_checkValid) {
checkValid();
}
// if this is the empty list, we have to barf
if (isEmpty()) {
throw new EmptyListUpdateException( "Attempt to add() to the empty list (rdf:nil)" );
}
// get the tail of the list (which may be cached)
RDFList tail = findElement( true, 0 );
// now do the concatenate
setTailAux( tail, newListCell( value, listNil() ), listRest() );
}
/**
* <p>
* Answer the list that is this list with the given value added to the end
* of the list. This operation differs from {@link #add} in that it will
* always work, even on an empty list, but the return value is the updated
* list. Specifically, in the case of adding a value to the empty list, the
* returned list will not be the same as this list. <strong>Client code should
* not assume that this is an in-place update, but should ensure that the resulting
* list is asserted back into the graph into the appropriate relationships.</strong>
* </p>
*
* @param value A value to add to the end of the list
* @return The list that results from adding a value to the end of this list
*/
public RDFList with( RDFNode value ) {
if (s_checkValid) {
checkValid();
}
// if this is the empty list, we create a new node containing value - i.e. cons
if (isEmpty()) {
return cons( value );
}
// get the tail of the list (which may be cached)
RDFList tail = findElement( true, 0 );
// now do the concatenate
setTailAux( tail, newListCell( value, listNil() ), listRest() );
return this;
}
/**
* <p>
* Answer the node that is the i'th element of the list, assuming that the
* head is item zero. If the list is too short to have an i'th element,
* throws a {@link ListIndexException}.
* </p>
*
* @param i The index into the list, from 0
* @return The list value at index i, or null
* @exception ListIndexException if the list has fewer than (i + 1)
* elements.
*/
public RDFNode get( int i ) {
if (s_checkValid) {
checkValid();
}
checkNotNil( "Tried to get an element from the empty list" );
return findElement( false, i ).getHead();
}
/**
* <p>
* Replace the value at the i'th position in the list with the given value.
* If the list is too short to have an i'th element, throws a {@link
* ListIndexException}.
* </p>
*
* @param i The index into the list, from 0
* @param value The new value to associate with the i'th list element
* @return The value that was previously at position i in the list
* @exception ListIndexException if the list has fewer than (i + 1)
* elements.
*/
public RDFNode replace( int i, RDFNode value ) {
if (s_checkValid) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -