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

Change subject: Error handling in DescriptionDeserializer
......................................................................


Error handling in DescriptionDeserializer

* Added error handling in DescriptionDeserializer
* Made DeserializationException non-abstract
* Added MissingTypeException

Change-Id: I0bd9623de0cafd6f855002dba08d1207903d7c89
---
M Tests/Integration/Serializers/QuerySerialializationTest.php
M Tests/Phpunit/Deserializers/DescriptionDeserializerTest.php
A Tests/Phpunit/Deserializers/Exceptions/DeserializationExceptionTest.php
A Tests/Phpunit/Deserializers/Exceptions/MissingTypeExceptionTest.php
M Tests/Phpunit/Deserializers/Exceptions/UnsupportedTypeExceptionTest.php
M Tests/Phpunit/Serializers/DescriptionSerializerTest.php
M includes/Ask/Deserializers/DescriptionDeserializer.php
M includes/Ask/Deserializers/Deserializer.php
M includes/Ask/Deserializers/Exceptions/DeserializationException.php
A includes/Ask/Deserializers/Exceptions/MissingTypeException.php
M includes/Ask/Deserializers/Exceptions/UnsupportedTypeException.php
M includes/Ask/Serializers/DescriptionSerializer.php
12 files changed, 587 insertions(+), 54 deletions(-)

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



diff --git a/Tests/Integration/Serializers/QuerySerialializationTest.php 
b/Tests/Integration/Serializers/QuerySerialializationTest.php
index 6bd2be3..386e257 100644
--- a/Tests/Integration/Serializers/QuerySerialializationTest.php
+++ b/Tests/Integration/Serializers/QuerySerialializationTest.php
@@ -88,7 +88,7 @@
                                                                'description' 
=> array(
                                                                        
'objectType' => 'description',
                                                                        
'descriptionType' => 'anyValue',
-                                                                       'value' 
=> null
+                                                                       'value' 
=> array()
                                                                ),
                                                                'isSubProperty' 
=> false
                                                        ),
diff --git a/Tests/Phpunit/Deserializers/DescriptionDeserializerTest.php 
b/Tests/Phpunit/Deserializers/DescriptionDeserializerTest.php
index 43897e3..05f3f73 100644
--- a/Tests/Phpunit/Deserializers/DescriptionDeserializerTest.php
+++ b/Tests/Phpunit/Deserializers/DescriptionDeserializerTest.php
@@ -6,6 +6,7 @@
 use Ask\Language\Description\Description;
 use Ask\Language\Description\SomeProperty;
 use Ask\Deserializers\DescriptionDeserializer;
+use Ask\Language\Description\ValueDescription;
 use DataTypes\DataTypeFactory;
 use DataValues\DataValueFactory;
 use DataValues\StringValue;
