jenkins-bot has submitted this change and it was merged.

Change subject: \SMW\SemanticDataSerializer
......................................................................


\SMW\SemanticDataSerializer

Code coverage: 100%
CRAP: 34

A full qualified serialization of a SemanticData container. Tests include
rountrips for various scenarios. The data model is described in
/serializer/README.md.

Change-Id: Ief0648e3ca70f9f815139e51528a1bc695bad1fc
---
M SemanticMediaWiki.classes.php
A includes/serializer/README.md
A includes/serializer/SemanticDataSerializer.php
A includes/serializer/SerializerFactory.php
A includes/serializer/SerializerInterface.php
A tests/phpunit/includes/serializer/SemanticDataSerializerTest.php
A tests/phpunit/includes/serializer/SerializerFactoryTest.php
7 files changed, 951 insertions(+), 0 deletions(-)

Approvals:
  Mwjames: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/SemanticMediaWiki.classes.php b/SemanticMediaWiki.classes.php
index 9fb5bbf..094dd91 100644
--- a/SemanticMediaWiki.classes.php
+++ b/SemanticMediaWiki.classes.php
@@ -97,6 +97,11 @@
        'SMW\Configurable'              => 'includes/Configurable.php',
        'SMW\StoreAccess'               => 'includes/StoreAccess.php',
 
+       // Serializer
+       'SMW\SerializerFactory'            => 
'includes/serializer/SerializerFactory.php',
+       'SMW\SerializerInterface'          => 
'includes/serializer/SerializerInterface.php',
+       'SMW\SemanticDataSerializer'       => 
'includes/serializer/SemanticDataSerializer.php',
+
        // Cache
        'SMW\CacheHandler'                => 'includes/cache/CacheHandler.php',
        'SMW\CacheableResultMapper'       => 
