Update to latest spec changes.

This commit is contained in:
Dave Longley 2012-04-27 16:18:05 -04:00
parent 0e6040c9e1
commit 2135f34a72
1 changed files with 97 additions and 73 deletions

View File

@ -838,7 +838,7 @@ class JsonLdProcessor {
// compact subject references // compact subject references
if(self::_isSubjectReference($element)) { if(self::_isSubjectReference($element)) {
$type = self::getContextValue($ctx, $property, '@type'); $type = self::getContextValue($ctx, $property, '@type');
if($type === '@id') { if($type === '@id' || $property === '@graph') {
$element = $this->_compactIri($ctx, $element->{'@id'}); $element = $this->_compactIri($ctx, $element->{'@id'});
return $element; return $element;
} }
@ -1000,14 +1000,9 @@ class JsonLdProcessor {
'jsonld.SyntaxError', array('value' => $value)); 'jsonld.SyntaxError', array('value' => $value));
} }
// @type must be a string, array of strings, or an empty JSON object // validate @type value
if($prop === '@type' && if($prop === '@type') {
!(is_string($value) || self::_isArrayOfStrings($value) || $this->_validateTypeValue($value);
self::_isEmptyObject($value))) {
throw new JsonLdException(
'Invalid JSON-LD syntax; "@type" value must a string, an array ' +
'of strings, or an empty object.',
'jsonld.SyntaxError', array('value' => $value));
} }
// @graph must be an array or an object // @graph must be an array or an object
@ -1060,6 +1055,25 @@ class JsonLdProcessor {
} }
} }
// optimize away @id for @type
if($prop === '@type') {
if(self::_isSubjectReference($value)) {
$value = $value->{'@id'};
}
else if(is_array($value)) {
$val = array();
foreach($value as $v) {
if(self::_isSubjectReference($v)) {
$val[] = $v->{'@id'};
}
else {
$val[] = $v;
}
}
$value = $val;
}
}
// add value, use an array if not @id, @type, @value, or @language // add value, use an array if not @id, @type, @value, or @language
$use_array = !($prop === '@id' || $prop === '@type' || $use_array = !($prop === '@id' || $prop === '@type' ||
$prop === '@value' || $prop === '@language'); $prop === '@value' || $prop === '@language');
@ -1363,8 +1377,8 @@ class JsonLdProcessor {
// get type definition from context // get type definition from context
$type = self::getContextValue($ctx, $property, '@type'); $type = self::getContextValue($ctx, $property, '@type');
// do @id expansion // do @id expansion (automatic for @graph)
if($type === '@id') { 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 // other type
@ -2427,11 +2441,6 @@ class JsonLdProcessor {
return $iri; return $iri;
} }
// compact rdf:type
if($iri === self::RDF_TYPE) {
return '@type';
}
// term is a keyword // term is a keyword
if(self::_isKeyword($iri)) { if(self::_isKeyword($iri)) {
// return alias if available // return alias if available
@ -2656,8 +2665,12 @@ class JsonLdProcessor {
'jsonld.SyntaxError', array('context' => $ctx)); 'jsonld.SyntaxError', array('context' => $ctx));
} }
// expand @id to full IRI // expand @id if it is not @type
$id = $this->_expandContextIri($active_ctx, $ctx, $id, $base, $defined); if($id !== '@type') {
// expand @id to full IRI
$id = $this->_expandContextIri(
$active_ctx, $ctx, $id, $base, $defined);
}
// add @id to mapping // add @id to mapping
$mapping->{'@id'} = $id; $mapping->{'@id'} = $id;
@ -3022,24 +3035,24 @@ class JsonLdProcessor {
/** /**
* Returns whether or not the given value is a keyword (or a keyword alias). * Returns whether or not the given value is a keyword (or a keyword alias).
* *
* @param string $value the value to check. * @param string $v the value to check.
* @param stdClass [$ctx] the active context to check against. * @param stdClass [$ctx] the active context to check against.
* *
* @return bool true if the value is a keyword, false if not. * @return bool true if the value is a keyword, false if not.
*/ */
protected static function _isKeyword($value, $ctx=null) { protected static function _isKeyword($v, $ctx=null) {
if($ctx !== null) { if($ctx !== null) {
if(property_exists($ctx->keywords, $value)) { if(property_exists($ctx->keywords, $v)) {
return true; return true;
} }
foreach($ctx->keywords as $kw => $aliases) { foreach($ctx->keywords as $kw => $aliases) {
if(in_array($value, $aliases) !== false) { if(in_array($v, $aliases) !== false) {
return true; return true;
} }
} }
} }
else { else {
switch($value) { switch($v) {
case '@context': case '@context':
case '@container': case '@container':
case '@default': case '@default':
@ -3061,125 +3074,136 @@ class JsonLdProcessor {
} }
/** /**
* Returns true if the given input is an empty Object. * Returns true if the given value is an empty Object.
* *
* @param mixed $input the input to check. * @param mixed $v the value to check.
* *
* @return bool true if the input is an empty Object, false if not. * @return bool true if the value is an empty Object, false if not.
*/ */
protected static function _isEmptyObject($input) { protected static function _isEmptyObject($v) {
return is_object($input) && count(get_object_vars($input)) === 0; return is_object($v) && count(get_object_vars($v)) === 0;
} }
/** /**
* Returns true if the given input is an Array of Strings. * Throws an exception if the given value is not a valid @type value.
* *
* @param mixed $input the input to check. * @param mixed $v the value to check.
*
* @return bool true if the input is an Array of Strings, false if not.
*/ */
protected static function _isArrayOfStrings($input) { protected static function _validateTypeValue($v) {
if(!is_array($input)) { // must be a string, subject reference, or empty object
return false; if(is_string($v) || self::_isSubjectReference($v) ||
self::_isEmptyObject($v)) {
return;
} }
foreach($input as $v) {
if(!is_string($v)) { // must be an array
return false; $is_valid = false;
if(is_array($v)) {
$is_valid = true;
foreach($v as $e) {
if(!(is_string($e) || self::_isSubjectReference($e))) {
$is_valid = false;
break;
}
} }
} }
return true;
if(!$is_valid) {
throw new JsonLdException(
'Invalid JSON-LD syntax; "@type" value must a string, an array ' +
'of strings, or an empty object.',
'jsonld.SyntaxError', array('value' => $v));
}
} }
/** /**
* Returns true if the given value is a subject with properties. * Returns true if the given value is a subject with properties.
* *
* @param mixed $value the value to check. * @param mixed $v the value to check.
* *
* @return bool true if the value is a subject with properties, false if not. * @return bool true if the value is a subject with properties, false if not.
*/ */
protected static function _isSubject($value) { protected static function _isSubject($v) {
$rval = false;
// Note: A value is a subject if all of these hold true: // Note: A value is a subject if all of these hold true:
// 1. It is an Object. // 1. It is an Object.
// 2. It is not a @value, @set, or @list. // 2. It is not a @value, @set, or @list.
// 3. It has more than 1 key OR any existing key is not @id. // 3. It has more than 1 key OR any existing key is not @id.
if(is_object($value) && $rval = false;
!property_exists($value, '@value') && if(is_object($v) &&
!property_exists($value, '@set') && !property_exists($v, '@value') &&
!property_exists($value, '@list')) { !property_exists($v, '@set') &&
$count = count(get_object_vars($value)); !property_exists($v, '@list')) {
$rval = ($count > 1 || !property_exists($value, '@id')); $count = count(get_object_vars($v));
$rval = ($count > 1 || !property_exists($v, '@id'));
} }
return $rval; return $rval;
} }
/** /**
* Returns true if the given value is a subject reference. * Returns true if the given value is a subject reference.
* *
* @param mixed $value the value to check. * @param mixed $v the value to check.
* *
* @return bool true if the value is a subject reference, false if not. * @return bool true if the value is a subject reference, false if not.
*/ */
protected static function _isSubjectReference($value) { protected static function _isSubjectReference($v) {
// Note: A value is a subject reference if all of these hold true: // Note: A value is a subject reference if all of these hold true:
// 1. It is an Object. // 1. It is an Object.
// 2. It has a single key: @id. // 2. It has a single key: @id.
return (is_object($value) && count(get_object_vars($value)) === 1 && return (is_object($v) && count(get_object_vars($v)) === 1 &&
property_exists($value, '@id')); property_exists($v, '@id'));
} }
/** /**
* Returns true if the given value is a @value. * Returns true if the given value is a @value.
* *
* @param mixed $value the value to check. * @param mixed $v the value to check.
* *
* @return bool true if the value is a @value, false if not. * @return bool true if the value is a @value, false if not.
*/ */
protected static function _isValue($value) { protected static function _isValue($v) {
// Note: A value is a @value if all of these hold true: // Note: A value is a @value if all of these hold true:
// 1. It is an Object. // 1. It is an Object.
// 2. It has the @value property. // 2. It has the @value property.
return is_object($value) && property_exists($value, '@value'); return is_object($v) && property_exists($v, '@value');
} }
/** /**
* Returns true if the given value is a @list. * Returns true if the given value is a @list.
* *
* @param mixed $value the value to check. * @param mixed $v the value to check.
* *
* @return bool true if the value is a @list, false if not. * @return bool true if the value is a @list, false if not.
*/ */
protected static function _isList($value) { protected static function _isList($v) {
// Note: A value is a @list if all of these hold true: // Note: A value is a @list if all of these hold true:
// 1. It is an Object. // 1. It is an Object.
// 2. It has the @list property. // 2. It has the @list property.
return is_object($value) && property_exists($value, '@list'); return is_object($v) && property_exists($v, '@list');
} }
/** /**
* Returns true if the given value is a blank node. * Returns true if the given value is a blank node.
* *
* @param mixed $value the value to check. * @param mixed $v the value to check.
* *
* @return bool true if the value is a blank node, false if not. * @return bool true if the value is a blank node, false if not.
*/ */
protected static function _isBlankNode($value) { protected static function _isBlankNode($v) {
$rval = false;
// Note: A value is a blank node if all of these hold true: // Note: A value is a blank node if all of these hold true:
// 1. It is an Object. // 1. It is an Object.
// 2. If it has an @id key its value begins with '_:'. // 2. If it has an @id key its value begins with '_:'.
// 3. It has no keys OR is not a @value, @set, or @list. // 3. It has no keys OR is not a @value, @set, or @list.
if(is_object($value)) { $rval = false;
if(property_exists($value, '@id')) { if(is_object($v)) {
$rval = (strpos($value->{'@id'}, '_:') === 0); if(property_exists($v, '@id')) {
$rval = (strpos($v->{'@id'}, '_:') === 0);
} }
else { else {
$rval = (count(get_object_vars($value)) === 0 || $rval = (count(get_object_vars($v)) === 0 ||
!(property_exists($value, '@value') || !(property_exists($v, '@value') ||
property_exists($value, '@set') || property_exists($v, '@set') ||
property_exists($value, '@list'))); property_exists($v, '@list')));
} }
} }
return $rval; return $rval;
@ -3188,12 +3212,12 @@ class JsonLdProcessor {
/** /**
* Returns true if the given value is an absolute IRI, false if not. * Returns true if the given value is an absolute IRI, false if not.
* *
* @param string $value the value to check. * @param string $v the value to check.
* *
* @return bool true if the value is an absolute IRI, false if not. * @return bool true if the value is an absolute IRI, false if not.
*/ */
protected static function _isAbsoluteIri($value) { protected static function _isAbsoluteIri($v) {
return strpos($value, ':') !== false; return strpos($v, ':') !== false;
} }
} }