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

Change subject: (bug 57214) use DispatchingEntitySerializer for JSON
......................................................................


(bug 57214) use DispatchingEntitySerializer for JSON

This introduces DispatchingEntitySerializer, a serializer for entities
that dispatches to the appropriate serializer based on entity type. This
allows dumpJson to generate the appropriate JSON representation for all
types of entitites.

This incidentally also causes the datatype to be included in serialized
snaks in the output from dumpJson, fixing bug #57212
(but not #57213 and #57231).

bug: 57214
bug: 57212

Change-Id: Ic360a399c3abebecaae90c3186e385b0292663f9
---
M lib/WikibaseLib.classes.php
A lib/includes/serializers/DispatchingEntitySerializer.php
M lib/includes/serializers/EntitySerializer.php
M lib/includes/serializers/SerializerFactory.php
M lib/tests/phpunit/Dumpers/JsonDumpGeneratorTest.php
A lib/tests/phpunit/serializers/DispatchingEntitySerializerTest.php
M lib/tests/phpunit/serializers/SerializerFactoryTest.php
M repo/maintenance/dumpJson.php
8 files changed, 333 insertions(+), 18 deletions(-)

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



diff --git a/lib/WikibaseLib.classes.php b/lib/WikibaseLib.classes.php
index f48a838..66cfa33 100644
--- a/lib/WikibaseLib.classes.php
+++ b/lib/WikibaseLib.classes.php
@@ -145,6 +145,7 @@
                'Wikibase\Lib\Serializers\ByPropertyListUnserializer' => 
'includes/serializers/ByPropertyListUnserializer.php',
                'Wikibase\Lib\Serializers\ClaimSerializer' => 
'includes/serializers/ClaimSerializer.php',
                'Wikibase\Lib\Serializers\ClaimsSerializer' => 
'includes/serializers/ClaimsSerializer.php',
+               'Wikibase\Lib\Serializers\DispatchingEntitySerializer' => 
'includes/serializers/DispatchingEntitySerializer.php',
                'Wikibase\Lib\Serializers\EntitySerializer' => 
'includes/serializers/EntitySerializer.php',
                'Wikibase\Lib\Serializers\ItemSerializer' => 
'includes/serializers/ItemSerializer.php',
                'Wikibase\Lib\Serializers\LabelSerializer' => 
'includes/serializers/LabelSerializer.php',
diff --git a/lib/includes/serializers/DispatchingEntitySerializer.php 
b/lib/includes/serializers/DispatchingEntitySerializer.php
new file mode 100644
index 0000000..42292c4
--- /dev/null
+++ b/lib/includes/serializers/DispatchingEntitySerializer.php
@@ -0,0 +1,107 @@
+<?php
+
+namespace Wikibase\Lib\Serializers;
+
+use InvalidArgumentException;
+use Wikibase\Claims;
+use Wikibase\DataModel\Entity\BasicEntityIdParser;
+use Wikibase\Entity;
+use Wikibase\EntityFactory;
+
+/**
+ * Serializer for entities, dispatching to the appropriate serializer for each 
entity type.
+ *
+ * See docs/json.wiki for details of the format.
+ *
+ * @since 0.5
+ *
+ * @licence GNU GPL v2+
+ * @author Daniel Kinzler
+ */
+class DispatchingEntitySerializer extends SerializerObject implements 
Unserializer {
+
+       /**
+        * @var SerializerFactory
+        */
+       protected $serializerFactory;
+
+       /**
+        * @var Serializer[]
+        */
+       protected $serializers;
+
+       /**
+        * @var Unserializer[]
+        */
+       protected $unserializers;
+
+       /**
+        * @param SerializerFactory $serializerFactory
+        * @param SerializationOptions $options
+        */
+       public function __construct( SerializerFactory $serializerFactory, 
SerializationOptions $options = null ) {
+               parent::__construct( $options );
+
+               $this->serializerFactory = $serializerFactory;
+       }
+
+       /**
+        * @param Entity $entity
+        *
+        * @return array
+        * @throws InvalidArgumentException
+        */
+       public function getSerialized( $entity ) {
+               if ( !( $entity instanceof Entity ) ) {
+                       throw new InvalidArgumentException( 'EntitySerializer 
can only serialize Entity objects' );
+               }
+
+               $serializer = $this->getSerializer( $entity->getType() );
+
+               return $serializer->getSerialized( $entity );
+       }
+
+       /**
+        * Constructs the original object from the provided serialization.
+        *
+        * @since 0.4
+        *
+        * @param array $serialization
+        *
+        * @return Entity
+        */
+       public function newFromSerialization( array $serialization ) {
+               if ( !isset( $serialization['type'] ) ) {
+                       throw new InvalidArgumentException( 
'$serialization[\'type\'] must be set' );
+               }
+
+               $entityType = $serialization['type'];
+               $serializer = $this->getUnserializer( $entityType );
+
+               return $serializer->newFromSerialization( $serialization );
+       }
+
+       /**
+        * @param string $entityType
+        * @return Serializer
+        */
+       protected function getSerializer( $entityType ) {
+               if ( !isset( $this->serializers[$entityType] ) ) {
+                       $this->serializers[$entityType] = 
$this->serializerFactory->newSerializerForEntity( $entityType, $this->options );
+               }
+
+               return $this->serializers[$entityType];
+       }
+
+       /**
+        * @param string $entityType
+        * @return Unserializer
+        */
+       protected function getUnserializer( $entityType ) {
+               if ( !isset( $this->unserializers[$entityType] ) ) {
+                       $this->unserializers[$entityType] = 
$this->serializerFactory->newUnserializerForEntity( $entityType, $this->options 
);
+               }
+
+               return $this->unserializers[$entityType];
+       }
+}
diff --git a/lib/includes/serializers/EntitySerializer.php 
b/lib/includes/serializers/EntitySerializer.php
index 505284d..f50696f 100644
--- a/lib/includes/serializers/EntitySerializer.php
+++ b/lib/includes/serializers/EntitySerializer.php
@@ -20,8 +20,9 @@
  * @author John Erling Blad < [email protected] >
  * @author Tobias Gritschacher < [email protected] >
  * @author Katie Filbert < [email protected] >
+ * @author Daniel Kinzler
  */
-class EntitySerializer extends SerializerObject implements Unserializer {
+abstract class EntitySerializer extends SerializerObject implements 
Unserializer {
 
        const SORT_ASC = 'ascending';
        const SORT_DESC = 'descending';
diff --git a/lib/includes/serializers/SerializerFactory.php 
b/lib/includes/serializers/SerializerFactory.php
index 9082484..3276d53 100644
--- a/lib/includes/serializers/SerializerFactory.php
+++ b/lib/includes/serializers/SerializerFactory.php
@@ -104,6 +104,7 @@
                                return $this->newItemSerializer( $options );
                        case ( $object instanceof Property ):
                                return $this->newPropertySerializer( $options );
+                       //TODO: support extra entity types!
                        case ( $object instanceof Claim ):
                                return $this->newClaimSerializer( $options );
                        case ( $object instanceof Claims ):
@@ -139,6 +140,7 @@
                                return $this->newItemUnserializer( $options );
                        case 'Wikibase\Property':
                                return $this->newPropertyUnserializer( $options 
);
+                       //TODO: support extra entity types!
                        case 'Wikibase\Snak':
                                return $this->newSnakUnserializer( $options );
                        case 'Wikibase\Reference':
@@ -157,14 +159,34 @@
         * @param SerializationOptions $options
         *
         * @throws InvalidArgumentException
+        * @return Serializer
+        */
+       public function newSerializerForEntity( $entityType, $options ) {
+               switch( $entityType ) {
+                       case Item::ENTITY_TYPE:
+                               return $this->newItemSerializer( $options );
+                       case Property::ENTITY_TYPE:
+                               return $this->newPropertySerializer( $options );
+                       //TODO: support extra entity types!
+                       default:
+                               throw new InvalidArgumentException( 
'$entityType is invalid' );
+               }
+       }
+
+       /**
+        * @param string $entityType
+        * @param SerializationOptions $options
+        *
+        * @throws InvalidArgumentException
         * @return Unserializer
         */
        public function newUnserializerForEntity( $entityType, $options ) {
                switch( $entityType ) {
-                       case 'wikibase-item':
+                       case Item::ENTITY_TYPE:
                                return $this->newItemUnserializer( $options );
-                       case 'wikibase-property':
+                       case Property::ENTITY_TYPE:
                                return $this->newPropertyUnserializer( $options 
);
+                       //TODO: support extra entity types!
                        default:
                                throw new InvalidArgumentException( 
'$entityType is invalid' );
                }
diff --git a/lib/tests/phpunit/Dumpers/JsonDumpGeneratorTest.php 
b/lib/tests/phpunit/Dumpers/JsonDumpGeneratorTest.php
index 387c38f..fbcb049 100644
--- a/lib/tests/phpunit/Dumpers/JsonDumpGeneratorTest.php
+++ b/lib/tests/phpunit/Dumpers/JsonDumpGeneratorTest.php
@@ -6,11 +6,15 @@
 use Wikibase\DataModel\Entity\EntityId;
 use Wikibase\DataModel\Entity\ItemId;
 use Wikibase\DataModel\Entity\PropertyId;
+use Wikibase\DataModel\SimpleSiteLink;
 use Wikibase\Dumpers\JsonDumpGenerator;
 use Wikibase\Entity;
 use Wikibase\EntityContentFactory;
 use Wikibase\EntityFactory;
 use Wikibase\Item;
+use Wikibase\Lib\Serializers\DispatchingEntitySerializer;
+use Wikibase\Lib\Serializers\SerializationOptions;
+use Wikibase\Lib\Serializers\SerializerFactory;
 use Wikibase\Property;
 use Wikibase\StorageException;
 
@@ -27,6 +31,23 @@
 class JsonDumpGeneratorTest extends \PHPUnit_Framework_TestCase {
 
        /**
+        * @var SerializerFactory
+        */
+       public $serializerFactory = null;
+
+       /**
+        * @var SerializationOptions
+        */
+       public $serializationOptions = null;
+
+       public function setUp() {
+               parent::setUp();
+
+               $this->serializerFactory = new SerializerFactory();
+               $this->serializationOptions = new SerializationOptions();
+       }
+
+       /**
         * @param EntityId[] $ids
         *
         * @return Entity[]
@@ -36,14 +57,34 @@
 
                /* @var EntityId $id */
                foreach ( $ids as $id ) {
-                       $entity = EntityFactory::singleton()->newEmpty( 
$id->getEntityType() );
-                       $entity->setId( $id );
+                       $entity = $this->makeEntity( $id );
 
                        $key = $id->getPrefixedId();
                        $entities[$key] = $entity;
                }
 
                return $entities;
+       }
+
+       /**
+        * @param EntityId $id
+        *
+        * @return Entity
+        */
+       protected function makeEntity( EntityId $id ) {
+               $entity = EntityFactory::singleton()->newEmpty( 
$id->getEntityType() );
+               $entity->setId( $id );
+               $entity->setLabel( 'en', 'label:' . $id->getSerialization() );
+
+               if ( $entity instanceof Property ) {
+                       $entity->setDataTypeId( 'wibblywobbly' );
+               }
+
+               if ( $entity instanceof Item ) {
+                       $entity->addSimpleSiteLink( new SimpleSiteLink( 'test', 
'Foo' ) );
+               }
+
+               return $entity;
        }
 
        /**
@@ -54,15 +95,7 @@
        protected function newDumpGenerator( array $ids = array(), array 
$missingIds = array() ) {
                $out = fopen( 'php://output', 'w' );
 
-               $serializer = $this->getMock( 
'Wikibase\Lib\Serializers\Serializer' );
-               $serializer->expects( $this->any() )
-                       ->method( 'getSerialized' )
-                       ->will( $this->returnCallback( function ( Entity 
$entity ) {
-                                               return array(
-                                                       'id' => 
$entity->getId()->getPrefixedId()
-                                               );
-                                       }
-                       ) );
+               $serializer = new DispatchingEntitySerializer( 
$this->serializerFactory );
 
                $entities = $this->makeEntities( $ids );
 
@@ -122,6 +155,24 @@
                }, $data );
 
                $this->assertEquals( $expectedIds, $actualIds );
+
+               foreach ( $data as $serialization ) {
+                       $id = EntityId::newFromPrefixedId( $serialization['id'] 
);
+                       $this->assertEntitySerialization( $id, $serialization );
+               }
+       }
+
+       protected function assertEntitySerialization( EntityId $id, $data ) {
+               $expectedEntity = $this->makeEntity( $id );
+
+               if ( !$expectedEntity ) {
+                       return;
+               }
+
+               $serializer = 
$this->serializerFactory->newUnserializerForEntity( $id->getEntityType(), 
$this->serializationOptions );
+               $actualEntity = $serializer->newFromSerialization( $data );
+
+               $this->assertTrue( $expectedEntity->equals( $actualEntity ), 
'Round trip failed for ' . $id->getSerialization() );
        }
 
        public static function typeFilterProvider() {
diff --git a/lib/tests/phpunit/serializers/DispatchingEntitySerializerTest.php 
b/lib/tests/phpunit/serializers/DispatchingEntitySerializerTest.php
new file mode 100644
index 0000000..d46c6c1
--- /dev/null
+++ b/lib/tests/phpunit/serializers/DispatchingEntitySerializerTest.php
@@ -0,0 +1,94 @@
+<?php
+
+namespace Wikibase\Test;
+
+use Wikibase\DataModel\Entity\ItemId;
+use Wikibase\DataModel\Entity\PropertyId;
+use Wikibase\DataModel\SimpleSiteLink;
+use Wikibase\Entity;
+use Wikibase\Item;
+use Wikibase\Lib\Serializers\ClaimSerializer;
+use Wikibase\Lib\Serializers\ItemSerializer;
+use Wikibase\Lib\Serializers\SerializationOptions;
+use Wikibase\Lib\Serializers\EntitySerializer;
+use Wikibase\Lib\Serializers\SerializerFactory;
+use Wikibase\Property;
+
+/**
+ * @covers Wikibase\Lib\Serializers\DispatchingEntitySerializer
+ *
+ * @since 0.5
+ *
+ * @group WikibaseLib
+ * @group Wikibase
+ * @group WikibaseSerialization
+ *
+ * @licence GNU GPL v2+
+ * @author Daniel Kinzler
+ */
+class DispatchingEntitySerializerTest extends EntitySerializerBaseTest {
+
+       /**
+        * @see SerializerBaseTest::getClass
+        *
+        * @since 0.5
+        *
+        * @return string
+        */
+       protected function getClass() {
+               return '\Wikibase\Lib\Serializers\DispatchingEntitySerializer';
+       }
+
+       /**
+        * @return ItemSerializer
+        */
+       protected function getInstance() {
+               $factory = new SerializerFactory();
+
+               $class = $this->getClass();
+               return new $class( $factory );
+       }
+
+       /**
+        * @see SerializerBaseTest::validProvider
+        *
+        * @since 0.5
+        *
+        * @return array
+        */
+       public function validProvider() {
+               return array(
+                       array( $this->getItemInstance() ),
+                       array( $this->getPropertyInstance() ),
+               );
+       }
+
+       /**
+        * @return Entity
+        */
+       protected function getEntityInstance() {
+               return $this->getInstance();
+       }
+
+       /**
+        * @return Entity
+        */
+       protected function getItemInstance() {
+               $item = Item::newEmpty();
+               $item->setId( new ItemId( 'Q17' ) );
+               $item->addSimpleSiteLink( new SimpleSiteLink( 'test', 'Foo' ) );
+
+               return $item;
+       }
+
+       /**
+        * @return Entity
+        */
+       protected function getPropertyInstance() {
+               $property = Property::newEmpty();
+               $property->setId( new PropertyId( 'P17' ) );
+               $property->setDataTypeId( 'wibbly' );
+
+               return $property;
+       }
+}
diff --git a/lib/tests/phpunit/serializers/SerializerFactoryTest.php 
b/lib/tests/phpunit/serializers/SerializerFactoryTest.php
index ae5658d..23155f0 100644
--- a/lib/tests/phpunit/serializers/SerializerFactoryTest.php
+++ b/lib/tests/phpunit/serializers/SerializerFactoryTest.php
@@ -6,6 +6,7 @@
 use Wikibase\Item;
 use Wikibase\Lib\Serializers\SerializationOptions;
 use Wikibase\Lib\Serializers\SerializerFactory;
+use Wikibase\Property;
 use Wikibase\PropertyNoValueSnak;
 use Wikibase\Reference;
 
@@ -83,6 +84,37 @@
                $unserializer->newFromSerialization( $serialization );
        }
 
+       public function entityTypeProvider() {
+               return array(
+                       array( Item::ENTITY_TYPE ),
+                       array( Property::ENTITY_TYPE ),
+               );
+       }
+
+       /**
+        * @dataProvider entityTypeProvider
+        */
+       public function testNewUnserializerForEntity( $entityType ) {
+               $factory = new SerializerFactory();
+               $options = new SerializationOPtions();
+
+               $unserializer = $factory->newUnserializerForEntity( 
$entityType, $options );
+
+               $this->assertInstanceOf( 
'Wikibase\Lib\Serializers\Unserializer', $unserializer );
+       }
+
+       /**
+        * @dataProvider entityTypeProvider
+        */
+       public function testNewSerializerForEntity( $entityType ) {
+               $factory = new SerializerFactory();
+               $options = new SerializationOPtions();
+
+               $unserializer = $factory->newSerializerForEntity( $entityType, 
$options );
+
+               $this->assertInstanceOf( 'Wikibase\Lib\Serializers\Serializer', 
$unserializer );
+       }
+
        public function newUnserializerProvider() {
                $names = array(
                        'SnakUnserializer',
diff --git a/repo/maintenance/dumpJson.php b/repo/maintenance/dumpJson.php
index 57ca15b..f45a25c 100644
--- a/repo/maintenance/dumpJson.php
+++ b/repo/maintenance/dumpJson.php
@@ -11,11 +11,11 @@
 use Wikibase\Dumpers\JsonDumpGenerator;
 use Wikibase\IO\EntityIdReader;
 use Wikibase\Lib\EntityIdFormatter;
-use Wikibase\Lib\Serializers\ClaimSerializer;
+use Wikibase\Lib\Serializers\DispatchingEntitySerializer;
 use Wikibase\Lib\Serializers\SerializationOptions;
 use Wikibase\Lib\Serializers\EntitySerializer;
 use Wikibase\Lib\Serializers\Serializer;
-use Wikibase\Lib\Serializers\SnakSerializer;
+use Wikibase\Lib\Serializers\SerializerFactory;
 use Wikibase\Repo\WikibaseRepo;
 
 $basePath = getenv( 'MW_INSTALL_PATH' ) !== false ? getenv( 'MW_INSTALL_PATH' 
) : __DIR__ . '/../../../..';
@@ -69,9 +69,16 @@
        }
 
        public function initServices() {
-               //FIXME: provide PropertyDataTypeLookup and make the entity 
serializer aware of different entity types
+               $entityFactory = new EntityFactory(); // this should come from 
WikibaseRepo, really
                $serializerOptions = new SerializationOptions();
-               $this->entitySerializer = new EntitySerializer( new 
ClaimSerializer( new SnakSerializer(), $serializerOptions), $serializerOptions 
);
+
+               $serializerFactory = new SerializerFactory(
+                       $serializerOptions,
+                       
WikibaseRepo::getDefaultInstance()->getPropertyDataTypeLookup(),
+                       $entityFactory
+               );
+
+               $this->entitySerializer = new DispatchingEntitySerializer( 
$serializerFactory, $serializerOptions );
 
                //TODO: allow injection for unit tests
                $this->entityPerPage = new EntityPerPageTable();

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

Gerrit-MessageType: merged
Gerrit-Change-Id: Ic360a399c3abebecaae90c3186e385b0292663f9
Gerrit-PatchSet: 11
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: Addshore <[email protected]>
Gerrit-Reviewer: Aude <[email protected]>
Gerrit-Reviewer: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: Tobias Gritschacher <[email protected]>
Gerrit-Reviewer: jenkins-bot

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

Reply via email to