Always use @value in expanded form.

This commit is contained in:
Dave Longley 2012-05-08 18:07:28 -04:00
parent 4c847440c7
commit 599e2352d1

View file

@ -882,6 +882,12 @@ class JsonLdProcessor {
if(is_object($element)) { if(is_object($element)) {
// element is a @value // element is a @value
if(self::_isValue($element)) { if(self::_isValue($element)) {
// if @value is the only key, return its value
if(count(get_object_vars($element)) === 1) {
return $element->{'@value'};
}
// get type and language context rules
$type = self::getContextValue($ctx, $property, '@type'); $type = self::getContextValue($ctx, $property, '@type');
$language = self::getContextValue($ctx, $property, '@language'); $language = self::getContextValue($ctx, $property, '@language');
@ -889,17 +895,6 @@ class JsonLdProcessor {
if($type !== null && if($type !== null &&
property_exists($element, '@type') && $element->{'@type'} === $type) { property_exists($element, '@type') && $element->{'@type'} === $type) {
$element = $element->{'@value'}; $element = $element->{'@value'};
// use native datatypes for certain xsd types
if($type === self::XSD_BOOLEAN) {
$element = !($element === 'false' || $element === '0');
}
else if($type === self::XSD_INTEGER) {
$element = intval($element);
}
else if($type === self::XSD_DOUBLE) {
$element = doubleval($element);
}
} }
// matching @language specified in context, compact element // matching @language specified in context, compact element
else if($language !== null && else if($language !== null &&
@ -1106,9 +1101,9 @@ class JsonLdProcessor {
'jsonld.SyntaxError', array('value' => $value)); 'jsonld.SyntaxError', array('value' => $value));
} }
// recurse into @list, @set, or @graph, keeping the active property // recurse into @list or @set keeping the active property
$is_list = ($prop === '@list'); $is_list = ($prop === '@list');
if($is_list || $prop === '@set' || $prop === '@graph') { if($is_list || $prop === '@set') {
$value = $this->_expand($ctx, $property, $value, $options, $is_list); $value = $this->_expand($ctx, $property, $value, $options, $is_list);
if($is_list && self::_isList($value)) { if($is_list && self::_isList($value)) {
throw new JsonLdException( throw new JsonLdException(
@ -1179,10 +1174,6 @@ class JsonLdProcessor {
'containing "@value" must be a string.', 'containing "@value" must be a string.',
'jsonld.SyntaxError', array('element' => $rval)); 'jsonld.SyntaxError', array('element' => $rval));
} }
// return only the value of @value if there is no @type or @language
else if($count === 1) {
$rval = $rval->{'@value'};
}
// drop null @values // drop null @values
else if($rval->{'@value'} === null) { else if($rval->{'@value'} === null) {
$rval = null; $rval = null;
@ -1551,13 +1542,34 @@ class JsonLdProcessor {
if(is_object($element)) { if(is_object($element)) {
// convert @value to object // convert @value to object
if(self::_isValue($element)) { if(self::_isValue($element)) {
$value = $element->{'@value'};
$datatype = (property_exists($element, '@type') ?
$element->{'@type'} : null);
if(is_bool($value) || is_double($value) || is_integer($value)) {
// convert to XSD datatype
if(is_bool($value)) {
$value = ($value ? 'true' : 'false');
$datatype or $datatype = self::XSD_BOOLEAN;
}
else if(is_double($value)) {
// do special JSON-LD double format, printf('%1.15e') equivalent
$value = preg_replace('/(e(?:\+|-))([0-9])$/', '${1}0${2}',
sprintf('%1.15e', $value));
$datatype or $datatype = self::XSD_DOUBLE;
}
else {
$value = strval($value);
$datatype or $datatype = self::XSD_INTEGER;
}
}
$object = (object)array( $object = (object)array(
'nominalValue' => $element->{'@value'}, 'nominalValue' => $value,
'interfaceName' => 'LiteralNode'); 'interfaceName' => 'LiteralNode');
if(property_exists($element, '@type')) { if($datatype !== null) {
$object->datatype = (object)array( $object->datatype = (object)array(
'nominalValue' => $element->{'@type'}, 'nominalValue' => $datatype,
'interfaceName' => 'IRI'); 'interfaceName' => 'IRI');
} }
else if(property_exists($element, '@language')) { else if(property_exists($element, '@language')) {
@ -1656,53 +1668,15 @@ class JsonLdProcessor {
return; return;
} }
// element must be an rdf:type IRI (@values covered above)
if(is_string($element)) { if(is_string($element)) {
// property can be null for string subject references in @graph // emit IRI
if($property === null) {
return;
}
// emit IRI for rdf:type, else plain literal
$statement = (object)array( $statement = (object)array(
'subject' => self::copy($subject), 'subject' => self::copy($subject),
'property' => self::copy($property), 'property' => self::copy($property),
'object' => (object)array( 'object' => (object)array(
'nominalValue' => $element, 'nominalValue' => $element,
'interfaceName' => (($property->nominalValue === self::RDF_TYPE) ? 'interfaceName' => 'IRI'));
'IRI' : 'LiteralNode')));
if($graph !== null) {
$statement->name = $graph;
}
$statements[] = $statement;
return;
}
if(is_bool($element) || is_double($element) || is_integer($element)) {
// convert to XSD datatype
if(is_bool($element)) {
$datatype = self::XSD_BOOLEAN;
$value = ($element ? 'true' : 'false');
}
else if(is_double($element)) {
$datatype = self::XSD_DOUBLE;
// do special JSON-LD double format, printf('%1.15e') equivalent
$value = preg_replace('/(e(?:\+|-))([0-9])$/', '${1}0${2}',
sprintf('%1.15e', $element));
}
else {
$datatype = self::XSD_INTEGER;
$value = strval($element);
}
// emit typed literal
$statement = (object)array(
'subject' => self::copy($subject),
'property' => self::copy($property),
'object' => (object)array(
'nominalValue' => $value,
'interfaceName' => 'LiteralNode',
'datatype' => (object)array(
'nominalValue' => $datatype,
'interfaceName' => 'IRI')));
if($graph !== null) { if($graph !== null) {
$statement->name = $graph; $statement->name = $graph;
} }
@ -1774,6 +1748,11 @@ class JsonLdProcessor {
* @return mixed the expanded value. * @return mixed the expanded value.
*/ */
protected function _expandValue($ctx, $property, $value, $base) { protected function _expandValue($ctx, $property, $value, $base) {
// nothing to expand
if($value === null) {
return null;
}
// default to simple string return value // default to simple string return value
$rval = $value; $rval = $value;
@ -1793,16 +1772,19 @@ class JsonLdProcessor {
if($type === '@id' || $prop === '@graph') { if($type === '@id' || $prop === '@graph') {
$rval = (object)array('@id' => $this->_expandTerm($ctx, $value, $base)); $rval = (object)array('@id' => $this->_expandTerm($ctx, $value, $base));
} }
// other type else if(!self::_isKeyword($prop)) {
else if($type !== null) { $rval = (object)array('@value' => $value);
$rval = (object)array('@value' => strval($value), '@type' => $type);
} // other type
// check for language tagging if($type !== null) {
else { $rval->{'@type'} = $type;
$language = self::getContextValue($ctx, $property, '@language'); }
if($language !== null) { // check for language tagging
$rval = (object)array( else {
'@value' => strval($value), '@language' => $language); $language = self::getContextValue($ctx, $property, '@language');
if($language !== null) {
$rval->{'@language'} = $language;
}
} }
} }
} }
@ -1833,6 +1815,18 @@ class JsonLdProcessor {
// add datatype // add datatype
if(property_exists($o, 'datatype')) { if(property_exists($o, 'datatype')) {
/*
// use native datatypes for certain xsd types
$type = $o->datatype->nominalValue;
if($type === self::XSD_BOOLEAN) {
$element = !($element === 'false' || $element === '0');
}
else if($type === self::XSD_INTEGER) {
$element = intval($element);
}
else if($type === self::XSD_DOUBLE) {
$element = doubleval($element);
}*/
$rval->{'@type'} = $o->datatype->nominalValue; $rval->{'@type'} = $o->datatype->nominalValue;
} }
// add language // add language
@ -2619,37 +2613,10 @@ class JsonLdProcessor {
return $sum; return $sum;
} }
// rank boolean or number
if(is_bool($value) || is_double($value) || is_integer($value)) {
if(is_bool($value)) {
$type = self::XSD_BOOLEAN;
}
else if(is_double($value)) {
$type = self::XSD_DOUBLE;
}
else {
$type = self::XSD_INTEGER;
}
if($has_type && $entry->{'@type'} === $type) {
return 3;
}
return (!$has_type && !$has_language) ? 2 : 1;
}
// rank string (this means the value has no @language)
if(is_string($value)) {
// entry @language is specifically null or no @type, @language, or default
if(($has_language && $entry->{'@language'} === null) ||
(!$has_type && !$has_language && !$has_default_language)) {
return 3;
}
return 0;
}
// Note: Value must be an object that is a @value or subject/reference. // Note: Value must be an object that is a @value or subject/reference.
// @value must have either @type or @language
if(self::_isValue($value)) { if(self::_isValue($value)) {
// value has a @type
if(property_exists($value, '@type')) { if(property_exists($value, '@type')) {
// @types match // @types match
if($has_type && $value->{'@type'} === $entry->{'@type'}) { if($has_type && $value->{'@type'} === $entry->{'@type'}) {
@ -2658,6 +2625,22 @@ class JsonLdProcessor {
return (!$has_type && !$has_language) ? 1 : 0; return (!$has_type && !$has_language) ? 1 : 0;
} }
// rank non-string value
if(!is_string($value->{'@value'})) {
return (!$has_type && !$has_language) ? 2 : 1;
}
// value has no @type or @language
if(!property_exists($value, '@language')) {
// entry @language is specifically null or no @type, @language, or
// default
if(($has_language && $entry->{'@language'} === null) ||
(!$has_type && !$has_language && !$has_default_language)) {
return 3;
}
return 0;
}
// @languages match or entry has no @type or @language but default // @languages match or entry has no @type or @language but default
// @language matches // @language matches
if(($has_language && $value->{'@language'} === $entry->{'@language'}) || if(($has_language && $value->{'@language'} === $entry->{'@language'}) ||
@ -3145,7 +3128,7 @@ class JsonLdProcessor {
* the @contexts from the urls map, false not to. * the @contexts from the urls map, false not to.
*/ */
protected function _findContextUrls($input, $urls, $replace) { protected function _findContextUrls($input, $urls, $replace) {
$count = count((array)$urls); $count = count(get_object_vars($urls));
if(is_array($input)) { if(is_array($input)) {
foreach($input as $e) { foreach($input as $e) {
$this->_findContextUrls($e, $urls, $replace); $this->_findContextUrls($e, $urls, $replace);
@ -3211,7 +3194,7 @@ class JsonLdProcessor {
* @return mixed the result. * @return mixed the result.
*/ */
protected function _resolveContextUrls(&$input, $cycles, $resolver) { protected function _resolveContextUrls(&$input, $cycles, $resolver) {
if(count((array)$cycles) > self::MAX_CONTEXT_URLS) { if(count(get_object_vars($cycles)) > self::MAX_CONTEXT_URLS) {
throw new JsonLdException( throw new JsonLdException(
'Maximum number of @context URLs exceeded.', 'Maximum number of @context URLs exceeded.',
'jsonld.ContextUrlError', array('max' => self::MAX_CONTEXT_URLS)); 'jsonld.ContextUrlError', array('max' => self::MAX_CONTEXT_URLS));