@@ -24,10 +25,17 @@
  */
 class DescriptionDeserializerTest extends \PHPUnit_Framework_TestCase {
 
+       protected function newDescriptionDeserializer() {
+               $dvFactory = new DataValueFactory();
+               $dvFactory->registerDataValue( 'string', 
'DataValues\StringValue' );
+
+               return new DescriptionDeserializer( $dvFactory );
+       }
+
        /**
-        * @dataProvider nonDescriptionProvider
+        * @dataProvider invalidObjectTypeProvider
         */
-       public function testCannotSerializeNonDescriptions( $notADescription ) {
+       public function testCannotDeserializeWithInvalidObjectType( 
$notADescription ) {
                $serializer = $this->newDescriptionDeserializer();
 
                $this->assertFalse( $serializer->canDeserialize( 
$notADescription ) );
@@ -36,29 +44,318 @@
                $serializer->deserialize( $notADescription );
        }
 
-       protected function newDescriptionDeserializer() {
-               $dvFactory = new DataValueFactory();
-               $dvFactory->registerDataValue( 'string', 
'DataValues\StringValue' );
-
-               return new DescriptionDeserializer( $dvFactory );
-       }
-
-       public function nonDescriptionProvider() {
+       public function invalidObjectTypeProvider() {
                $argLists = array();
-
-//             $argLists[] = array( null );
-//             $argLists[] = array( array() );
-//             $argLists[] = array( 'foo bar' );
-//
-//             $argLists[] = array( array(
-//                     'descriptionType' => 'anyValue',
-//                     'value' => null
-//             ) );
 
                $argLists[] = array( array(
                        'objectType' => 'foobar',
                        'descriptionType' => 'anyValue',
-                       'value' => null
+                       'value' => array()
+               ) );
+
+               $argLists[] = array( array(
+                       'objectType' => 'DESCRIPTION',
+                       'descriptionType' => 'anyValue',
+                       'value' => array()
+               ) );
+
+               $argLists[] = array( array(
+                       'objectType' => null,
+                       'descriptionType' => 'anyValue',
+                       'value' => array()
+               ) );
+
+               $argLists[] = array( array(
+                       'objectType' => array(),
+                       'descriptionType' => 'anyValue',
+                       'value' => array()
+               ) );
+
+               $argLists[] = array( array(
+                       'objectType' => 42,
+                       'descriptionType' => 'anyValue',
+                       'value' => array()
+               ) );
+
+               return $argLists;
+       }
+
+       /**
+        * @dataProvider missingObjectTypeProvider
+        */
+       public function testCannotDeserilaizeWithoutObjectType( 
$notADescription ) {
+               $serializer = $this->newDescriptionDeserializer();
+
+               $this->assertFalse( $serializer->canDeserialize( 
$notADescription ) );
+
+               $this->setExpectedException( 
'Ask\Deserializers\Exceptions\MissingTypeException' );
+               $serializer->deserialize( $notADescription );
+       }
+
+       public function missingObjectTypeProvider() {
+               $argLists = array();
+
+               $argLists[] = array( null );
+               $argLists[] = array( array() );
+               $argLists[] = array( 'foo bar' );
+
+               $argLists[] = array( array(
+                       'descriptionType' => 'anyValue',
+                       'value' => array()
+               ) );
+
+               $argLists[] = array( array(
+                       'ObjectType' => 'description',
+                       'descriptionType' => 'anyValue',
+                       'value' => array()
+               ) );
+
+               $argLists[] = array( array(
+                       'OBJECTTYPE' => 'description',
+                       'descriptionType' => 'anyValue',
+                       'value' => array()
+               ) );
+
+               return $argLists;
+       }
+
+       public function testCannotDeserilaizeWithUnknownDescriptionType() {
+               $notADescription = array(
+                       'objectType' => 'description',
+                       'descriptionType' => 'fooBar',
+                       'value' => array()
+               );
+
+               $this->setExpectedException( 
'Ask\Deserializers\Exceptions\InvalidAttributeException' );
+               $this->newDescriptionDeserializer()->deserialize( 
$notADescription );
+       }
+
+       public function testCannotDeserilaizeWithoutDescriptionType() {
+               $notADescription = array(
+                       'objectType' => 'description',
+                       'value' => array()
+               );
+
+               $this->setExpectedException( 
'Ask\Deserializers\Exceptions\MissingAttributeException' );
+               $this->newDescriptionDeserializer()->deserialize( 
$notADescription );
+       }
+
+       /**
+        * @dataProvider somePropertyWithMissingAttributeProvider
+        */
+       public function testSomePropertyRequiresAllAttributes( array 
$invalidValue ) {
+               $invalidDescription = array(
+                       'objectType' => 'description',
+                       'descriptionType' => 'someProperty',
+                       'value' => $invalidValue,
+               );
+
+               $this->setExpectedException( 
'Ask\Deserializers\Exceptions\MissingAttributeException' );
+               $this->newDescriptionDeserializer()->deserialize( 
$invalidDescription );
+       }
+
+       public function somePropertyWithMissingAttributeProvider() {
+               $argLists = array();
+
+               $argLists[] = array( array(
+               ) );
+
+               $argLists[] = array( array(
+                       'property' => 'foo',
+                       'isSubProperty' => true,
+               ) );
+
+               $argLists[] = array( array(
+                       'property' => 'foo',
+                       'description' => array(),
+               ) );
+
+               $argLists[] = array( array(
+                       'description' => array(),
+                       'isSubProperty' => true,
+               ) );
+
+               return $argLists;
+       }
+
+       /**
+        * @dataProvider somePropertyWithInvalidAttributeProvider
+        */
+       public function testSomePropertyRequiresValidAttributes( array 
$invalidValue ) {
+               $invalidDescription = array(
+                       'objectType' => 'description',
+                       'descriptionType' => 'someProperty',
+                       'value' => $invalidValue,
+               );
+
+               $this->setExpectedException( 
'Ask\Deserializers\Exceptions\DeserializationException' );
+               $this->newDescriptionDeserializer()->deserialize( 
$invalidDescription );
+       }
+
+       public function somePropertyWithInvalidAttributeProvider() {
+               $argLists = array();
+
+               $p1337 = new StringValue( '1337prop' );
+
+               $argLists[] = array( array(
+                       'property' => $p1337->toArray(),
+                       'description' => array(
+                               'objectType' => 'description',
+                               'descriptionType' => 'anyValue',
+                               'value' => array()
+                       ),
+                       'isSubProperty' => 42,
+               ) );
+
+               $argLists[] = array( array(
+                       'property' => null,
+                       'description' => array(
+                               'objectType' => 'description',
+                               'descriptionType' => 'anyValue',
+                               'value' => array()
+                       ),
+                       'isSubProperty' => true,
+               ) );
+
+               $argLists[] = array( array(
+                       'property' => array( 'foo' => 'bar' ),
+                       'description' => array(
+                               'objectType' => 'description',
+                               'descriptionType' => 'anyValue',
+                               'value' => array()
+                       ),
+                       'isSubProperty' => true,
+               ) );
+
+               $argLists[] = array( array(
+                       'property' => $p1337->toArray(),
+                       'description' => array(
+                       ),
+                       'isSubProperty' => true,
+               ) );
+
+               return $argLists;
+       }
+
+       /**
+        * @dataProvider valueDescriptionWithMissingAttributeProvider
+        */
+       public function testValueDescriptionRequiresAllAttributes( array 
$invalidValue ) {
+               $invalidDescription = array(
+                       'objectType' => 'description',
+                       'descriptionType' => 'valueDescription',
+                       'value' => $invalidValue,
+               );
+
+               $this->setExpectedException( 
'Ask\Deserializers\Exceptions\MissingAttributeException' );
+               $this->newDescriptionDeserializer()->deserialize( 
$invalidDescription );
+       }
+
+       public function valueDescriptionWithMissingAttributeProvider() {
+               $argLists = array();
+
+               $p1337 = new StringValue( '1337prop' );
+
+               $argLists[] = array( array(
+               ) );
+
+               $argLists[] = array( array(
+                       'value' => $p1337->toArray(),
+               ) );
+
+               $argLists[] = array( array(
+                       'comparator' => ValueDescription::COMP_EQUAL, // TODO: 
use string
+               ) );
+
+               return $argLists;
+       }
+
+       /**
+        * @dataProvider valueDescriptionWithInvalidAttributeProvider
+        */
+       public function testValueDescriptionRequiresValidAttributes( array 
$invalidValue ) {
+               $invalidDescription = array(
+                       'objectType' => 'description',
+                       'descriptionType' => 'valueDescription',
+                       'value' => $invalidValue,
+               );
+
+               $this->setExpectedException( 
'Ask\Deserializers\Exceptions\DeserializationException' );
+               $this->newDescriptionDeserializer()->deserialize( 
$invalidDescription );
+       }
+
+       public function valueDescriptionWithInvalidAttributeProvider() {
+               $argLists = array();
+
+               $p1337 = new StringValue( '1337prop' );
+
+               $argLists[] = array( array(
+                       'value' => $p1337->toArray(),
+                       'comparator' => 'hax',
+               ) );
+
+               $argLists[] = array( array(
+                       'value' => null,
+                       'comparator' => ValueDescription::COMP_EQUAL, // TODO: 
use string
+               ) );
+
+               return $argLists;
+       }
+
+       /**
+        * @dataProvider conjunctionWithMissingAttributeProvider
+        */
+       public function testConjunctionRequiresAllAttributes( array 
$invalidValue ) {
+               $invalidDescription = array(
+                       'objectType' => 'description',
+                       'descriptionType' => 'conjunction',
+                       'value' => $invalidValue,
+               );
+
+               $this->setExpectedException( 
'Ask\Deserializers\Exceptions\MissingAttributeException' );
+               $this->newDescriptionDeserializer()->deserialize( 
$invalidDescription );
+       }
+
+       public function conjunctionWithMissingAttributeProvider() {
+               $argLists = array();
+
+               $argLists[] = array( array(
+               ) );
+
+               return $argLists;
+       }
+
+       /**
+        * @dataProvider conjunctionWithInvalidAttributeProvider
+        */
+       public function testConjunctionRequiresValidAttributes( array 
$invalidValue ) {
+               $invalidDescription = array(
+                       'objectType' => 'description',
+                       'descriptionType' => 'conjunction',
+                       'value' => $invalidValue,
+               );
+
+               $this->setExpectedException( 
'Ask\Deserializers\Exceptions\DeserializationException' );
+               $this->newDescriptionDeserializer()->deserialize( 
$invalidDescription );
+       }
+
+       public function conjunctionWithInvalidAttributeProvider() {
+               $argLists = array();
+
+               $argLists[] = array( array(
+                       'descriptions' => null,
+               ) );
+
+               $argLists[] = array( array(
+                       'descriptions' => array( null ),
+               ) );
+
+               $argLists[] = array( array(
+                       'descriptions' => array( 42 ),
+               ) );
+
+               $argLists[] = array( array(
+                       'descriptions' => 42,
                ) );
 
                return $argLists;
@@ -84,7 +381,7 @@
                        array(
                                'objectType' => 'description',
                                'descriptionType' => 'anyValue',
-                               'value' => null
+                               'value' => array()
                        )
                );
 
@@ -101,7 +398,7 @@
                                        'description' => array(
                                                'objectType' => 'description',
                                                'descriptionType' => 'anyValue',
-                                               'value' => null
+                                               'value' => array()
                                        ),
                                        'isSubProperty' => false
                                ),
diff --git 
a/Tests/Phpunit/Deserializers/Exceptions/DeserializationExceptionTest.php 
b/Tests/Phpunit/Deserializers/Exceptions/DeserializationExceptionTest.php
new file mode 100644
index 0000000..11f378b
--- /dev/null
+++ b/Tests/Phpunit/Deserializers/Exceptions/DeserializationExceptionTest.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace Ask\Tests\Phpunit\Deserializers\Exceptions;
+
+use Ask\Deserializers\Exceptions\DeserializationException;
+
+/**
+ * @covers Ask\Deserializers\Exceptions\DeserializationException
+ *
+ * @file
+ * @since 0.1
+ *
+ * @ingroup Ask
+ * @group Ask
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < [email protected] >
+ */
+class DeserializationExceptionTest extends \PHPUnit_Framework_TestCase {
+
+       public function testConstructorWithOnlyRequiredArguments() {
+               $deserializer = $this->getMock( 
'Ask\Deserializers\Deserializer' );
+
+               $exception = new DeserializationException( $deserializer );
+
+               $this->assertRequiredFieldsAreSet( $exception, $deserializer );
+       }
+
+       public function testConstructorWithAllArguments() {
+               $deserializer = $this->getMock( 
'Ask\Deserializers\Deserializer' );
+               $message = 'NyanData all the way across the sky!';
+               $previous = new \Exception( 'Onoez!' );
+
+               $exception = new DeserializationException( $deserializer, 
$message, $previous );
+
+               $this->assertRequiredFieldsAreSet( $exception, $deserializer );
+               $this->assertEquals( $message, $exception->getMessage() );
+               $this->assertEquals( $previous, $exception->getPrevious() );
+       }
+
+       protected function assertRequiredFieldsAreSet( DeserializationException 
$exception, $deserializer ) {
+               $this->assertEquals( $deserializer, 
$exception->getDeserializer() );
+       }
+
+}
diff --git 
a/Tests/Phpunit/Deserializers/Exceptions/MissingTypeExceptionTest.php 
b/Tests/Phpunit/Deserializers/Exceptions/MissingTypeExceptionTest.php
new file mode 100644
index 0000000..f1acad9
--- /dev/null
+++ b/Tests/Phpunit/Deserializers/Exceptions/MissingTypeExceptionTest.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace Ask\Tests\Phpunit\Deserializers\Exceptions;
+
+use Ask\Deserializers\Exceptions\MissingTypeException;
+
+/**
+ * @covers Ask\Deserializers\Exceptions\MissingTypeException
+ *
+ * @file
+ * @since 0.1
+ *
+ * @ingroup Ask
+ * @group Ask
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < [email protected] >
+ */
+class MissingTypeExceptionTest extends \PHPUnit_Framework_TestCase {
+
+       public function testConstructorWithOnlyRequiredArguments() {
+               $deserializer = $this->getMock( 
'Ask\Deserializers\Deserializer' );
+
+               $exception = new MissingTypeException( $deserializer );
+
+               $this->assertRequiredFieldsAreSet( $exception, $deserializer );
+       }
+
+       public function testConstructorWithAllArguments() {
+               $deserializer = $this->getMock( 
'Ask\Deserializers\Deserializer' );
+               $message = 'NyanData all the way across the sky!';
+               $previous = new \Exception( 'Onoez!' );
+
+               $exception = new MissingTypeException( $deserializer, $message, 
$previous );
+
+               $this->assertRequiredFieldsAreSet( $exception, $deserializer );
+               $this->assertEquals( $message, $exception->getMessage() );
+               $this->assertEquals( $previous, $exception->getPrevious() );
+       }
+
+       protected function assertRequiredFieldsAreSet( MissingTypeException 
$exception, $deserializer ) {
+               $this->assertEquals( $deserializer, 
$exception->getDeserializer() );
+       }
+
+}
diff --git 
a/Tests/Phpunit/Deserializers/Exceptions/UnsupportedTypeExceptionTest.php 
b/Tests/Phpunit/Deserializers/Exceptions/UnsupportedTypeExceptionTest.php
index 18d0e0d..0bb215b 100644
--- a/Tests/Phpunit/Deserializers/Exceptions/UnsupportedTypeExceptionTest.php
+++ b/Tests/Phpunit/Deserializers/Exceptions/UnsupportedTypeExceptionTest.php
@@ -19,29 +19,29 @@
 class UnsupportedTypeExceptionTest extends \PHPUnit_Framework_TestCase {
 
        public function testConstructorWithOnlyRequiredArguments() {
-               $serialization = array( 'the' => 'game' );
+               $unsupportedType = 'fooBarBaz';
                $deserializer = $this->getMock( 
'Ask\Deserializers\Deserializer' );
 
-               $exception = new UnsupportedTypeException( $serialization, 
$deserializer );
+               $exception = new UnsupportedTypeException( $unsupportedType, 
$deserializer );
 
-               $this->assertRequiredFieldsAreSet( $exception, $serialization, 
$deserializer );
+               $this->assertRequiredFieldsAreSet( $exception, 
$unsupportedType, $deserializer );
        }
 
        public function testConstructorWithAllArguments() {
-               $serialization = array( 'the' => 'game' );
+               $unsupportedType = 'fooBarBaz';
                $deserializer = $this->getMock( 
'Ask\Deserializers\Deserializer' );
                $message = 'NyanData all the way across the sky!';
                $previous = new \Exception( 'Onoez!' );
 
-               $exception = new UnsupportedTypeException( $serialization, 
$deserializer, $message, $previous );
+               $exception = new UnsupportedTypeException( $unsupportedType, 
$deserializer, $message, $previous );
 
-               $this->assertRequiredFieldsAreSet( $exception, $serialization, 
$deserializer );
+               $this->assertRequiredFieldsAreSet( $exception, 
$unsupportedType, $deserializer );
                $this->assertEquals( $message, $exception->getMessage() );
                $this->assertEquals( $previous, $exception->getPrevious() );
        }
 
-       protected function assertRequiredFieldsAreSet( UnsupportedTypeException 
$exception, $object, $deserializer ) {
-               $this->assertEquals( $object, $exception->getUnsupportedType() 
);
+       protected function assertRequiredFieldsAreSet( UnsupportedTypeException 
$exception, $unsupportedType, $deserializer ) {
+               $this->assertEquals( $unsupportedType, 
$exception->getUnsupportedType() );
                $this->assertEquals( $deserializer, 
$exception->getDeserializer() );
        }
 
diff --git a/Tests/Phpunit/Serializers/DescriptionSerializerTest.php 
b/Tests/Phpunit/Serializers/DescriptionSerializerTest.php
index 032c78b..b771641 100644
--- a/Tests/Phpunit/Serializers/DescriptionSerializerTest.php
+++ b/Tests/Phpunit/Serializers/DescriptionSerializerTest.php
@@ -67,7 +67,7 @@
                        array(
                                'objectType' => 'description',
                                'descriptionType' => 'anyValue',
-                               'value' => null
+                               'value' => array()
                        )
                );
 
@@ -84,7 +84,7 @@
                                        'description' => array(
                                                'objectType' => 'description',
                                                'descriptionType' => 'anyValue',
-                                               'value' => null
+                                               'value' => array()
                                        ),
                                        'isSubProperty' => false
                                ),
diff --git a/includes/Ask/Deserializers/DescriptionDeserializer.php 
b/includes/Ask/Deserializers/DescriptionDeserializer.php
index c20669e..6d0ff3d 100644
--- a/includes/Ask/Deserializers/DescriptionDeserializer.php
+++ b/includes/Ask/Deserializers/DescriptionDeserializer.php
@@ -2,6 +2,10 @@
 
 namespace Ask\Deserializers;
 
+use Ask\Deserializers\Exceptions\DeserializationException;
+use Ask\Deserializers\Exceptions\InvalidAttributeException;
+use Ask\Deserializers\Exceptions\MissingAttributeException;
+use Ask\Deserializers\Exceptions\MissingTypeException;
 use Ask\Language\Description\AnyValue;
 use Ask\Language\Description\Conjunction;
 use Ask\Language\Description\Description;
@@ -12,6 +16,9 @@
 use DataValues\DataValueFactory;
 
 /**
+ * TODO: split individual description handling to own classes to we can use
+ * polymorphic dispatch and not have this big OCP violation.
+ *
  * @since 0.1
  *
  * @file
@@ -34,53 +41,152 @@
        }
 
        protected function assertCanDeserialize( $serialization ) {
-               if ( !$this->canDeserialize( $serialization ) ) {
+               if ( !$this->hasObjectType( $serialization ) ) {
+                       throw new MissingTypeException( $this );
+               }
+
+               if ( !$this->hasCorrectObjectType( $serialization ) ) {
                        throw new UnsupportedTypeException( 
$serialization['objectType'], $this );
                }
        }
 
-       public function canDeserialize( $askObject ) {
-               return $askObject['objectType'] === 'description'; // TODO: 
check element existence
+       public function canDeserialize( $serialization ) {
+               return $this->hasObjectType( $serialization ) && 
$this->hasCorrectObjectType( $serialization );
+       }
+
+       protected function hasCorrectObjectType( $serialization ) {
+               return $serialization['objectType'] === 'description';
+       }
+
+       protected function hasObjectType( $serialization ) {
+               return is_array( $serialization )
+                       && array_key_exists( 'objectType', $serialization );
        }
 
        protected function getDeserializedDescription( array $serialization ) {
+               if ( !array_key_exists( 'descriptionType', $serialization ) ) {
+                       throw new MissingAttributeException(
+                               'descriptionType',
+                               $this
+                       );
+               }
+
+               $this->requireAttribute( $serialization, 'descriptionType' );
+               $this->requireAttribute( $serialization, 'value' );
+               $this->assertAttributeIsArray( $serialization, 'value' );
+
                $descriptionType = $serialization['descriptionType'];
                $descriptionValue = $serialization['value'];
 
+               return $this->getDeserializedValue( $descriptionType, 
$descriptionValue );
+       }
+
+       protected function requireAttribute( array $array, $attributeName ) {
+               if ( !array_key_exists( $attributeName, $array ) ) {
+                       throw new MissingAttributeException(
+                               $attributeName,
+                               $this
+                       );
+               }
+       }
+
+       protected function requireAttributes( array $array ) {
+               $requiredAttributes = func_get_args();
+               array_shift( $requiredAttributes );
+
+               foreach ( $requiredAttributes as $attribute ) {
+                       $this->requireAttribute( $array, $attribute );
+               }
+       }
+
+       protected function getDeserializedValue( $descriptionType, 
$descriptionValue ) {
                if ( $descriptionType === 'anyValue' ) {
                        return new AnyValue();
                }
 
                if ( $descriptionType === 'someProperty' ) {
-                       return new SomeProperty(
+                       return $this->newSomeProperty( $descriptionValue );
+               }
+
+               if ( $descriptionType === 'valueDescription' ) {
+                       return $this->newValueDescription( $descriptionValue );
+               }
+
+               if ( $descriptionType === 'conjunction' ) {
+                       return $this->newConjunction( $descriptionValue );
+               }
+
+               if ( $descriptionType === 'disjunction' ) {
+                       return $this->newDisjunction( $descriptionValue );
+               }
+
+               throw new InvalidAttributeException(
+                       'descriptionType',
+                       $this,
+                       'The provided descriptionType is not supported by this 
deserializer'
+               );
+       }
+
+       protected function assertAttributeIsArray( array $array, $attributeName 
) {
+               if ( !is_array( $array[$attributeName] ) ) {
+                       throw new InvalidAttributeException(
+                               $attributeName,
+                               $this
+                       );
+               }
+       }
+
+       protected function newSomeProperty( array $descriptionValue ) {
+               $this->requireAttributes( $descriptionValue, 'property', 
'description', 'isSubProperty' );
+               $this->assertAttributeIsArray( $descriptionValue, 'property' );
+
+               try {
+                       $someProperty = new SomeProperty(
                                $this->dataValueFactory->newFromArray( 
$descriptionValue['property'] ),
                                $this->deserialize( 
$descriptionValue['description'] ),
                                $descriptionValue['isSubProperty']
                        );
                }
+               catch ( \InvalidArgumentException $ex ) {
+                       throw new DeserializationException( $this, '', $ex );
+               }
 
-               if ( $descriptionType === 'valueDescription' ) {
-                       return new ValueDescription(
+               return $someProperty;
+       }
+
+       protected function newValueDescription( array $descriptionValue ) {
+               $this->requireAttributes( $descriptionValue, 'value', 
'comparator' );
+               $this->assertAttributeIsArray( $descriptionValue, 'value' );
+
+               try {
+                       $valueDescription = new ValueDescription(
                                $this->dataValueFactory->newFromArray( 
$descriptionValue['value'] ),
                                $descriptionValue['comparator']
                        );
                }
-
-               if ( $descriptionType === 'conjunction' ) {
-                       return new Conjunction(
-                               $this->deserializeDescriptions( 
$descriptionValue['descriptions'] )
-                       );
+               catch ( \InvalidArgumentException $ex ) {
+                       throw new DeserializationException( $this, '', $ex );
                }
 
-               if ( $descriptionType === 'disjunction' ) {
-                       return new Disjunction(
-                               $this->deserializeDescriptions( 
$descriptionValue['descriptions'] )
-                       );
-               }
+               return $valueDescription;
+       }
 
-               // TODO: handle desc type unknown
-               // TODO: validate elements are there
-               // TODO: validate element types
+       protected function newConjunction( array $descriptionValue ) {
+               $this->requireAttribute( $descriptionValue, 'descriptions' );
+               $this->assertAttributeIsArray( $descriptionValue, 
'descriptions' );
+
+               return new Conjunction(
+                       $this->deserializeDescriptions( 
$descriptionValue['descriptions'] )
+               );
+       }
+
+       protected function newDisjunction( array $descriptionValue ) {
+               $this->requireAttribute( $descriptionValue, 'descriptions' );
+               $this->assertAttributeIsArray( $descriptionValue, 
'descriptions' );
+
+               return new Disjunction(
+                       $this->deserializeDescriptions( 
$descriptionValue['descriptions'] )
+               );
        }
 
        /**
diff --git a/includes/Ask/Deserializers/Deserializer.php 
b/includes/Ask/Deserializers/Deserializer.php
index dc10cc1..100dde0 100644
--- a/includes/Ask/Deserializers/Deserializer.php
+++ b/includes/Ask/Deserializers/Deserializer.php
@@ -26,6 +26,13 @@
        public function deserialize( $serialization );
 
        /**
+        * Returns if the deserializer can deserialzie the provided object.
+        *
+        * Note: deserializers are expected to do checks to verify the provided
+        * object is of a type they can deserialize. No full deserialization is
+        * attempted. Thus when providing invalid data structures, it is 
possible
+        * this method returns true even though deserialization will fail.
+        *
         * @since 0.1
         *
         * @param mixed $serialization
diff --git a/includes/Ask/Deserializers/Exceptions/DeserializationException.php 
b/includes/Ask/Deserializers/Exceptions/DeserializationException.php
index 40145ef..40551df 100644
--- a/includes/Ask/Deserializers/Exceptions/DeserializationException.php
+++ b/includes/Ask/Deserializers/Exceptions/DeserializationException.php
@@ -13,7 +13,7 @@
  * @licence GNU GPL v2+
  * @author Jeroen De Dauw < [email protected] >
  */
-abstract class DeserializationException extends \RuntimeException {
+class DeserializationException extends \RuntimeException {
 
        protected $deserializer;
 
diff --git a/includes/Ask/Deserializers/Exceptions/MissingTypeException.php 
b/includes/Ask/Deserializers/Exceptions/MissingTypeException.php
new file mode 100644
index 0000000..63cece9
--- /dev/null
+++ b/includes/Ask/Deserializers/Exceptions/MissingTypeException.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Ask\Deserializers\Exceptions;
+
+use Ask\Deserializers\Deserializer;
+
+/**
+ * Indicates the objectType key is missing in the serialization.
+ *
+ * @since 0.1
+ *
+ * @file
+ * @ingroup Ask
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < [email protected] >
+ */
+class MissingTypeException extends DeserializationException {
+
+       protected $unsupportedType;
+
+       /**
+        * @param Deserializer $deserializer
+        * @param string $message
+        * @param \Exception $previous
+        */
+       public function __construct( Deserializer $deserializer, $message = '', 
\Exception $previous = null ) {
+               parent::__construct( $deserializer, $message, $previous );
+       }
+
+}
diff --git a/includes/Ask/Deserializers/Exceptions/UnsupportedTypeException.php 
b/includes/Ask/Deserializers/Exceptions/UnsupportedTypeException.php
index 0f420e8..fe9fe3b 100644
--- a/includes/Ask/Deserializers/Exceptions/UnsupportedTypeException.php
+++ b/includes/Ask/Deserializers/Exceptions/UnsupportedTypeException.php
@@ -5,6 +5,8 @@
 use Ask\Deserializers\Deserializer;
 
 /**
+ * Indicates the objectType specified in the serialization is not supported by 
a deserializer.
+ *
  * @since 0.1
  *
  * @file
diff --git a/includes/Ask/Serializers/DescriptionSerializer.php 
b/includes/Ask/Serializers/DescriptionSerializer.php
index ea91a2d..40bf0a6 100644
--- a/includes/Ask/Serializers/DescriptionSerializer.php
+++ b/includes/Ask/Serializers/DescriptionSerializer.php
@@ -35,7 +35,7 @@
 
        protected function getDescriptionValueSerialization( Description 
$description ) {
                if ( $description instanceof AnyValue ) {
-                       return null;
+                       return array();
                }
 
                if ( $description instanceof SomeProperty ) {

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I0bd9623de0cafd6f855002dba08d1207903d7c89
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Ask
Gerrit-Branch: master
Gerrit-Owner: Jeroen De Dauw <[email protected]>
Gerrit-Reviewer: Addshore <[email protected]>
Gerrit-Reviewer: Anja Jentzsch <[email protected]>
Gerrit-Reviewer: Ataherivand <[email protected]>
Gerrit-Reviewer: Aude <[email protected]>
Gerrit-Reviewer: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: Daniel Werner <[email protected]>
Gerrit-Reviewer: Denny Vrandecic <[email protected]>
Gerrit-Reviewer: Henning Snater <[email protected]>
Gerrit-Reviewer: Jens Ohlig <[email protected]>
Gerrit-Reviewer: Jeroen De Dauw <[email protected]>
Gerrit-Reviewer: John Erling Blad <[email protected]>
Gerrit-Reviewer: Liangent <[email protected]>
Gerrit-Reviewer: Lydia Pintscher <[email protected]>
Gerrit-Reviewer: Markus Kroetzsch <[email protected]>
Gerrit-Reviewer: Nikola Smolenski <[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