3 * ARC2 Remote RDF Store
5 * @author Benjamin Nowack <bnowack@semsol.com>
6 * @license http://arc.semsol.org/license
13 class ARC2_RemoteStore extends ARC2_Class {
15 function __construct($a = '', &$caller) {
16 parent::__construct($a, $caller);
19 function ARC2_RemoteStore($a = '', &$caller) {
20 $this->__construct($a, $caller);
42 function insert($doc, $g, $keep_bnode_ids = 0) {
43 return $this->query('INSERT INTO <' . $g . '> { ' . $this->toNTriples($doc, '', 1) . ' }');
46 function delete($doc, $g) {
48 return $this->query('DELETE FROM <' . $g . '>');
51 return $this->query('DELETE FROM <' . $g . '> { ' . $this->toNTriples($doc, '', 1) . ' }');
55 function replace($doc, $g, $doc_2) {
56 return array($this->delete($doc, $g), $this->insert($doc_2, $g));
61 function query($q, $result_format = '', $src = '', $keep_bnode_ids = 0, $log_query = 0) {
62 if ($log_query) $this->logQuery($q);
63 ARC2::inc('SPARQLPlusParser');
64 $p = & new ARC2_SPARQLPlusParser($this->a, $this);
66 $infos = $p->getQueryInfos();
68 if (!$errs = $p->getErrors()) {
69 $qt = $infos['query']['type'];
70 $r = array('query_type' => $qt, 'result' => $this->runQuery($q, $qt, $infos));
73 $r = array('result' => '');
76 $r['query_time'] = $t2 - $t1;
78 if ($result_format == 'raw') {
81 if ($result_format == 'rows') {
82 return $this->v('rows', array(), $r['result']);
84 if ($result_format == 'row') {
85 if (!isset($r['result']['rows'])) return array();
86 return $r['result']['rows'] ? $r['result']['rows'][0] : array();
91 function runQuery($q, $qt = '', $infos = '') {
93 $ep = $this->v('remote_store_endpoint', 0, $this->a);
94 if (!$ep) return false;
96 $q = $this->completeQuery($q);
98 $mthd = 'run' . $this->camelCase($qt) . 'Query';
99 if (method_exists($this, $mthd)) {
100 return $this->$mthd($q, $infos);
103 $mthd = in_array($qt, array('load', 'insert', 'delete')) ? 'POST' : 'GET';
106 $reader =& new ARC2_Reader($this->a, $this);
107 $reader->setAcceptHeader('Accept: application/sparql-results+xml; q=0.9, application/rdf+xml; q=0.9, */*; q=0.1');
108 if ($mthd == 'GET') {
110 $url .= strpos($ep, '?') ? '&' : '?';
111 $url .= 'query=' . urlencode($q);
112 if ($k = $this->v('store_read_key', '', $this->a)) $url .= '&key=' . urlencode($k);
116 $reader->setHTTPMethod($mthd);
117 $reader->setCustomHeaders("Content-Type: application/x-www-form-urlencoded");
118 $suffix = ($k = $this->v('store_write_key', '', $this->a)) ? '&key=' . rawurlencode($k) : '';
119 $reader->setMessageBody('query=' . rawurlencode($q) . $suffix);
121 $to = $this->v('remote_store_timeout', 0, $this->a);
122 $reader->activate($url, '', 0, $to);
123 $format = $reader->getFormat();
125 while ($d = $reader->readStream()) {
126 $resp .= $this->toUTF8($d);
128 $reader->closeStream();
129 $ers = $reader->getErrors();
130 $this->a['reader_auth_infos'] = $reader->getAuthInfos();
131 unset($this->reader);
132 if ($ers) return array('errors' => $ers);
133 $mappings = array('rdfxml' => 'RDFXML', 'sparqlxml' => 'SPARQLXMLResult', 'turtle' => 'Turtle');
134 if (!$format || !isset($mappings[$format])) {
136 //return $this->addError('No parser available for "' . $format . '" SPARQL result');
139 $suffix = $mappings[$format] . 'Parser';
141 $cls = 'ARC2_' . $suffix;
142 $parser =& new $cls($this->a, $this);
143 $parser->parse($ep, $resp);
144 /* ask|load|insert|delete */
145 if (in_array($qt, array('ask', 'load', 'insert', 'delete'))) {
146 $bid = $parser->getBooleanInsertedDeleted();
148 $r = $bid['boolean'];
155 elseif (($qt == 'select') && !method_exists($parser, 'getRows')) {
158 elseif ($qt == 'select') {
159 $r = array('rows' => $parser->getRows(), 'variables' => $parser->getVariables());
163 $r = $parser->getSimpleIndex(0);
171 function optimizeTables() {}
175 function getResourceLabel($res, $unnamed_label = 'An unnamed resource') {
176 if (!isset($this->resource_labels)) $this->resource_labels = array();
177 if (isset($this->resource_labels[$res])) return $this->resource_labels[$res];
178 if (!preg_match('/^[a-z0-9\_]+\:[^\s]+$/si', $res)) return $res;/* literal */
180 if (preg_match('/^\_\:/', $res)) {
181 return $unnamed_label;
183 $row = $this->query('SELECT ?o WHERE { <' . $res . '> ?p ?o . FILTER(REGEX(str(?p), "(label|name)$", "i"))}', 'row');
188 $r = preg_replace("/^(.*[\/\#])([^\/\#]+)$/", '\\2', str_replace('#self', '', $res));
189 $r = str_replace('_', ' ', $r);
190 $r = preg_replace('/([a-z])([A-Z])/e', '"\\1 " . strtolower("\\2")', $r);
192 $this->resource_labels[$res] = $r;
196 function getDomains($p) {
198 foreach($this->query('SELECT DISTINCT ?type WHERE {?s <' . $p . '> ?o ; a ?type . }', 'rows') as $row) {