Source for file DbModel.php

Documentation is available at DbModel.php

  1. <?php
  2.  
  3. // ----------------------------------------------------------------------------------
  4. // Class: DbModel
  5. // ----------------------------------------------------------------------------------
  6.  
  7. /**
  8. * This class provides methods for manipulating DbModels from DbStore.
  9. * A DbModel is an RDF Model, which is persistently stored in a relational database.
  10. * This Class uses ADOdb Library for PHP V3.60 (http://php.weblogs.com/ADODB).
  11. *
  12. * <BR><BR>History:<UL>
  13. * <LI>12-06-2004 : improved namespace handling added (tobias.gauss@web.de)</LI>
  14. * <LI>10-07-2004 : Function findFirstMatchingStatement() added paramter $offset
  15. * to set an search offset
  16. * <LI>16-08-2004 : Function getUniqueResourceURI() has been made faster,</LI>
  17. * addWithoutDuplicates() added</LI>
  18. * <LI>05-24-2004 : Bug in _getNodeFlag() fixed (auer@informatik.uni-leipzig.de)</LI>
  19. * <LI>03-29-2004 : Function addModel() fixed, saveAs() added</LI>
  20. * <LI>11-13-2003 : Functions load,saveAs moved to class model
  21. * <LI>11-12-2003 : Function rdqlQueryAsIterator() added.</LI>
  22. * <LI>06-17-2003 : First version of this class</LI>
  23. *
  24. * @version V0.9.3
  25. * @author Radoslaw Oldakowski <radol@gmx.de>
  26. *
  27. * @package model
  28. * @access public
  29. */
  30.  
  31.  
  32. class DbModel extends Model{
  33.  
  34. /**
  35. * Database connection object
  36. *
  37. * @var object ADOConnection
  38. * @access private
  39. */
  40. var $dbConn;
  41.  
  42. /**
  43. * Unique model URI.
  44. * Used to identify the DbModel.
  45. *
  46. * @var string
  47. * @access private
  48. */
  49. var $modelURI;
  50.  
  51.  
  52. /**
  53. * Database internal modelID.
  54. * Used to avoid JOINs.
  55. *
  56. * @var string
  57. * @access private
  58. */
  59. var $modelID;
  60.  
  61.  
  62.  
  63.  
  64. /**
  65. * Constructor
  66. * Do not call this directly.
  67. * Use the method getModel,getNewModel or putModel of the Class DbStore instead.
  68. *
  69. * @param object ADOConnection &$dbConnection
  70. * @param string $modelURI
  71. * @param string $modelID
  72. * @param string $baseURI
  73. * @access public
  74. */
  75. function DbModel(&$dbConnection, $modelURI, $modelID, $baseURI=NULL) {
  76.  
  77. $this->dbConn =& $dbConnection;
  78. $this->modelURI = $modelURI;
  79. $this->modelID = $modelID;
  80. $this->baseURI = $this->_checkBaseURI($baseURI);
  81. }
  82.  
  83.  
  84. /**
  85. * Set a base URI for the DbModel.
  86. * Affects creating of new resources and serialization syntax.
  87. *
  88. * @param string $uri
  89. * @throws SqlError
  90. * @access public
  91. */
  92. function setBaseURI($uri) {
  93.  
  94. $this->baseURI = $this->_checkBaseURI($uri);
  95.  
  96. $rs = $this->dbConn->execute("UPDATE models SET baseURI=''" .$this->baseURI ."''
  97. WHERE modelID=" .$this->modelID);
  98. if (!$rs)
  99. $this->dbConn->errorMsg();
  100. }
  101.  
  102.  
  103. /**
  104. * Return the number of statements in this DbModel
  105. *
  106. * @return integer
  107. * @access public
  108. */
  109. function size() {
  110.  
  111. $count =& $this->dbConn->getOne(''SELECT COUNT(modelID) FROM statements
  112. WHERE modelID = '' .$this->modelID);
  113. return $count;
  114. }
  115.  
  116.  
  117. /**
  118. * Check if this DbModel is empty
  119. *
  120. * @return boolean
  121. * @access public
  122. */
  123. function isEmpty() {
  124.  
  125. if ($this->size() == 0)
  126. return TRUE;
  127. return FALSE;
  128. }
  129.  
  130.  
  131. /**
  132. * Add a new triple to this DbModel.
  133. *
  134. * @param object Statement &$statement
  135. * @throws PhpError
  136. * @throws SqlError
  137. * @access public
  138. */
  139. function add(&$statement) {
  140.  
  141. if (!is_a($statement, ''Statement'')) {
  142. $errmsg = RDFAPI_ERROR . ''(class: DbModel; method: add): Statement expected.'';
  143. trigger_error($errmsg, E_USER_ERROR);
  144. }
  145.  
  146. if (!$this->contains($statement)) {
  147.  
  148. $subject_is = $this->_getNodeFlag($statement->subject());
  149. $sql = "INSERT INTO statements VALUES
  150. (" .$this->modelID .","
  151. ."''" .$statement->getLabelSubject() ."'',"
  152. ."''" .$statement->getLabelPredicate() ."'',";
  153.  
  154. if (is_a($statement->object(), ''Literal'')) {
  155. $quotedLiteral = $this->dbConn->qstr($statement->obj->getLabel());
  156. $sql .= $quotedLiteral .","
  157. ."''" .$statement->obj->getLanguage() ."'',"
  158. ."''" .$statement->obj->getDatatype() ."'',"
  159. ."''" .$subject_is ."'',"
  160. ."''l'')";
  161. }else{
  162. $object_is = $this->_getNodeFlag($statement->object());
  163. $sql .= "''" .$statement->obj->getLabel() ."'',"
  164. ."'''',"
  165. ."'''',"
  166. ."''" .$subject_is ."'',"
  167. ."''" .$object_is ."'')";
  168. }
  169. $rs =& $this->dbConn->execute($sql);
  170. if (!$rs)
  171. $this->dbConn->errorMsg();
  172. }
  173. }
  174.  
  175.  
  176. /**
  177. * Alias for the method add()
  178. *
  179. * @param object Statement &$statement
  180. * @throws PhpError
  181. * @throws SqlError
  182. * @access public
  183. */
  184. function addWithoutDuplicates(&$statement) {
  185.  
  186. $this->add($statement);
  187. }
  188.  
  189.  
  190. /**
  191. * Remove the given triple from this DbModel.
  192. *
  193. * @param object Statement &$statement
  194. * @throws PhpError
  195. * @throws SqlError
  196. * @access public
  197. */
  198. function remove(&$statement) {
  199.  
  200. if (!is_a($statement, ''Statement'')) {
  201. $errmsg = RDFAPI_ERROR . ''(class: DbModel; method: remove): Statement expected.'';
  202. trigger_error($errmsg, E_USER_ERROR);
  203. }
  204.  
  205. $sql = ''DELETE FROM statements
  206. WHERE modelID='' .$this->modelID;
  207. $sql .= $this->_createDynSqlPart_SPO ($statement->subj, $statement->pred, $statement->obj);
  208.  
  209. $rs =& $this->dbConn->execute($sql);
  210. if (!$rs)
  211. $this->dbConn->errorMsg();
  212. }
  213.  
  214.  
  215. /**
  216. * Short dump of the DbModel.
  217. *
  218. * @return string
  219. * @access public
  220. */
  221. function toString() {
  222.  
  223. return ''DbModel[modelURI='' .$this->modelURI .''; baseURI='' .$this->getBaseURI() .''; size='' .$this->size() .'']'';
  224. }
  225.  
  226.  
  227. /**
  228. * Dump of the DbModel including all triples.
  229. *
  230. * @return string
  231. * @access public
  232. */
  233. function toStringIncludingTriples() {
  234.  
  235. $memModel =& $this->getMemModel();
  236. return $memModel->toStringIncludingTriples();
  237. }
  238.  
  239.  
  240.  
  241. /**
  242. * Create a MemModel containing all the triples of the current DbModel
  243. *
  244. * @return object MemModel
  245. * @access public
  246. */
  247. function & getMemModel() {
  248.  
  249. $recordSet = $this->_getRecordSet($this);
  250. return $this->_convertRecordSetToMemModel($recordSet);
  251. }
  252.  
  253.  
  254. /**
  255. * Write the RDF serialization of the _DbModel as HTML.
  256. *
  257. * @access public
  258. */
  259. function writeAsHtml() {
  260.  
  261. $memModel =& $this->getMemModel();
  262. $memModel->writeAsHtml();
  263. }
  264.  
  265.  
  266. /**
  267. * Write the RDF serialization of the DbModel as HTML table.
  268. *
  269. * @access public
  270. */
  271. function writeAsHtmlTable() {
  272. include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
  273. $memModel =& $this->getMemModel();
  274. RDFUtil::writeHTMLTable($memModel);
  275. }
  276.  
  277.  
  278. /**
  279. * Write the RDF serialization of the DbModel to string
  280. *
  281. * @return string
  282. * @access public
  283. */
  284. function writeRdfToString() {
  285.  
  286. $memModel =& $this->getMemModel();
  287. return $memModel->writeRdfToString();
  288. }
  289.  
  290.  
  291. /**
  292. * Saves the RDF,N3 or N-Triple serialization of the DbModel to a file.
  293. * You can decide to which format the model should be serialized by using a
  294. * corresponding suffix-string as $type parameter. If no $type parameter
  295. * is placed this method will serialize the model to XML/RDF format.
  296. * Returns FALSE if the DbModel couldn''t be saved to the file.
  297. *
  298. * @access public
  299. * @param string $filename
  300. * @param string $type
  301. * @throw PhpError
  302. * @return boolean
  303. */
  304. function saveAs($filename, $type =''rdf'') {
  305.  
  306. $memModel = $this->getMemModel();
  307. $memModel->saveAs($filename, $type);
  308.  
  309. }
  310.  
  311.  
  312. /**
  313. * Check if the DbModel contains the given statement
  314. *
  315. * @param object Statement &$statement
  316. * @return boolean
  317. * @access public
  318. */
  319. function contains(&$statement) {
  320.  
  321. $sql = ''SELECT modelID FROM statements
  322. WHERE modelID = '' .$this->modelID;
  323. $sql .= $this->_createDynSqlPart_SPO($statement->subj, $statement->pred, $statement->obj);
  324.  
  325. $res =& $this->dbConn->getOne($sql);
  326.  
  327. if (!$res)
  328. return FALSE;
  329. return TRUE;
  330. }
  331.  
  332.  
  333. /**
  334. * Determine if all of the statements in the given model are also contained in this DbModel.
  335. *
  336. * @param object Model &$model
  337. * @return boolean
  338. * @access public
  339. */
  340. function containsAll(&$model) {
  341.  
  342. if (is_a($model, ''MemModel'')) {
  343.  
  344. foreach($model->triples as $statement)
  345. if(!$this->contains($statement))
  346. return FALSE;
  347. return TRUE;
  348. }
  349.  
  350. elseif (is_a($model, ''DbModel'')) {
  351.  
  352. $recordSet =& $this->_getRecordSet($model);
  353. while (!$recordSet->EOF) {
  354. if (!$this->_containsRow($recordSet->fields))
  355. return FALSE;
  356. $recordSet->moveNext();
  357. }
  358. return TRUE;
  359. }
  360.  
  361. $errmsg = RDFAPI_ERROR . ''(class: DbModel; method: containsAll): Model expected.'';
  362. trigger_error($errmsg, E_USER_ERROR);
  363. }
  364.  
  365.  
  366. /**
  367. * Determine if any of the statements in the given model are also contained in this DbModel.
  368. *
  369. * @param object Model &$model
  370. * @return boolean
  371. * @access public
  372. */
  373. function containsAny(&$model) {
  374.  
  375. if (is_a($model, ''MemModel'')) {
  376.  
  377. foreach($model->triples as $statement)
  378. if($this->contains($statement))
  379. return TRUE;
  380. return FALSE;
  381. }
  382.  
  383. elseif (is_a($model, ''DbModel'')) {
  384.  
  385. $recordSet =& $this->_getRecordSet($model);
  386. while (!$recordSet->EOF) {
  387. if ($this->_containsRow($recordSet->fields))
  388. return TRUE;
  389. $recordSet->moveNext();
  390. }
  391. return FALSE;
  392. }
  393.  
  394. $errmsg = RDFAPI_ERROR . ''(class: DbModel; method: containsAny): Model expected.'';
  395. trigger_error($errmsg, E_USER_ERROR);
  396. }
  397.  
  398.  
  399. /**
  400. * General method to search for triples in the DbModel.
  401. * NULL input for any parameter will match anything.
  402. * Example: $result = $m->find( NULL, NULL, $node );
  403. * Finds all triples with $node as object.
  404. *
  405. * @param object Resource $subject
  406. * @param object Resource $predicate
  407. * @param object Node $object
  408. * @return object MemModel
  409. * @throws PhpError
  410. * @throws SqlError
  411. * @access public
  412. */
  413. function find($subject, $predicate, $object) {
  414.  
  415. if ((!is_a($subject, ''Resource'') && $subject != NULL) ||
  416. (!is_a($predicate, ''Resource'') && $predicate != NULL) ||
  417. (!is_a($object, ''Node'') && $object != NULL)) {
  418.  
  419. $errmsg = RDFAPI_ERROR . ''(class: DbModel; method: find): Parameters must be subclasses of Node or NULL'';
  420. trigger_error($errmsg, E_USER_ERROR);
  421. }
  422.  
  423. // static part of the sql statement
  424. $sql = ''SELECT subject, predicate, object, l_language, l_datatype, subject_is, object_is
  425. FROM statements
  426. WHERE modelID = '' .$this->modelID;
  427.  
  428. // dynamic part of the sql statement
  429. $sql .= $this->_createDynSqlPart_SPO($subject, $predicate, $object);
  430.  
  431. // execute the query
  432. $recordSet =& $this->dbConn->execute($sql);
  433.  
  434. if (!$recordSet)
  435. echo $this->dbConn->errorMsg();
  436.  
  437. // write the recordSet into memory Model
  438. else
  439. return $this->_convertRecordSetToMemModel($recordSet);
  440. }
  441.  
  442.  
  443. /**
  444. * Method to search for triples using Perl-style regular expressions.
  445. * NULL input for any parameter will match anything.
  446. * Example: $result = $m->find_regex( NULL, NULL, $regex );
  447. * Finds all triples where the label of the object node matches
  448. the regular expression.
  449. * Return an empty MemModel if nothing is found.
  450. * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  451. * WARNING: Mhis method loads a DbModel into memory and performs the search
  452. * on a MemModel, which can be slow with large models.
  453. * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  454. *
  455. * @param string $subject_regex
  456. * @param string $predicate_regex
  457. * @param string $object_regex
  458. * @return object MemModel
  459. * @throws PhpError
  460. * @throws SqlError
  461. * @access public
  462. */
  463. function findRegex($subject_regex, $predicate_regex, $object_regex) {
  464.  
  465. $mm =& $this->getMemModel();
  466.  
  467. return $mm->findRegex($subject_regex, $predicate_regex, $object_regex);
  468. }
  469.  
  470.  
  471. /**
  472. * Return all tripels of a certain vocabulary.
  473. * $vocabulary is the namespace of the vocabulary inluding a # : / char at the end.
  474. * e.g. http://www.w3.org/2000/01/rdf-schema#
  475. * Return an empty model if nothing is found.
  476. *
  477. * @param string $vocabulary
  478. * @return object MemModel
  479. * @throws PhpError
  480. * @throws SqlError
  481. * @access public
  482. */
  483. function findVocabulary($vocabulary) {
  484.  
  485. $sql = "SELECT subject, predicate, object, l_language, l_datatype, subject_is, object_is
  486. FROM statements
  487. WHERE modelID = " .$this->modelID ."
  488. AND predicate LIKE ''" .$vocabulary ."%''";
  489.  
  490. $recordSet =& $this->dbConn->execute($sql);
  491.  
  492. if (!$recordSet)
  493. echo $this->dbConn->errorMsg();
  494.  
  495. // write the recordSet into memory Model
  496. else
  497. return $this->_convertRecordSetToMemModel($recordSet);
  498. }
  499.  
  500.  
  501. /**
  502. * Search for triples and return the first matching statement.
  503. * NULL input for any parameter will match anything.
  504. * Return an NULL if nothing is found.
  505. * You can set an search offset with $offset.
  506. *
  507. * @param object Resource $subject
  508. * @param object Resource $predicate
  509. * @param object Node $object
  510. * @param integer $offset
  511. * @return object Statement
  512. * @throws PhpError
  513. * @throws SqlError
  514. * @access public
  515. */
  516. function findFirstMatchingStatement($subject, $predicate, $object, $offset = -1) {
  517.  
  518. if ((!is_a($subject, ''Resource'') && $subject != NULL) ||
  519. (!is_a($predicate, ''Resource'') && $predicate != NULL) ||
  520. (!is_a($object, ''Node'') && $object != NULL)) {
  521.  
  522. $errmsg = RDFAPI_ERROR . ''(class: DbModel; method: find): Parameters must be subclasses of Node or NULL'';
  523. trigger_error($errmsg, E_USER_ERROR);
  524. }
  525.  
  526. // static part of the sql statement
  527. $sql = ''SELECT subject, predicate, object, l_language, l_datatype, subject_is, object_is
  528. FROM statements
  529. WHERE modelID = '' .$this->modelID;
  530.  
  531. // dynamic part of the sql statement
  532. $sql .= $this->_createDynSqlPart_SPO($subject, $predicate, $object);
  533.  
  534. // execute the query
  535. $recordSet =& $this->dbConn->selectLimit($sql,1,($offset));
  536.  
  537. if (!$recordSet)
  538. echo $this->dbConn->errorMsg();
  539. else {
  540. if (!$recordSet->fields)
  541. return NULL;
  542. else {
  543. $memModel = $this->_convertRecordSetToMemModel($recordSet);
  544. return $memModel->triples[0];
  545. }
  546. }
  547. }
  548.  
  549.  
  550. /**
  551. * Search for triples and return the number of matches.
  552. * NULL input for any parameter will match anything.
  553. *
  554. * @param object Resource $subject
  555. * @param object Resource $predicate
  556. * @param object Node $object
  557. * @return integer
  558. * @throws PhpError
  559. * @throws SqlError
  560. * @access public
  561. */
  562. function findCount($subject, $predicate, $object) {
  563.  
  564. if ((!is_a($subject, ''Resource'') && $subject != NULL) ||
  565. (!is_a($predicate, ''Resource'') && $predicate != NULL) ||
  566. (!is_a($object, ''Node'') && $object != NULL)) {
  567.  
  568. $errmsg = RDFAPI_ERROR . ''(class: DbModel; method: find): Parameters must be subclasses of Node or NULL'';
  569. trigger_error($errmsg, E_USER_ERROR);
  570. }
  571.  
  572. // static part of the sql statement
  573. $sql = ''SELECT COUNT(*)
  574. FROM statements
  575. WHERE modelID = '' .$this->modelID;
  576.  
  577. // dynamic part of the sql statement
  578. $sql .= $this->_createDynSqlPart_SPO($subject, $predicate, $object);
  579.  
  580. // execute the query
  581. $recordSet =& $this->dbConn->execute($sql);
  582.  
  583. if (!$recordSet)
  584. echo $this->dbConn->errorMsg();
  585. else
  586. return $recordSet->fields[0];
  587. }
  588.  
  589.  
  590. /**
  591. * Perform an RDQL query on this DbModel.
  592. * This method returns an associative array of variable bindings.
  593. * The values of the query variables can either be RAP''s objects (instances of Node)
  594. * if $returnNodes set to TRUE, or their string serialization.
  595. *
  596. * @access public
  597. * @param string $queryString
  598. * @param boolean $returnNodes
  599. * @return array [][?VARNAME] = object Node (if $returnNodes = TRUE)
  600. * OR array [][?VARNAME] = string
  601. *
  602. */
  603. function rdqlQuery($queryString, $returnNodes = TRUE) {
  604. require_once(RDFAPI_INCLUDE_DIR.PACKAGE_RDQL);
  605. $parser = new RdqlParser();
  606. $parsedQuery =& $parser->parseQuery($queryString);
  607.  
  608. // this method can only query this DbModel
  609. // if another model was specified in the from clause throw an error
  610. if (isset($parsedQuery[''sources''][0]))
  611. if($parsedQuery[''sources''][0] != $this->modelURI) {
  612. $errmsg = RDFAPI_ERROR . ''(class: DbModel; method: rdqlQuery):'';
  613. $errmsg .= '' this method can only query this DbModel'';
  614. trigger_error($errmsg, E_USER_ERROR);
  615. }
  616.  
  617. $engine = new RdqlDbEngine();
  618. $res =& $engine->queryModel($this, $parsedQuery, $returnNodes);
  619.  
  620. return $res;
  621. }
  622.  
  623.  
  624. /**
  625. * Perform an RDQL query on this DBModel.
  626. * This method returns an RdqlResultIterator of variable bindings.
  627. * The values of the query variables can either be RAP''s objects (instances of Node)
  628. * if $returnNodes set to TRUE, or their string serialization.
  629. *
  630. * @access public
  631. * @param string $queryString
  632. * @param boolean $returnNodes
  633. * @return object RdqlResultIterator = with values as object Node (if $returnNodes = TRUE)
  634. * OR object RdqlResultIterator = with values as strings if (if $returnNodes = FALSE)
  635. *
  636. */
  637. function rdqlQueryAsIterator($queryString, $returnNodes = TRUE) {
  638. require_once(RDFAPI_INCLUDE_DIR.PACKAGE_RDQL);
  639. return new RdqlResultIterator($this->rdqlQuery($queryString, $returnNodes));
  640. }
  641.  
  642. /**
  643. * General method to replace nodes of a DbModel.
  644. * NULL input for any parameter will match nothing.
  645. * Example: $m->replace($resource, NULL, $node, $replacement);
  646. * Replaces all $node objects beeing subject or object in
  647. * any triple of the model with the $replacement node.
  648. * Throw an error in case of a paramter mismatch.
  649. *
  650. * @param object Resource $subject
  651. * @param object Resource $predicate
  652. * @param object Node $object
  653. * @param object Node $replacement
  654. * @throws PhpError
  655. * @throws SqlError
  656. * @access public
  657. */
  658. function replace($subject, $predicate, $object, $replacement) {
  659.  
  660. // check the correctness of the passed parameters
  661. if ( ((!is_a($subject, ''Resource'') && $subject != NULL) ||
  662. (!is_a($predicate, ''Resource'') && $predicate != NULL) ||
  663. (!is_a($object, ''Node'') && $object != NULL)) ||
  664. (($subject != NULL && is_a($replacement, ''Literal'')) ||
  665. ($predicate != NULL && (is_a($replacement, ''Literal'') ||
  666. is_a($replacement, ''BlankNode'')))) )
  667. {
  668. $errmsg = RDFAPI_ERROR . ''(class: DbModel; method: find): Parameter mismatch'';
  669. trigger_error($errmsg, E_USER_ERROR);
  670. }
  671.  
  672. if (!(!$subject && !$predicate && !$object)) {
  673.  
  674. // create an update sql statement
  675. $comma = '''';
  676. $sql = ''UPDATE statements
  677. SET '';
  678. if ($subject) {
  679. $sql .= " subject =''" .$replacement->getLabel() ."'', "
  680. ." subject_is=''" .$this->_getNodeFlag($replacement) ."'' ";
  681. $comma = '','';
  682. }
  683. if ($predicate) {
  684. $sql .= $comma ." predicate=''" .$replacement->getLabel() ."'' ";
  685. $comma = '','';
  686. }
  687. if ($object) {
  688. $quotedObject = $this->dbConn->qstr($replacement->getLabel());
  689. $sql .= $comma .'' object='' .$quotedObject
  690. .", object_is=''" .$this->_getNodeFlag($replacement) ."'' ";
  691. if (is_a($replacement, ''Literal'')) {
  692. $sql .= ", l_language=''" .$replacement->getLanguage() ."'' "
  693. .", l_datatype=''" .$replacement->getDataType() ."'' ";
  694. }
  695. }
  696. $sql .= ''WHERE modelID = '' .$this->modelID;
  697. $sql .= $this->_createDynSqlPart_SPO($subject, $predicate, $object);
  698.  
  699. // execute the query
  700. $rs =& $this->dbConn->execute($sql);
  701.  
  702. if (!$rs)
  703. echo $this->dbConn->errorMsg();
  704. }
  705. }
  706.  
  707.  
  708. /**
  709. * Check if two models are equal.
  710. * Two models are equal if and only if the two RDF graphs they represent are isomorphic.
  711. *
  712. * Warning: This method doesn''t work correct with models where the same blank node has different
  713. * identifiers in the two models. We will correct this in a future version.
  714. *
  715. * @param object model &$that
  716. * @return boolean
  717. * @throws PhpError
  718. * @access public
  719. */
  720.  
  721. function equals(&$that) {
  722.  
  723. if (!is_a($that, ''Model'')) {
  724. $errmsg = RDFAPI_ERROR . ''(class: DbModel; method: equals): Model expected.'';
  725. trigger_error($errmsg, E_USER_ERROR);
  726. }
  727.  
  728. if ($this->size() != $that->size())
  729. return FALSE;
  730.  
  731. if (!$this->containsAll($that))
  732. return FALSE;
  733. return TRUE;
  734. }
  735.  
  736.  
  737. /**
  738. * Return a new MemModel that is the set-union the model with another model.
  739. *
  740. * The result of taking the set-union of two or more RDF graphs (i.e. sets of triples)
  741. * is another graph, which we will call the merge of the graphs.
  742. * Each of the original graphs is a subgraph of the merged graph. Notice that when forming
  743. * a merged graph, two occurrences of a given uriref or literal as nodes in two different
  744. * graphs become a single node in the union graph (since by definition they are the same
  745. * uriref or literal) but blank nodes are not ''merged'' in this way; and arcs are of course
  746. * never merged. In particular, this means that every blank node in a merged graph can be
  747. * identified as coming from one particular graph in the original set of graphs.
  748. *
  749. * Notice that one does not, in general, obtain the merge of a set of graphs by concatenating
  750. * their corresponding N-triples documents and constructing the graph described by the merged
  751. * document, since if some of the documents use the same node identifiers, the merged document
  752. * will describe a graph in which some of the blank nodes have been ''accidentally'' merged.
  753. * To merge Ntriples documents it is necessary to check if the same nodeID is used in two or
  754. * more documents, and to replace it with a distinct nodeID in each of them, before merging the
  755. * documents. (Not implemented yet !!!!!!!!!!!)
  756. *
  757. * @param object Model $model
  758. * @return object MemModel
  759. * @throws PhpError
  760. * @access public
  761. *
  762. */
  763. function & unite(&$model) {
  764.  
  765. if (!is_a($model, ''Model'')) {
  766. $errmsg = RDFAPI_ERROR . ''(class: DbModel; method: unite): Model expected.'';
  767. trigger_error($errmsg, E_USER_ERROR);
  768. }
  769.  
  770. if (is_a($model, ''MemModel'')) {
  771.  
  772. $thisModel =& $this->getMemModel();
  773. return $thisModel->unite($model);
  774. }
  775.  
  776. elseif (is_a($model, ''DbModel'')) {
  777.  
  778. $thisModel =& $this->getMemModel();
  779. $thatModel =& $model->getMemModel();
  780. return $thisModel->unite($thatModel);
  781. }
  782. }
  783.  
  784.  
  785. /**
  786. * Return a new MemModel that is the subtraction of another model from this DbModel.
  787. *
  788. * @param object Model $model
  789. * @return object MemModel
  790. * @throws PhpError
  791. * @access public
  792. */
  793.  
  794. function & subtract(&$model) {
  795.  
  796. if (!is_a($model, ''Model'')) {
  797. $errmsg = RDFAPI_ERROR . ''(class: DbModel; method: subtract): Model expected.'';
  798. trigger_error($errmsg, E_USER_ERROR);
  799. }
  800.  
  801. if (is_a($model, ''MemModel'')) {
  802.  
  803. $thisModel =& $this->getMemModel();
  804. return $thisModel->subtract($model);
  805. }
  806.  
  807. elseif (is_a($model, ''DbModel'')) {
  808.  
  809. $thisModel =& $this->getMemModel();
  810. $thatModel =& $model->getMemModel();
  811. return $thisModel->subtract($thatModel);
  812. }
  813. }
  814.  
  815.  
  816. /**
  817. * Return a new MemModel containing all the statements which are in both
  818. * this model and the given model.
  819. *
  820. * @param object Model $model
  821. * @return object MemModel
  822. * @throws PhpError
  823. * @access public
  824. */
  825. function & intersect(&$model) {
  826.  
  827. if (is_a($model, ''MemModel'')) {
  828.  
  829. $thisModel =& $this->getMemModel();
  830. return $thisModel->intersect($model);
  831. }
  832.  
  833. elseif (is_a($model, ''DbModel'')) {
  834.  
  835. $thisModel =& $this->getMemModel();
  836. $thatModel =& $model->getMemModel();
  837. return $thisModel->intersect($thatModel);
  838. }
  839.  
  840. $errmsg = RDFAPI_ERROR . ''(class: DbModel; method: intersect: Model expected.'';
  841. trigger_error($errmsg, E_USER_ERROR);
  842. }
  843.  
  844.  
  845. /**
  846. * Add the given model to this DbModel.
  847. * This function monitors for SQL errors, and will commit if no errors have occured,
  848. * otherwise it will rollback.
  849. * If any statement of the model to be added to this model contains a blankNode
  850. * with an identifier already existing in this model, a new blankNode is generated.
  851. *
  852. * @param object Model $model
  853. * @throw PhpError
  854. * @access public
  855. */
  856. function addModel(&$model) {
  857.  
  858. if (!is_a($model, ''Model'')) {
  859. $errmsg = RDFAPI_ERROR . ''(class: DbModel; method: addModel): Model expected.'';
  860. trigger_error($errmsg, E_USER_ERROR);
  861. }
  862.  
  863. $blankNodes_tmp = array();
  864.  
  865. if (is_a($model, ''MemModel'')) {
  866.  
  867. $this->dbConn->startTrans();
  868. foreach ($model->triples as $statement)
  869. $this->_addStatementFromAnotherModel($statement, $blankNodes_tmp);
  870. $this->addParsedNamespaces($model->getParsedNamespaces());
  871.  
  872. $this->dbConn->completeTrans();
  873. }
  874.  
  875. elseif (is_a($model, ''DbModel'')) {
  876.  
  877. $this->dbConn->startTrans();
  878. $memModel =& $model->getMemModel();
  879. foreach($memModel->triples as $statement)
  880. $this->_addStatementFromAnotherModel($statement, $blankNodes_tmp);
  881. $this->addParsedNamespaces($model->getParsedNamespaces());
  882. $this->dbConn->completeTrans();
  883. }
  884. }
  885.  
  886.  
  887. /**
  888. * Reify the DbModel.
  889. * Return a new MemModel that contains the reifications of all statements of this DbModel.
  890. *
  891. * @return object MemModel
  892. * @access public
  893. */
  894. function & reify() {
  895.  
  896. $memModel =& $this->getMemModel();
  897. return $memModel->reify();
  898. }
  899.  
  900. /**
  901. * Remove this DbModel from database and clean up.
  902. * This function monitors for SQL errors, and will commit if no errors have occured,
  903. * otherwise it will rollback.
  904. *
  905. * @throws SqlError
  906. * @access public
  907. */
  908. function delete() {
  909.  
  910. $this->dbConn->startTrans();
  911. $this->dbConn->execute(''DELETE FROM models
  912. WHERE modelID='' .$this->modelID);
  913. $this->dbConn->execute(''DELETE FROM statements
  914. WHERE modelID='' .$this->modelID);
  915.  
  916. if (!$this->dbConn->completeTrans())
  917. echo $this->dbConn->errorMsg();
  918. else
  919. $this->close();
  920. }
  921.  
  922.  
  923. /**
  924. * Close this DbModel
  925. *
  926. * @access public
  927. */
  928. function close() {
  929.  
  930. unset($this);
  931. }
  932.  
  933.  
  934. // =============================================================================
  935. // **************************** private methods ********************************
  936. // =============================================================================
  937.  
  938.  
  939.  
  940.  
  941.  
  942. /**
  943. * If the URI doesn''t end with # : or /, then a # is added to the URI.
  944. * Used at setting the baseURI of this DbModel.
  945. *
  946. * @param string $uri
  947. * @return string
  948. * @access private
  949. */
  950. function _checkBaseURI($uri) {
  951.  
  952. if ($uri != NULL) {
  953. $c = substr($uri, strlen($uri)-1 ,1);
  954. if (!($c==''#'' || $c=='':'' || $c==''/'' || $c=="\\"))
  955. $uri .= ''#'';
  956. }
  957. return $uri;
  958. }
  959.  
  960.  
  961. /**''
  962. * Return the flag of the Node object.
  963. * r - Resource, b - BlankNode, l - Literal
  964. *
  965. * @param object Node $object
  966. * @return string
  967. * @access private
  968. */
  969. function _getNodeFlag($object) {
  970.  
  971. return is_a($object,''BlankNode'')?''b'':(is_a($object,''Resource'')?''r'':''l'');
  972. }
  973.  
  974.  
  975. /**
  976. * Convert an ADORecordSet to a memory Model.
  977. *
  978. * Every successful database query returns an ADORecordSet object which is actually
  979. * a cursor that holds the current row in the array fields[].
  980. * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  981. * !!! This method can only be applied to a RecordSet with array fields[]
  982. * !!! containing a representation of the database table: statements,
  983. * !!! with an index corresponding to following table columns:
  984. * !!! [0] - subject, [1] - predicate, [2] - object, [3] - l_language,
  985. * !!! [4] - l_datatype, [5] - subject_is, [6] - object_is
  986. * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  987. *
  988. * @param object ADORecordSet
  989. * @return object MemModel
  990. * @access private
  991. */
  992. function _convertRecordSetToMemModel(&$recordSet) {
  993.  
  994. $res = new MemModel($this->baseURI);
  995. while (!$recordSet->EOF) {
  996.  
  997. // subject
  998. if ($recordSet->fields[5] == ''r'')
  999. $sub = new Resource($recordSet->fields[0]);
  1000. else
  1001. $sub = new BlankNode($recordSet->fields[0]);
  1002.  
  1003. // predicate
  1004. $pred = new Resource($recordSet->fields[1]);
  1005.  
  1006. // object
  1007. if ($recordSet->fields[6] == ''r'')
  1008. $obj = new Resource($recordSet->fields[2]);
  1009. elseif ($recordSet->fields[6] == ''b'')
  1010. $obj = new BlankNode($recordSet->fields[2]);
  1011. else {
  1012. $obj = new Literal($recordSet->fields[2], $recordSet->fields[3]);
  1013. if ($recordSet->fields[4])
  1014. $obj->setDatatype($recordSet->fields[4]);
  1015. }
  1016.  
  1017. $statement = new Statement($sub, $pred, $obj);
  1018. $res->add($statement);
  1019.  
  1020. $recordSet->moveNext();
  1021. }
  1022. $res->addParsedNamespaces($this->getParsedNamespaces());
  1023. return $res;
  1024. }
  1025.  
  1026.  
  1027. /**
  1028. * Create the dynamic part of an sql statement selecting triples with the
  1029. * given parameters ($subject, $predicate, $object).
  1030. *
  1031. * @param object Resource $subject
  1032. * @param object Resource $predicate
  1033. * @param object Node $object
  1034. * @return string
  1035. * @access private
  1036. */
  1037. function _createDynSqlPart_SPO($subject, $predicate, $object) {
  1038.  
  1039. // conditions derived from the parameters passed to the function
  1040. $subject_is=is_a($subject,''BlankNode'')?''b'':(is_a($subject,''Resource'')?''r'':''l'');
  1041. $sql='''';
  1042. if ($subject != NULL)
  1043. $sql .= " AND subject=''" .$subject->getLabel() ."''
  1044. AND subject_is=''" .$subject_is ."''";
  1045. if ($predicate != NULL)
  1046. $sql .= " AND predicate=''" .$predicate->getLabel() ."''";
  1047. if ($object != NULL) {
  1048. $object_is = is_a($object,''BlankNode'')?''b'':(is_a($object,''Resource'')?''r'':''l'');
  1049. if (is_a($object, ''Resource''))
  1050. $sql .= " AND object=''" .$object->getLabel() ."''
  1051. AND object_is =''" .$object_is ."''";
  1052. else {
  1053. $quotedLiteral = $this->dbConn->qstr($object->getLabel());
  1054. $sql .= " AND object=" .$quotedLiteral ."
  1055. AND l_language=''" .$object->getLanguage() ."''
  1056. AND l_datatype=''" .$object->getDataType() ."''
  1057. AND object_is =''" .$object_is ."''";
  1058. }
  1059. }
  1060. return $sql;
  1061. }
  1062.  
  1063.  
  1064. /**
  1065. * Get an ADORecordSet with array fields[] containing a representation of
  1066. * the given DbModel stored in the table: statements, with an index corresponding
  1067. * to following table columns:
  1068. * [0] - subject, [1] - predicate, [2] - object, [3] - l_language,
  1069. * [4] - l_datatype, [5] - subject_is, [6] - object_is
  1070. * (This method operates on data from a DbModel without loading it into a memory model
  1071. * in order to save resources and improve speed).
  1072. *
  1073. * @param object DbModel $DbModel
  1074. * @return object ADORecordSet
  1075. * @access private
  1076. */
  1077. function _getRecordSet (&$dbModel) {
  1078.  
  1079. $sql = ''SELECT subject, predicate, object, l_language, l_datatype, subject_is, object_is
  1080. FROM statements
  1081. WHERE modelID = '' .$dbModel->modelID;
  1082.  
  1083. return $recordSet =& $this->dbConn->execute($sql);
  1084. }
  1085.  
  1086.  
  1087. /**
  1088. * Check if this DbModel contains the given row from the array fields[] of an ADORecordSet
  1089. * The array index corresponds to following table columns:
  1090. * [0] - subject, [1] - predicate, [2] - object, [3] - l_language,
  1091. * [4] - l_datatype, [5] - subject_is, [6] - object_is
  1092. *
  1093. * @param array $row
  1094. * @return boolean
  1095. * @access private
  1096. */
  1097. function _containsRow ($row) {
  1098.  
  1099. $quotedObject = $this->dbConn->qstr($row[2]);
  1100. $sql = "SELECT modelID FROM statements
  1101. WHERE modelID = " .$this->modelID ."
  1102. AND subject =''" .$row[0] ."''
  1103. AND predicate =''" .$row[1] ."''
  1104. AND object =" .$quotedObject ."
  1105. AND l_language=''" .$row[3] ."''
  1106. AND l_datatype=''" .$row[4] ."''
  1107. AND subject_is=''" .$row[5] ."''
  1108. AND object_is=''" .$row[6] ."''";
  1109.  
  1110. $res =& $this->dbConn->getOne($sql);
  1111.  
  1112. if (!$res)
  1113. return FALSE;
  1114. return TRUE;
  1115. }
  1116.  
  1117.  
  1118.  
  1119.  
  1120.  
  1121. /**
  1122. * Returns the models namespaces.
  1123. *
  1124. * @author Tobias Gauß <tobias.gauss@web.de>
  1125. * @access public
  1126. * @return Array
  1127. */
  1128. function getParsedNamespaces(){
  1129. $sql = "SELECT * FROM namespaces
  1130. WHERE modelID = " .$this->modelID;
  1131. $temp=false;
  1132. $res = $this->dbConn->execute($sql);
  1133. if($res){
  1134. while (!$res->EOF) {
  1135. $temp[$res->fields[1]]=$res->fields[2];
  1136. $res->moveNext();
  1137. }
  1138. }
  1139. return $temp;
  1140. }
  1141.  
  1142.  
  1143.  
  1144. /**
  1145. * Adds the namespaces to the model. This method is called by
  1146. * the parser. !!!! addParsedNamespaces() not overwrites manual
  1147. * added namespaces in the model !!!!
  1148. *
  1149. * @author Tobias Gauß <tobias.gauss@web.de>
  1150. * @access public
  1151. * @param Array $newNs
  1152. */
  1153. function addParsedNamespaces($newNs){
  1154. if($newNs)
  1155. foreach($newNs as $namespace => $prefix){
  1156. $this->addNamespace($prefix, $namespace);
  1157. }
  1158. }
  1159.  
  1160.  
  1161. /**
  1162. * Adds a namespace and prefix to the model.
  1163. *
  1164. * @author Tobias Gauß <tobias.gauss@web.de>
  1165. * @access public
  1166. * @param String $prefix, String $nmsp
  1167. */
  1168. function addNamespace($prefix,$nmsp){
  1169.  
  1170. if($nmsp != '''' && $prefix !=''''){
  1171. if($this->_checkNamespace($nmsp)){
  1172. $sql = "UPDATE namespaces SET prefix=''".$prefix."'' WHERE
  1173. modelID=".$this->modelID." AND namespace=''".$nmsp."''";
  1174. }else{
  1175. $sql = "INSERT INTO namespaces VALUES
  1176. (" .$this->modelID .","
  1177. ."''" .$nmsp ."'',"
  1178. ."''" .$prefix."'')";
  1179. }
  1180.  
  1181. $rs =& $this->dbConn->execute($sql);
  1182. if (!$rs)
  1183. $this->dbConn->errorMsg();
  1184. }
  1185. }
  1186.  
  1187. /**
  1188. * checks if a namespace is already in the model.
  1189. *
  1190. * @author Tobias Gauß <tobias.gauss@web.de>
  1191. * @access private
  1192. * @param Array $newNs
  1193. */
  1194. function _checkNamespace($nmsp){
  1195. $res = true;
  1196. $sql = "SELECT * FROM namespaces
  1197. WHERE modelID = " .$this->modelID." AND
  1198. namespace=''".$nmsp."''" ;
  1199. $rs =& $this->dbConn->execute($sql);
  1200. if (!$rs){
  1201. $this->dbConn->errorMsg();
  1202. }else{
  1203. if($rs->fields == false)
  1204. $res = false;
  1205. }
  1206. return $res;
  1207.  
  1208.  
  1209. }
  1210.  
  1211.  
  1212. /**
  1213. * removes a single namespace from the model
  1214. *
  1215. * @author Tobias Gauß <tobias.gauss@web.de>
  1216. * @access public
  1217. * @param String $nmsp
  1218. */
  1219. function removeNamespace($nmsp){
  1220.  
  1221. $sql = ''DELETE FROM namespaces
  1222. WHERE modelID='' .$this->modelID." AND namespace=''".$nmsp."''";
  1223.  
  1224. $rs =& $this->dbConn->execute($sql);
  1225. if (!$rs)
  1226. $this->dbConn->errorMsg();
  1227. }
  1228.  
  1229.  
  1230.  
  1231.  
  1232. /**
  1233. * Add the given row from the array fields[] of an ADORecordSet to this DbModel
  1234. * The array index corresponds to following table columns:
  1235. * [0] - subject, [1] - predicate, [2] - object, [3] - l_language,
  1236. * [4] - l_datatype, [5] - subject_is, [6] - object_is
  1237. *
  1238. * @param array $row
  1239. * @throws SqlError
  1240. * @access private
  1241. *
  1242. function _insertRow ($row) {
  1243.  
  1244. $quotedObject = $this->dbConn->qstr($row[2]);
  1245. $sql = "INSERT INTO statements VALUES
  1246. (" .$this->modelID .","
  1247. ."''" .$row[0] ."'',"
  1248. ."''" .$row[1] ."'',"
  1249. ."" .$quotedObject .","
  1250. ."''" .$row[3] ."'',"
  1251. ."''" .$row[4] ."'',"
  1252. ."''" .$row[5] ."'',"
  1253. ."''" .$row[6] ."'')";
  1254.  
  1255. $rs =& $this->dbConn->execute($sql);
  1256. if (!$rs)
  1257. $this->dbConn->errorMsg();
  1258. }
  1259. */
  1260.  
  1261. } // end: Class DbModel
  1262. ?>

Documentation generated on Fri, 13 Jan 2006 07:48:08 +0100 by phpDocumentor 1.3.0RC4