⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rdflistimpl.java

📁 Jena推理机
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************
 * 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 + -