'includes/cache/CacheableResultMapper.php',
diff --git a/includes/serializer/README.md b/includes/serializer/README.md
new file mode 100644
index 0000000..d30f5c8
--- /dev/null
+++ b/includes/serializer/README.md
@@ -0,0 +1,152 @@
+This document contains information about Semantic MediaWiki serializers.
+
+## Components
+
+### SerializerInterface
+A common interface describing a class that implements specific 
serialize/unserialze functionality.
+
+### SerializerFactory
+A factory class that assigns registered serializers to an object and 
identifies an unserializer based on the invoked array. A serialized record has 
a reference to the generator (serializer) class which will automatically be 
used during unserialization. Each record includes a version number to compare 
the data model used and enable a consistency check before an attempt to 
unserialize a record.
+
+```php
+$foo = new Foo( ... );
+$serialized = SerializerFactory::serialize( $foo );
+$unserialized = SerializerFactory::unserialize( $serialized );
+```
+
+### SemanticDataSerializer
+Implements the SerialzierInterface for the SMW\SemanticData object.
+
+#### Data model
+```php
+[subject] -> Subject serialization
+[data] -> array container
+       [property] -> Property serialization
+       [dataitem] -> DataItem serialization
+       ...
+[sobj] -> array container
+       [subject] -> Subobject subject serialization
+       [data] -> array container
+               [property] -> Property serialization
+               [dataitem] -> DataItem serialization
+               ...
+[serializer] -> Class of the generator and entry point for the un-serializer
+[version] -> Number to compare structural integrity between serialization and 
un-serialization
+```
+#### Example
+For a page called "Foo" that contains <code>[[Has property::Bar]]</code>, 
<code>{{#subobject:|Has subobjects=Bam}}</code>, <code>{{#ask:Has 
subobjects::Bam}}</code>, the Serializer will output:
+
+```php
+[subject] => Foo#0#
+[data] => Array (
+       [0] => Array (
+               [property] => Has_property
+               [dataitem] => Array (
+                       [0] => Array (
+                               [type] => 9
+                               [item] => Bar#0#
+                       )
+               )
+       )
+       [1] => Array (
+               [property] => _ASK
+               [dataitem] => Array (
+                       [0] => Array (
+                               [type] => 9
+                               [item] => 
Foo#0##_QUERYc8606da8f325fc05aa8e8b958821c3b4
+                               [sobj] => _QUERYc8606da8f325fc05aa8e8b958821c3b4
+                       )
+               )
+       )
+       [2] => Array (
+               [property] => _MDAT
+               [dataitem] => Array (
+                       [0] => Array (
+                               [type] => 6
+                               [item] => 1/2013/10/10/14/55/40
+                       )
+               )
+       )
+       [3] => Array (
+               [property] => _SKEY
+               [dataitem] => Array (
+                       [0] => Array (
+                               [type] => 2
+                               [item] => Foo
+                       )
+               )
+       )
+       [4] => Array (
+               [property] => _SOBJ
+               [dataitem] => Array (
+                       [0] => Array (
+                               [type] => 9
+                               [item] => 
Foo#0##_fc4b104aabf80eb06429e946aa8f7070
+                               [sobj] => _fc4b104aabf80eb06429e946aa8f7070
+                       )
+               )
+       )
+)
+[sobj] => Array (
+       [0] => Array (
+               [subject] => Foo#0##_fc4b104aabf80eb06429e946aa8f7070
+               [data] => Array (
+                       [0] => Array (
+                               [property] => Has_subobjects
+                               [dataitem] => Array (
+                                       [0] => Array (
+                                               [type] => 9
+                                               [item] => Bam#0#
+                                       )
+                               )
+                       )
+               )
+       )
+       [1] => Array (
+               [subject] => Foo#0##_QUERYc8606da8f325fc05aa8e8b958821c3b4
+               [data] => Array (
+                       [0] => Array (
+                               [property] => _ASKDE
+                               [dataitem] => Array (
+                                       [0] => Array (
+                                               [type] => 1
+                                               [item] => 1
+                                       )
+                               )
+                       )
+                       [1] => Array (
+                               [property] => _ASKFO
+                               [dataitem] => Array (
+                                       [0] => Array (
+                                               [type] => 2
+                                               [item] => list
+                                       )
+                               )
+                       )
+                       [2] => Array (
+                               [property] => _ASKSI
+                               [dataitem] => Array (
+                                       [0] => Array (
+                                               [type] => 1
+                                               [item] => 2
+                                       )
+                               )
+                       )
+                       [3] => Array (
+                               [property] => _ASKST
+                               [dataitem] => Array (
+                                       [0] => Array (
+                                               [type] => 2
+                                               [item] => [[Has 
subobjects::Bam]]
+                                       )
+                               )
+                       )
+               )
+       )
+)
+[serializer] => SMW\SemanticDataSerializer
+[version] => 0.3
+```
+
+### QueryResultSerializer
+N/A (see \SMW\DISerializer)
diff --git a/includes/serializer/SemanticDataSerializer.php 
b/includes/serializer/SemanticDataSerializer.php
new file mode 100644
index 0000000..f683d6b
--- /dev/null
+++ b/includes/serializer/SemanticDataSerializer.php
@@ -0,0 +1,299 @@
+<?php
+
+namespace SMW;
+
+use SMWContainerSemanticData;
+use SMWDIContainer as DIContainer;
+use SMWDataItem as DataItem;
+use SMWErrorValue as ErrorValue;
+
+use OutOfBoundsException;
+
+/**
+ * SemanticData serializer / unserializer
+ *
+ * @file
+ *
+ * @license GNU GPL v2+
+ * @since   1.9
+ *
+ * @author mwjames
+ */
+
+/**
+ * SemanticData serializer / unserializer
+ *
+ * @ingroup SMW
+ */
+class SemanticDataSerializer implements SerializerInterface {
+
+       /**
+        * The version number is an indicator among serialized data to track 
structural
+        * integrity which means that any change in its output format is to be 
accompanied
+        * by a version number change
+        *
+        * The unserializer will raise an exception if the version of the 
incoming
+        * data does not match with the version number found in this class.
+        */
+       const VERSION = 0.1;
+
+       /**
+        * Cache for already processed Id's which is to minimize lock-up 
performance
+        * during unserialization
+        *
+        * @var array
+        */
+       protected $dataItemTypeIdCache = array();
+
+       /**
+        * Initiates serialization of a SemanticData object
+        *
+        * @since 1.9
+        *
+        * @return array
+        * @throws OutOfBoundsException
+        */
+       public function serialize( $semanticData ) {
+
+               if ( !( $semanticData instanceOf SemanticData ) ) {
+                       throw new OutOfBoundsException( 'Object was not 
identified as a SemanticData instance' );
+               }
+
+               return $this->serializeSemanticData( $semanticData ) + array( 
'serializer' => __CLASS__, 'version' => self::VERSION );
+       }
+
+       /**
+        * Initiates unserialization of an object
+        *
+        * @since 1.9
+        *
+        * @return SemanticData
+        * @throws OutOfBoundsException
+        */
+       public function unserialize( array $data ) {
+
+               $semanticData = null;
+
+               if ( isset( $data['version'] ) && $data['version'] !== 
self::VERSION ) {
+                       throw new OutOfBoundsException( 
'Serializer/Unserializer version do not match, please update your data' );
+               }
+
+               if ( isset( $data['subject'] ) ) {
+                       $semanticData = new SemanticData( 
DIWikiPage::doUnserialize( $data['subject'] ) );
+               }
+
+               if ( !( $semanticData instanceOf SemanticData ) ) {
+                       throw new OutOfBoundsException( 'SemanticData could not 
be created probably due to a missing subject' );
+               }
+
+               $this->unserializeSemanticData( $data, $semanticData );
+
+               return $semanticData;
+       }
+
+       /**
+        * Returns serialized SemanticData
+        *
+        * @return array
+        */
+       protected function serializeSemanticData( SemanticData $semanticData ) {
+
+               $output = array();
+
+               $output['subject'] = 
$semanticData->getSubject()->getSerialization();
+
+               /**
+                * Build property and dataItem serialization record
+                */
+               foreach ( $semanticData->getProperties() as $key => $property ) 
{
+
+                       $prop = array();
+
+                       $prop['property'] = $property->getSerialization();
+
+                       foreach ( $semanticData->getPropertyValues( $property ) 
as $dataItem ) {
+                               $prop['dataitem'][] = $this->serializeDataItem( 
$dataItem );
+                       }
+
+                       $output['data'][] = $prop;
+
+               }
+
+               $this->serializeSubobject( $semanticData->getSubSemanticData(), 
$output );
+
+               return $output;
+       }
+
+       /**
+        * Returns DataItem serialization
+        *
+        * @note 'type' is added to ensure that during unserialization the type
+        * definition of the requested data is in alignment with the definition 
found
+        * in the system (type changes that can occur during the time between
+        * serialization and unserialization)
+        *
+        * @note 'sobj' is only added for when a subobject is present
+        *
+        * @return array
+        */
+       protected function serializeDataItem( DataItem $dataItem ) {
+
+               $di = array(
+                       'type' => $dataItem->getDIType(),
+                       'item' => $dataItem->getSerialization()
+               );
+
+               if ( $dataItem->getDIType() === DataItem::TYPE_WIKIPAGE && 
$dataItem->getSubobjectName() ) {
+                       $di += array( 'sobj' => $dataItem->getSubobjectName() );
+               }
+
+               return $di;
+       }
+
+       /**
+        * Returns all subobjects of a SemanticData instance
+        *
+        * @note The subobject name is used as reference key as it is the only
+        * reliable unique key to allow a performable lookup during 
unserialization
+        *
+        * @return array
+        */
+       protected function serializeSubobject( $subSemanticData, &$output ) {
+
+               foreach ( $subSemanticData as $semanticData ) {
+                       $output['sobj'][] = $this->serializeSemanticData( 
$semanticData );
+               }
+
+       }
+
+       /**
+        * @return null
+        */
+       protected function unserializeSemanticData( $data, &$semanticData ) {
+
+               $property = null;
+
+               if ( !isset( $data['data'] ) ) {
+                       return;
+               }
+
+               foreach ( $data['data'] as $values ) {
+
+                       if ( is_array( $values ) ) {
+
+                               foreach ( $values as $key => $value ) {
+
+                                       /**
+                                        * @var DIProperty $property
+                                        */
+                                       if ( $key === 'property' ) {
+                                               $property = 
DIProperty::doUnserialize( $value );
+                                       }
+
+                                       /**
+                                        * @var DataItem
+                                        */
+                                       if ( $key === 'dataitem' ) {
+                                               foreach ( $value as $val ) {
+                                                       
$this->unserializeDataItem( $property, $data, $val, $semanticData );
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /**
+        * @return DataItem
+        */
+       protected function unserializeDataItem( $property, $data, $value, 
$semanticData ) {
+
+               $dataItem = null;
+
+               $type = $this->getDataItemId( $property );
+
+               // Verify that the current property type definition and the 
type of the
+               // property during serialization do match, throw an error value 
to avoid any
+               // exception during unserialization caused by the DataItem 
object due to a
+               // mismatch of type definitions
+               if ( $type === $value['type'] ) {
+                       $dataItem = DataItem::newFromSerialization( 
$value['type'], $value['item'] );
+               } else {
+                       $dataItem = $property->getDiWikiPage();
+                       $property = new DIProperty( DIProperty::TYPE_ERROR );
+
+                       $semanticData->addError( array(
+                               new ErrorValue( $type, 'type mismatch', 
$property->getLabel() )
+                       ) );
+
+               }
+
+               // Check whether the current dataItem has a subobject reference
+               if ( isset( $value['sobj'] ) && $value['sobj'] !== null ) {
+
+                       $dataItem = $this->unserializeSubobject(
+                               $data,
+                               $value['item'],
+                               new SMWContainerSemanticData( $dataItem )
+                       );
+
+               }
+
+               // Ensure that errors are collected from a subobject level as 
well and
+               // made available at the top
+               if ( $dataItem instanceOf DIContainer ) {
+                       $semanticData->addError( 
$dataItem->getSemanticData()->getErrors() );
+               }
+
+               if ( $property !== null ) {
+                       $semanticData->addPropertyObjectValue( $property, 
$dataItem );
+               }
+
+       }
+
+       /**
+        * Resolves properties and dataitems assigned to a subobject recursively
+        *
+        * @return DIContainer
+        */
+       protected function unserializeSubobject( $data, $id, $semanticData ) {
+
+               foreach ( $data['sobj'] as $subobject ) {
+
+                       if ( $subobject['subject'] === $id ) {
+                               $this->unserializeSemanticData( $subobject, 
$semanticData );
+                       }
+
+               }
+
+               return new DIContainer( $semanticData );
+       }
+
+       /**
+        * Returns DataItemId for a property
+        *
+        * @note Not sure why matching can only be done with the help of 
DataValueFactory
+        * because it is the only place the holds both definitions
+        *
+        * Word of caution, findPropertyTypeID is calling the Store to find the
+        * typeId reference this is costly but at the moment there is no other
+        * way to determine the typeId without the Store being involved
+        *
+        * Reason for this check is to ensure that during unserialization the
+        * correct item in terms of its definition is being sought otherwise
+        * inconsistencies can occur due to type changes of a property between
+        * the time of serialization and its unserialization (e.g for when the
+        * serialization object is stored in cache, DB etc.)
+        *
+        * @return integer
+        */
+       protected function getDataItemId( DIProperty $property ) {
+
+               if ( !isset( $this->dataItemTypeIdCache[ $property->getKey() ] 
) ) {
+                       $this->dataItemTypeIdCache[ $property->getKey() ] = 
DataValueFactory::getDataItemId( $property->findPropertyTypeID() );
+               }
+
+               return $this->dataItemTypeIdCache[ $property->getKey() ];
+       }
+
+}
diff --git a/includes/serializer/SerializerFactory.php 
b/includes/serializer/SerializerFactory.php
new file mode 100644
index 0000000..0120c9f
--- /dev/null
+++ b/includes/serializer/SerializerFactory.php
@@ -0,0 +1,77 @@
+<?php
+
+namespace SMW;
+
+use OutOfBoundsException;
+
+/**
+ * Serializer handler for a serializable object
+ *
+ * @file
+ *
+ * @license GNU GPL v2+
+ * @since   1.9
+ *
+ * @author mwjames
+ */
+
+/**
+ * A factory class that assigns registered serializers to an object and
+ * identifies an unserializer based on the invoked array.
+ *
+ * @ingroup SMW
+ */
+class SerializerFactory {
+
+       /**
+        * Initiates serialization of an object
+        *
+        * @since 1.9
+        *
+        * @param mixed $object
+        *
+        * @return array
+        */
+       public static function serialize( $object ) {
+
+               $serializer = null;
+
+               if ( $object instanceof SemanticData ) {
+                       $serializer = new SemanticDataSerializer;
+               }
+
+               if ( !( $serializer instanceof SerializerInterface ) ) {
+                       throw new OutOfBoundsException( 'For the object no 
serializer has been registered' );
+               }
+
+               return $serializer->serialize( $object );
+       }
+
+       /**
+        * Initiates unserialization of an object
+        *
+        * @note Each object is expected to hold the serializer/unserializer 
reference
+        * class within in its records otherwise an exception is raised
+        *
+        * @since 1.9
+        *
+        * @param array $object
+        *
+        * @return mixed
+        */
+       public static function unserialize( array $object ) {
+
+               $serializer = null;
+
+               if ( isset( $object['serializer'] ) && $object['serializer'] 
!== '' ) {
+                       $serializer = new $object['serializer'];
+               }
+
+               if ( !( $serializer instanceof SerializerInterface ) ) {
+                       throw new OutOfBoundsException( 'The array has no 
unserializer reference point' );
+               }
+
+               return $serializer->unserialize( $object );
+       }
+
+}
diff --git a/includes/serializer/SerializerInterface.php 
b/includes/serializer/SerializerInterface.php
new file mode 100644
index 0000000..94bf2a2
--- /dev/null
+++ b/includes/serializer/SerializerInterface.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace SMW;
+
+/**
+ * Serializer interface
+ *
+ * @file
+ *
+ * @license GNU GPL v2+
+ * @since   1.9
+ *
+ * @author mwjames
+ */
+
+/**
+ * Common interface to access a serializable object
+ *
+ * @ingroup SMW
+ */
+interface SerializerInterface {
+
+       /**
+        * Initiates serialization of an arbitrary object
+        *
+        * @since 1.9
+        *
+        * @param mixed $object
+        *
+        * @return array
+        */
+       public function serialize( $object );
+
+       /**
+        * Initiates unserialization of an arbitrary object
+        *
+        * @since 1.9
+        *
+        * @param array $object
+        *
+        * @return mixed
+        */
+       public function unserialize( array $object );
+
+}
diff --git a/tests/phpunit/includes/serializer/SemanticDataSerializerTest.php 
b/tests/phpunit/includes/serializer/SemanticDataSerializerTest.php
new file mode 100644
index 0000000..bb4ceef
--- /dev/null
+++ b/tests/phpunit/includes/serializer/SemanticDataSerializerTest.php
@@ -0,0 +1,250 @@
+<?php
+
+namespace SMW\Test;
+
+use SMW\SemanticDataSerializer;
+use SMW\DataValueFactory;
+use SMw\SemanticData;
+use SMW\DIWikiPage;
+use SMW\Subobject;
+
+/**
+ * Tests for the SemanticDataSerializer class
+ *
+ * @file
+ *
+ * @license GNU GPL v2+
+ * @since   1.9
+ *
+ * @author mwjames
+ */
+
+/**
+ * @covers \SMW\SemanticDataSerializer
+ *
+ * @ingroup Test
+ *
+ * @group SMW
+ * @group SMWExtension
+ */
+class SemanticDataSerializerTest extends SemanticMediaWikiTestCase {
+
+       /**
+        * Returns the name of the class to be tested
+        *
+        * @return string|false
+        */
+       public function getClass() {
+               return '\SMW\SemanticDataSerializer';
+       }
+
+       /**
+        * Helper method that returns a SemanticDataSerializer object
+        *
+        * @since 1.9
+        *
+        * @param $data
+        *
+        * @return SemanticDataSerializer
+        */
+       private function newInstance() {
+               return new SemanticDataSerializer();
+       }
+
+       /**
+        * @since 1.9
+        */
+       public function testConstructor() {
+               $this->assertInstanceOf( $this->getClass(), 
$this->newInstance() );
+       }
+
+       /**
+        * @since 1.9
+        */
+       public function testSerializeOutOfBoundsException() {
+
+               $this->setExpectedException( 'OutOfBoundsException' );
+
+               $instance = $this->newInstance();
+               $instance->serialize( 'Foo' );
+
+       }
+
+       /**
+        * @since 1.9
+        */
+       public function testUnserializeInvalidVersionOutOfBoundsException() {
+
+               $this->setExpectedException( 'OutOfBoundsException' );
+
+               $instance = $this->newInstance();
+               $instance->unserialize( array( 'version' => 'Foo' ) );
+
+       }
+
+       /**
+        * @since 1.9
+        */
+       public function testUnserializeInvalidSubjectDataItemException() {
+
+               $this->setExpectedException( '\SMW\DataItemException' );
+
+               $instance = $this->newInstance();
+               $instance->unserialize( array( 'subject' => '--#Foo' ) );
+
+       }
+
+       /**
+        * @since 1.9
+        */
+       public function testUnserializeMissingSubjectOutOfBoundsException() {
+
+               $this->setExpectedException( 'OutOfBoundsException' );
+
+               $instance = $this->newInstance();
+               $instance->unserialize( array() );
+
+       }
+
+       /**
+        * @dataProvider semanticDataProvider
+        *
+        * @since 1.9
+        */
+       public function testSerializerUnserializerRountrip( $data ) {
+
+               $instance   = $this->newInstance();
+               $serialized = $instance->serialize( $data );
+
+               $this->assertEquals(
+                       $serialized,
+                       $instance->serialize( $instance->unserialize( 
$serialized ) ),
+                       'Asserts that the intial serialized container is equal 
to a container after a roundtrip'
+               );
+
+
+               $this->assertEquals(
+                       $data->getHash(),
+                       $instance->unserialize( $serialized )->getHash(),
+                       'Asserts that the hash of the orginal SemanticData 
container equals that of the serialized-un-serialized container'
+               );
+       }
+
+       /**
+        * @dataProvider typeChangeSemanticDataProvider
+        *
+        * @since 1.9
+        */
+       public function testForcedTypeErrorDuringRountrip( $data, $type ) {
+
+               $instance   = $this->newInstance();
+               $serialized = $instance->serialize( $data );
+
+               // Injects a different type to cause an error (this would 
normally
+               // happen when a property definition is changed such as page -> 
text
+               // etc.)
+               $reflector = $this->newReflector();
+               $property  = $reflector->getProperty( 'dataItemTypeIdCache' );
+               $property->setAccessible( true );
+               $property->setValue( $instance, array( $type => 2 ) );
+
+               $unserialized = $instance->unserialize( $serialized );
+
+               $this->assertInstanceOf(
+                       'SMW\SemanticData',
+                       $unserialized,
+                       'Asserts the instance'
+               );
+
+               $this->assertNotEmpty(
+                       $unserialized->getErrors(),
+                       'Asserts that getErrors() returns not empty'
+               );
+
+       }
+
+       /**
+        * @return array
+        */
+       public function semanticDataProvider() {
+
+               $provider = array();
+               $title = $this->newTitle( NS_MAIN, 'Foo' );
+
+               // #0 Empty container
+               $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+               $provider[] = array( $foo );
+
+               // #1 Single entry
+               $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+               $foo->addDataValue( DataValueFactory::newPropertyValue( 'Has 
fooQuex', 'Bar' ) );
+               $provider[] = array( $foo );
+
+               // #2 Single + single subobject entry
+               $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+               $foo->addDataValue( DataValueFactory::newPropertyValue( 'Has 
fooQuex', 'Bar' ) );
+
+               $subobject = new Subobject( $title );
+               $subobject->setSemanticData( 'Foo' );
+               $subobject->addDataValue( DataValueFactory::newPropertyValue( 
'Has subobjects', 'Bam' ) );
+
+               $foo->addPropertyObjectValue( $subobject->getProperty(), 
$subobject->getContainer() );
+
+               $provider[] = array( $foo );
+
+               // #3 Multiple entries
+               $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+               $foo->addDataValue( DataValueFactory::newPropertyValue( 'Has 
fooQuex', 'Bar' ) );
+               $foo->addDataValue( DataValueFactory::newPropertyValue( 'Has 
queez', 'Xeey' ) );
+
+               $subobject = new Subobject( $title );
+               $subobject->setSemanticData( 'Foo' );
+               $subobject->addDataValue( DataValueFactory::newPropertyValue( 
'Has subobjects', 'Bam' ) );
+               $subobject->addDataValue( DataValueFactory::newPropertyValue( 
'Has fooQuex', 'Fuz' ) );
+
+               $subobject->setSemanticData( 'Bar' );
+               $subobject->addDataValue( DataValueFactory::newPropertyValue( 
'Has fooQuex', 'Fuz' ) );
+
+               $foo->addPropertyObjectValue( $subobject->getProperty(), 
$subobject->getContainer() );
+
+               $provider[] = array( $foo );
+
+               return $provider;
+       }
+
+       /**
+        * @return array
+        */
+       public function typeChangeSemanticDataProvider() {
+
+               $provider = array();
+               $title = $this->newTitle( NS_MAIN, 'Foo' );
+
+               // #0 Single entry
+               $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+               $foo->addDataValue( DataValueFactory::newPropertyValue( 'Has 
fooQuex', 'Bar' ) );
+
+               $provider[] = array( $foo, 'Has_fooQuex' );
+
+               // #1 Single subobject entry
+               $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+
+               $subobject = new Subobject( $title );
+               $subobject->setSemanticData( 'Foo' );
+               $subobject->addDataValue( DataValueFactory::newPropertyValue( 
'Has fomQuex', 'Bam' ) );
+
+               $foo->addPropertyObjectValue( $subobject->getProperty(), 
$subobject->getContainer() );
+
+               $provider[] = array( $foo, 'Has_fomQuex' );
+
+               // #2 Combined
+               $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+               $foo->addDataValue( DataValueFactory::newPropertyValue( 'Has 
fooQuex', 'Bar' ) );
+               $foo->addPropertyObjectValue( $subobject->getProperty(), 
$subobject->getContainer() );
+
+               $provider[] = array( $foo, 'Has_fomQuex' );
+
+               return $provider;
+       }
+
+}
diff --git a/tests/phpunit/includes/serializer/SerializerFactoryTest.php 
b/tests/phpunit/includes/serializer/SerializerFactoryTest.php
new file mode 100644
index 0000000..bd0fcfc
--- /dev/null
+++ b/tests/phpunit/includes/serializer/SerializerFactoryTest.php
@@ -0,0 +1,123 @@
+<?php
+
+namespace SMW\Test;
+
+use SMW\SerializerFactory;
+use SMw\SemanticData;
+use SMW\DIWikiPage;
+
+/**
+ * Tests for the SerializerFactory class
+ *
+ * @file
+ *
+ * @license GNU GPL v2+
+ * @since   1.9
+ *
+ * @author mwjames
+ */
+
+/**
+ * @covers \SMW\SerializerFactory
+ *
+ * @ingroup Test
+ *
+ * @group SMW
+ * @group SMWExtension
+ */
+class SerializerFactoryTest extends SemanticMediaWikiTestCase {
+
+       /**
+        * Returns the name of the class to be tested
+        *
+        * @return string|false
+        */
+       public function getClass() {
+               return '\SMW\SerializerFactory';
+       }
+
+       /**
+        * @since 1.9
+        */
+       public function testUnregisteredSerializeObjectOutOfBoundsException() {
+
+               $this->setExpectedException( 'OutOfBoundsException' );
+
+               SerializerFactory::serialize( 'Foo' );
+
+       }
+
+       /**
+        * @since 1.9
+        */
+       public function testUnregisteredUnserializeObjectOutOfBoundsException() 
{
+
+               $this->setExpectedException( 'OutOfBoundsException' );
+
+               SerializerFactory::unserialize( array() );
+
+       }
+
+       /**
+        * @dataProvider serializerDataProvider
+        *
+        * @since 1.9
+        */
+       public function testRegisteredSerializerFactory( $object ) {
+
+               $serialized = SerializerFactory::serialize( $object );
+
+               $this->assertInternalType(
+                       'array',
+                       $serialized,
+                       'Asserts that serialize() returns an array'
+               );
+
+       }
+
+       /**
+        * @dataProvider unserializerDataProvider
+        *
+        * @since 1.9
+        */
+       public function testRegisteredUnserializerFactory( $object, $instance ) 
{
+
+               $unserialized = SerializerFactory::unserialize( $object );
+
+               $this->assertInstanceOf(
+                       $instance,
+                       $unserialized,
+                       "Asserts that unserialize() returns a {$instance} 
instance"
+               );
+
+       }
+
+       /**
+        * @return array
+        */
+       public function serializerDataProvider() {
+
+               $provider = array();
+
+               // #0 SemanticData
+               $provider[] = array(
+                        new SemanticData( DIWikiPage::newFromTitle( 
$this->newTitle() ) ),
+               );
+
+               return $provider;
+       }
+
+       /**
+        * @return array
+        */
+       public function unserializerDataProvider() {
+
+               $provider = array();
+
+               // #0 SemanticData
+               $provider[] = array( array( 'serializer' => 
'\SMW\SemanticDataSerializer', 'subject' => 'Foo#0#' ), '\SMW\SemanticData' );
+
+               return $provider;
+       }
+
+}

-- 
To view, visit https://gerrit.wikimedia.org/r/89098
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ief0648e3ca70f9f815139e51528a1bc695bad1fc
Gerrit-PatchSet: 5
Gerrit-Project: mediawiki/extensions/SemanticMediaWiki
Gerrit-Branch: master
Gerrit-Owner: Mwjames <[email protected]>
Gerrit-Reviewer: Jeroen De Dauw <[email protected]>
Gerrit-Reviewer: Mwjames <[email protected]>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to