Source for file DbModel.php

Documentation is available at DbModel.php

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

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