Source for file MemModel.php

Documentation is available at MemModel.php

  1. <?php
  2.  
  3. // ----------------------------------------------------------------------------------
  4. // Class: MemModel
  5. // ----------------------------------------------------------------------------------
  6.  
  7.  
  8.  
  9. /**
  10. * A MemModel is an RDF Model, which is stored in the main memory.
  11. * This class provides methods for manipulating MemModels.
  12. *
  13. * <BR><BR>History:<UL>
  14. * <LI>12-06-2004 : improved namespace handling added (tobias.gauss@web.de)</LI>
  15. * <LI>10-07-2004 : Function findFirstMatchingStatement() added paramter $offset
  16. * to set an search offset
  17. * <LI>09-09-2004 : Function remove() bug removed: now removes ALL matching statements.
  18. Function addWithoutDuplicates() now uses the contains() / add() functions.
  19. Functions reify(),addModel(),unite(),subtract() changed to use the statement iterator.</LI>
  20. * <LI>16-08-2004 : Function getUniqueResourceURI() has been made faster</LI>
  21. * <LI>08-06-2004 : Function findAsIterator() added</LI>
  22. * <LI>06-13-2004 : Improved function index() which allows the definition of different search indexes</LI>
  23. * <LI>03-29-2004 : Function addModel() fixed, reindexing of triples in remove() added</LI>
  24. * <LI>11-13-2003 : Functions load, saveAs moved to class model
  25. * <LI>11-12-2003 : Function rdqlQueryAsIterator() added.</LI>
  26. * <LI>07-31-2003 : Class renamed from Model to MemModel.
  27. * Variable BaseURI and Function getBaseURI() moved to Model.
  28. * Functions containsAll(), containsAny(), equals(), unite(),
  29. * subtract(), intersect(), addModel() can now
  30. * get DbModel as paramter.
  31. * Functions load() and saveAs() can now work with n3 format too.
  32. * Function rdqlQuery added. radol@gmx.de</LI>
  33. * <LI>05-31-2003 : Functions load(), saveAs() and writeXX() findFirstMatchingStatement() added.
  34. * Changed function index() to a faster index type.</LI>
  35. * <LI>05-28-2003 : Functions addWithoutDuplicates() and addModel() added, optimised bits and pieces.</LI>
  36. * <LI>05-19-2003 : Function add() made more efficient, optimised bits and pieces. ggrimnes@csd.abdn.ac.uk</LI>
  37. * <LI>05-19-2003 : Functions index() and isIndexed() added, ggrimnes@csd.abdn.ac.uk</LI>
  38. * <LI>02-21-2003 : Function findCount() added.</LI>
  39. * <LI>01-13-2003 : Function equals() made more efficient.</LI>
  40. * <LI>09-10-2002 : First version of this class.</LI>
  41. *
  42. * @version V0.9.1
  43. * @author Chris Bizer <chris@bizer.de>
  44. * @author Gunnar AAstrand Grimnes <ggrimnes@csd.abdn.ac.uk>
  45. * @author Radoslaw Oldakowski <radol@gmx.de>
  46. * @author Daniel Westphal <mail@d-westphal.de>
  47. * @author Tobias Gauß <tobias.gauss@web.de>
  48. *
  49. * @package model
  50. * @todo nothing
  51. * @access public
  52. */
  53.  
  54. class MemModel extends Model {
  55.  
  56. /**
  57. * Triples of the MemModel
  58. * @var array
  59. * @access private
  60. */
  61. var $triples = array();
  62.  
  63. /**
  64. * Array containing the search indices
  65. * @var array['INDEX_TYPE'][]['label'][]['PosInModel']
  66. *
  67. * @access private
  68. */
  69. var $indexArr ;
  70.  
  71.  
  72. /**
  73. * depending on which index is used this variable is -1,0,1,2 or 3
  74. *
  75. * -1 : no index
  76. * 0 : default indices over subject, predicate, object separate
  77. * 1 : index over subject+predicate+object
  78. * 2 : index over subject+predicate
  79. * 3 : index over subject+object
  80. *
  81. * @var int
  82. * @access private
  83. */
  84. var $indexed;
  85.  
  86.  
  87.  
  88. /**
  89. * Array of namespaces
  90. *
  91. * @var array
  92. * @access private
  93. */
  94. var $parsedNamespaces=array();
  95.  
  96.  
  97.  
  98. /**
  99. * Constructor
  100. * You can supply a base_uri
  101. *
  102. * @param string $baseURI
  103. * @access public
  104. */
  105. function MemModel($baseURI = NULL) {
  106. $this->setBaseURI($baseURI);
  107. $this->indexed = INDEX_TYPE;
  108. }
  109.  
  110. /**
  111. * Set a base URI for the MemModel.
  112. * Affects creating of new resources and serialization syntax.
  113. * If the URI doesn't end with # : or /, then a # is added to the URI.
  114. * @param string $uri
  115. * @access public
  116. */
  117. function setBaseURI($uri) {
  118.  
  119. if ($uri != NULL) {
  120. $c = substr($uri, strlen($uri)-1 ,1);
  121. if (!($c=='#' || $c==':' || $c=='/' || $c=="\\"))
  122. $uri .= '#';
  123. }
  124. $this->baseURI = $uri;
  125. }
  126.  
  127.  
  128. /**
  129. * Number of triples in the MemModel
  130. *
  131. * @return integer
  132. * @access public
  133. */
  134. function size() {
  135. return count($this->triples);
  136. }
  137.  
  138. /**
  139. * Checks if MemModel is empty
  140. *
  141. * @return boolean
  142. * @access public
  143. */
  144. function isEmpty() {
  145. if (count($this->triples) == 0) {
  146. return TRUE;
  147. } else {
  148. return FALSE;
  149. };
  150. }
  151.  
  152.  
  153. /**
  154. * Adds a new triple to the MemModel without checking if the statement is already in the MemModel.
  155. * So if you want a duplicate free MemModel use the addWithoutDuplicates() function (which is slower then add())
  156. *
  157. * @param object Statement $statement
  158. * @access public
  159. * @throws PhpError
  160. */
  161. function add($statement) {
  162. if (!is_a($statement, 'Statement')) {
  163. $errmsg = RDFAPI_ERROR . '(class: MemModel; method: add): Statement expected.';
  164. trigger_error($errmsg, E_USER_ERROR);
  165. }
  166.  
  167. if($this->indexed != -1){
  168. $this->triples[] = $statement;
  169. end($this->triples);
  170. $k=key($this->triples);
  171. if($this->indexed==0){
  172. // index over S
  173. $this->_indexOpr($statement,$k,4,1);
  174. // index over P
  175. $this->_indexOpr($statement,$k,5,1);
  176. // index over O
  177. $this->_indexOpr($statement,$k,6,1);
  178. }else{
  179. $this->_indexOpr($statement,$k,$this->indexed,1);
  180. }
  181.  
  182. }else{
  183. $this->triples[] = $statement;
  184. }
  185. }
  186.  
  187.  
  188.  
  189. /**
  190. * Checks if a new statement is already in the MemModel and adds the statement, if it is not in the MemModel.
  191. * addWithoutDuplicates() is significantly slower then add().
  192. * Retruns TRUE if the statement is added.
  193. * FALSE otherwise.
  194. *
  195. * @param object Statement $statement
  196. * @return boolean
  197. * @access public
  198. * @throws PhpError
  199. */
  200. function addWithoutDuplicates($statement) {
  201.  
  202. if (!is_a($statement, 'Statement')) {
  203. $errmsg = RDFAPI_ERROR . '(class: MemModel; method: addWithoutDuplicates): Statement expected.';
  204. trigger_error($errmsg, E_USER_ERROR);
  205. }
  206.  
  207. if (!$this->contains($statement)) {
  208. $this->add($statement);
  209. return true;
  210. }else{
  211. return false;
  212. }
  213. }
  214.  
  215. /**
  216. * Removes the triple from the MemModel.
  217. * TRUE if the triple is removed.
  218. * FALSE otherwise.
  219. *
  220. * @param object Statement $statement
  221. * @return boolean
  222. * @access public
  223. * @throws PhpError
  224. */
  225. function remove($statement) {
  226.  
  227. if (!is_a($statement, 'Statement')) {
  228. $errmsg = RDFAPI_ERROR . '(class: MemModel; method: remove): Statement expected.';
  229. trigger_error($errmsg, E_USER_ERROR);
  230. }
  231. if($this->indexed==-1){
  232. $pass=false;
  233. foreach($this->triples as $key => $value) {
  234. if ($this->matchStatement($value, $statement->subject(), $statement->predicate(), $statement->object())) {
  235. unset($this->triples[$key]);
  236. $pass= true;
  237. }
  238. }
  239. return $pass;
  240. }else{
  241. $k= null;
  242. if($this->indexed==0){
  243. $pass=false;
  244. $del=false;
  245. while($del!=-1){
  246. // index over S
  247. $del=$this->_indexOpr($statement,$k,4,0);
  248. // index over P
  249. $this->_indexOpr($statement,$k,5,0);
  250. // index over O
  251. $this->_indexOpr($statement,$k,6,0);
  252. if($del!=-1){
  253. unset($this->triples[$del]);
  254. $pass=true;
  255. }
  256. }
  257. return $pass;
  258. }else{
  259. $pass=false;
  260. $del=false;
  261. while($del!=-1){
  262. $del=$this->_indexOpr($statement,$k,$this->indexed,0);
  263. if($del!=-1){
  264. unset($this->triples[$del]);
  265. $pass=true;
  266. }
  267. }
  268. return $pass;
  269. }
  270. }
  271. }
  272.  
  273. /**
  274. * Short Dump of the MemModel.
  275. *
  276. * @access public
  277. * @return string
  278. */
  279. function toString() {
  280. return 'MemModel[baseURI=' . $this->getBaseURI() . '; size=' . $this->size() . ']';
  281. }
  282.  
  283. /**
  284. * Dumps of the MemModel including all triples.
  285. *
  286. * @access public
  287. * @return string
  288. */
  289. function toStringIncludingTriples() {
  290. $dump = $this->toString() . chr(13);
  291. foreach($this->triples as $value) {
  292. $dump .= $value->toString() . chr(13);
  293. }
  294. return $dump;
  295. }
  296.  
  297.  
  298.  
  299.  
  300. /**
  301. * Writes the RDF serialization of the MemModel as HTML.
  302. *
  303. * @access public
  304. */
  305. function writeAsHtml() {
  306. require_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
  307. $ser = new RdfSerializer();
  308. $rdf =& $ser->serialize($this);
  309. $rdf = htmlspecialchars($rdf, ENT_QUOTES);
  310. $rdf = str_replace(' ', '&nbsp;', $rdf);
  311. $rdf = nl2br($rdf);
  312. echo $rdf;
  313. }
  314.  
  315. /**
  316. * Writes the RDF serialization of the MemModel as HTML table.
  317. *
  318. * @access public
  319. */
  320. function writeAsHtmlTable() {
  321. // Import Package Utility
  322. include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
  323. RDFUtil::writeHTMLTable($this);
  324. }
  325.  
  326.  
  327. /**
  328. * Writes the RDF serialization of the MemModel as HTML table.
  329. *
  330. * @access public
  331. * @return string
  332. */
  333. function writeRdfToString() {
  334. // Import Package Syntax
  335. include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
  336. $ser = new RdfSerializer();
  337. $rdf =& $ser->serialize($this);
  338. return $rdf;
  339. }
  340.  
  341.  
  342. /**
  343. * Saves the RDF,N3 or N-Triple serialization of the MemModel to a file.
  344. * You can decide to which format the model should be serialized by using a
  345. * corresponding suffix-string as $type parameter. If no $type parameter
  346. * is placed this method will serialize the model to XML/RDF format.
  347. * Returns FALSE if the MemModel couldn't be saved to the file.
  348. *
  349. * @access public
  350. * @param string $filename
  351. * @param string $type
  352. * @throw PhpError
  353. * @return boolean
  354. */
  355. function saveAs($filename, $type ='rdf') {
  356.  
  357.  
  358. // get suffix and create a corresponding serializer
  359. if ($type=='rdf') {
  360. // Import Package Syntax
  361. include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
  362. $ser=new RdfSerializer();
  363. }elseif ($type=='nt') {
  364. // Import Package Syntax
  365. include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_N3);
  366. $ser=new NTripleSerializer();
  367. }elseif ($type=='n3') {
  368. // Import Package Syntax
  369. include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_N3);
  370. $ser=new N3Serializer();
  371. }else {
  372. print ('Serializer type not properly defined. Use the strings "rdf","n3" or "nt".');
  373. return false;
  374. };
  375.  
  376. return $ser->saveAs($this, $filename);
  377. }
  378.  
  379.  
  380. /**
  381. * Tests if the MemModel contains the given triple.
  382. * TRUE if the triple belongs to the MemModel;
  383. * FALSE otherwise.
  384. *
  385. * @param object Statement &$statement
  386. * @return boolean
  387. * @access public
  388. */
  389. function contains(&$statement) {
  390.  
  391. // no index ->linear contains
  392. if ($this->indexed==-1){
  393. foreach($this->triples as $value) {
  394. if ($value->equals($statement)){
  395. return TRUE; }
  396. }
  397. return false;
  398. }
  399. if ($this->indexed==0){
  400. $res = $this->_containsIndex($statement,4);
  401. return $res;
  402. }else{
  403. return $this->_containsIndex($statement,$this->indexed);
  404. }
  405. }
  406.  
  407.  
  408. /**
  409. * Determine if all of the statements in a model are also contained in this MemModel.
  410. * True if all of the statements in $model are also contained in this MemModel and false otherwise.
  411. *
  412. * @param object Model &$model
  413. * @return boolean
  414. * @access public
  415. */
  416. function containsAll(&$model) {
  417.  
  418. if (is_a($model, 'MemModel')) {
  419.  
  420. foreach($model->triples as $statement)
  421. if(!$this->contains($statement))
  422. return FALSE;
  423. return TRUE;
  424.  
  425. }elseif (is_a($model, 'DbModel'))
  426.  
  427. return $model->containsAll($this);
  428.  
  429. $errmsg = RDFAPI_ERROR . '(class: MemModel; method: containsAll): Model expected.';
  430. trigger_error($errmsg, E_USER_ERROR);
  431. }
  432.  
  433. /**
  434. * Determine if any of the statements in a model are also contained in this MemModel.
  435. * True if any of the statements in $model are also contained in this MemModel and false otherwise.
  436. *
  437. * @param object Model &$model
  438. * @return boolean
  439. * @access public
  440. */
  441. function containsAny(&$model) {
  442.  
  443. if (is_a($model, 'MemModel')) {
  444.  
  445. foreach($model->triples as $modelStatement)
  446. if($this->contains($modelStatement))
  447. return TRUE;
  448. return FALSE;
  449.  
  450. }elseif (is_a($model, 'DbModel'))
  451.  
  452. return $model->containsAny($this);
  453.  
  454. $errmsg = RDFAPI_ERROR . '(class: MemModel; method: containsAll): Model expected.';
  455. trigger_error($errmsg, E_USER_ERROR);
  456. }
  457.  
  458.  
  459. /**
  460. * Builds a search index for the statements in the MemModel.
  461. * The index is used by the find(),contains(),add() and remove() functions.
  462. * Performance example using a model with 43000 statements on a Linux machine:
  463. * Find without index takes 1.7 seconds.
  464. * Indexing takes 1.8 seconds.
  465. * Find with index takes 0.001 seconds.
  466. * So if you want to query a model more then once, build a index first.
  467. * The defaultindex is indices over subject, predicate, object seperate.
  468. *
  469. * mode = 0 : indices over subject,predicate,object (default)
  470. * mode = 1 : index over subject+predicate+object
  471. * mode = 2 : index over subject+predicate
  472. * mode = 3 : index over subject+object
  473. *
  474. * @param int $mode
  475. * @access public
  476. */
  477. function index($mode) {
  478.  
  479. unset($this->indexArr);
  480. $this->indexArr=array();
  481. switch($mode){
  482. // unset indices
  483. case -1:
  484. $this->indexed=-1;
  485. unset($this->indexArr);
  486. break;
  487. // index over SPO
  488. case 0:
  489. $this->indexed=0;
  490. foreach($this->triples as $k => $t) {
  491. // index over S
  492. $this->_indexOpr($t,$k,4,1);
  493. // index over P
  494. $this->_indexOpr($t,$k,5,1);
  495. // index over O
  496. $this->_indexOpr($t,$k,6,1);
  497. }
  498. break;
  499. default:
  500. $this->indexed=$mode;
  501. foreach($this->triples as $k => $t) {
  502. $this->_indexOpr($t,$k,$this->indexed,1);
  503. }
  504. break;
  505. }
  506. }
  507.  
  508.  
  509. /**
  510. * Returns true if there is an index, false if not.
  511. *
  512. * @return boolean
  513. * @access public
  514. */
  515. function isIndexed() {
  516. if($this->indexed!=-1){
  517. return TRUE;
  518. }else{
  519. return FALSE;
  520. }
  521. }
  522.  
  523. /**
  524. * Returns the indextype:
  525. * -1 if there is no index, 0 if there are indices over S,P,O(separate),
  526. * 1 if there is an index over SPO, 2 if there is an index over SP and 3 if
  527. * there is an index over SO.
  528. *
  529. * @return int
  530. * @access public
  531. *
  532. */
  533. function getIndexType(){
  534. return $this->indexed;
  535. }
  536.  
  537. /**
  538. * General method to search for triples.
  539. * NULL input for any parameter will match anything.
  540. * Example: $result = $m->find( NULL, NULL, $node );
  541. * Finds all triples with $node as object.
  542. * Returns an empty MemModel if nothing is found.
  543. *
  544. * @param object Node $subject
  545. * @param object Node $predicate
  546. * @param object Node $object
  547. * @return object MemModel
  548. * @access public
  549. * @throws PhpError
  550. */
  551.  
  552. function find($subject,$predicate,$object) {
  553.  
  554. if (
  555. (!is_a($subject, 'Resource') && $subject != NULL) ||
  556. (!is_a($predicate, 'Resource') && $predicate != NULL) ||
  557. (!is_a($object, 'Node') && $object != NULL)
  558. ) {
  559. $errmsg = RDFAPI_ERROR . '(class: MemModel; method: find): Parameters must be subclasses of Node or NULL';
  560. trigger_error($errmsg, E_USER_ERROR);
  561. }
  562.  
  563. $res = new MemModel($this->getBaseURI());
  564. $res->indexed=-1;
  565.  
  566. if($this->isEmpty())
  567. return $res;
  568.  
  569. if($subject == NULL && $predicate == NULL && $object == NULL)
  570. return $this;
  571.  
  572. switch($this->indexed){
  573. case 1:
  574. if($subject!=NULL && $predicate != NULL && $object != NULL){
  575. $pos=$subject->getLabel().$predicate->getLabel().$object->getLabel();
  576. return $this->_findInIndex($pos,$subject,$predicate,$object,1);
  577. }else{
  578. break;
  579. }
  580.  
  581. case 2:
  582. if($subject!=NULL && $predicate != NULL){
  583. $pos=$subject->getLabel().$predicate->getLabel();
  584. return $this->_findInIndex($pos,$subject,$predicate,$object,2);
  585. }else{
  586. break;
  587. }
  588.  
  589. case 3:
  590. if($subject!=NULL && $object != NULL){
  591. $pos=$subject->getLabel().$object->getLabel();
  592. return $this->_findInIndex($pos,$subject,$predicate,$object,3);
  593. }else{
  594. break;
  595. }
  596. case 0:
  597. if($subject!= null){
  598. $pos=$subject->getLabel();
  599. return $this->_findInIndex($pos,$subject,$predicate,$object,4);
  600. }
  601. if($predicate!= null){
  602. $pos=$predicate->getLabel();
  603. return $this->_findInIndex($pos,$subject,$predicate,$object,5);
  604. }
  605. if($object!= null){
  606. $pos=$object->getLabel();
  607. return $this->_findInIndex($pos,$subject,$predicate,$object,6);
  608. }
  609. }
  610. // if no index: linear search
  611. foreach($this->triples as $value) {
  612. if ($this->matchStatement($value, $subject, $predicate, $object))
  613. $res->add($value);
  614. }
  615. return $res;
  616.  
  617. }
  618.  
  619.  
  620.  
  621.  
  622.  
  623. /**
  624. * Method to search for triples using Perl-style regular expressions.
  625. * NULL input for any parameter will match anything.
  626. * Example: $result = $m->find_regex( NULL, NULL, $regex );
  627. * Finds all triples where the label of the object node matches the regular expression.
  628. * Returns an empty MemModel if nothing is found.
  629. *
  630. * @param string $subject_regex
  631. * @param string $predicate_regex
  632. * @param string $object_regex
  633. * @return object MemModel
  634. * @access public
  635. */
  636. function findRegex($subject_regex, $predicate_regex, $object_regex) {
  637.  
  638. $res = new MemModel($this->getBaseURI());
  639.  
  640. if($this->size() == 0)
  641. return $res;
  642.  
  643. if($subject_regex == NULL && $predicate_regex == NULL && $object_regex == NULL)
  644. return $this;
  645.  
  646. foreach($this->triples as $value) {
  647. if (
  648. ($subject_regex == NULL || preg_match($subject_regex, $value->subj->getLabel())) &&
  649. ($predicate_regex == NULL || preg_match($predicate_regex, $value->pred->getLabel())) &&
  650. ($object_regex == NULL || preg_match($object_regex, $value->obj->getLabel()))
  651. ) $res->add($value);
  652. }
  653.  
  654. return $res;
  655.  
  656. }
  657.  
  658. /**
  659. * Returns all tripels of a certain vocabulary.
  660. * $vocabulary is the namespace of the vocabulary inluding a # : / char at the end.
  661. * e.g. http://www.w3.org/2000/01/rdf-schema#
  662. * Returns an empty MemModel if nothing is found.
  663. *
  664. * @param string $vocabulary
  665. * @return object MemModel
  666. * @access public
  667. */
  668. function findVocabulary($vocabulary) {
  669.  
  670. if($this->size() == 0)
  671. return $res;
  672. if($vocabulary == NULL || $vocabulary == '')
  673. return $this;
  674.  
  675. $res = new MemModel($this->getBaseURI());
  676. if($this->indexed==0){
  677. foreach($this->indexArr[5] as $key => $value){
  678. $pos=strpos($key,'#')+1;
  679. if(substr($key,0,$pos)==$vocabulary){
  680. for($i=1;$i<=$value[0];$i++){
  681. $res->add($this->triples[$value[$i]]);
  682. }
  683. }
  684. }
  685. return $res;
  686. }else{
  687. // Import Package Utility
  688. include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
  689. foreach($this->triples as $value) {
  690. if (RDFUtil::getNamespace($value->getPredicate()) == $vocabulary)
  691. $res->add($value);
  692. }
  693. return $res;
  694. }
  695. }
  696.  
  697. /**
  698. * Searches for triples and returns the first matching statement.
  699. * NULL input for any parameter will match anything.
  700. * Example: $result = $m->findFirstMatchingStatement( NULL, NULL, $node );
  701. * Returns the first statement of the MemModel where the object equals $node.
  702. * Returns an NULL if nothing is found.
  703. * You can define an offset to search for. Default = 0
  704. *
  705. * @param object Node $subject
  706. * @param object Node $predicate
  707. * @param object Node $object
  708. * @param integer $offset
  709. * @return object Statement
  710. * @access public
  711. */
  712. function findFirstMatchingStatement($subject, $predicate, $object, $offset = 0) {
  713.  
  714. $loopCount=0;
  715. $currentOffset = 0;
  716. do
  717. {
  718. $res = $this->findFirstMatchOff($subject, $predicate, $object, $currentOffset);
  719. $currentOffset+=($res+1);
  720. $loopCount++;
  721. } while ($res != -1 && $offset >= $loopCount);
  722. if ($res != -1) {
  723. return $this->triples[$res];
  724. } else {
  725. return NULL;
  726. }
  727. }
  728.  
  729.  
  730.  
  731.  
  732. /**
  733. * Searches for triples and returns the first matching statement from a given offset.
  734. * This method is used by the util/findIterator. NULL input for any parameter will match anything.
  735. * Example: $result = $m->findFirstMatchingStatement( NULL, NULL, $node, $off );
  736. * Returns the position of the first statement of the MemModel where the object equals $node from the given
  737. * offset.
  738. * Returns an -1 if nothing is found.
  739. *
  740. * @param object Node $subject
  741. * @param object Node $predicate
  742. * @param object Node $object
  743. * @param int $off
  744. * @return int
  745. * @access private
  746. */
  747. function findFirstMatchOff($subject,$predicate, $object,$off) {
  748.  
  749. if (
  750. (!is_a($subject, 'Resource') && $subject != NULL) ||
  751. (!is_a($predicate, 'Resource') && $predicate != NULL) ||
  752. (!is_a($object, 'Node') && $object != NULL)
  753. ) {
  754. $errmsg = RDFAPI_ERROR . '(class: MemModel; method: find): Parameters must be subclasses of Node or NULL';
  755. trigger_error($errmsg, E_USER_ERROR);
  756. }
  757.  
  758. $match=-1;
  759. $ind=$this->indexed;
  760. if($subject == NULL && $predicate == NULL && $object == NULL){
  761. if($this->size()>0)
  762. if($off==$this->size()){
  763. return -1;
  764. }else{
  765. return $off;
  766. }
  767. }
  768. switch($ind){
  769. case 1:
  770. if($subject!=NULL && $predicate != NULL && $object != NULL){
  771. $pos=$subject->getLabel().$predicate->getLabel().$object->getLabel();
  772. return $this->_findMatchIndex($pos,$subject,$predicate,$object,1,$off);
  773. }else{
  774. break;
  775. }
  776.  
  777. case 2:
  778. if($subject!=NULL && $predicate != NULL){
  779. $pos=$subject->getLabel().$predicate->getLabel();
  780. return $this->_findMatchIndex($pos,$subject,$predicate,$object,2,$off);
  781. }else{
  782. break;
  783. }
  784.  
  785. case 3:
  786. if($subject!=NULL && $object != NULL){
  787. $pos=$subject->getLabel().$object->getLabel();
  788. return $this->_findMatchIndex($pos,$subject,$predicate,$object,3,$off);
  789. }else{
  790. break;
  791. }
  792. case 0:
  793. if($subject!= null){
  794. $pos=$subject->getLabel();
  795. return $this->_findMatchIndex($pos,$subject,$predicate,$object,4,$off);
  796. }
  797. if($predicate!= null){
  798. $pos=$predicate->getLabel();
  799. return $this->_findMatchIndex($pos,$subject,$predicate,$object,5,$off);
  800. }
  801. if($object!= null){
  802. $pos=$object->getLabel();
  803. return $this->_findMatchIndex($pos,$subject,$predicate,$object,6,$off);
  804. }
  805. break;
  806. }
  807. // if no index: linear search
  808. foreach($this->triples as $key => $value){
  809. if ($this->matchStatement($value, $subject, $predicate, $object)){
  810. if($off<=$key){
  811. $match=$key;
  812. break;
  813. }
  814. }
  815. }
  816. return $match;
  817. }
  818.  
  819.  
  820. /**
  821. * Searches for triples and returns the number of matches.
  822. * NULL input for any parameter will match anything.
  823. * Example: $result = $m->findCount( NULL, NULL, $node );
  824. * Finds all triples with $node as object.
  825. *
  826. * @param object Node $subject
  827. * @param object Node $predicate
  828. * @param object Node $object
  829. * @return integer
  830. * @access public
  831. */
  832. function findCount($subject, $predicate, $object) {
  833.  
  834. $res = $this->find($subject, $predicate, $object);
  835. return $res->size();
  836.  
  837. }
  838.  
  839.  
  840. /**
  841. * Perform an RDQL query on this MemModel.
  842. * This method returns an associative array of variable bindings.
  843. * The values of the query variables can either be RAP's objects (instances of Node)
  844. * if $returnNodes set to TRUE, or their string serialization.
  845. *
  846. * @access public
  847. * @param string $queryString
  848. * @param boolean $returnNodes
  849. * @return array [][?VARNAME] = object Node (if $returnNodes = TRUE)
  850. * OR array [][?VARNAME] = string
  851. *
  852. */
  853. function rdqlQuery($queryString, $returnNodes = TRUE) {
  854.  
  855. // Import RDQL Package
  856. include_once(RDFAPI_INCLUDE_DIR.PACKAGE_RDQL);
  857.  
  858. $parser = new RdqlParser();
  859. $parsedQuery =& $parser->parseQuery($queryString);
  860.  
  861. // this method can only query this MemModel
  862. // if another model was specified in the from clause throw an error
  863. if (isset($parsedQuery['sources'][1])) {
  864. $errmsg = RDFAPI_ERROR . '(class: MemModel; method: rdqlQuery):';
  865. $errmsg .= ' this method can only query this MemModel';
  866. trigger_error($errmsg, E_USER_ERROR);
  867. }
  868.  
  869. $engine = new RdqlMemEngine();
  870. $res =& $engine->queryModel($this, $parsedQuery, $returnNodes);
  871.  
  872. return $res;
  873. }
  874.  
  875. /**
  876. * Perform an RDQL query on this MemModel.
  877. * This method returns an RdqlResultIterator of variable bindings.
  878. * The values of the query variables can either be RAP's objects (instances of Node)
  879. * if $returnNodes set to TRUE, or their string serialization.
  880. *
  881. * @access public
  882. * @param string $queryString
  883. * @param boolean $returnNodes
  884. * @return object RdqlResultIterator = with values as object Node (if $returnNodes = TRUE)
  885. * OR object RdqlResultIterator = with values as strings if (if $returnNodes = FALSE)
  886. *
  887. */
  888. function rdqlQueryAsIterator($queryString, $returnNodes = TRUE) {
  889. // Import RDQL Package
  890. include_once(RDFAPI_INCLUDE_DIR.PACKAGE_RDQL);
  891. return new RdqlResultIterator($this->rdqlQuery($queryString, $returnNodes));
  892. }
  893.  
  894. /**
  895. * General method to replace nodes of a MemModel.
  896. * NULL input for any parameter will match nothing.
  897. * Example: $m->replace($node, NULL, $node, $replacement);
  898. * Replaces all $node objects beeing subject or object in
  899. * any triple of the MemModel with the $needle node.
  900. *
  901. * @param object Node $subject
  902. * @param object Node $predicate
  903. * @param object Node $object
  904. * @param object Node $replacement
  905. * @access public
  906. * @throws PhpError
  907. */
  908. function replace($subject, $predicate, $object, $replacement) {
  909.  
  910. if (
  911. (!is_a($replacement, 'Node')) ||
  912. (!is_a($subject, 'Resource') && $subject != NULL) ||
  913. (!is_a($predicate, 'Resource') && $predicate != NULL) ||
  914. (!is_a($object, 'Node') && $object != NULL)
  915. ) {
  916. $errmsg = RDFAPI_ERROR . '(class: MemModel; method: replace): Parameters must be subclasses of Node or NULL';
  917. trigger_error($errmsg, E_USER_ERROR);
  918. }
  919.  
  920. if($this->size() == 0)
  921. break;
  922. foreach($this->triples as $key => $value) {
  923. if ($this->triples[$key]->subj->equals($subject)) {
  924. $this->triples[$key]->subj = $replacement;
  925. }
  926. if ($this->triples[$key]->pred->equals($predicate))
  927. $this->triples[$key]->pred = $replacement;
  928. if ($this->triples[$key]->obj->equals($object))
  929. $this->triples[$key]->obj = $replacement;
  930.  
  931. }
  932. $this->index($this->indexed);
  933. }
  934.  
  935.  
  936. /**
  937. * Internal method that checks, if a statement matches a S, P, O or NULL combination.
  938. * NULL input for any parameter will match anything.
  939. *
  940. * @param object Statement $statement
  941. * @param object Node $subject
  942. * @param object Node $predicate
  943. * @param object Node $object
  944. * @return boolean
  945. * @access private
  946. */
  947. function matchStatement($statement, $subject, $predicate, $object) {
  948.  
  949. if(($subject != NULL) AND !($statement->subj->equals($subject)))
  950. return false;
  951.  
  952. if($predicate != NULL && !($statement->pred->equals($predicate)))
  953. return false;
  954.  
  955. if($object != NULL && !($statement->obj->equals($object)))
  956. return false;
  957.  
  958. return true;
  959. }
  960.  
  961.  
  962.  
  963.  
  964. /**
  965. * Checks if two models are equal.
  966. * Two models are equal if and only if the two RDF graphs they represent are isomorphic.
  967. *
  968. * Warning: This method doesn't work correct with models where the same blank node has different
  969. * identifiers in the two models. We will correct this in a future version.
  970. *
  971. * @access public
  972. * @param object model &$that
  973. * @throws phpErrpr
  974. * @return boolean
  975. */
  976.  
  977. function equals(&$that) {
  978.  
  979. if (!is_a($that, 'Model')) {
  980. $errmsg = RDFAPI_ERROR . '(class: MemModel; method: equals): Model expected.';
  981. trigger_error($errmsg, E_USER_ERROR);
  982. }
  983.  
  984. if ($this->size() != $that->size())
  985. return FALSE;
  986.  
  987. if (!$this->containsAll($that))
  988. return FALSE;
  989. return TRUE;
  990. }
  991.  
  992. /**
  993. * Returns a new MemModel that is the set-union of the MemModel with another model.
  994. * Duplicate statements are removed. If you want to allow duplicates, use addModel() which is much faster.
  995. *
  996. * The result of taking the set-union of two or more RDF graphs (i.e. sets of triples)
  997. * is another graph, which we will call the merge of the graphs.
  998. * Each of the original graphs is a subgraph of the merged graph. Notice that when forming
  999. * a merged graph, two occurrences of a given uriref or literal as nodes in two different
  1000. * graphs become a single node in the union graph (since by definition they are the same
  1001. * uriref or literal) but blank nodes are not 'merged' in this way; and arcs are of course
  1002. * never merged. In particular, this means that every blank node in a merged graph can be
  1003. * identified as coming from one particular graph in the original set of graphs.
  1004. *
  1005. * Notice that one does not, in general, obtain the merge of a set of graphs by concatenating
  1006. * their corresponding N-triples documents and constructing the graph described by the merged
  1007. * document, since if some of the documents use the same node identifiers, the merged document
  1008. * will describe a graph in which some of the blank nodes have been 'accidentally' merged.
  1009. * To merge Ntriples documents it is necessary to check if the same nodeID is used in two or
  1010. * more documents, and to replace it with a distinct nodeID in each of them, before merging the
  1011. * documents. (Not implemented yet !!!!!!!!!!!)
  1012. *
  1013. * @param object Model $model
  1014. * @return object MemModel
  1015. * @access public
  1016. * @throws phpErrpr
  1017. *
  1018. */
  1019. function & unite(&$model) {
  1020.  
  1021. if (!is_a($model, 'Model')) {
  1022. $errmsg = RDFAPI_ERROR . '(class: MemModel; method: unite): Model expected.';
  1023. trigger_error($errmsg, E_USER_ERROR);
  1024. }
  1025.  
  1026. $res = $this;
  1027.  
  1028. if (is_a($model, 'MemModel')) {
  1029. include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
  1030. $stateIt=new StatementIterator($model);
  1031. while($statement=$stateIt->next())
  1032. {
  1033. $res->addWithoutDuplicates($statement);
  1034. }
  1035. }
  1036.  
  1037. elseif (is_a($model, 'DbModel')) {
  1038. $memModel =& $model->getMemModel();
  1039. foreach($memModel->triples as $value)
  1040. $res->addWithoutDuplicates($value);
  1041. }
  1042.  
  1043. return $res;
  1044. }
  1045.  
  1046. /**
  1047. * Returns a new MemModel that is the subtraction of another model from this MemModel.
  1048. *
  1049. * @param object Model $model
  1050. * @return object MemModel
  1051. * @access public
  1052. * @throws phpErrpr
  1053. */
  1054.  
  1055. function & subtract(&$model) {
  1056.  
  1057. if (!is_a($model, 'Model')) {
  1058. $errmsg = RDFAPI_ERROR . '(class: MemModel; method: subtract): Model expected.';
  1059. trigger_error($errmsg, E_USER_ERROR);
  1060. }
  1061.  
  1062. $res = $this;
  1063.  
  1064.  
  1065. if (is_a($model, 'MemModel'))
  1066. {
  1067. include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
  1068. $stateIt=new StatementIterator($model);
  1069. while($statement=$stateIt->next())
  1070. {
  1071. $res->remove($statement);
  1072. }
  1073. }
  1074. elseif (is_a($model, 'DbModel'))
  1075. {
  1076. $memModel =& $model->getMemModel();
  1077. foreach($memModel->triples as $value)
  1078. $res->remove($value);
  1079. }
  1080.  
  1081.  
  1082. return $res;
  1083. }
  1084.  
  1085. /**
  1086. * Returns a new MemModel containing all the statements which are in both this MemModel and another.
  1087. *
  1088. * @param object Model $model
  1089. * @return object MemModel
  1090. * @access public
  1091. * @throws phpErrpr
  1092. */
  1093. function & intersect(&$model) {
  1094.  
  1095. if (!is_a($model, 'Model')) {
  1096. $errmsg = RDFAPI_ERROR . '(class: MemModel; method: intersect: Model expected.';
  1097. trigger_error($errmsg, E_USER_ERROR);
  1098. }
  1099.  
  1100. $res = new MemModel($this->getBaseURI());
  1101.  
  1102. if (is_a($model, 'DbModel') || is_a($model, 'RDFSBModel'))
  1103. {
  1104. $memModel =& $model->getMemModel();
  1105. foreach($memModel->triples as $value) {
  1106. if ($this->contains($value))
  1107. $res->add($value);
  1108. }
  1109. }
  1110.  
  1111. elseif (is_a($model, 'MemModel'))
  1112. {
  1113. foreach($model->triples as $value) {
  1114. if ($this->contains($value))
  1115. $res->add($value);
  1116. }
  1117. }
  1118.  
  1119.  
  1120.  
  1121. return $res;
  1122. }
  1123.  
  1124.  
  1125. /**
  1126. * Adds another model to this MemModel.
  1127. * Duplicate statements are not removed.
  1128. * If you don't want duplicates, use unite().
  1129. * If any statement of the model to be added to this model contains a blankNode
  1130. * with an identifier already existing in this model, a new blankNode is generated.
  1131. *
  1132. * @param object Model $model
  1133. * @access public
  1134. * @throws phpErrpr
  1135. *
  1136. */
  1137. function addModel(&$model) {
  1138.  
  1139. if (!is_a($model, 'Model')) {
  1140. $errmsg = RDFAPI_ERROR . '(class: MemModel; method: addModel): Model expected.';
  1141. trigger_error($errmsg, E_USER_ERROR);
  1142. }
  1143.  
  1144. $blankNodes_tmp = array();
  1145.  
  1146. if (is_a($model, 'MemModel')) {
  1147. include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
  1148. $stateIt=new StatementIterator($model);
  1149. while($statement=$stateIt->next())
  1150. {
  1151. $this->_addStatementFromAnotherModel($statement, $blankNodes_tmp);
  1152. };
  1153. $this->addParsedNamespaces($model->getParsedNamespaces());
  1154. }
  1155.  
  1156. elseif (is_a($model, 'DbModel')) {
  1157. $memModel =& $model->getMemModel();
  1158. foreach($memModel->triples as $value)
  1159. $this->_addStatementFromAnotherModel($value, $blankNodes_tmp);
  1160. }
  1161. $this->index($this->indexed);
  1162. }
  1163.  
  1164.  
  1165. /**
  1166. * Reifies the MemModel.
  1167. * Returns a new MemModel that contains the reifications of all statements of this MemModel.
  1168. *
  1169. * @access public
  1170. * @return object MemModel
  1171. */
  1172. function & reify() {
  1173. $res = new MemModel($this->getBaseURI());
  1174.  
  1175. $stateIt=$this->getStatementIterator();
  1176. while($statement=$stateIt->next())
  1177. {
  1178. $pointer =& $statement->reify($res);
  1179. $res->addModel($pointer);
  1180. };
  1181.  
  1182. return $res;
  1183. }
  1184.  
  1185. /**
  1186. * Returns a StatementIterator for traversing the MemModel.
  1187. * @access public
  1188. * @return object StatementIterator
  1189. */
  1190. function & getStatementIterator() {
  1191. // Import Package Utility
  1192. include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
  1193.  
  1194. return new StatementIterator($this);
  1195. }
  1196.  
  1197. /**
  1198. * Returns a FindIterator for traversing the MemModel.
  1199. * @access public
  1200. * @return object FindIterator
  1201. */
  1202. function & findAsIterator($sub=null,$pred=null,$obj=null) {
  1203. // Import Package Utility
  1204. include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
  1205.  
  1206. return new FindIterator($this,$sub,$pred,$obj);
  1207. }
  1208.  
  1209.  
  1210. /**
  1211. * Returns the models namespaces.
  1212. *
  1213. * @author Tobias Gauß <tobias.gauss@web.de>
  1214. * @access public
  1215. * @return Array
  1216. */
  1217. function getParsedNamespaces(){
  1218. if(count($this->parsedNamespaces)!=0){
  1219. return $this->parsedNamespaces;
  1220. }else{
  1221. return false;
  1222. }
  1223. }
  1224.  
  1225.  
  1226.  
  1227. /**
  1228. * Adds the namespaces to the model. This method is called by
  1229. * the parser. !!!! addParsedNamespaces() not overwrites manual
  1230. * added namespaces in the model !!!!
  1231. *
  1232. * @author Tobias Gauß <tobias.gauss@web.de>
  1233. * @access public
  1234. * @param Array $newNs
  1235. */
  1236. function addParsedNamespaces($newNs){
  1237. if($newNs)
  1238. $this->parsedNamespaces = $this->parsedNamespaces + $newNs;
  1239. }
  1240.  
  1241.  
  1242. /**
  1243. * Adds a namespace and prefix to the model.
  1244. *
  1245. * @author Tobias Gauß <tobias.gauss@web.de>
  1246. * @access public
  1247. * @param String $prefix, String $nmsp
  1248. */
  1249. function addNamespace($prefix, $nmsp){
  1250. $this->parsedNamespaces[$nmsp]=$prefix;
  1251. }
  1252.  
  1253. /**
  1254. * removes a single namespace from the model
  1255. *
  1256. * @author Tobias Gauß <tobias.gauss@web.de>
  1257. * @access public
  1258. * @param String $nmsp
  1259. */
  1260. function removeNamespace($nmsp){
  1261. if(isset($this->parsedNamespaces[$nmsp])){
  1262. unset($this->parsedNamespaces[$nmsp]);
  1263. return true;
  1264. }else{
  1265. return false;
  1266. }
  1267. }
  1268.  
  1269.  
  1270.  
  1271. /**
  1272. * Close the MemModel and free up resources held.
  1273. *
  1274. * @access public
  1275. */
  1276. function close() {
  1277. unset( $baseURI );
  1278. unset( $triples );
  1279. }
  1280.  
  1281. // =============================================================================
  1282. // *************************** helper functions ********************************
  1283. // =============================================================================
  1284. /**
  1285. * Checks if $statement is in index
  1286. *
  1287. * @param int $ind
  1288. * @param Statement &$statement
  1289. * @return boolean
  1290. * @access private
  1291. */
  1292. function _containsIndex(&$statement,$ind){
  1293. switch($ind){
  1294. case 4:
  1295. $sub=$statement->getSubject();
  1296. $pos=$sub->getLabel();
  1297. break;
  1298. case 1:
  1299. $sub=$statement->getSubject();
  1300. $pred=$statement->getPredicate();
  1301. $obj=$statement->getObject();
  1302. $pos=$sub->getLabel().$pred->getLabel().$obj->getLabel();
  1303. break;
  1304. case 2:
  1305. $sub=$statement->getSubject();
  1306. $pred=$statement->getPredicate();
  1307. $pos=$sub->getLabel().$pred->getLabel();
  1308. break;
  1309. case 3:
  1310. $sub=$statement->getSubject();
  1311. $obj=$statement->getObject();
  1312. $pos=$sub->getLabel().$obj->getLabel();
  1313. break;
  1314. }
  1315.  
  1316. if (!isset($this->indexArr[$ind][$pos]))
  1317. return FALSE;
  1318. foreach ($this->indexArr[$ind][$pos] as $key => $value) {
  1319. $t=$this->triples[$value];
  1320. if ($t->equals($statement))
  1321. return TRUE;
  1322. }
  1323. return FALSE;
  1324. }
  1325.  
  1326.  
  1327.  
  1328.  
  1329.  
  1330. /**
  1331. * finds a statement in an index. $pos is the Position in the index
  1332. * and $ind the adequate searchindex
  1333. *
  1334. * @param String $pos
  1335. * @param Object Subject &$subject
  1336. * @param Object Predicate &$predicate
  1337. * @param Object Object &$object
  1338. * @param int &ind
  1339. * @return MemModel $res
  1340. * @access private
  1341. */
  1342. function _findInIndex($pos,&$subject,&$predicate,&$object,$ind){
  1343. $res = new MemModel($this->getBaseURI());
  1344. $res->indexed=-1;
  1345. if (!isset($this->indexArr[$ind][$pos]))
  1346. return $res;
  1347. foreach($this->indexArr[$ind][$pos] as $key =>$value){
  1348. $t=$this->triples[$value];
  1349. if ($this->matchStatement($t,$subject,$predicate,$object))
  1350. $res->add($t);
  1351. }
  1352. return $res;
  1353. }
  1354. /**
  1355. * adds/removes a statement into/from an index.
  1356. * mode=0 removes the statement from the index;
  1357. * mode=1 adds the statement into the index.
  1358. * returns the statements position.
  1359. *
  1360. * @param Object Statement &$statement
  1361. * @param int $k
  1362. * @param int $ind
  1363. * @param int $mode
  1364. * @return int $k
  1365. * @access private
  1366. */
  1367. function _indexOpr(&$statement,$k,$ind,$mode){
  1368. // determine position in adequate index
  1369. switch($ind){
  1370. case 1:
  1371. $s=$statement->getSubject();
  1372. $p=$statement->getPredicate();
  1373. $o=$statement->getObject();
  1374. $pos=$s->getLabel().$p->getLabel().$o->getLabel();
  1375. break;
  1376. case 2:
  1377. $s=$statement->getSubject();
  1378. $p=$statement->getPredicate();
  1379. $pos=$s->getLabel().$p->getLabel();
  1380. break;
  1381. case 3:
  1382. $s=$statement->getSubject();
  1383. $o=$statement->getObject();
  1384. $pos=$s->getLabel().$o->getLabel();
  1385. break;
  1386. case 4:
  1387. $s=$statement->getSubject();
  1388. $pos=$s->getLabel();
  1389. break;
  1390. case 5:
  1391. $p=$statement->getPredicate();
  1392. $pos=$p->getLabel();
  1393. break;
  1394. case 6:
  1395. $o=$statement->getObject();
  1396. $pos=$o->getLabel();
  1397. break;
  1398. }
  1399. switch($mode){
  1400. // add in Index
  1401. case 1:
  1402. if(isset($this->indexArr[$ind][$pos])){
  1403. $this->indexArr[$ind][$pos][] = $k;
  1404. }else{
  1405. $this->indexArr[$ind][$pos][0] = $k;
  1406. }
  1407. break;
  1408. // remove from Index
  1409. case 0:
  1410. $subject=$statement->getSubject();
  1411. $predicate=$statement->getPredicate();
  1412. $object=$statement->getObject();
  1413. $k=-1;
  1414. if(!isset($this->indexArr[$ind][$pos])){
  1415. return -1;
  1416. }
  1417. $num=count($this->indexArr[$ind][$pos]);
  1418. foreach($this->indexArr[$ind][$pos] as $key => $value){
  1419. $t=$this->triples[$value];
  1420. if($this->matchStatement($t,$subject,$predicate,$object)){
  1421. $k=$value;
  1422. if($num==1){
  1423. unset($this->indexArr[$ind][$pos]);
  1424. }else{
  1425. unset($this->indexArr[$ind][$pos][$key]);
  1426. }
  1427. return $k;
  1428. }
  1429. }
  1430. break;
  1431. }
  1432. return $k;
  1433. }
  1434.  
  1435.  
  1436. /**
  1437. * finds next or previous matching statement.
  1438. * Returns Position in model or -1 if there is no match.
  1439. *
  1440. *
  1441. * @param String
  1442. * @param object Subject
  1443. * @param object Predicate
  1444. * @param object Object
  1445. * @param integer
  1446. * @param integer
  1447. * @return integer
  1448. * @access private
  1449. */
  1450. function _findMatchIndex($pos,&$s,&$p,&$o,$ind,$off){
  1451. $match=-1;
  1452. if (!isset($this->indexArr[$ind][$pos])) {
  1453. return $match;}
  1454. foreach($this->indexArr[$ind][$pos] as $key =>$value){
  1455. $t=$this->triples[$value];
  1456. if ($this->matchStatement($t,$s,$p,$o)){
  1457. if($off <= $value){
  1458. $match= $value;
  1459. return $match;
  1460. }
  1461. }
  1462. }
  1463.  
  1464. return $match;
  1465.  
  1466. }
  1467.  
  1468.  
  1469.  
  1470.  
  1471. } // end: MemModel
  1472.  
  1473.  
  1474. ?>

Documentation generated on Fri, 17 Dec 2004 16:15:42 +0100 by phpDocumentor 1.3.0RC3