1 19 20 package com.hp.hpl.jena.rdf.model.impl; 23 24 25 import com.hp.hpl.jena.ontology.*; 28 import com.hp.hpl.jena.rdf.model.*; 29 import com.hp.hpl.jena.shared.*; 30 import com.hp.hpl.jena.util.iterator.*; 31 import com.hp.hpl.jena.enhanced.*; 32 import com.hp.hpl.jena.graph.*; 33 import com.hp.hpl.jena.vocabulary.*; 34 35 import java.util.*; 36 37 import org.apache.commons.logging.Log; 38 import org.apache.commons.logging.LogFactory; 39 40 41 50 public class RDFListImpl 51 extends ResourceImpl 52 implements RDFList 53 { 54 57 58 61 64 public static Implementation factory = new Implementation() { 65 public EnhNode wrap( Node n, EnhGraph eg ) { 66 if (canWrap( n, eg )) { 67 RDFListImpl impl = new RDFListImpl( n, eg ); 68 69 if (eg instanceof OntModel) { 71 Profile prof = ((OntModel) eg).getProfile(); 72 impl.m_listFirst = prof.FIRST(); 73 impl.m_listRest = prof.REST(); 74 impl.m_listNil = prof.NIL(); 75 impl.m_listType = prof.LIST(); 76 } 77 78 return impl; 79 } 80 else { 81 throw new JenaException( "Cannot convert node " + n + " to RDFList"); 82 } 83 } 84 85 public boolean canWrap( Node node, EnhGraph eg ) { 86 Graph g = eg.asGraph(); 87 88 Resource first = RDF.first; 90 Resource rest = RDF.rest; 91 Resource nil = RDF.nil; 92 93 if (eg instanceof OntModel) { 94 Profile prof = ((OntModel) eg).getProfile(); 95 first = prof.FIRST(); 96 rest = prof.REST(); 97 nil = prof.NIL(); 98 } 99 100 return node.equals( nil.asNode() ) || 102 g.find( node, first.asNode(), Node.ANY ).hasNext() || 103 g.find( node, rest.asNode(), Node.ANY ).hasNext() || 104 g.find( node, RDF.type.asNode(), RDF.List.asNode() ).hasNext(); 105 } 106 }; 107 108 109 protected static boolean s_checkValid = false; 110 111 private static final Log log = LogFactory.getLog( RDFListImpl.class ); 112 113 114 117 118 protected String m_errorMsg = null; 119 120 121 protected RDFList m_tail = null; 122 123 124 protected Property m_listFirst = RDF.first; 125 126 127 protected Property m_listRest = RDF.rest; 128 129 130 protected Resource m_listNil = RDF.nil; 131 132 133 protected Resource m_listType = RDF.List; 134 135 136 137 140 149 public RDFListImpl( Node n, EnhGraph g ) { 150 super( n, g ); 151 } 152 153 154 157 public Resource listType() { return m_listType; } 159 public Resource listNil() { return m_listNil; } 160 public Property listFirst() { return m_listFirst; } 161 public Property listRest() { return m_listRest; } 162 public Class listAbstractionClass() { return RDFList.class; } 163 164 165 172 public int size() { 173 if (s_checkValid) { 174 checkValid(); 175 } 176 177 int size = 0; 178 179 for (Iterator i = iterator(); i.hasNext(); i.next()) { 180 size++; 181 } 182 return size; 183 } 184 185 186 194 public RDFNode getHead() { 195 if (s_checkValid) { 196 checkValid(); 197 } 198 199 checkNotNil( "Tried to get the head of an empty list" ); 200 201 return getRequiredProperty( listFirst() ).getObject(); 202 } 203 204 205 214 public RDFNode setHead( RDFNode value ) { 215 if (s_checkValid) { 216 checkValid(); 217 } 218 219 checkNotNil( "Tried to set the head of an empty list" ); 220 221 Statement current = getRequiredProperty( listFirst() ); 223 RDFNode n = current.getObject(); 224 current.remove(); 225 226 addProperty( listFirst(), value ); 228 229 return n; 230 } 231 232 233 241 public RDFList getTail() { 242 if (s_checkValid) { 243 checkValid(); 244 } 245 246 checkNotNil( "Tried to get the tail of an empty list" ); 247 248 Resource tail = getRequiredProperty( listRest() ).getResource(); 249 return (RDFList) tail.as( listAbstractionClass() ); 250 } 251 252 253 262 public RDFList setTail( RDFList tail ) { 263 if (s_checkValid) { 264 checkValid(); 265 } 266 267 checkNotNil( "Tried to set the tail of an empty list" ); 268 269 return (RDFList) (setTailAux( this, tail, listRest() )).as( listAbstractionClass() ); 270 } 271 272 273 278 public boolean isEmpty() { 279 if (s_checkValid) { 280 checkValid(); 281 } 282 283 return equals( listNil() ); 284 } 285 286 287 296 public RDFList cons( RDFNode value ) { 297 if (s_checkValid) { 298 checkValid(); 299 } 300 301 return (RDFList) (newListCell( value, this )).as( listAbstractionClass() ); 304 } 305 306 307 323 public void add( RDFNode value ) { 324 if (s_checkValid) { 325 checkValid(); 326 } 327 328 if (isEmpty()) { 330 throw new EmptyListUpdateException( "Attempt to add() to the empty list (rdf:nil)" ); 331 } 332 333 RDFList tail = findElement( true, 0 ); 335 336 setTailAux( tail, newListCell( value, listNil() ), listRest() ); 338 } 339 340 341 355 public RDFList with( RDFNode value ) { 356 if (s_checkValid) { 357 checkValid(); 358 } 359 360 if (isEmpty()) { 362 return cons( value ); 363 } 364 365 RDFList tail = findElement( true, 0 ); 367 368 setTailAux( tail, newListCell( value, listNil() ), listRest() ); 370 return this; 371 } 372 373 374 386 public RDFNode get( int i ) { 387 if (s_checkValid) { 388 checkValid(); 389 } 390 391 checkNotNil( "Tried to get an element from the empty list" ); 392 return findElement( false, i ).getHead(); 393 } 394 395 396 409 public RDFNode replace( int i, RDFNode value ) { 410 if (s_checkValid) { 411 checkValid(); 412 } 413 414 checkNotNil( "Tried to replace a value in the empty list" ); 415 return findElement( false, i ).setHead( value ); 416 } 417 418 419 428 public boolean contains( RDFNode value ) { 429 return indexOf( value, 0 ) >= 0; 430 } 431 432 433 443 public int indexOf( RDFNode value ) { 444 return indexOf( value, 0 ); 445 } 446 447 448 463 public int indexOf( RDFNode value, int start ) { 464 if (s_checkValid) { 465 checkValid(); 466 } 467 468 Resource l = findElement( false, start ); 470 int index = start; 471 472 Property head = listFirst(); 473 Property tail = listRest(); 474 Resource nil = listNil(); 475 476 boolean found = l.hasProperty( head, value ); 477 478 while (!found && !l.equals( nil )) { 480 l = l.getRequiredProperty( tail ).getResource(); 481 index++; 482 found = l.hasProperty( head, value ); 483 } 484 485 return found ? index : -1; 486 } 487 488 489 503 public RDFList append( Iterator nodes ) { 504 return append( copy( nodes) ); 505 } 506 507 508 521 public RDFList append( RDFList list ) { 522 if (s_checkValid) { 523 checkValid(); 524 } 525 526 if (isEmpty()) { 527 return list; 529 } 530 else { 531 RDFList copy = copy( iterator() ); 534 copy.concatenate( list ); 535 return copy; 536 } 537 } 538 539 540 556 public void concatenate( RDFList list ) { 557 if (s_checkValid) { 558 checkValid(); 559 } 560 561 if (isEmpty()) { 562 throw new EmptyListUpdateException( "Tried to concatenate onto the empty list" ); 564 } 565 else { 566 findElement( true, 0 ).setTail( list ); 568 } 569 } 570 571 572 581 public void concatenate( Iterator nodes ) { 582 concatenate( copy( nodes ) ); 584 } 585 586 587 595 public RDFList copy() { 596 if (s_checkValid) { 597 checkValid(); 598 } 599 600 return copy( iterator() ); 601 } 602 603 604 611 public void apply( ApplyFn fn ) { 612 if (s_checkValid) { 613 checkValid(); 614 } 615 616 for (Iterator i = iterator(); i.hasNext(); ) { 617 fn.apply( (RDFNode) i.next() ); 618 } 619 } 620 621 622 633 public Object reduce( ReduceFn fn, Object initial ) { 634 if (s_checkValid) { 635 checkValid(); 636 } 637 638 Object acc = initial; 639 640 for (Iterator i = iterator(); i.hasNext(); ) { 641 acc = fn.reduce( (RDFNode) i.next(), acc ); 642 } 643 644 return acc; 645 } 646 647 648 654 public ExtendedIterator mapWith( Map1 fn ) { 655 return iterator().mapWith( fn ); 656 } 657 658 659 671 public RDFList removeHead() { 672 if (s_checkValid) { 673 checkValid(); 674 } 675 676 checkNotNil( "Attempted to delete the head of a nil list" ); 677 678 RDFList tail = getTail(); 679 removeProperties(); 680 681 return tail; 682 } 683 684 685 696 public RDFList remove( RDFNode val ) { 697 if (s_checkValid) { 698 checkValid(); 699 } 700 701 RDFList prev = null; 702 RDFList cell = this; 703 boolean searching = true; 704 705 while (searching && !cell.isEmpty()) { 706 if (cell.getHead().equals( val )) { 707 RDFList tail = cell.getTail(); 709 if (prev != null) { 710 prev.setTail( tail ); 711 } 712 713 cell.removeProperties(); 714 715 return (prev == null) ? tail : this; 717 } 718 else { 719 prev = cell; 721 cell = cell.getTail(); 722 } 723 } 724 725 return this; 727 } 728 729 730 736 public void removeAll() { 737 removeList(); 738 } 739 740 741 757 public void removeList() { 758 for (Iterator i = collectStatements().iterator(); i.hasNext(); ) { 759 ((Statement) i.next()).remove(); 760 } 761 } 762 763 764 769 public Set collectStatements() { 770 Set stmts = new HashSet(); 771 RDFList l = this; 772 773 do { 774 for (Iterator i = l.listProperties(); i.hasNext(); ) { 776 stmts.add( i.next() ); 777 } 778 779 l = l.getTail(); 781 } while (!l.isEmpty()); 782 783 return stmts; 784 } 785 786 787 798 public ExtendedIterator iterator() { 799 return new RDFListIterator( this ); 800 } 801 802 803 810 public List asJavaList() { 811 List l = new ArrayList(); 812 813 for (Iterator i = iterator(); i.hasNext(); ) { 814 l.add( i.next() ); 815 } 816 817 return l; 818 } 819 820 821 834 public boolean sameListAs( RDFList list ) { 835 if (s_checkValid) { 836 checkValid(); 837 } 838 839 Resource r0 = this; 840 Resource r1 = list; 841 842 Property head = listFirst(); 843 Property tail = listRest(); 844 Resource nil = listNil(); 845 846 while (!(r0.equals( nil ) || r1.equals( nil ))) { 848 RDFNode n0 = r0.getRequiredProperty( head ).getObject(); 849 RDFNode n1 = r1.getRequiredProperty( head ).getObject(); 850 851 if (n0 == null || !n0.equals( n1 )) { 852 return false; 854 } 855 else { 856 r0 = r0.getRequiredProperty( tail ).getResource(); 858 r1 = r1.getRequiredProperty( tail ).getResource(); 859 } 860 } 861 862 return r0.equals( nil ) && r1.equals( nil ); 864 } 865 866 867 875 public boolean getStrict() { 876 return s_checkValid; 877 } 878 879 880 890 public void setStrict( boolean strict ) { 891 s_checkValid = strict; 892 } 893 894 895 904 public boolean isValid() { 905 m_errorMsg = null; 906 907 try { 908 checkValid(); 909 } 910 catch (InvalidListException e) { 911 m_errorMsg = e.getMessage(); 912 } 913 914 return (m_errorMsg == null); 915 } 916 917 918 926 public String getValidityErrorMessage() { 927 return m_errorMsg; 928 } 929 930 931 940 public Resource newListCell( RDFNode value, Resource tail ) { 941 Resource cell = getModel().createResource(); 943 944 cell.addProperty( listFirst(), value ); 946 cell.addProperty( listRest(), tail ); 947 948 return cell; 949 } 950 951 952 955 967 protected void checkValid() { 968 if (!equals( listNil() )) { 969 973 checkValidProperty( listFirst(), null ); 974 checkValidProperty( listRest(), null ); 975 } 976 } 977 978 private void checkValidProperty( Property p, RDFNode expected ) { 979 int count = 0; 980 981 for (StmtIterator j = getModel().listStatements( this, p, expected ); j.hasNext(); j.next()) { 982 count++; 983 } 984 985 if (count == 0) { 987 if (log.isDebugEnabled()) { 988 log.debug( "Failed validity check on " + toString() ); 989 for (StmtIterator i = listProperties(); i.hasNext(); ) { 990 log.debug( " this => " + i.next() ); 991 } 992 for (StmtIterator i = getModel().listStatements( null, null, this ); i.hasNext(); ) { 993 log.debug( " => this " + i.next() ); 994 } 995 } 996 throw new InvalidListException( "List node " + toString() + " is not valid: it should have property " + 997 p.toString() + 998 (expected == null ? "" : ( " with value " + expected )) ); 999 } 1000 else if (count > 1) { 1001 throw new InvalidListException( "List node " + toString() + " is not valid: it has more than one value for " + 1002 p.toString() ); 1003 } 1004 } 1005 1006 1007 1008 1017 protected void checkNotNil( String msg ) { 1018 if (isEmpty()) { 1019 throw new EmptyListException( msg ); 1020 } 1021 } 1022 1023 1024 1041 protected RDFList findElement( boolean last, int index ) { 1042 Property tail = listRest(); 1043 Resource nil = listNil(); 1044 1045 Resource l = this; 1046 int i = index; 1047 boolean found = (last && l.hasProperty( tail, nil )) || (!last && (i == 0)); 1048 1049 while (!found && !l.equals( nil )) { 1051 l = l.getRequiredProperty( tail ).getResource(); 1052 found = (last && l.hasProperty( tail, nil )) || (!last && (--i == 0)); 1053 } 1054 1055 if (!found) { 1056 if (!last) { 1058 throw new ListIndexException( "Tried to access element " + index + " that is beyond the length of the list" ); 1059 } 1060 else { 1061 throw new InvalidListException( "Could not find last element of list (suggests list is not valid)" ); 1062 } 1063 } 1064 else { 1065 return (RDFList) l.as( listAbstractionClass() ); 1066 } 1067 } 1068 1069 1070 1078 protected RDFList copy( Iterator i ) { 1079 Resource list = null; 1080 Resource start = null; 1081 1082 Property head = listFirst(); 1083 Property tail = listRest(); 1084 Resource cellType = listType(); 1085 1086 while (i.hasNext()){ 1087 Resource cell = getModel().createResource( cellType ); 1089 cell.addProperty( head, (RDFNode) i.next() ); 1090 1091 if (list != null) { 1093 list.addProperty( tail, cell ); 1094 } 1095 else { 1096 start = cell; 1098 } 1099 1100 list = cell; 1101 } 1102 1103 list.addProperty( tail, listNil() ); 1105 1106 return (RDFList) start.as( listAbstractionClass() ); 1107 } 1108 1109 1110 1121 protected static Resource setTailAux( Resource root, Resource tail, Property pTail ) { 1122 Statement current = root.getRequiredProperty( pTail ); 1123 Resource oldTail = current.getResource(); 1124 1125 current.remove(); 1127 root.addProperty( pTail, tail ); 1128 1129 return oldTail; 1130 } 1131 1132 1133 1134 1138 1144 protected class RDFListIterator 1145 extends NiceIterator 1146 { 1147 1149 1150 protected RDFList m_head; 1151 1152 1153 protected RDFList m_seen = null; 1154 1155 1156 1159 1162 protected RDFListIterator( RDFList head ) { 1163 m_head = head; 1164 } 1165 1166 1167 1170 1173 public boolean hasNext() { 1174 return !m_head.isEmpty(); 1175 } 1176 1177 1180 public Object next() { 1181 m_seen = m_head; 1182 m_head = m_head.getTail(); 1183 1184 return m_seen.getHead(); 1185 } 1186 1187 1190 public void remove() { 1191 if (m_seen == null) { 1192 throw new IllegalStateException ( "Illegal remove from list operator" ); 1193 } 1194 1195 ((Resource) m_seen).removeProperties(); 1197 m_seen = null; 1198 } 1199 } 1200} 1201 1202 1203 1232 | Popular Tags |