Remove extra bnode naming, fix active context caching bugs.

This commit is contained in:
Dave Longley 2013-06-07 12:06:39 -04:00
parent b4c2f11910
commit 15414cfe80
1 changed files with 56 additions and 54 deletions

View File

@ -1,7 +1,7 @@
<?php <?php
/** /**
* PHP implementation of the JSON-LD API. * PHP implementation of the JSON-LD API.
* Version: 0.0.35 * Version: 0.0.36
* *
* @author Dave Longley * @author Dave Longley
* *
@ -134,7 +134,7 @@ function jsonld_normalize($input, $options=array()) {
* [useRdfType] true to use rdf:type, false to use @type * [useRdfType] true to use rdf:type, false to use @type
* (default: false). * (default: false).
* [useNativeTypes] true to convert XSD types into native types * [useNativeTypes] true to convert XSD types into native types
* (boolean, integer, double), false not to (default: true). * (boolean, integer, double), false not to (default: false).
* *
* @return array the JSON-LD output. * @return array the JSON-LD output.
*/ */
@ -319,6 +319,10 @@ function jsonld_unregister_rdf_parser($content_type) {
* @return assoc the parsed URL. * @return assoc the parsed URL.
*/ */
function jsonld_parse_url($url) { function jsonld_parse_url($url) {
if($url === null) {
$url = '';
}
$rval = parse_url($url); $rval = parse_url($url);
// malformed url // malformed url
@ -954,7 +958,7 @@ class JsonLdProcessor {
* [useRdfType] true to use rdf:type, false to use @type * [useRdfType] true to use rdf:type, false to use @type
* (default: false). * (default: false).
* [useNativeTypes] true to convert XSD types into native types * [useNativeTypes] true to convert XSD types into native types
* (boolean, integer, double), false not to (default: true). * (boolean, integer, double), false not to (default: false).
* *
* @return array the JSON-LD output. * @return array the JSON-LD output.
*/ */
@ -963,7 +967,7 @@ class JsonLdProcessor {
// set default options // set default options
isset($options['useRdfType']) or $options['useRdfType'] = false; isset($options['useRdfType']) or $options['useRdfType'] = false;
isset($options['useNativeTypes']) or $options['useNativeTypes'] = true; isset($options['useNativeTypes']) or $options['useNativeTypes'] = false;
if(!isset($options['format']) && is_string($dataset)) { if(!isset($options['format']) && is_string($dataset)) {
// set default format to nquads // set default format to nquads
@ -1028,15 +1032,11 @@ class JsonLdProcessor {
$this->_createNodeMap($expanded, $node_map, '@default', $namer); $this->_createNodeMap($expanded, $node_map, '@default', $namer);
// output RDF dataset // output RDF dataset
$namer = new UniqueNamer('_:b');
$dataset = new stdClass(); $dataset = new stdClass();
$graph_names = array_keys((array)$node_map); $graph_names = array_keys((array)$node_map);
sort($graph_names); sort($graph_names);
foreach($graph_names as $graph_name) { foreach($graph_names as $graph_name) {
$graph = $node_map->{$graph_name}; $graph = $node_map->{$graph_name};
if(strpos($graph_name, '_:') === 0) {
$graph_name = $namer->getName($graph_name);
}
$dataset->{$graph_name} = $this->_graphToRDF($graph, $namer); $dataset->{$graph_name} = $this->_graphToRDF($graph, $namer);
} }
@ -2675,19 +2675,6 @@ class JsonLdProcessor {
protected function _processContext($active_ctx, $local_ctx, $options) { protected function _processContext($active_ctx, $local_ctx, $options) {
global $jsonld_cache; global $jsonld_cache;
$rval = null;
// get context from cache if available
if(property_exists($jsonld_cache, 'activeCtx')) {
$rval = $jsonld_cache->activeCtx->get($active_ctx, $local_ctx);
if($rval) {
return $rval;
}
}
// initialize the resulting context
$rval = self::_cloneActiveContext($active_ctx);
// normalize local context to an array // normalize local context to an array
if(is_object($local_ctx) && property_exists($local_ctx, '@context') && if(is_object($local_ctx) && property_exists($local_ctx, '@context') &&
is_array($local_ctx->{'@context'})) { is_array($local_ctx->{'@context'})) {
@ -2695,11 +2682,19 @@ class JsonLdProcessor {
} }
$ctxs = self::arrayify($local_ctx); $ctxs = self::arrayify($local_ctx);
// no contexts in array, clone existing context
if(count($ctxs) === 0) {
return self::_cloneActiveContext($active_ctx);
}
// process each context in order // process each context in order
$rval = $active_ctx;
$must_clone = true;
foreach($ctxs as $ctx) { foreach($ctxs as $ctx) {
// reset to initial context // reset to initial context
if($ctx === null) { if($ctx === null) {
$rval = $this->_getInitialContext($options); $rval = $this->_getInitialContext($options);
$must_clone = false;
continue; continue;
} }
@ -2715,6 +2710,22 @@ class JsonLdProcessor {
'jsonld.SyntaxError', array('context' => $ctx)); 'jsonld.SyntaxError', array('context' => $ctx));
} }
// get context from cache if available
if(property_exists($jsonld_cache, 'activeCtx')) {
$cached = $jsonld_cache->activeCtx->get($active_ctx, $ctx);
if($cached) {
$rval = $cached;
$must_clone = true;
continue;
}
}
// clone context, if required, before updating
if($must_clone) {
$rval = self::_cloneActiveContext($rval);
$must_clone = false;
}
// define context mappings for keys in local context // define context mappings for keys in local context
$defined = new stdClass(); $defined = new stdClass();
@ -2786,11 +2797,11 @@ class JsonLdProcessor {
foreach($ctx as $k => $v) { foreach($ctx as $k => $v) {
$this->_createTermDefinition($rval, $ctx, $k, $defined); $this->_createTermDefinition($rval, $ctx, $k, $defined);
} }
}
// cache result // cache result
if(property_exists($jsonld_cache, 'activeCtx')) { if(property_exists($jsonld_cache, 'activeCtx')) {
$jsonld_cache->activeCtx->set($active_ctx, $local_ctx, $rval); $jsonld_cache->activeCtx->set($active_ctx, $ctx, $rval);
}
} }
return $rval; return $rval;
@ -2961,25 +2972,14 @@ class JsonLdProcessor {
foreach($items as $item) { foreach($items as $item) {
// RDF subject // RDF subject
$subject = new stdClass(); $subject = new stdClass();
if(strpos($id, '_:') === 0) { $subject->type = (strpos($id, '_:') === 0) ? 'blank node' : 'IRI';
$subject->type = 'blank node'; $subject->value = $id;
$subject->value = $namer->getName($id);
}
else {
$subject->type = 'IRI';
$subject->value = $id;
}
// RDF predicate // RDF predicate
$predicate = new stdClass(); $predicate = new stdClass();
if(strpos($property, '_:') === 0) { $predicate->type = (strpos($property, '_:') === 0 ?
$predicate->type = 'blank node'; 'blank node' : 'IRI');
$predicate->value = $namer->getName($property); $predicate->value = $property;
}
else {
$predicate->type = 'IRI';
$predicate->value = $property;
}
// convert @list to triples // convert @list to triples
if(self::_isList($item)) { if(self::_isList($item)) {
@ -2988,7 +2988,7 @@ class JsonLdProcessor {
} }
// convert value or node object to triple // convert value or node object to triple
else { else {
$object = $this->_objectToRDF($item, $namer); $object = $this->_objectToRDF($item);
$rval[] = (object)array( $rval[] = (object)array(
'subject' => $subject, 'subject' => $subject,
'predicate' => $predicate, 'predicate' => $predicate,
@ -3027,7 +3027,7 @@ class JsonLdProcessor {
$subject = $blank_node; $subject = $blank_node;
$predicate = $first; $predicate = $first;
$object = $this->_objectToRDF($item, $namer); $object = $this->_objectToRDF($item);
$triples[] = (object)array( $triples[] = (object)array(
'subject' => $subject, 'predicate' => $predicate, 'object' => $object); 'subject' => $subject, 'predicate' => $predicate, 'object' => $object);
@ -3043,11 +3043,10 @@ class JsonLdProcessor {
* node object to an RDF resource. * node object to an RDF resource.
* *
* @param mixed $item the JSON-LD value or node object. * @param mixed $item the JSON-LD value or node object.
* @param UniqueNamer $namer for assign blank node names.
* *
* @return stdClass the RDF literal or RDF resource. * @return stdClass the RDF literal or RDF resource.
*/ */
protected function _objectToRDF($item, $namer) { protected function _objectToRDF($item) {
$object = new stdClass(); $object = new stdClass();
if(self::_isValue($item)) { if(self::_isValue($item)) {
@ -3083,14 +3082,8 @@ class JsonLdProcessor {
// convert string/node object to RDF // convert string/node object to RDF
else { else {
$id = is_object($item) ? $item->{'@id'} : $item; $id = is_object($item) ? $item->{'@id'} : $item;
if(strpos($id, '_:') === 0) { $object->type = (strpos($id, '_:') === 0) ? 'blank node' : 'IRI';
$object->type = 'blank node'; $object->value = $id;
$object->value = $namer->getName($id);
}
else {
$object->type = 'IRI';
$object->value = $id;
}
} }
return $object; return $object;
@ -3148,7 +3141,7 @@ class JsonLdProcessor {
$rval->{'@type'} = $type; $rval->{'@type'} = $type;
} }
} }
else { else if($type !== self::XSD_STRING) {
$rval->{'@type'} = $type; $rval->{'@type'} = $type;
} }
} }
@ -3205,6 +3198,15 @@ class JsonLdProcessor {
// Note: At this point, input must be a subject. // Note: At this point, input must be a subject.
// spec requires @type to be named first, so assign names early
if(property_exists($input, '@type')) {
foreach($input->{'@type'} as $type) {
if(strpos($type, '_:') === 0) {
$namer->getName($type);
}
}
}
// get name for subject // get name for subject
if($name === null) { if($name === null) {
if(property_exists($input, '@id')) { if(property_exists($input, '@id')) {