Source Code Cross Referenced for RDFListImpl.java in  » RSS-RDF » Jena-2.5.5 » com » hp » hpl » jena » rdf » model » impl » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » RSS RDF » Jena 2.5.5 » com.hp.hpl.jena.rdf.model.impl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*****************************************************************************
0002:         * Source code information
0003:         * -----------------------
0004:         * Original author    Ian Dickinson, HP Labs Bristol
0005:         * Author email       Ian.Dickinson@hp.com
0006:         * Package            Jena 2
0007:         * Web                http://sourceforge.net/projects/jena/
0008:         * Created            24 Jan 2003
0009:         * Filename           $RCSfile: RDFListImpl.java,v $
0010:         * Revision           $Revision: 1.17 $
0011:         * Release status     $State: Exp $
0012:         *
0013:         * Last modified on   $Date: 2008/01/02 12:05:10 $
0014:         *               by   $Author: andy_seaborne $
0015:         *
0016:         * (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
0017:         * (see footer for full conditions)
0018:         *****************************************************************************/package com.hp.hpl.jena.rdf.model.impl;
0019:
0020:        // Imports
0021:        ///////////////
0022:        import com.hp.hpl.jena.ontology.*;
0023:        import com.hp.hpl.jena.rdf.model.*;
0024:        import com.hp.hpl.jena.shared.*;
0025:        import com.hp.hpl.jena.util.iterator.*;
0026:        import com.hp.hpl.jena.enhanced.*;
0027:        import com.hp.hpl.jena.graph.*;
0028:        import com.hp.hpl.jena.vocabulary.*;
0029:
0030:        import java.util.*;
0031:
0032:        import org.apache.commons.logging.Log;
0033:        import org.apache.commons.logging.LogFactory;
0034:
0035:        /**
0036:         * <p>
0037:         * Standard implementation the list abstraction from rdf.model.
0038:         * </p>
0039:         * 
0040:         * @author Ian Dickinson, HP Labs 
0041:         *         (<a  href="mailto:Ian.Dickinson@hp.com" >email</a>)
0042:         * @version CVS $Id: RDFListImpl.java,v 1.17 2008/01/02 12:05:10 andy_seaborne Exp $
0043:         */
0044:        public class RDFListImpl extends ResourceImpl implements  RDFList {
0045:            // Constants
0046:            //////////////////////////////////
0047:
0048:            // Static variables
0049:            //////////////////////////////////
0050:
0051:            /**
0052:             * A factory for generating RDFList facets from nodes in enhanced graphs.
0053:             */
0054:            public static Implementation factory = new Implementation() {
0055:                public EnhNode wrap(Node n, EnhGraph eg) {
0056:                    if (canWrap(n, eg)) {
0057:                        RDFListImpl impl = new RDFListImpl(n, eg);
0058:
0059:                        // pass on the vocabulary terms, if available
0060:                        if (eg instanceof  OntModel) {
0061:                            Profile prof = ((OntModel) eg).getProfile();
0062:                            impl.m_listFirst = prof.FIRST();
0063:                            impl.m_listRest = prof.REST();
0064:                            impl.m_listNil = prof.NIL();
0065:                            impl.m_listType = prof.LIST();
0066:                        }
0067:
0068:                        return impl;
0069:                    } else {
0070:                        throw new JenaException("Cannot convert node " + n
0071:                                + " to RDFList");
0072:                    }
0073:                }
0074:
0075:                public boolean canWrap(Node node, EnhGraph eg) {
0076:                    Graph g = eg.asGraph();
0077:
0078:                    // if we are using a language profile, get the first, rest and next resources from there
0079:                    Resource first = RDF.first;
0080:                    Resource rest = RDF.rest;
0081:                    Resource nil = RDF.nil;
0082:
0083:                    if (eg instanceof  OntModel) {
0084:                        Profile prof = ((OntModel) eg).getProfile();
0085:                        first = prof.FIRST();
0086:                        rest = prof.REST();
0087:                        nil = prof.NIL();
0088:                    }
0089:
0090:                    // 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
0091:                    return node.equals(nil.asNode())
0092:                            || g.contains(node, first.asNode(), Node.ANY)
0093:                            || g.contains(node, rest.asNode(), Node.ANY)
0094:                            || g.contains(node, RDF.type.asNode(), RDF.List
0095:                                    .asNode());
0096:                }
0097:            };
0098:
0099:            /** Flag to indicate whether we are checking for valid lists during list operations. Default false. */
0100:            protected static boolean s_checkValid = false;
0101:
0102:            private static final Log log = LogFactory.getLog(RDFListImpl.class);
0103:
0104:            // Instance variables
0105:            //////////////////////////////////
0106:
0107:            /** Error message if validity check fails */
0108:            protected String m_errorMsg = null;
0109:
0110:            /** Pointer to the node that is the tail of the list */
0111:            protected RDFList m_tail = null;
0112:
0113:            /** The URI for the 'first' property in this list */
0114:            protected Property m_listFirst = RDF.first;
0115:
0116:            /** The URI for the 'rest' property in this list */
0117:            protected Property m_listRest = RDF.rest;
0118:
0119:            /** The URI for the 'nil' Resource in this list */
0120:            protected Resource m_listNil = RDF.nil;
0121:
0122:            /** The URI for the rdf:type of this list */
0123:            protected Resource m_listType = RDF.List;
0124:
0125:            // Constructors
0126:            //////////////////////////////////
0127:
0128:            /**
0129:             * <p>
0130:             * Construct an implementation of RDFList in the given graph, where the
0131:             * given node is the head of the list.
0132:             * </p>
0133:             * 
0134:             * @param n The node that is the head of the list, currently
0135:             * @param g The enh graph that contains n
0136:             */
0137:            public RDFListImpl(Node n, EnhGraph g) {
0138:                super (n, g);
0139:            }
0140:
0141:            // External signature methods
0142:            //////////////////////////////////
0143:
0144:            // vocabulary terms
0145:            public Resource listType() {
0146:                return m_listType;
0147:            }
0148:
0149:            public Resource listNil() {
0150:                return m_listNil;
0151:            }
0152:
0153:            public Property listFirst() {
0154:                return m_listFirst;
0155:            }
0156:
0157:            public Property listRest() {
0158:                return m_listRest;
0159:            }
0160:
0161:            public Class listAbstractionClass() {
0162:                return RDFList.class;
0163:            }
0164:
0165:            /**
0166:             * <p>
0167:             * Answer the number of elements in the list.
0168:             * </p>
0169:             * 
0170:             * @return The length of the list as an integer
0171:             */
0172:            public int size() {
0173:                if (s_checkValid) {
0174:                    checkValid();
0175:                }
0176:
0177:                int size = 0;
0178:
0179:                for (Iterator i = iterator(); i.hasNext(); i.next()) {
0180:                    size++;
0181:                }
0182:                return size;
0183:            }
0184:
0185:            /**
0186:             * <p>
0187:             * Answer the value that is at the head of the list.
0188:             * </p>
0189:             * 
0190:             * @return The value that is associated with the head of the list.
0191:             * @exception EmptyListException if this list is the empty list
0192:             */
0193:            public RDFNode getHead() {
0194:                if (s_checkValid) {
0195:                    checkValid();
0196:                }
0197:
0198:                checkNotNil("Tried to get the head of an empty list");
0199:
0200:                return getRequiredProperty(listFirst()).getObject();
0201:            }
0202:
0203:            /**
0204:             * <p>
0205:             * Update the head of the list to have the given value, and return the
0206:             * previous value.
0207:             * </p>
0208:             * 
0209:             * @param value The value that will become the value of the list head
0210:             * @exception EmptyListException if this list is the empty list
0211:             */
0212:            public RDFNode setHead(RDFNode value) {
0213:                if (s_checkValid) {
0214:                    checkValid();
0215:                }
0216:
0217:                checkNotNil("Tried to set the head of an empty list");
0218:
0219:                // first remove the existing head
0220:                Statement current = getRequiredProperty(listFirst());
0221:                RDFNode n = current.getObject();
0222:                current.remove();
0223:
0224:                // now add the new head value to the graph
0225:                addProperty(listFirst(), value);
0226:
0227:                return n;
0228:            }
0229:
0230:            /**
0231:             * <p>
0232:             * Answer the list that is the tail of this list.
0233:             * </p>
0234:             * 
0235:             * @return The tail of the list, as a list
0236:             * @exception EmptyListException if this list is the empty list
0237:             */
0238:            public RDFList getTail() {
0239:                if (s_checkValid) {
0240:                    checkValid();
0241:                }
0242:
0243:                checkNotNil("Tried to get the tail of an empty list");
0244:
0245:                Resource tail = getRequiredProperty(listRest()).getResource();
0246:                return (RDFList) tail.as(listAbstractionClass());
0247:            }
0248:
0249:            /**
0250:             * <p>
0251:             * Update the list cell at the front of the list to have the given list as
0252:             * tail. The old tail is returned, and remains in the model.
0253:             * </p>
0254:             * 
0255:             * @param tail The new tail for this list.
0256:             * @return The old tail.
0257:             */
0258:            public RDFList setTail(RDFList tail) {
0259:                if (s_checkValid) {
0260:                    checkValid();
0261:                }
0262:
0263:                checkNotNil("Tried to set the tail of an empty list");
0264:
0265:                return (RDFList) (setTailAux(this , tail, listRest()))
0266:                        .as(listAbstractionClass());
0267:            }
0268:
0269:            /**
0270:             * Answer true if this list is the empty list.
0271:             * 
0272:             * @return True if this is the empty (nil) list, otherwise false.
0273:             */
0274:            public boolean isEmpty() {
0275:                if (s_checkValid) {
0276:                    checkValid();
0277:                }
0278:
0279:                return equals(listNil());
0280:            }
0281:
0282:            /**
0283:             * <p>
0284:             * Return a reference to a new list cell whose head is <code>value</code>
0285:             * and whose tail is this list.
0286:             * </p>
0287:             * 
0288:             * @param value A new value to add to the head of the list
0289:             * @return The new list, whose head is <code>value</code>
0290:             */
0291:            public RDFList cons(RDFNode value) {
0292:                if (s_checkValid) {
0293:                    checkValid();
0294:                }
0295:
0296:                // create a new, anonymous typed resource to be the list cell
0297:                // map to a list facet
0298:                return (RDFList) (newListCell(value, this ))
0299:                        .as(listAbstractionClass());
0300:            }
0301:
0302:            /**
0303:             * <p>
0304:             * Add the given value to the end of the list. This is a side-effecting 
0305:             * operation on the underlying model that is only defined if this is not the
0306:             * empty list.  If this list is the empty (nil) list, we cannot perform a 
0307:             * side-effecting update without changing the URI of this node (from <code>rdf:nil</code)
0308:             * to a blank-node for the new list cell) without violating a Jena invariant.
0309:             * Therefore, this update operation will throw an exception if an attempt is
0310:             * made to add to the nil list.  Safe ways to add to an empty list include
0311:             * {@link #with} and {@link #cons}.
0312:             * </p>
0313:             * 
0314:             * @param value A value to add to the end of the list
0315:             * @exception EmptyListUpdateException if an attempt is made to 
0316:             * <code>add</code> to the empty list.
0317:             */
0318:            public void add(RDFNode value) {
0319:                if (s_checkValid) {
0320:                    checkValid();
0321:                }
0322:
0323:                // if this is the empty list, we have to barf
0324:                if (isEmpty()) {
0325:                    throw new EmptyListUpdateException(
0326:                            "Attempt to add() to the empty list (rdf:nil)");
0327:                }
0328:
0329:                // get the tail of the list (which may be cached)
0330:                RDFList tail = findElement(true, 0);
0331:
0332:                // now do the concatenate
0333:                setTailAux(tail, newListCell(value, listNil()), listRest());
0334:            }
0335:
0336:            /**
0337:             * <p>
0338:             * Answer the list that is this list with the given value added to the end
0339:             * of the list.  This operation differs from {@link #add} in that it will
0340:             * always work, even on an empty list, but the return value is the updated
0341:             * list.  Specifically, in the case of adding a value to the empty list, the
0342:             * returned list will not be the same as this list. <strong>Client code should
0343:             * not assume that this is an in-place update, but should ensure that the resulting
0344:             * list is asserted back into the graph into the appropriate relationships.</strong>
0345:             * </p>
0346:             * 
0347:             * @param value A value to add to the end of the list
0348:             * @return The list that results from adding a value to the end of this list 
0349:             */
0350:            public RDFList with(RDFNode value) {
0351:                if (s_checkValid) {
0352:                    checkValid();
0353:                }
0354:
0355:                // if this is the empty list, we create a new node containing value - i.e. cons
0356:                if (isEmpty()) {
0357:                    return cons(value);
0358:                }
0359:
0360:                // get the tail of the list (which may be cached)
0361:                RDFList tail = findElement(true, 0);
0362:
0363:                // now do the concatenate
0364:                setTailAux(tail, newListCell(value, listNil()), listRest());
0365:                return this ;
0366:            }
0367:
0368:            /**
0369:             * <p>
0370:             * Answer the node that is the i'th element of the list, assuming that the 
0371:             * head is item zero.  If the list is too short to have an i'th element,
0372:             * throws a {@link ListIndexException}.
0373:             * </p>
0374:             * 
0375:             * @param i The index into the list, from 0
0376:             * @return The list value at index i, or null
0377:             * @exception ListIndexException if the list has fewer than (i + 1)
0378:             * elements.
0379:             */
0380:            public RDFNode get(int i) {
0381:                if (s_checkValid) {
0382:                    checkValid();
0383:                }
0384:
0385:                checkNotNil("Tried to get an element from the empty list");
0386:                return findElement(false, i).getHead();
0387:            }
0388:
0389:            /**
0390:             * <p>
0391:             * Replace the value at the i'th position in the list with the given value.
0392:             * If the list is too short to have an i'th element, throws a {@link
0393:             * ListIndexException}.
0394:             * </p>
0395:             * 
0396:             * @param i The index into the list, from 0
0397:             * @param value The new value to associate with the i'th list element
0398:             * @return The value that was previously at position i in the list
0399:             * @exception ListIndexException if the list has fewer than (i + 1)
0400:             * elements.
0401:             */
0402:            public RDFNode replace(int i, RDFNode value) {
0403:                if (s_checkValid) {
0404:                    checkValid();
0405:                }
0406:
0407:                checkNotNil("Tried to replace a value in the empty list");
0408:                return findElement(false, i).setHead(value);
0409:            }
0410:
0411:            /**
0412:             * <p>
0413:             * Answer true if the given node appears as the value of a value of any
0414:             * of the cells of this list.
0415:             * </p>
0416:             * 
0417:             * @param value A value to test for
0418:             * @return True if the list contains value.
0419:             */
0420:            public boolean contains(RDFNode value) {
0421:                return indexOf(value, 0) >= 0;
0422:            }
0423:
0424:            /**
0425:             * <p>
0426:             * Answer the index of the first occurrence of the given value in the list,
0427:             * or -1 if the value is not in the list.
0428:             * </p>
0429:             * 
0430:             * @param value The value to search for
0431:             * @return The index of the first occurrence of value in the list, or
0432:             * <code>-1</code> if not found.
0433:             */
0434:            public int indexOf(RDFNode value) {
0435:                return indexOf(value, 0);
0436:            }
0437:
0438:            /**
0439:             * <p>
0440:             * Answer the index of the first occurrence of the given value in the list
0441:             * after index <code>start</code>, or -1 if the value is not in the list
0442:             * after the given start point.
0443:             * </p>
0444:             * 
0445:             * @param value The value to search for
0446:             * @param start The index into the list to start searching from
0447:             * @return The index (from zero, the front of the list) of the first
0448:             * occurrence of <code>value</code> in the list not less than
0449:             * <code>start</code>, or <code>-1</code> if not found.
0450:             * @exception ListIndexException if <code>start</code> is greater than the
0451:             * length of the list.
0452:             */
0453:            public int indexOf(RDFNode value, int start) {
0454:                if (s_checkValid) {
0455:                    checkValid();
0456:                }
0457:
0458:                // first get to where we start
0459:                Resource l = findElement(false, start);
0460:                int index = start;
0461:
0462:                Property head = listFirst();
0463:                Property tail = listRest();
0464:                Resource nil = listNil();
0465:
0466:                boolean found = l.hasProperty(head, value);
0467:
0468:                // search for the element whose value is, er, value
0469:                while (!found && !l.equals(nil)) {
0470:                    l = l.getRequiredProperty(tail).getResource();
0471:                    index++;
0472:                    found = l.hasProperty(head, value);
0473:                }
0474:
0475:                return found ? index : -1;
0476:            }
0477:
0478:            /**
0479:             * <p>
0480:             * Answer a new list that is formed by adding each element of this list to
0481:             * the head of the the list formed from the 
0482:             * given <code>nodes</code>. This is a non side-effecting
0483:             * operation on either this list or the given list, but generates a copy
0484:             * of this list.  For a more storage efficient alternative, see {@link
0485:             * #concatenate concatenate}.
0486:             * </p>
0487:             * 
0488:             * @param nodes An iterator whose range is RDFNode
0489:             * @return A new RDFList that contains all of this elements of this list,
0490:             * followed by all of the elements of the given iterator.
0491:             */
0492:            public RDFList append(Iterator nodes) {
0493:                return append(copy(nodes));
0494:            }
0495:
0496:            /**
0497:             * <p>
0498:             * Answer a new list that is formed by adding each element of this list to
0499:             * the head of the given <code>list</code>. This is a non side-effecting
0500:             * operation on either this list or the given list, but generates a copy
0501:             * of this list.  For a more storage efficient alternative, see {@link
0502:             * #concatenate concatenate}.
0503:             * </p>
0504:             * 
0505:             * @param list The argument list
0506:             * @return A new RDFList that contains all of this elements of this list,
0507:             * followed by all of the elements of the given list.
0508:             */
0509:            public RDFList append(RDFList list) {
0510:                if (s_checkValid) {
0511:                    checkValid();
0512:                }
0513:
0514:                if (isEmpty()) {
0515:                    // special case
0516:                    return list;
0517:                } else {
0518:                    // could do this recursively, but for long lists it's better to iterate
0519:                    // do the copy, then change the last tail pointer to point to the arg
0520:                    RDFList copy = copy(iterator());
0521:                    copy.concatenate(list);
0522:                    return copy;
0523:                }
0524:            }
0525:
0526:            /**
0527:             * <p>
0528:             * Change the tail of this list to point to the given list, so that this
0529:             * list becomes the list of the concatenation of the elements of both lists.
0530:             * This is a side-effecting operation on this list; for a non side-effecting
0531:             * alternative, see {@link #append}.  Due to the problem of maintaining
0532:             * the URI invariant on a node, this operation will throw an exception if an
0533:             * attempt is made to concatenate onto an empty list.  To avoid this, test for
0534:             * an empty list: if true replace the empty list with the argument list, otherwise
0535:             * proceed with the concatenate as usual.  An alternative solution is to use
0536:             * {@link #append} and replace the original list with the return value.
0537:             * </p>
0538:             * 
0539:             * @param list The argument list to concatenate to this list
0540:             * @exception EmptyListUpdateException if this list is the nil list
0541:             */
0542:            public void concatenate(RDFList list) {
0543:                if (s_checkValid) {
0544:                    checkValid();
0545:                }
0546:
0547:                if (isEmpty()) {
0548:                    // concatenating list onto the empty list is an error
0549:                    throw new EmptyListUpdateException(
0550:                            "Tried to concatenate onto the empty list");
0551:                } else {
0552:                    // find the end of this list and link it to the argument list
0553:                    findElement(true, 0).setTail(list);
0554:                }
0555:            }
0556:
0557:            /**
0558:             * <p>
0559:             * Add the nodes returned by the given iterator to the end of this list.
0560:             * </p>
0561:             * 
0562:             * @param nodes An iterator whose range is RDFNode
0563:             * @exception EmptyListUpdateException if this list is the nil list
0564:             * @see #concatenate(RDFList) for details on avoiding the empty list update exception.
0565:             */
0566:            public void concatenate(Iterator nodes) {
0567:                // make a list of the nodes and add to the end of this
0568:                concatenate(copy(nodes));
0569:            }
0570:
0571:            /**
0572:             * <p>
0573:             * Answer a list that contains all of the elements of this list in the same
0574:             * order, but is a duplicate copy in the underlying model.
0575:             * </p>
0576:             * 
0577:             * @return A copy of the current list
0578:             */
0579:            public RDFList copy() {
0580:                if (s_checkValid) {
0581:                    checkValid();
0582:                }
0583:
0584:                return copy(iterator());
0585:            }
0586:
0587:            /**
0588:             * <p>
0589:             * Apply a function to each value in the list in turn.
0590:             * </p>
0591:             * 
0592:             * @param fn The function to apply to each list node.
0593:             */
0594:            public void apply(ApplyFn fn) {
0595:                if (s_checkValid) {
0596:                    checkValid();
0597:                }
0598:
0599:                for (Iterator i = iterator(); i.hasNext();) {
0600:                    fn.apply((RDFNode) i.next());
0601:                }
0602:            }
0603:
0604:            /**
0605:             * <p>
0606:             * Apply a function to each value in the list in turn, accumulating the
0607:             * results in an accumulator. The final value of the accumulator is returned
0608:             * as the value of <code>reduce()</code>.
0609:             * </p>
0610:             * 
0611:             * @param fn The reduction function to apply
0612:             * @param initial The initial value for the accumulator
0613:             * @return The final value of the accumulator.
0614:             */
0615:            public Object reduce(ReduceFn fn, Object initial) {
0616:                if (s_checkValid) {
0617:                    checkValid();
0618:                }
0619:
0620:                Object acc = initial;
0621:
0622:                for (Iterator i = iterator(); i.hasNext();) {
0623:                    acc = fn.reduce((RDFNode) i.next(), acc);
0624:                }
0625:
0626:                return acc;
0627:            }
0628:
0629:            /**
0630:             * <p>Answer an iterator of the elements of this list, to each of which
0631:             * the given map function has been applied.</p>
0632:             * @param fn A Map function
0633:             * @return The iterator of the elements of this list mapped with the given map function.
0634:             */
0635:            public ExtendedIterator mapWith(Map1 fn) {
0636:                return iterator().mapWith(fn);
0637:            }
0638:
0639:            /**
0640:             * <p>
0641:             * Remove the value from the head of the list.  The tail of the list remains
0642:             * in the model.  Note that no changes are made to list cells that point to
0643:             * this list cell as their tail.  Immediately following a
0644:             * <code>removeHead</code> operation, such lists will be in a non-valid
0645:             * state.
0646:             * </p>
0647:             * 
0648:             * @return The remainder of the list after the head is removed (i&#046;e&#046; the
0649:             * pre-removal list tail)
0650:             */
0651:            public RDFList removeHead() {
0652:                if (s_checkValid) {
0653:                    checkValid();
0654:                }
0655:
0656:                checkNotNil("Attempted to delete the head of a nil list");
0657:
0658:                RDFList tail = getTail();
0659:                removeProperties();
0660:
0661:                return tail;
0662:            }
0663:
0664:            /**
0665:             * <p>Remove the given value from this list. If <code>val</code> does not occur in
0666:             * the list, no action is taken.  Since removing the head of the list will invalidate
0667:             * the list head cell, in general the list must return the list that results from this
0668:             * operation. However, in many cases the return value will be the same as the object
0669:             * that this method is invoked on</p>
0670:             * 
0671:             * @param val The value to be removed from the list
0672:             * @return The resulting list, which will be the same as the current list in most
0673:             * cases, except when <code>val</code> occurs at the head of the list.
0674:             */
0675:            public RDFList remove(RDFNode val) {
0676:                if (s_checkValid) {
0677:                    checkValid();
0678:                }
0679:
0680:                RDFList prev = null;
0681:                RDFList cell = this ;
0682:                boolean searching = true;
0683:
0684:                while (searching && !cell.isEmpty()) {
0685:                    if (cell.getHead().equals(val)) {
0686:                        // found the value to be removed
0687:                        RDFList tail = cell.getTail();
0688:                        if (prev != null) {
0689:                            prev.setTail(tail);
0690:                        }
0691:
0692:                        cell.removeProperties();
0693:
0694:                        // return this unless we have removed the head element
0695:                        return (prev == null) ? tail : this ;
0696:                    } else {
0697:                        // not found yet
0698:                        prev = cell;
0699:                        cell = cell.getTail();
0700:                    }
0701:                }
0702:
0703:                // not found
0704:                return this ;
0705:            }
0706:
0707:            /**
0708:             * <p>Deprecated. Since an <code>RDFList</code> does not behave like a Java container, it is not
0709:             * the case that the contents of the list can be removed and the container filled with values
0710:             * again. Therefore, this method name has been deprecated in favour of {@link #removeList}</p>
0711:             * @deprecated Replaced by {@link #removeList}
0712:             */
0713:            public void removeAll() {
0714:                removeList();
0715:            }
0716:
0717:            /**
0718:             * <p>Remove all of the components of this list from the model. Once this operation
0719:             * has completed, the {@link RDFList} resource on which it was called will no
0720:             * longer be a resource in the model, so further methods calls on the list object
0721:             * (for example, {@link #size} will fail.  Due to restrictions on the encoding
0722:             * of lists in RDF, it is not possible to perform an operation which empties a list
0723:             * and then adds further values to that list. Client code wishing to perform
0724:             * such an operation should do so in two steps: first remove the old list, then 
0725:             * create a new list with the new contents. It is important that RDF statements
0726:             * that reference the old list (in the object position) be updated to point 
0727:             * to the newly created list.  
0728:             * Note that this
0729:             * is operation is only removing the list cells themselves, not the resources
0730:             * referenced by the list - unless being the object of an <code>rdf:first</code>
0731:             * statement is the only mention of that resource in the model.</p>
0732:             */
0733:            public void removeList() {
0734:                for (Iterator i = collectStatements().iterator(); i.hasNext();) {
0735:                    ((Statement) i.next()).remove();
0736:                }
0737:            }
0738:
0739:            /**
0740:             * <p>Answer a set of all of the RDF statements whose subject is one of the cells
0741:             * of this list.</p>
0742:             * @return A list of the statements that form the encoding of this list.
0743:             */
0744:            public Set collectStatements() {
0745:                Set stmts = new HashSet();
0746:                RDFList l = this ;
0747:
0748:                do {
0749:                    // collect all statements of this list cell
0750:                    for (Iterator i = l.listProperties(); i.hasNext();) {
0751:                        stmts.add(i.next());
0752:                    }
0753:
0754:                    // move on to next cell
0755:                    l = l.getTail();
0756:                } while (!l.isEmpty());
0757:
0758:                return stmts;
0759:            }
0760:
0761:            /**
0762:             * <p>
0763:             * Answer an iterator over the elements of the list. Note that this iterator
0764:             * does not take a snapshot of the list, so changes to the list statements
0765:             * in the model while iterating will affect the behaviour of the iterator.
0766:             * To get an iterator that is not affected by model changes, use {@link
0767:             * #asJavaList}.
0768:             * </p>
0769:             * 
0770:             * @return A closable iterator over the elements of the list.
0771:             */
0772:            public ExtendedIterator iterator() {
0773:                return new RDFListIterator(this );
0774:            }
0775:
0776:            /**
0777:             * <p>
0778:             * Answer the contents of this RDF list as a Java list of RDFNode values.
0779:             * </p>
0780:             * 
0781:             * @return The contents of this list as a Java List.
0782:             */
0783:            public List asJavaList() {
0784:                List l = new ArrayList();
0785:
0786:                for (Iterator i = iterator(); i.hasNext();) {
0787:                    l.add(i.next());
0788:                }
0789:
0790:                return l;
0791:            }
0792:
0793:            /**
0794:             * <p>
0795:             * Answer true if this list has the same elements in the same order as the
0796:             * given list.  Note that the standard <code>equals</code> test just tests
0797:             * for equality of two given list cells.  While such a test is sufficient
0798:             * for many purposes, this test provides a broader equality definition, but
0799:             * is correspondingly more expensive to test.
0800:             * </p>
0801:             * 
0802:             * @param list The list to test against
0803:             * @return True if the given list and this list are the same length, and
0804:             * contain equal elements in the same order.
0805:             */
0806:            public boolean sameListAs(RDFList list) {
0807:                if (s_checkValid) {
0808:                    checkValid();
0809:                }
0810:
0811:                Resource r0 = this ;
0812:                Resource r1 = list;
0813:
0814:                Property head = listFirst();
0815:                Property tail = listRest();
0816:                Resource nil = listNil();
0817:
0818:                // iterate through to the end of the list
0819:                while (!(r0.equals(nil) || r1.equals(nil))) {
0820:                    RDFNode n0 = r0.getRequiredProperty(head).getObject();
0821:                    RDFNode n1 = r1.getRequiredProperty(head).getObject();
0822:
0823:                    if (n0 == null || !n0.equals(n1)) {
0824:                        // not equal at this position
0825:                        return false;
0826:                    } else {
0827:                        // advance along the lists
0828:                        r0 = r0.getRequiredProperty(tail).getResource();
0829:                        r1 = r1.getRequiredProperty(tail).getResource();
0830:                    }
0831:                }
0832:
0833:                // lists are equal if they terminate together
0834:                return r0.equals(nil) && r1.equals(nil);
0835:            }
0836:
0837:            /**
0838:             * <p>
0839:             * Answer true lists are operating in strict mode, in which the
0840:             * well- formedness of the list is checked at every operation.
0841:             * </p>
0842:             * 
0843:             * @return True lists are being strictly checked.
0844:             */
0845:            public boolean getStrict() {
0846:                return s_checkValid;
0847:            }
0848:
0849:            /**
0850:             * <p>
0851:             * Set a flag to indicate whether to strictly check the well-formedness of
0852:             * lists at each operation. Default false.  Note that the flag that is
0853:             * manipulated is actually a static: it applies to all lists. However, RDFList
0854:             * is a Java interface, and Java does not permit static methods in interfaces.
0855:             * </p>
0856:             * 
0857:             * @param strict The <b>static</b> flag for whether lists will be checked strictly.
0858:             */
0859:            public void setStrict(boolean strict) {
0860:                s_checkValid = strict;
0861:            }
0862:
0863:            /**
0864:             * <p>
0865:             * Answer true if the list is well-formed, by checking that each node is
0866:             * correctly typed, and has a head and tail pointer from the correct
0867:             * vocabulary.
0868:             * </p>
0869:             * 
0870:             * @return True if the list is well-formed.
0871:             */
0872:            public boolean isValid() {
0873:                m_errorMsg = null;
0874:
0875:                try {
0876:                    checkValid();
0877:                } catch (InvalidListException e) {
0878:                    m_errorMsg = e.getMessage();
0879:                }
0880:
0881:                return (m_errorMsg == null);
0882:            }
0883:
0884:            /**
0885:             * <p>
0886:             * Answer the error message returned by the last failed validity check,
0887:             * if any.
0888:             * </p>
0889:             * 
0890:             * @return The most recent error message, or null.
0891:             */
0892:            public String getValidityErrorMessage() {
0893:                return m_errorMsg;
0894:            }
0895:
0896:            /**
0897:             * <p>
0898:             * Construct a new list cell with the given value and tail.
0899:             * </p>
0900:             * 
0901:             * @param value The value at the head of the new list cell
0902:             * @param tail The tail of the list cell
0903:             * @return A new list cell as a resource
0904:             */
0905:            public Resource newListCell(RDFNode value, Resource tail) {
0906:                // Note: following the RDF WG decision, we no longer assert rdf:type rdf:List for list cells
0907:                Resource cell = getModel().createResource();
0908:
0909:                // set the head and tail
0910:                cell.addProperty(listFirst(), value);
0911:                cell.addProperty(listRest(), tail);
0912:
0913:                return cell;
0914:            }
0915:
0916:            // Internal implementation methods
0917:            //////////////////////////////////
0918:
0919:            /**
0920:             * <p>
0921:             * Answer true if this is a valid list cell, which means either that it
0922:             * is nil, or it has the appropriate type and a first and next relation.
0923:             * Updated 17-06-2003: RDFCore last comments process has decided that the
0924:             * rdf:type of a list is implied by the domain constraints on rdf:first
0925:             * and rdf:rest, so no longer needs to be asserted directly.  The test
0926:             * for rdf:type has therefore been removed.
0927:             * </p>
0928:             * 
0929:             * @return True if this list cell passes basic validity checks
0930:             */
0931:            protected void checkValid() {
0932:                if (!equals(listNil())) {
0933:                    // note that the rdf:type of list cells is now implied by the RDF M&S
0934:                    // so we don't check explicitly
0935:                    // checkValidProperty( RDF.type, listType() );
0936:
0937:                    checkValidProperty(listFirst(), null);
0938:                    checkValidProperty(listRest(), null);
0939:                }
0940:            }
0941:
0942:            private void checkValidProperty(Property p, RDFNode expected) {
0943:                int count = 0;
0944:
0945:                for (StmtIterator j = getModel().listStatements(this , p,
0946:                        expected); j.hasNext(); j.next()) {
0947:                    count++;
0948:                }
0949:
0950:                // exactly one value is expected
0951:                if (count == 0) {
0952:                    if (log.isDebugEnabled()) {
0953:                        log.debug("Failed validity check on " + toString());
0954:                        for (StmtIterator i = listProperties(); i.hasNext();) {
0955:                            log.debug("  this => " + i.next());
0956:                        }
0957:                        for (StmtIterator i = getModel().listStatements(null,
0958:                                null, this ); i.hasNext();) {
0959:                            log.debug("  => this " + i.next());
0960:                        }
0961:                    }
0962:                    throw new InvalidListException("List node "
0963:                            + toString()
0964:                            + " is not valid: it should have property "
0965:                            + p.toString()
0966:                            + (expected == null ? ""
0967:                                    : (" with value " + expected)));
0968:                } else if (count > 1) {
0969:                    throw new InvalidListException("List node " + toString()
0970:                            + " is not valid: it has more than one value for "
0971:                            + p.toString());
0972:                }
0973:            }
0974:
0975:            /**
0976:             * <p>
0977:             * Check that the current list cell is not the nil list, and throw an empty
0978:             * list exception if it is.
0979:             * </p>
0980:             * 
0981:             * @param msg The context message for the empty list exception
0982:             * @exception EmptyListException if the list is the nil list
0983:             */
0984:            protected void checkNotNil(String msg) {
0985:                if (isEmpty()) {
0986:                    throw new EmptyListException(msg);
0987:                }
0988:            }
0989:
0990:            /**
0991:             * <p>
0992:             * Find and return an element of this list - either the last element before
0993:             * the end of the list, or the i'th element from the front (starting from
0994:             * zero).  Note that this method assumes the pre-condition that
0995:             * <code>this</code> is not the empty list.
0996:             * </p>
0997:             * 
0998:             * @param last If true, find the element whose tail is nil
0999:             * @param index If <code>last</code> is false, find the index'th element
1000:             * from the head of the list
1001:             * @return The list cell
1002:             * @exception ListIndexException if try to access an element beyond the end
1003:             * of the list
1004:             * @exception InvalidListException if try to find the end of a badly formed
1005:             * list
1006:             */
1007:            protected RDFList findElement(boolean last, int index) {
1008:                Property tail = listRest();
1009:                Resource nil = listNil();
1010:
1011:                Resource l = this ;
1012:                int i = index;
1013:                boolean found = (last && l.hasProperty(tail, nil))
1014:                        || (!last && (i == 0));
1015:
1016:                // search for the element whose tail is nil, or whose index is now zero
1017:                while (!found && !l.equals(nil)) {
1018:                    l = l.getRequiredProperty(tail).getResource();
1019:                    found = (last && l.hasProperty(tail, nil))
1020:                            || (!last && (--i == 0));
1021:                }
1022:
1023:                if (!found) {
1024:                    // premature end of list
1025:                    if (!last) {
1026:                        throw new ListIndexException("Tried to access element "
1027:                                + index
1028:                                + " that is beyond the length of the list");
1029:                    } else {
1030:                        throw new InvalidListException(
1031:                                "Could not find last element of list (suggests list is not valid)");
1032:                    }
1033:                } else {
1034:                    return (RDFList) l.as(listAbstractionClass());
1035:                }
1036:            }
1037:
1038:            /**
1039:             * <p>
1040:             * Create a copy of the list of nodes returned by an iterator.
1041:             * </p>
1042:             * 
1043:             * @param i An iterator of RDFNodes
1044:             * @return A list formed from all of the nodes of i, in sequence
1045:             */
1046:            protected RDFList copy(Iterator i) {
1047:                Resource list = null;
1048:                Resource start = null;
1049:
1050:                Property head = listFirst();
1051:                Property tail = listRest();
1052:                Resource cellType = listType();
1053:
1054:                while (i.hasNext()) {
1055:                    // create a list cell to hold the next value from the existing list
1056:                    Resource cell = getModel().createResource(cellType);
1057:                    cell.addProperty(head, (RDFNode) i.next());
1058:
1059:                    // point the previous list cell to this one
1060:                    if (list != null) {
1061:                        list.addProperty(tail, cell);
1062:                    } else {
1063:                        // must be the first cell we're adding
1064:                        start = cell;
1065:                    }
1066:
1067:                    list = cell;
1068:                }
1069:
1070:                // finally close the list
1071:                list.addProperty(tail, listNil());
1072:
1073:                return (RDFList) start.as(listAbstractionClass());
1074:            }
1075:
1076:            /**
1077:             * <p>
1078:             * Helper method for setting the list tail, that assumes we have
1079:             * a resource that is a list.
1080:             * </p>
1081:             * 
1082:             * @param root The resource representing the list cell we're setting the
1083:             * tail of
1084:             * @param tail The new tail for this list, as a resource.
1085:             * @return The old tail, as a resource.
1086:             */
1087:            protected static Resource setTailAux(Resource root, Resource tail,
1088:                    Property pTail) {
1089:                Statement current = root.getRequiredProperty(pTail);
1090:                Resource oldTail = current.getResource();
1091:
1092:                // out with the old, in with the new
1093:                current.remove();
1094:                root.addProperty(pTail, tail);
1095:
1096:                return oldTail;
1097:            }
1098:
1099:            //==============================================================================
1100:            // Inner class definitions
1101:            //==============================================================================
1102:
1103:            /**
1104:             * <p>
1105:             * Iterator that can step along chains of list pointers to the end of the
1106:             * list.
1107:             * </p>
1108:             */
1109:            protected class RDFListIterator extends NiceIterator {
1110:                // Instance variables
1111:
1112:                /** The current list node */
1113:                protected RDFList m_head;
1114:
1115:                /** The most recently seen node */
1116:                protected RDFList m_seen = null;
1117:
1118:                // Constructor
1119:                //////////////
1120:
1121:                /**
1122:                 * Construct an iterator for walking the list starting at head
1123:                 */
1124:                protected RDFListIterator(RDFList head) {
1125:                    m_head = head;
1126:                }
1127:
1128:                // External contract methods
1129:                ////////////////////////////
1130:
1131:                /**
1132:                 * @see Iterator#hasNext
1133:                 */
1134:                public boolean hasNext() {
1135:                    return !m_head.isEmpty();
1136:                }
1137:
1138:                /**
1139:                 * @see Iterator#next
1140:                 */
1141:                public Object next() {
1142:                    m_seen = m_head;
1143:                    m_head = m_head.getTail();
1144:
1145:                    return m_seen.getHead();
1146:                }
1147:
1148:                /**
1149:                 * @see Iterator#remove
1150:                 */
1151:                public void remove() {
1152:                    if (m_seen == null) {
1153:                        throw new IllegalStateException(
1154:                                "Illegal remove from list operator");
1155:                    }
1156:
1157:                    // will remove three statements in a well-formed list
1158:                    ((Resource) m_seen).removeProperties();
1159:                    m_seen = null;
1160:                }
1161:            }
1162:        }
1163:
1164:        /*
1165:         (c) Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
1166:         All rights reserved.
1167:
1168:         Redistribution and use in source and binary forms, with or without
1169:         modification, are permitted provided that the following conditions
1170:         are met:
1171:
1172:         1. Redistributions of source code must retain the above copyright
1173:         notice, this list of conditions and the following disclaimer.
1174:
1175:         2. Redistributions in binary form must reproduce the above copyright
1176:         notice, this list of conditions and the following disclaimer in the
1177:         documentation and/or other materials provided with the distribution.
1178:
1179:         3. The name of the author may not be used to endorse or promote products
1180:         derived from this software without specific prior written permission.
1181:
1182:         THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1183:         IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1184:         OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1185:         IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1186:         INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1187:         NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1188:         DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1189:         THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1190:         (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1191:         THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1192:         */
ww__w___.__ja__v__a__2s.___c__o__m_ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.