Source for file Model.php

Documentation is available at Model.php

  1. <?php
  2.  
  3. // ----------------------------------------------------------------------------------
  4. // Class: Model
  5. // ----------------------------------------------------------------------------------
  6.  
  7.  
  8.  
  9. /**
  10. * Abstract superclass of MemModel and DbModel. A model is a programming interface to an RDF graph.
  11. * An RDF graph is a directed labeled graph, as described in http://www.w3.org/TR/rdf-mt/.
  12. * It can be defined as a set of <S, P, O> triples, where P is a uriref, S is either
  13. * a uriref or a blank node, and O is either a uriref, a blank node, or a literal.
  14. *
  15. * <BR><BR>History:<UL>
  16. * <LI>12-06-2004 : Functions findForward() and getMemModelByRDQL() added. (anton1@koestlbacher.de) </LI>
  17. * <LI>10-30-2004 : GRDDL-Support (see http://www.w3.org/TR/grddl/) added. (tobias.gauss@web.de) </LI>
  18. * <LI>09-22-2004 : Function getUniqueResourceURI(): default bNode prefix is used,
  19. * if no other is defined. Returns unique URIs, without checking the model first.
  20. * <LI>09-07-2004 : Function load improved. (auer@informatik.uni-leipzig.de)</LI>
  21. * <LI>03-26-2004 : _addStatementFromAnotherModel() added
  22. * : saveAs() moved to the child classes</LI>
  23. * <LI>11-13-2003 : Function saveAs added
  24. * <LI>07-27-2003 : This is an abstract parent class for MemModel and DbModel.
  25. * The previous class Model has been renamed to MemModel
  26. *
  27. *
  28. *
  29. * @version V0.9.1
  30. * @author Radoslaw Oldakowski <radol@gmx.de>
  31. * @author Daniel Westphal <mail@d-westphal.de>
  32. *
  33. * @package model
  34. * @access public
  35. */
  36.  
  37. Class Model extends Object {
  38.  
  39.  
  40. /**
  41. * Base URI of the Model.
  42. * Affects creating of new resources and serialization syntax.
  43. *
  44. * @var string
  45. * @access private
  46. */
  47. var $baseURI;
  48.  
  49. /**
  50. * Number of the last assigned bNode.
  51. *
  52. *
  53. * @var integer
  54. * @access private
  55. */
  56. var $bNodeCount;
  57.  
  58. /**
  59. * Notice for people who are used to work with older versions of RAP.
  60. *
  61. * @throws PHPError
  62. * @access public
  63. */
  64. function Model() {
  65.  
  66. $errmsg = 'Since RAP 0.6 the class for manipulating memory models has been renamed to MemModel.';
  67. $errmsg .= '<br>Sorry for this inconvenience.<br>';
  68.  
  69. trigger_error($errmsg, E_USER_ERROR);
  70. }
  71.  
  72.  
  73. /**
  74. * Return current baseURI.
  75. *
  76. * @return string
  77. * @access public
  78. */
  79. function getBaseURI() {
  80.  
  81. return $this->baseURI;
  82. }
  83.  
  84. /**
  85. * Load a model from a file containing RDF, N3, N-Triples or a xhtml document containing RDF.
  86. * This function recognizes the suffix of the filename (.n3 or .rdf) and
  87. * calls a suitable parser, if no $type is given as string ("rdf" "n3" "nt");
  88. * If the model is not empty, the contents of the file is added to this DbModel.
  89. *
  90. * @param string $filename
  91. * @param string $type
  92. * @param boolean $stream
  93. * @access public
  94. */
  95. function load($filename, $type = NULL, $stream=false) {
  96. if ((isset($type)) && ($type =='n3') OR ($type =='nt')) {
  97. // Import Package Syntax
  98. include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_N3);
  99. $parser = new N3Parser();
  100. }elseif ((isset($type)) && ($type =='rdf')) {
  101. // Import Package Syntax
  102. include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
  103. $parser = new RdfParser();
  104. }elseif ((isset($type)) && ($type =='grddl')) {
  105. // Import Package Syntax
  106. include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_GRDDL);
  107. $parser = new GRDDLParser();
  108. }else {
  109. // create a parser according to the suffix of the filename
  110. // if there is no suffix assume the file to be XML/RDF
  111. preg_match("/\.([a-zA-Z0-9_]+)$/", $filename, $suffix);
  112. if (isset($suffix[1]) && (strtolower($suffix[1]) == 'n3' OR strtolower($suffix[1]) == 'nt')){
  113. // Import Package Syntax
  114. include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_N3);
  115. $parser = new N3Parser();
  116. }elseif (isset($suffix[1]) && (strtolower($suffix[1]) == 'htm' OR strtolower($suffix[1]) == 'html' OR strtolower($suffix[1]) == 'xhtml')){
  117. include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_GRDDL);
  118. $parser = new GRDDLParser();
  119. }else{
  120. // Import Package Syntax
  121. include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
  122. $parser = new RdfParser();}
  123. };
  124. if(($stream && $type=='rdf')||($stream && $type=='n3'))
  125. $temp=&$parser->generateModel($filename,false,$this);
  126. else{
  127. $temp=&$parser->generateModel($filename);
  128. }
  129. $this->addModel($temp);
  130. if($this->getBaseURI()== null)
  131. $this->setBaseURI($temp->getBaseURI());
  132. }
  133.  
  134.  
  135. /**
  136. * Adds a statement from another model to this model.
  137. * If the statement to be added contains a blankNode with an identifier
  138. * already existing in this model, a new blankNode is generated.
  139. *
  140. * @param Object Statement $statement
  141. * @access private
  142. */
  143. function _addStatementFromAnotherModel($statement, &$blankNodes_tmp) {
  144. $subject = $statement->getSubject();
  145. $object = $statement->getObject();
  146. if (is_a($subject, "BlankNode")) {
  147. $label = $subject->getLabel();
  148. if (!array_key_exists($label, $blankNodes_tmp))
  149. {
  150. if ($this->findFirstMatchingStatement($subject, NULL, NULL)
  151. || $this->findFirstMatchingStatement(NULL, NULL, $subject))
  152. {
  153. $blankNodes_tmp[$label] = new BlankNode($this);
  154. $statement->subj = $blankNodes_tmp[$label];
  155. } else {
  156. $blankNodes_tmp[$label] = $subject;
  157. }
  158. } else
  159. $statement->subj = $blankNodes_tmp[$label];
  160. }
  161.  
  162. if (is_a($object, "BlankNode")) {
  163. $label = $object->getLabel();
  164. if (!array_key_exists($label, $blankNodes_tmp))
  165. {
  166. if ($this->findFirstMatchingStatement($object, NULL, NULL)
  167. || $this->findFirstMatchingStatement(NULL, NULL, $object))
  168. {
  169. $blankNodes_tmp[$label] = new BlankNode($this);
  170. $statement->obj = $blankNodes_tmp[$label];
  171. } else {
  172. $blankNodes_tmp[$label] = $object;
  173. }
  174. } else
  175. $statement->obj = $blankNodes_tmp[$label];
  176. }
  177. $this->add($statement);
  178. }
  179. /**
  180. * Internal method, that returns a resource URI that is unique for the Model.
  181. * URIs are generated using the base_uri of the DbModel, the prefix and a unique number.
  182. * If no prefix is defined, the bNode prefix, defined in constants.php, is used.
  183. *
  184. * @param string $prefix
  185. * @return string
  186. * @access private
  187. */
  188. function getUniqueResourceURI($prefix = false)
  189. {
  190. static $bNodeCount;
  191. if(!$bNodeCount)
  192. $bNodeCount = 0;
  193. if(!$prefix)
  194. $prefix=BNODE_PREFIX;
  195. return $prefix.++$bNodeCount;
  196. }
  197.  
  198. /**
  199. * Returns a ResModel with this model as baseModel.
  200. *
  201. * @param constant $modelType
  202. * @param string $baseURI
  203. * @return object MemModel
  204. * @access public
  205. */
  206. function & getResmodel()
  207. {
  208. require_once( RDFAPI_INCLUDE_DIR . PACKAGE_RESMODEL);
  209. return new ResModel($this);
  210. }
  211. /**
  212. * Returns an OntModel with this model as baseModel.
  213. * $vocabulary has to be one of the following constants (currently only one is supported):
  214. * RDFS_VOCABULARY to select a RDFS Vocabulary.
  215. * You can supply a base URI
  216. *
  217. * @param constant $vocabulary
  218. * @return object OntModel
  219. * @access public
  220. */
  221. function & getOntModel($vocabulary)
  222. {
  223. require_once( RDFAPI_INCLUDE_DIR . PACKAGE_ONTMODEL);
  224. return new OntModel(& $this, $vocab);
  225. }
  226. /**
  227. * Searches for triples using find() and tracks forward blank nodes
  228. * until the final objects in the retrieved subgraphs are all named resources.
  229. * The method calls itself recursivly until the result is complete.
  230. * NULL input for subject, predicate or object will match anything.
  231. * Inputparameters are ignored for recursivly found statements.
  232. * Returns a new MemModel or adds (without checking for duplicates)
  233. * the found statements to a given MemModel.
  234. * Returns an empty MemModel, if nothing is found.
  235. * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  236. * WARNING: This method can be slow with large models.
  237. * NOTE: Blank nodes are not renamed, they keep the same nodeIDs
  238. * as in the queried model!
  239. * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  240. *
  241. * @author Anton Köstlbacher <anton1@koestlbacher.de>
  242. * @param object Node $subject
  243. * @param object Node $predicate
  244. * @param object Node $object
  245. * @param object MemModel $object
  246. * @return object MemModel
  247. * @access public
  248. * @throws PhpError
  249. */
  250.  
  251. function findForward($subject, $predicate, $object, $newModel = NULL)
  252. {
  253. if (!is_a($newModel, "MemModel"))
  254. {
  255. $newModel = New MemModel;
  256. }
  257.  
  258. if (is_a($this, "DbModel"))
  259. {
  260. $model = $this;
  261. $res = $model->find($subject, $predicate, $object);
  262. $it = $res->getStatementIterator();
  263. }
  264. elseif (is_a($this, "MemModel")) {
  265. $model = $this;
  266. $it = $model->findAsIterator($subject, $predicate, $object);
  267. }
  268. elseif (is_a($this, "ResModel")) {
  269. $model = $this->model;
  270. $it = $model->findAsIterator($subject, $predicate, $object);
  271. }
  272.  
  273. while ($it->hasNext())
  274. {
  275. $statement = $it->next();
  276. $newModel->add($statement);
  277. if (is_a($statement->object(),'BlankNode'))
  278. {
  279. $model->findForward($statement->object(), NULL, NULL,&$newModel);
  280. }
  281. }
  282. return $newModel;
  283. }
  284.  
  285.  
  286. /**
  287. * Perform an RDQL query on this Model. Should work with all types of models.
  288. * This method returns a MemModel containing the result statements.
  289. * If $closure is set to TRUE, the result will additionally contain
  290. * statements found by the findForward-method for blank nodes.
  291. * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  292. * WARNING: If called with $closure = TRUE this method
  293. * can be slow with large models.
  294. * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  295. *
  296. * @author Anton Köstlbacher <anton1@koestlbacher.de>
  297. * @author code snippets taken from the RAP Netapi by Phil Dawes and Chris Bizer
  298. * @access public
  299. * @param string $queryString
  300. * @param boolean $closure
  301. * @return object MemModel
  302. *
  303. */
  304.  
  305. function & getMemModelByRDQL($queryString, $closure = FALSE)
  306. {
  307. require_once(RDFAPI_INCLUDE_DIR.PACKAGE_RDQL);
  308. $parser = new RdqlParser();
  309. $parsedQuery =& $parser->parseQuery($queryString);
  310.  
  311. // If there are variables used in the pattern but not
  312. // in the select clause, add them to the select clause
  313. foreach ($parsedQuery['patterns'] as $n => $pattern)
  314. {
  315. foreach ($pattern as $key => $val_1)
  316. {
  317. if ($val_1['value']{0}=='?')
  318. {
  319. if (!in_array($val_1['value'],$parsedQuery['selectVars']))
  320. {
  321. array_push($parsedQuery['selectVars'],$val_1['value']);
  322. }
  323. }
  324. }
  325. }
  326.  
  327. if (is_a($this, "DbModel"))
  328. {
  329. $engine = new RdqlDbEngine();
  330. $model = $this;
  331. }
  332. elseif (is_a($this, "MemModel"))
  333. {
  334. $engine = new RdqlMemEngine();
  335. $model = $this;
  336. }
  337. elseif (is_a($this, "ResModel"))
  338. {
  339. $engine = new RdqlMemEngine();
  340. $model = $this->model;
  341. }
  342.  
  343. $res = $engine->queryModel($model,$parsedQuery,TRUE);
  344. $rdqlIter = new RdqlResultIterator($res);
  345. $newModel = new MemModel();
  346.  
  347. // Build statements from RdqlResultIterator
  348. while ($rdqlIter->hasNext()) {
  349. $result = $rdqlIter->next();
  350. foreach ($parsedQuery['patterns'] as $n => $pattern)
  351. {
  352. if (substr($pattern['subject']['value'], 0, 1) == '?')
  353. {
  354. $subj = $result[$pattern['subject']['value']];
  355. }
  356. else
  357. {
  358. $subj = new Resource($pattern['subject']['value']);
  359. }
  360. if (substr($pattern['predicate']['value'], 0, 1) == '?')
  361. {
  362. $pred = $result[$pattern['predicate']['value']];
  363. }
  364. else
  365. {
  366. $pred = new Resource($pattern['predicate']['value']);
  367. }
  368.  
  369. if (substr($pattern['object']['value'], 0, 1) == '?')
  370. {
  371. $obj = $result[$pattern['object']['value']];
  372. }
  373. else
  374. {
  375. if ($pattern['object']['is_literal'])
  376. {
  377. $obj = new Literal($pattern['object']['value']);
  378. $obj->setDatatype($pattern['object']['l_dtype']);
  379. $obj->setLanguage($pattern['object']['l_lang']);
  380. }
  381. else
  382. {
  383. $obj = new Resource($pattern['object']['value']);
  384. }
  385. }
  386.  
  387. $statement = new Statement($subj,$pred,$obj);
  388. $newModel->add($statement);
  389.  
  390. // findForward() Statements containing an eventually given blank node
  391. // and add them to the result, if closure = true
  392. if (is_a($statement->object(),'BlankNode') && $closure == True)
  393. {
  394. $newModel = $model->findForward($statement->object(),NULL,NULL,&$newModel);
  395. }
  396. if (is_a($statement->subject(),'BlankNode') && $closure == True)
  397. {
  398. $newModel = $model->findForward($statement->subject(),NULL,NULL,&$newModel);
  399. }
  400. }
  401. }
  402. return $newModel;
  403. }
  404.  
  405.  
  406. } // end: Model
  407.  
  408. ?>

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