]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/SemanticWeb.php
add rcs Log
[SourceForge/phpwiki.git] / lib / SemanticWeb.php
1 <?php rcs_id('$Id: SemanticWeb.php,v 1.10 2007-07-14 12:03:32 rurban Exp $');
2 /**
3  * What to do on ?format=rdf  What to do on ?format=owl
4  *
5  * Map relations on a wikipage to a RDF ressource to build a "Semantic Web" 
6  * - a web ontology frontend compatible to OWL (web ontology language).
7  * http://www.w3.org/2001/sw/Activity
8  * Simple RDF ontologies contain facts and rules, expressed by RDF triples:
9  *   Subject (page) -> Predicate (verb, relation) -> Object (links)
10  * OWL extents that to represent a typical OO framework. 
11  *  OO predicates: 
12  *    is_a, has_a, ...
13  *  OWL predicates:
14  *    subClassOf, restrictedBy, onProperty, intersectionOf, allValuesFrom, ...
15  *    someValuesFrom, unionOf, equivalentClass, disjointWith, ...
16  *    plus the custom vocabulary (ontology): canRun, canBite, smellsGood, ...
17  *  OWL Subjects: Class, Restriction, ...
18  *  OWL Properties: type, label, comment, ...
19  * DAML should also be supported.
20  *
21  * Purpose:
22  * - Another way to represent various KB models in various DL languages. 
23  *   (OWL/DAML/other DL)
24  * - Frontend to various KB model reasoners and representations. 
25  * - Generation/update of static wiki pages based on external OWL/DL/KB 
26  *   (=> ModelTest/Categories)
27  *   KB Blackboard and Visualization.
28  * - OWL generation based on static wiki pages (ModelTest?format=owl)
29  *
30  * Facts: (may be represented by special links on a page)
31  *  - Each page must be representable with an unique URL.
32  *  - Each fact must be representable with an unique RDF triple.
33  *  - A class is represented by a category page.
34  *  - To represent more expressive description logic, "enriched" 
35  *    links will not be enough (? variable symbolic objects).
36  *
37  * Rules: (may be represented by special content on a page)
38  *  - Syntax: reasoner backend specific, or common or ?
39  *
40  * RDF Triple: (representing facts)
41  *   Subject (page) -> Predicate (verb, relation) -> Object (links)
42  * Subject: a page
43  * Verb: 
44  *   Special link qualifiers represent RDF triples, based on RDF standard notation.
45  *   See RDF standard DTD's on daml.org and w3.org, plus your custom predicates. 
46  *   (need your own DTD)
47  *   Example: page [Ape] isa:Animal, ...
48  * Object: special links on a page.
49  * Class: WikiCategory
50  * Model: Basepage for a KB. (parametrizeable pages or copies of modified snapshots?)
51  *
52  * DL: Description Logic
53  * KB: Knowledge Base
54  *
55  * Discussion:
56  * Of course *real* expert systems ("reasoners") will help/must be used in
57  * optimization and maintainance of the SemanticWeb KB (Knowledge
58  * Base). Hooks will be tested to KM (an interactive KB playground),
59  * LISA (standard unifier), FaCT, RACER, ... 
60
61  * Maybe also ZEBU (parser generator) is needed to convert the wiki KB
62  * syntax to the KB reasoner backend (LISA, KM, CLIPS, JESS, FaCT,
63  * ...) and forth.
64
65  * pOWL is a simple php backend with some very simple AI logic in PHP,
66  * though I strongly doubt the usefulness of reasoners not written in
67  * Common Lisp.
68  *
69  * SEAL (omntoweb.org) is similar to that, just on top of the Zope CMF.
70  * FaCT uses e.g. this KB DTD:
71 <!ELEMENT KNOWLEDGEBASE (DEFCONCEPT|DEFROLE|IMPLIESC|EQUALC|IMPLIESR|EQUALR|TRANSITIVE|FUNCTIONAL)*> 
72 <!ELEMENT CONCEPT (PRIMITIVE|TOP|BOTTOM|AND|OR|NOT|SOME|ALL|ATMOST|ATLEAST)> 
73 <!ELEMENT ROLE (PRIMROLE|INVROLE)> 
74 ... (facts and rules described in XML)
75  *
76  * Links:
77  *   http://phpwiki.org/SemanticWeb, 
78  *   http://en.wikipedia.org/wiki/Knowledge_representation
79  *   http://www.ontoweb.org/
80  *   http://www.semwebcentral.org/ (OWL on top of GForge)
81  *
82  *
83  * Author: Reini Urban <rurban@x-ray.at>
84  */
85 /*============================================================================*/
86 /*
87  Copyright 2004,2007 Reini Urban
88
89  This file is part of PhpWiki.
90
91  PhpWiki is free software; you can redistribute it and/or modify
92  it under the terms of the GNU General Public License as published by
93  the Free Software Foundation; either version 2 of the License, or
94  (at your option) any later version.
95
96  PhpWiki is distributed in the hope that it will be useful,
97  but WITHOUT ANY WARRANTY; without even the implied warranty of
98  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
99  GNU General Public License for more details.
100
101  You should have received a copy of the GNU General Public License
102  along with PhpWiki; if not, write to the Free Software
103  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
104  */
105
106 require_once('lib/RssWriter.php');
107 require_once('lib/TextSearchQuery.php');
108 require_once('lib/Units.php');
109
110
111 /**
112  * RdfWriter - A class to represent a single(?) wikipage as RDF. Supports ?format=rdf
113  *
114  * RdfWriter
115  *  - RssWriter
116  *    - RecentChanges (RecentChanges?format=rss)
117  *      channel: ... item: ...
118  */
119 class RdfWriter extends RssWriter // in fact it should be rewritten to be other way round.
120 {
121     function RdfWriter () {
122         $this->XmlElement('rdf:RDF',
123                           array('xmlns' => "http://purl.org/rss/1.0/",
124                                 'xmlns:rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'));
125
126         $this->_modules = array(
127             //Standards
128             'content'   => "http://purl.org/rss/1.0/modules/content/",
129             'dc'        => "http://purl.org/dc/elements/1.1/",
130             );
131
132         $this->_uris_seen = array();
133         $this->_items = array();
134
135         $this->wiki_xmlns_xml = WikiURL(_("URIResolver")."/",false,true);
136         $this->wiki_xmlns_url = PHPWIKI_BASE_URL;
137
138         $this->pre_ns_buffer =
139             "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" .
140             "<!DOCTYPE rdf:RDF[\n" .
141             "\t"."<!ENTITY rdf 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'>\n" .
142             "\t"."<!ENTITY rdfs 'http://www.w3.org/2000/01/rdf-schema#'>\n" .
143             "\t"."<!ENTITY owl 'http://www.w3.org/2002/07/owl#'>\n" .
144             "\t"."<!ENTITY smw 'http://smw.ontoware.org/2005/smw#'>\n" .
145             "\t"."<!ENTITY smwdt 'http://smw.ontoware.org/2005/smw-datatype#'>\n" .
146             // A note on "wiki": this namespace is crucial as a fallback when it would be illegal to start e.g. with a number. In this case, one can always use wiki:... followed by "_" and possibly some namespace, since _ is legal as a first character.
147             "\t"."<!ENTITY wiki '" . $this->wiki_xmlns_xml .  "'>\n" .
148             "\t"."<!ENTITY relation '" . $this->wiki_xmlns_xml .
149             $this->makeXMLExportId(urlencode(str_replace(' ', '_', _("Relation") . ':'))) .  "'>\n" .
150             "\t"."<!ENTITY attribute '" . $this->wiki_xmlns_xml .
151             $this->makeXMLExportId(urlencode(str_replace(' ', '_', _("Attribute") . ':'))) .  "'>\n" .
152             "\t"."<!ENTITY wikiurl '" . $this->wiki_xmlns_url .  "'>\n" .
153             "]>\n\n" .
154             "<rdf:RDF\n" .
155             "\t"."xmlns:rdf=\"&rdf;\"\n" .
156             "\t"."xmlns:rdfs=\"&rdfs;\"\n" .
157             "\t"."xmlns:owl =\"&owl;\"\n" .
158             "\t"."xmlns:smw=\"&smw;\"\n" .
159             "\t"."xmlns:wiki=\"&wiki;\"\n" .
160             "\t"."xmlns:relation=\"&relation;\"\n" .
161             "\t"."xmlns:attribute=\"&attribute;\"";
162         $this->post_ns_buffer =
163             "\n\t<!-- reference to the Semantic MediaWiki schema -->\n" .
164             "\t"."<owl:AnnotationProperty rdf:about=\"&smw;hasArticle\">\n" .
165             "\t\t"."<rdfs:isDefinedBy rdf:resource=\"http://smw.ontoware.org/2005/smw\"/>\n" .
166             "\t"."</owl:AnnotationProperty>\n" .
167             "\t"."<owl:AnnotationProperty rdf:about=\"&smw;hasType\">\n" .
168             "\t\t"."<rdfs:isDefinedBy rdf:resource=\"http://smw.ontoware.org/2005/smw\"/>\n" .
169             "\t"."</owl:AnnotationProperty>\n" .
170             "\t"."<owl:Class rdf:about=\"&smw;Thing\">\n" .
171             "\t\t"."<rdfs:isDefinedBy rdf:resource=\"http://smw.ontoware.org/2005/smw\"/>\n" .
172             "\t"."</owl:Class>\n" .
173             "\t<!-- exported page data -->\n";
174     }
175
176     function format() {
177         header( "Content-type: application/rdf+xml; charset=UTF-8" );
178         echo $this->pre_ns_buffer;
179         echo ">\n";
180         echo $this->post_ns_buffer;
181         echo "</rdf:RDF>\n";
182     }
183
184         /** This function transforms a valid url-encoded URI into a string
185          *  that can be used as an XML-ID. The mapping should be injective.
186          */
187         function makeXMLExportId($uri) {
188                 $uri = str_replace( '-', '-2D', $uri);
189                 //$uri = str_replace( ':', '-3A', $uri); //already done by PHP
190                 //$uri = str_replace( '_', '-5F', $uri); //not necessary
191                 $uri = str_replace( array('"','#','&',"'",'+','%'),
192                                     array('-22','-23','-26','-27','-2B','-'),
193                                     $uri);
194                 return $uri;
195         }
196
197         /** This function transforms an XML-ID string into a valid
198          *  url-encoded URI. This is the inverse to makeXMLExportID.
199          */
200         function makeURIfromXMLExportId($id) {
201                 $id = str_replace( array('-22','-23','-26','-27','-2B','-'),
202                                    array('"','#','&',"'",'+','%'),
203                                    $id);
204                 $id = str_replace( '-2D', '-', $id);
205                 return $id;
206         }
207 }
208
209 /**
210  * OwlWriter - A class to represent a set of wiki pages (a DL model) as OWL.
211  * Requires an actionpage returning a pagelist.
212  * Supports ?format=owl
213  *
214  * OwlWriter
215  *  - RdfWriter
216  *  - Reasoner
217 */
218 class OwlWriter extends RdfWriter {
219 };
220
221 /**
222  * ModelWriter - Export a KB as set of wiki pages. 
223  * Requires an actionpage returning a pagelist.
224  * Probably based on some convenient DL expression syntax. (deffact, defrule, ...)
225  *
226  * ModelWriter
227  *  - OwlWriter
228  *  - ReasonerBackend
229 */
230 class ModelWriter extends OwlWriter {
231 };
232
233 /**
234  *  NumericSearchQuery can do: 
235  *         ("population < 20000 and area > 1000000", array("population", "area"))
236  *  ->match(array('population' => 100000, 'area' => 10000000)) 
237  * @see NumericSearchQuery
238  *
239  *  SemanticAttributeSearchQuery can detect and unify units in numbers.
240  *         ("population < 2million and area > 100km2", array("population", "area"))
241  *  ->match(array('population' => 100000, 'area' => 10000000))
242  *
243  * Do we need a real parser or can we just regexp over some allowed unit 
244  * suffixes to detect the numbers?
245  * See man units(1) and /usr/share/units.dat
246  * base units: $ units "1 million miles"
247  *                     Definition: 1.609344e+09 m
248  */
249 class SemanticAttributeSearchQuery
250 extends NumericSearchQuery
251 {
252     /*
253     var $base_units = array('m'   => explode(',','km,miles,cm,dm,mm,ft,inch,inches,meter'),
254                             'm^2' => explode(',','km^2,ha,cm^2,mi^2'),
255                             'm^3' => explode(',','km^3,lit,cm^3,dm^3,gallons'),
256                             );
257     */
258
259     /**
260      * We need to detect units from the freetext query:
261      * population > 1 million
262      */
263     function SemanticAttributeSearchQuery($search_query, $placeholders, $unit = '') {
264         $this->NumericSearchQuery($search_query, $placeholders);
265         $this->_units = new Units();
266         $this->unit = $unit;
267     }
268
269     /**
270      * Strip non-numeric chars from the variable (as the groupseperator) and replace 
271      * it in the symbolic query for evaluation.
272      * This version unifies the attribute values from the database to a 
273      * numeric basevalue before comparison. (area:=963.6km^2 => 9.366e+08 m^2)
274      *
275      * @access private
276      * @param $value number   A numerical value: integer, float or string.
277      * @param $x string       The variable name to be replaced in the query.
278      * @return string
279      */
280     function _bind($value, $x) {
281         $ori_value = $value;
282         $value = preg_replace("/,/", "", $value);
283         $this->_bound[] = array('linkname'  => $x,
284                                 'linkvalue' => $value);
285         // We must ensure that the same baseunits are matched against. 
286         // We cannot compare m^2 to m or ''
287         $val_base = $this->_units->basevalue($value);
288         if (!DISABLE_UNITS and $this->_units->baseunit($value) != $this->unit) {
289             // Poor user has selected an attribute, but no unit. assume he means the baseunit
290             if (count($this->getVars() == 1) and $this->unit == '') {
291                 ;
292             } else {
293                 // non-matching units are silently ignored
294                 $this->_workquery = '';
295                 return '';
296             }
297         }
298         $value = $val_base;
299         if (!is_numeric($value)) {
300             $this->_workquery = ''; //must return false
301             trigger_error("Cannot match against non-numeric attribute value $x := $ori_value", 
302                           E_USER_NOTICE);
303             return '';
304         }
305
306         $this->_workquery = preg_replace("/\b".preg_quote($x,"/")."\b/", $value, $this->_workquery);
307         return $this->_workquery;
308     }
309
310 }
311
312 /**
313  *  SemanticSearchQuery can do:
314  *     (is_a::city and population < 20000) and (*::city and area > 1000000)
315  *  ->match(array('is_a' => 'city', 'linkfrom' => array(), 
316  *          population' => 100000, 'area' => 10000000))
317  * @return array  A list of found and bound matches
318  */
319 class SemanticSearchQuery
320 extends SemanticAttributeSearchQuery
321 {
322     function hasAttributes() { // TODO 
323     }
324     function hasRelations()  { // TODO 
325     }
326     function getLinkNames()  { // TODO 
327     }
328 }
329
330 /**
331  * ReasonerBackend - hooks to reasoner backends.
332  * via http as with DIG,
333  * or internally
334  */
335 class ReasonerBackend {
336     function ReasonerBackend () {
337         ;
338     }
339     /**
340      * transform to reasoner syntax
341      */
342     function transformTo () {
343         ;
344     }
345     /**
346      * transform from reasoner syntax
347      */
348     function transformFrom () {
349         ;
350     }
351     /**
352      * call the reasoner
353      */
354     function invoke () {
355         ;
356     }
357 };
358
359 class ReasonerBackend_LISA extends ReasonerBackend {
360 };
361
362 class ReasonerBackend_Racer extends ReasonerBackend {
363 };
364
365 class ReasonerBackend_KM extends ReasonerBackend {
366 };
367
368 // $Log: not supported by cvs2svn $
369
370 // (c-file-style: "gnu")
371 // Local Variables:
372 // mode: php
373 // tab-width: 8
374 // c-basic-offset: 4
375 // c-hanging-comment-ender-p: nil
376 // indent-tabs-mode: nil
377 // End:   
378 ?>