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

Change subject: Upgrade justinrainbow/json-schema to 3.0.0
......................................................................


Upgrade justinrainbow/json-schema to 3.0.0

mediawiki/core change: Ie37e2ebc48684783abf8d99d2f775ee6a5988da7

Bug: T141281
Change-Id: I5687286da9f7fa2bb2b84699fa43ab3c2547fe03
---
M composer.json
M composer.lock
M composer/autoload_classmap.php
M composer/installed.json
M justinrainbow/json-schema/LICENSE
M justinrainbow/json-schema/README.md
M justinrainbow/json-schema/bin/validate-json
M justinrainbow/json-schema/composer.json
M justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php
M justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php
M justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php
M justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php
M justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php
M justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php
M justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php
M justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php
M justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php
M justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php
A 
justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/LooseTypeCheck.php
A 
justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/StrictTypeCheck.php
A 
justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/TypeCheckInterface.php
M justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php
M justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php
A justinrainbow/json-schema/src/JsonSchema/Entity/JsonPointer.php
A justinrainbow/json-schema/src/JsonSchema/Exception/ExceptionInterface.php
M 
justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.php
M 
justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.php
M justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php
M 
justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.php
A justinrainbow/json-schema/src/JsonSchema/Exception/RuntimeException.php
A 
justinrainbow/json-schema/src/JsonSchema/Exception/UnresolvableJsonPointerException.php
M justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.php
A justinrainbow/json-schema/src/JsonSchema/Iterator/ObjectIterator.php
D justinrainbow/json-schema/src/JsonSchema/RefResolver.php
A justinrainbow/json-schema/src/JsonSchema/Rfc3339.php
A justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php
M justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php
M justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php
M justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php
A justinrainbow/json-schema/src/JsonSchema/UriResolverInterface.php
A justinrainbow/json-schema/src/JsonSchema/UriRetrieverInterface.php
M justinrainbow/json-schema/src/JsonSchema/Validator.php
42 files changed, 1,189 insertions(+), 722 deletions(-)

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



diff --git a/composer.json b/composer.json
index 7b93d52..1016ecc 100644
--- a/composer.json
+++ b/composer.json
@@ -12,7 +12,7 @@
                "composer/semver": "1.4.1",
                "cssjanus/cssjanus": "1.1.2",
                "firebase/php-jwt": "3.0.0",
-               "justinrainbow/json-schema": "1.6.1",
+               "justinrainbow/json-schema": "3.0.0",
                "liuggio/statsd-php-client": "1.0.18",
                "mediawiki/at-ease": "1.1.0",
                "monolog/monolog": "1.18.2",
diff --git a/composer.lock b/composer.lock
index d2e78bb..c6c2b85 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,8 @@
         "Read more about it at 
https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file";,
         "This file is @generated automatically"
     ],
-    "hash": "734c21496ddd54f2917041bdc05df0b5",
-    "content-hash": "1ea81f4b4d9c4f4ca0977e563301ced4",
+    "hash": "1cc6a5de43fe526c49c5f85b20122f91",
+    "content-hash": "a98e839402d2e58bf05a4b999e86c14d",
     "packages": [
         {
             "name": "composer/semver",
@@ -149,25 +149,25 @@
         },
         {
             "name": "justinrainbow/json-schema",
-            "version": "1.6.1",
+            "version": "3.0.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/justinrainbow/json-schema.git";,
-                "reference": "cc84765fb7317f6b07bd8ac78364747f95b86341"
+                "reference": "12965831120bb18852e9865804a6089906323b8e"
             },
             "dist": {
                 "type": "zip",
-                "url": 
"https://api.github.com/repos/justinrainbow/json-schema/zipball/cc84765fb7317f6b07bd8ac78364747f95b86341";,
-                "reference": "cc84765fb7317f6b07bd8ac78364747f95b86341",
+                "url": 
"https://api.github.com/repos/justinrainbow/json-schema/zipball/12965831120bb18852e9865804a6089906323b8e";,
+                "reference": "12965831120bb18852e9865804a6089906323b8e",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.3.29"
+                "php": ">=5.3.3"
             },
             "require-dev": {
-                "json-schema/json-schema-test-suite": "1.1.0",
+                "json-schema/json-schema-test-suite": "1.2.0",
                 "phpdocumentor/phpdocumentor": "~2",
-                "phpunit/phpunit": "~3.7"
+                "phpunit/phpunit": "^4.8.22"
             },
             "bin": [
                 "bin/validate-json"
@@ -175,7 +175,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "1.6.x-dev"
+                    "dev-master": "2.0.x-dev"
                 }
             },
             "autoload": {
@@ -185,7 +185,7 @@
             },
             "notification-url": "https://packagist.org/downloads/";,
             "license": [
-                "BSD-3-Clause"
+                "MIT"
             ],
             "authors": [
                 {
@@ -211,7 +211,7 @@
                 "json",
                 "schema"
             ],
-            "time": "2016-01-25 15:43:01"
+            "time": "2016-08-15 16:39:11"
         },
         {
             "name": "liuggio/statsd-php-client",
diff --git a/composer/autoload_classmap.php b/composer/autoload_classmap.php
index 3b5596c..db509a9 100644
--- a/composer/autoload_classmap.php
+++ b/composer/autoload_classmap.php
@@ -309,15 +309,26 @@
     'JsonSchema\\Constraints\\ObjectConstraint' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php',
     'JsonSchema\\Constraints\\SchemaConstraint' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php',
     'JsonSchema\\Constraints\\StringConstraint' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php',
+    'JsonSchema\\Constraints\\TypeCheck\\LooseTypeCheck' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/LooseTypeCheck.php',
+    'JsonSchema\\Constraints\\TypeCheck\\StrictTypeCheck' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/StrictTypeCheck.php',
+    'JsonSchema\\Constraints\\TypeCheck\\TypeCheckInterface' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/TypeCheckInterface.php',
     'JsonSchema\\Constraints\\TypeConstraint' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php',
     'JsonSchema\\Constraints\\UndefinedConstraint' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php',
+    'JsonSchema\\Entity\\JsonPointer' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Entity/JsonPointer.php',
+    'JsonSchema\\Exception\\ExceptionInterface' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Exception/ExceptionInterface.php',
     'JsonSchema\\Exception\\InvalidArgumentException' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.php',
     'JsonSchema\\Exception\\InvalidSchemaMediaTypeException' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.php',
     'JsonSchema\\Exception\\InvalidSourceUriException' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSourceUriException.php',
     'JsonSchema\\Exception\\JsonDecodingException' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php',
     'JsonSchema\\Exception\\ResourceNotFoundException' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.php',
+    'JsonSchema\\Exception\\RuntimeException' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Exception/RuntimeException.php',
+    'JsonSchema\\Exception\\UnresolvableJsonPointerException' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Exception/UnresolvableJsonPointerException.php',
     'JsonSchema\\Exception\\UriResolverException' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.php',
-    'JsonSchema\\RefResolver' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/RefResolver.php',
+    'JsonSchema\\Iterator\\ObjectIterator' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Iterator/ObjectIterator.php',
+    'JsonSchema\\Rfc3339' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Rfc3339.php',
+    'JsonSchema\\SchemaStorage' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php',
+    'JsonSchema\\UriResolverInterface' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/UriResolverInterface.php',
+    'JsonSchema\\UriRetrieverInterface' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/UriRetrieverInterface.php',
     'JsonSchema\\Uri\\Retrievers\\AbstractRetriever' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/AbstractRetriever.php',
     'JsonSchema\\Uri\\Retrievers\\Curl' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/Curl.php',
     'JsonSchema\\Uri\\Retrievers\\FileGetContents' => $vendorDir . 
'/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php',
diff --git a/composer/installed.json b/composer/installed.json
index 994c9c5..8d04c7a 100644
--- a/composer/installed.json
+++ b/composer/installed.json
@@ -1466,74 +1466,6 @@
         "homepage": "https://www.mediawiki.org/wiki/HtmlFormatter";
     },
     {
-        "name": "justinrainbow/json-schema",
-        "version": "1.6.1",
-        "version_normalized": "1.6.1.0",
-        "source": {
-            "type": "git",
-            "url": "https://github.com/justinrainbow/json-schema.git";,
-            "reference": "cc84765fb7317f6b07bd8ac78364747f95b86341"
-        },
-        "dist": {
-            "type": "zip",
-            "url": 
"https://api.github.com/repos/justinrainbow/json-schema/zipball/cc84765fb7317f6b07bd8ac78364747f95b86341";,
-            "reference": "cc84765fb7317f6b07bd8ac78364747f95b86341",
-            "shasum": ""
-        },
-        "require": {
-            "php": ">=5.3.29"
-        },
-        "require-dev": {
-            "json-schema/json-schema-test-suite": "1.1.0",
-            "phpdocumentor/phpdocumentor": "~2",
-            "phpunit/phpunit": "~3.7"
-        },
-        "time": "2016-01-25 15:43:01",
-        "bin": [
-            "bin/validate-json"
-        ],
-        "type": "library",
-        "extra": {
-            "branch-alias": {
-                "dev-master": "1.6.x-dev"
-            }
-        },
-        "installation-source": "dist",
-        "autoload": {
-            "psr-4": {
-                "JsonSchema\\": "src/JsonSchema/"
-            }
-        },
-        "notification-url": "https://packagist.org/downloads/";,
-        "license": [
-            "BSD-3-Clause"
-        ],
-        "authors": [
-            {
-                "name": "Bruno Prieto Reis",
-                "email": "bruno.p.r...@gmail.com"
-            },
-            {
-                "name": "Justin Rainbow",
-                "email": "justin.rain...@gmail.com"
-            },
-            {
-                "name": "Igor Wiedler",
-                "email": "i...@wiedler.ch"
-            },
-            {
-                "name": "Robert Schönthal",
-                "email": "seros...@googlemail.com"
-            }
-        ],
-        "description": "A library to validate a json schema.",
-        "homepage": "https://github.com/justinrainbow/json-schema";,
-        "keywords": [
-            "json",
-            "schema"
-        ]
-    },
-    {
         "name": "ruflin/elastica",
         "version": "3.1.1",
         "version_normalized": "3.1.1.0",
@@ -1879,5 +1811,73 @@
         ],
         "description": "Provides library of common widgets, layouts, and 
windows.",
         "homepage": "https://www.mediawiki.org/wiki/OOjs_UI";
+    },
+    {
+        "name": "justinrainbow/json-schema",
+        "version": "3.0.0",
+        "version_normalized": "3.0.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/justinrainbow/json-schema.git";,
+            "reference": "12965831120bb18852e9865804a6089906323b8e"
+        },
+        "dist": {
+            "type": "zip",
+            "url": 
"https://api.github.com/repos/justinrainbow/json-schema/zipball/12965831120bb18852e9865804a6089906323b8e";,
+            "reference": "12965831120bb18852e9865804a6089906323b8e",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.3"
+        },
+        "require-dev": {
+            "json-schema/json-schema-test-suite": "1.2.0",
+            "phpdocumentor/phpdocumentor": "~2",
+            "phpunit/phpunit": "^4.8.22"
+        },
+        "time": "2016-08-15 16:39:11",
+        "bin": [
+            "bin/validate-json"
+        ],
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "2.0.x-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "JsonSchema\\": "src/JsonSchema/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/";,
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Bruno Prieto Reis",
+                "email": "bruno.p.r...@gmail.com"
+            },
+            {
+                "name": "Justin Rainbow",
+                "email": "justin.rain...@gmail.com"
+            },
+            {
+                "name": "Igor Wiedler",
+                "email": "i...@wiedler.ch"
+            },
+            {
+                "name": "Robert Schönthal",
+                "email": "seros...@googlemail.com"
+            }
+        ],
+        "description": "A library to validate a json schema.",
+        "homepage": "https://github.com/justinrainbow/json-schema";,
+        "keywords": [
+            "json",
+            "schema"
+        ]
     }
 ]
diff --git a/justinrainbow/json-schema/LICENSE 
b/justinrainbow/json-schema/LICENSE
index 6210e7c..fa020fc 100644
--- a/justinrainbow/json-schema/LICENSE
+++ b/justinrainbow/json-schema/LICENSE
@@ -1,29 +1,21 @@
-Copyright (c) 2008, Gradua Networks
-Author: Bruno Prieto Reis
-All rights reserved.
+MIT License
 
+Copyright (c) 2016
 
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
 
- * Redistributions of source code must retain the above copyright notice, this
-   list of conditions and the following disclaimer.
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
 
- * Redistributions in binary form must reproduce the above copyright notice,
-   this list of conditions and the following disclaimer in the documentation
-   and/or other materials provided with the distribution.
-
- * Neither the name of the Gradua Networks nor the names of its contributors
-   may be used to endorse or promote products derived from this software
-   without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/justinrainbow/json-schema/README.md 
b/justinrainbow/json-schema/README.md
index 3f9c58c..c0c9feb 100644
--- a/justinrainbow/json-schema/README.md
+++ b/justinrainbow/json-schema/README.md
@@ -19,26 +19,18 @@
 #### [`Composer`](https://github.com/composer/composer) (*will use the 
Composer ClassLoader*)
 
     $ wget http://getcomposer.org/composer.phar
-    $ php composer.phar require justinrainbow/json-schema:~1.3
+    $ php composer.phar require justinrainbow/json-schema:~2.0
 
 ## Usage
 
 ```php
 <?php
 
-// Get the schema and data as objects
-$retriever = new JsonSchema\Uri\UriRetriever;
-$schema = $retriever->retrieve('file://' . realpath('schema.json'));
 $data = json_decode(file_get_contents('data.json'));
 
-// If you use $ref or if you are unsure, resolve those references here
-// This modifies the $schema object
-$refResolver = new JsonSchema\RefResolver($retriever);
-$refResolver->resolve($schema, 'file://' . __DIR__);
-
 // Validate
-$validator = new JsonSchema\Validator();
-$validator->check($data, $schema);
+$validator = new JsonSchema\Validator;
+$validator->check($data, (object)['$ref' => 'file://' . 
realpath('schema.json')]);
 
 if ($validator->isValid()) {
     echo "The supplied JSON validates against the schema.\n";
diff --git a/justinrainbow/json-schema/bin/validate-json 
b/justinrainbow/json-schema/bin/validate-json
index e93d53a..915b5a3 100755
--- a/justinrainbow/json-schema/bin/validate-json
+++ b/justinrainbow/json-schema/bin/validate-json
@@ -200,22 +200,14 @@
         echo $urlSchema . "\n";
         exit();
     }
-
-    $schema = $retriever->retrieve($urlSchema);
-    if ($schema === null) {
-        echo "Error loading JSON schema file\n";
-        echo $urlSchema . "\n";
-        showJsonError();
-        exit(2);
-    }
 } catch (Exception $e) {
     echo "Error loading JSON schema file\n";
     echo $urlSchema . "\n";
     echo $e->getMessage() . "\n";
     exit(2);
 }
-$refResolver = new JsonSchema\RefResolver($retriever);
-$refResolver->resolve($schema, $urlSchema);
+$refResolver = new JsonSchema\RefResolver($retriever, $resolver);
+$schema = $refResolver->resolve($urlSchema);
 
 if (isset($arOptions['--dump-schema'])) {
     $options = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0;
@@ -242,4 +234,3 @@
     echo "Error code: " . $e->getCode() . "\n";
     exit(24);
 }
-?>
diff --git a/justinrainbow/json-schema/composer.json 
b/justinrainbow/json-schema/composer.json
index 68b3933..a6d7b42 100644
--- a/justinrainbow/json-schema/composer.json
+++ b/justinrainbow/json-schema/composer.json
@@ -4,7 +4,7 @@
     "keywords": ["json", "schema"],
     "homepage": "https://github.com/justinrainbow/json-schema";,
     "type": "library",
-    "license": "BSD-3-Clause",
+    "license": "MIT",
     "authors": [
         {
             "name": "Bruno Prieto Reis",
@@ -27,32 +27,32 @@
         "type": "package",
         "package": {
             "name": "json-schema/JSON-Schema-Test-Suite",
-            "version": "1.1.0",
+            "version": "1.2.0",
             "source": {
                 "url": "https://github.com/json-schema/JSON-Schema-Test-Suite";,
                 "type": "git",
-                "reference": "1.1.0"
+                "reference": "1.2.0"
             }
         }
     }],
     "require": {
-        "php": ">=5.3.29"
+        "php": ">=5.3.3"
     },
     "require-dev": {
-        "json-schema/JSON-Schema-Test-Suite": "1.1.0",
-        "phpunit/phpunit": "~3.7",
+        "json-schema/JSON-Schema-Test-Suite": "1.2.0",
+        "phpunit/phpunit": "^4.8.22",
         "phpdocumentor/phpdocumentor": "~2"
     },
     "autoload": {
         "psr-4": { "JsonSchema\\": "src/JsonSchema/" }
     },
     "autoload-dev": {
-        "psr-4": { "JsonSchema\\Tests\\": "tests/JsonSchema/Tests/" }
+        "psr-4": { "JsonSchema\\Tests\\": "tests/" }
     },
     "bin": ["bin/validate-json"],
     "extra": {
         "branch-alias": {
-            "dev-master": "1.6.x-dev"
+            "dev-master": "2.0.x-dev"
         }
     }
 }
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php 
b/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php
index b43bace..1b1554a 100644
--- 
a/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php
+++ 
b/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php
@@ -9,6 +9,8 @@
 
 namespace JsonSchema\Constraints;
 
+use JsonSchema\Entity\JsonPointer;
+
 /**
  * The CollectionConstraint Constraints, validates an array against a given 
schema
  *
@@ -20,7 +22,7 @@
     /**
      * {@inheritDoc}
      */
-    public function check($value, $schema = null, $path = null, $i = null)
+    public function check($value, $schema = null, JsonPointer $path = null, $i 
= null)
     {
         // Verify minItems
         if (isset($schema->minItems) && count($value) < $schema->minItems) {
@@ -52,12 +54,12 @@
     /**
      * Validates the items
      *
-     * @param array     $value
-     * @param \stdClass $schema
-     * @param string    $path
-     * @param string    $i
+     * @param array            $value
+     * @param \stdClass        $schema
+     * @param JsonPointer|null $path
+     * @param string           $i
      */
-    protected function validateItems($value, $schema = null, $path = null, $i 
= null)
+    protected function validateItems($value, $schema = null, JsonPointer $path 
= null, $i = null)
     {
         if (is_object($schema->items)) {
             // just one type definition for the whole array
@@ -76,7 +78,7 @@
                 // Reset errors if needed
                 if (isset($secondErrors) && count($secondErrors) < 
count($this->getErrors())) {
                     $this->errors = $secondErrors;
-                } else if (isset($secondErrors) && count($secondErrors) === 
count($this->getErrors())) {
+                } elseif (isset($secondErrors) && count($secondErrors) === 
count($this->getErrors())) {
                     $this->errors = $initErrors;
                 }
             }
@@ -102,7 +104,7 @@
             }
 
             // Treat when we have more schema definitions than values, not for 
empty arrays
-            if(count($value) > 0) {
+            if (count($value) > 0) {
                 for ($k = count($value); $k < count($schema->items); $k++) {
                     $this->checkUndefined(new UndefinedConstraint(), 
$schema->items[$k], $path, $k);
                 }
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php 
b/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php
index cb3ee80..521a0e0 100644
--- a/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php
+++ b/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php
@@ -9,7 +9,10 @@
 
 namespace JsonSchema\Constraints;
 
+use JsonSchema\SchemaStorage;
 use JsonSchema\Uri\UriRetriever;
+use JsonSchema\UriRetrieverInterface;
+use JsonSchema\Entity\JsonPointer;
 
 /**
  * The Base Constraints, all Validators should extend this class
@@ -19,6 +22,7 @@
  */
 abstract class Constraint implements ConstraintInterface
 {
+    protected $schemaStorage;
     protected $checkMode = self::CHECK_MODE_NORMAL;
     protected $uriRetriever;
     protected $errors = array();
@@ -33,24 +37,29 @@
     private $factory;
 
     /**
-     * @param int          $checkMode
-     * @param UriRetriever $uriRetriever
-     * @param Factory      $factory
+     * @param int $checkMode
+     * @param SchemaStorage $schemaStorage
+     * @param UriRetrieverInterface $uriRetriever
+     * @param Factory $factory
      */
-    public function __construct($checkMode = self::CHECK_MODE_NORMAL, 
UriRetriever $uriRetriever = null, Factory $factory = null)
-    {
-        $this->checkMode    = $checkMode;
-        $this->uriRetriever = $uriRetriever;
-        $this->factory = $factory;
+    public function __construct(
+        $checkMode = self::CHECK_MODE_NORMAL,
+        SchemaStorage $schemaStorage = null,
+        UriRetrieverInterface $uriRetriever = null,
+        Factory $factory = null
+    ) {
+        $this->checkMode     = $checkMode;
+        $this->uriRetriever  = $uriRetriever;
+        $this->factory       = $factory;
+        $this->schemaStorage = $schemaStorage;
     }
 
     /**
-     * @return UriRetriever $uriRetriever
+     * @return UriRetrieverInterface $uriRetriever
      */
     public function getUriRetriever()
     {
-        if (is_null($this->uriRetriever))
-        {
+        if (is_null($this->uriRetriever)) {
             $this->setUriRetriever(new UriRetriever);
         }
 
@@ -63,16 +72,28 @@
     public function getFactory()
     {
         if (!$this->factory) {
-            $this->factory = new Factory($this->getUriRetriever());
+            $this->factory = new Factory($this->getSchemaStorage(), 
$this->getUriRetriever(), $this->checkMode);
         }
 
         return $this->factory;
     }
 
     /**
-     * @param UriRetriever $uriRetriever
+     * @return SchemaStorage
      */
-    public function setUriRetriever(UriRetriever $uriRetriever)
+    public function getSchemaStorage()
+    {
+        if (is_null($this->schemaStorage)) {
+            $this->schemaStorage = new SchemaStorage($this->getUriRetriever());
+        }
+
+        return $this->schemaStorage;
+    }
+
+    /**
+     * @param UriRetrieverInterface $uriRetriever
+     */
+    public function setUriRetriever(UriRetrieverInterface $uriRetriever)
     {
         $this->uriRetriever = $uriRetriever;
     }
@@ -80,10 +101,11 @@
     /**
      * {@inheritDoc}
      */
-    public function addError($path, $message, $constraint='', array $more=null)
+    public function addError(JsonPointer $path = null, $message, 
$constraint='', array $more=null)
     {
         $error = array(
-            'property' => $path,
+            'property' => $this->convertJsonPointerIntoPropertyPath($path ?: 
new JsonPointer('')),
+            'pointer' => ltrim(strval($path ?: new JsonPointer('')), '#'),
             'message' => $message,
             'constraint' => $constraint,
         );
@@ -132,37 +154,32 @@
     /**
      * Bubble down the path
      *
-     * @param string $path Current path
-     * @param mixed  $i    What to append to the path
+     * @param JsonPointer|null $path Current path
+     * @param mixed            $i    What to append to the path
      *
-     * @return string
+     * @return JsonPointer;
      */
-    protected function incrementPath($path, $i)
+    protected function incrementPath(JsonPointer $path = null, $i)
     {
-        if ($path !== '') {
-            if (is_int($i)) {
-                $path .= '[' . $i . ']';
-            } elseif ($i == '') {
-                $path .= '';
-            } else {
-                $path .= '.' . $i;
-            }
-        } else {
-            $path = $i;
-        }
-
+        $path = $path ?: new JsonPointer('');
+        $path = $path->withPropertyPaths(
+            array_merge(
+                $path->getPropertyPaths(),
+                array_filter(array($i), 'strlen')
+            )
+        );
         return $path;
     }
 
     /**
      * Validates an array
      *
-     * @param mixed $value
-     * @param mixed $schema
-     * @param mixed $path
-     * @param mixed $i
+     * @param mixed            $value
+     * @param mixed            $schema
+     * @param JsonPointer|null $path
+     * @param mixed            $i
      */
-    protected function checkArray($value, $schema = null, $path = null, $i = 
null)
+    protected function checkArray($value, $schema = null, JsonPointer $path = 
null, $i = null)
     {
         $validator = $this->getFactory()->createInstanceFor('collection');
         $validator->check($value, $schema, $path, $i);
@@ -173,13 +190,13 @@
     /**
      * Validates an object
      *
-     * @param mixed $value
-     * @param mixed $schema
-     * @param mixed $path
-     * @param mixed $i
-     * @param mixed $patternProperties
+     * @param mixed            $value
+     * @param mixed            $schema
+     * @param JsonPointer|null $path
+     * @param mixed            $i
+     * @param mixed            $patternProperties
      */
-    protected function checkObject($value, $schema = null, $path = null, $i = 
null, $patternProperties = null)
+    protected function checkObject($value, $schema = null, JsonPointer $path = 
null, $i = null, $patternProperties = null)
     {
         $validator = $this->getFactory()->createInstanceFor('object');
         $validator->check($value, $schema, $path, $i, $patternProperties);
@@ -190,12 +207,12 @@
     /**
      * Validates the type of a property
      *
-     * @param mixed $value
-     * @param mixed $schema
-     * @param mixed $path
-     * @param mixed $i
+     * @param mixed            $value
+     * @param mixed            $schema
+     * @param JsonPointer|null $path
+     * @param mixed            $i
      */
-    protected function checkType($value, $schema = null, $path = null, $i = 
null)
+    protected function checkType($value, $schema = null, JsonPointer $path = 
null, $i = null)
     {
         $validator = $this->getFactory()->createInstanceFor('type');
         $validator->check($value, $schema, $path, $i);
@@ -206,15 +223,15 @@
     /**
      * Checks a undefined element
      *
-     * @param mixed $value
-     * @param mixed $schema
-     * @param mixed $path
-     * @param mixed $i
+     * @param mixed            $value
+     * @param mixed            $schema
+     * @param JsonPointer|null $path
+     * @param mixed            $i
      */
-    protected function checkUndefined($value, $schema = null, $path = null, $i 
= null)
+    protected function checkUndefined($value, $schema = null, JsonPointer 
$path = null, $i = null)
     {
         $validator = $this->getFactory()->createInstanceFor('undefined');
-        $validator->check($value, $schema, $path, $i);
+        $validator->check($value, 
$this->schemaStorage->resolveRefSchema($schema), $path, $i);
 
         $this->addErrors($validator->getErrors());
     }
@@ -222,12 +239,12 @@
     /**
      * Checks a string element
      *
-     * @param mixed $value
-     * @param mixed $schema
-     * @param mixed $path
-     * @param mixed $i
+     * @param mixed            $value
+     * @param mixed            $schema
+     * @param JsonPointer|null $path
+     * @param mixed            $i
      */
-    protected function checkString($value, $schema = null, $path = null, $i = 
null)
+    protected function checkString($value, $schema = null, JsonPointer $path = 
null, $i = null)
     {
         $validator = $this->getFactory()->createInstanceFor('string');
         $validator->check($value, $schema, $path, $i);
@@ -238,12 +255,12 @@
     /**
      * Checks a number element
      *
-     * @param mixed $value
-     * @param mixed $schema
-     * @param mixed $path
-     * @param mixed $i
+     * @param mixed       $value
+     * @param mixed       $schema
+     * @param JsonPointer $path
+     * @param mixed       $i
      */
-    protected function checkNumber($value, $schema = null, $path = null, $i = 
null)
+    protected function checkNumber($value, $schema = null, JsonPointer $path = 
null, $i = null)
     {
         $validator = $this->getFactory()->createInstanceFor('number');
         $validator->check($value, $schema, $path, $i);
@@ -254,12 +271,12 @@
     /**
      * Checks a enum element
      *
-     * @param mixed $value
-     * @param mixed $schema
-     * @param mixed $path
-     * @param mixed $i
+     * @param mixed            $value
+     * @param mixed            $schema
+     * @param JsonPointer|null $path
+     * @param mixed            $i
      */
-    protected function checkEnum($value, $schema = null, $path = null, $i = 
null)
+    protected function checkEnum($value, $schema = null, JsonPointer $path = 
null, $i = null)
     {
         $validator = $this->getFactory()->createInstanceFor('enum');
         $validator->check($value, $schema, $path, $i);
@@ -267,7 +284,15 @@
         $this->addErrors($validator->getErrors());
     }
 
-    protected function checkFormat($value, $schema = null, $path = null, $i = 
null)
+    /**
+     * Checks format of an element
+     *
+     * @param mixed            $value
+     * @param mixed            $schema
+     * @param JsonPointer|null $path
+     * @param mixed            $i
+     */
+    protected function checkFormat($value, $schema = null, JsonPointer $path = 
null, $i = null)
     {
         $validator = $this->getFactory()->createInstanceFor('format');
         $validator->check($value, $schema, $path, $i);
@@ -276,16 +301,27 @@
     }
 
     /**
-     * @param string $uri JSON Schema URI
-     * @return string JSON Schema contents
+     * Get the type check based on the set check mode.
+     *
+     * @return TypeCheck\TypeCheckInterface
      */
-    protected function retrieveUri($uri)
+    protected function getTypeCheck()
     {
-        if (null === $this->uriRetriever) {
-            $this->setUriRetriever(new UriRetriever);
-        }
-        $jsonSchema = $this->uriRetriever->retrieve($uri);
-        // TODO validate using schema
-        return $jsonSchema;
+        return $this->getFactory()->getTypeCheck();
+    }
+
+    /**
+     * @param JsonPointer $pointer
+     * @return string property path
+     */
+    protected function convertJsonPointerIntoPropertyPath(JsonPointer $pointer)
+    {
+        $result = array_map(
+            function($path) {
+                return sprintf(is_numeric($path) ? '[%d]' : '.%s', $path);
+            },
+            $pointer->getPropertyPaths()
+        );
+        return trim(implode('', $result), '.');
     }
 }
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php 
b/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php
index 34280f4..ca12363 100644
--- 
a/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php
+++ 
b/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php
@@ -9,6 +9,8 @@
 
 namespace JsonSchema\Constraints;
 
+use JsonSchema\Entity\JsonPointer;
+
 /**
  * The Constraints Interface
  *
@@ -33,12 +35,12 @@
     /**
      * adds an error
      *
-     * @param string $path
-     * @param string $message
-     * @param string $constraint the constraint/rule that is broken, e.g.: 
'minLength'
-     * @param array $more more array elements to add to the error
+     * @param JsonPointer|null $path
+     * @param string           $message
+     * @param string           $constraint the constraint/rule that is broken, 
e.g.: 'minLength'
+     * @param array            $more more array elements to add to the error
      */
-    public function addError($path, $message, $constraint='', array 
$more=null);
+    public function addError(JsonPointer $path = null, $message, 
$constraint='', array $more=null);
 
     /**
      * checks if the validator has not raised errors
@@ -51,10 +53,11 @@
      * invokes the validation of an element
      *
      * @abstract
-     * @param mixed $value
-     * @param mixed $schema
-     * @param mixed $path
-     * @param mixed $i
+     * @param mixed            $value
+     * @param mixed            $schema
+     * @param JsonPointer|null $path
+     * @param mixed            $i
+     * @throws \JsonSchema\Exception\ExceptionInterface
      */
-    public function check($value, $schema = null, $path = null, $i = null);
+    public function check($value, $schema = null, JsonPointer $path = null, $i 
= null);
 }
\ No newline at end of file
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php 
b/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php
index df413e4..69fd030 100644
--- a/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php
+++ b/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php
@@ -8,6 +8,8 @@
  */
 
 namespace JsonSchema\Constraints;
+use JsonSchema\Validator;
+use JsonSchema\Entity\JsonPointer;
 
 /**
  * The EnumConstraint Constraints, validates an element against a given set of 
possibilities
@@ -20,27 +22,33 @@
     /**
      * {@inheritDoc}
      */
-    public function check($element, $schema = null, $path = null, $i = null)
+    public function check($element, $schema = null, JsonPointer $path = null, 
$i = null)
     {
         // Only validate enum if the attribute exists
         if ($element instanceof UndefinedConstraint && 
(!isset($schema->required) || !$schema->required)) {
             return;
         }
+        $type = gettype($element);
 
         foreach ($schema->enum as $enum) {
-            $type = gettype($element);
+            $enumType = gettype($enum);
+            if ($this->checkMode === self::CHECK_MODE_TYPE_CAST && $type == 
"array" && $enumType == "object") {
+                if ((object)$element == $enum) {
+                    return;
+                }
+            }
+
             if ($type === gettype($enum)) {
                 if ($type == "object") {
-                    if ($element == $enum)
+                    if ($element == $enum) {
                         return;
-                } else {
-                    if ($element === $enum)
-                        return;
-
+                    }
+                } elseif ($element === $enum) {
+                    return;
                 }
             }
         }
 
-        $this->addError($path, "Does not have a value in the enumeration " . 
print_r($schema->enum, true), 'enum', array('enum' => $schema->enum,));
+        $this->addError($path, "Does not have a value in the enumeration " . 
json_encode($schema->enum), 'enum', array('enum' => $schema->enum,));
     }
 }
diff --git a/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php 
b/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php
index 8cd25c1..bb12ece 100644
--- a/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php
+++ b/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php
@@ -10,8 +10,9 @@
 namespace JsonSchema\Constraints;
 
 use JsonSchema\Exception\InvalidArgumentException;
+use JsonSchema\SchemaStorage;
 use JsonSchema\Uri\UriRetriever;
-use JsonSchema\Validator;
+use JsonSchema\UriRetrieverInterface;
 
 /**
  * Factory for centralize constraint initialization.
@@ -19,9 +20,24 @@
 class Factory
 {
     /**
+     * @var SchemaStorage
+     */
+    protected $schemaStorage;
+   
+    /**
      * @var UriRetriever $uriRetriever
      */
     protected $uriRetriever;
+
+    /**
+     * @var int
+     */
+    private $checkMode;
+
+    /**
+     * @var TypeCheck\TypeCheckInterface[]
+     */
+    private $typeCheck = array();
 
     /**
      * @var array $constraintMap
@@ -41,23 +57,42 @@
     );
 
     /**
-     * @param UriRetriever $uriRetriever
+     * @param SchemaStorage $schemaStorage
+     * @param UriRetrieverInterface $uriRetriever
+     * @param int $checkMode
      */
-    public function __construct(UriRetriever $uriRetriever = null)
-    {
-        if (!$uriRetriever) {
-            $uriRetriever = new UriRetriever();
-        }
-
-        $this->uriRetriever = $uriRetriever;
+    public function __construct(
+        SchemaStorage $schemaStorage = null,
+        UriRetrieverInterface $uriRetriever = null,
+        $checkMode = Constraint::CHECK_MODE_NORMAL
+    ) {
+        $this->uriRetriever = $uriRetriever ?: new UriRetriever;
+        $this->schemaStorage = $schemaStorage ?: new 
SchemaStorage($this->uriRetriever);
+        $this->checkMode = $checkMode;
     }
 
     /**
-     * @return UriRetriever
+     * @return UriRetrieverInterface
      */
     public function getUriRetriever()
     {
         return $this->uriRetriever;
+    }
+    
+    public function getSchemaStorage()
+    {
+        return $this->schemaStorage;
+    }
+
+    public function getTypeCheck()
+    {
+        if (!isset($this->typeCheck[$this->checkMode])) {
+            $this->typeCheck[$this->checkMode] = $this->checkMode === 
Constraint::CHECK_MODE_TYPE_CAST
+                ? new TypeCheck\LooseTypeCheck
+                : new TypeCheck\StrictTypeCheck;
+        }
+
+        return $this->typeCheck[$this->checkMode];
     }
 
     /**
@@ -67,16 +102,16 @@
      */
     public function setConstraintClass($name, $class)
     {
-      // Ensure class exists
-      if (!class_exists($class)) {
-        throw new InvalidArgumentException('Unknown constraint ' . $name);
-      }
-      // Ensure class is appropriate
-      if (!in_array('JsonSchema\Constraints\ConstraintInterface', 
class_implements($class))) {
-        throw new InvalidArgumentException('Invalid class ' . $name);
-      }
-      $this->constraintMap[$name] = $class;
-      return $this;
+        // Ensure class exists
+        if (!class_exists($class)) {
+            throw new InvalidArgumentException('Unknown constraint ' . $name);
+        }
+        // Ensure class is appropriate
+        if (!in_array('JsonSchema\Constraints\ConstraintInterface', 
class_implements($class))) {
+            throw new InvalidArgumentException('Invalid class ' . $name);
+        }
+        $this->constraintMap[$name] = $class;
+        return $this;
     }
 
     /**
@@ -89,7 +124,12 @@
     public function createInstanceFor($constraintName)
     {
         if (array_key_exists($constraintName, $this->constraintMap)) {
-          return new 
$this->constraintMap[$constraintName](Constraint::CHECK_MODE_NORMAL, 
$this->uriRetriever, $this);
+            return new $this->constraintMap[$constraintName](
+                $this->checkMode,
+                $this->schemaStorage,
+                $this->uriRetriever,
+                $this
+            );
         }
         throw new InvalidArgumentException('Unknown constraint ' . 
$constraintName);
     }
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php 
b/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php
index c789753..05d6de9 100644
--- a/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php
+++ b/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php
@@ -9,6 +9,9 @@
 
 namespace JsonSchema\Constraints;
 
+use JsonSchema\Rfc3339;
+use JsonSchema\Entity\JsonPointer;
+
 /**
  * Validates against the "format" property
  *
@@ -20,7 +23,7 @@
     /**
      * {@inheritDoc}
      */
-    public function check($element, $schema = null, $path = null, $i = null)
+    public function check($element, $schema = null, JsonPointer $path = null, 
$i = null)
     {
         if (!isset($schema->format)) {
             return;
@@ -40,11 +43,7 @@
                 break;
 
             case 'date-time':
-                if (!$this->validateDateTime($element, 'Y-m-d\TH:i:s\Z') &&
-                    !$this->validateDateTime($element, 'Y-m-d\TH:i:s.u\Z') &&
-                    !$this->validateDateTime($element, 'Y-m-d\TH:i:sP') &&
-                    !$this->validateDateTime($element, 'Y-m-d\TH:i:sO')
-                ) {
+                if (null === Rfc3339::createFromString($element)) {
                     $this->addError($path, sprintf('Invalid date-time %s, 
expected format YYYY-MM-DDThh:mm:ssZ or YYYY-MM-DDThh:mm:ss+hh:mm', 
json_encode($element)), 'format', array('format' => $schema->format,));
                 }
                 break;
@@ -138,7 +137,7 @@
         // which will fail the above string comparison because the passed
         // $datetime may be '2000-05-01T12:12:12.123Z' but format() will return
         // '2000-05-01T12:12:12.123000Z'
-        if ((strpos('u', $format) !== -1) && (intval($dt->format('u')) > 0)) {
+        if ((strpos('u', $format) !== -1) && (preg_match('/\.\d+Z$/', 
$datetime))) {
             return true;
         }
 
@@ -176,6 +175,7 @@
 
     protected function validateHostname($host)
     {
-        return preg_match('/^[_a-z]+\.([_a-z]+\.?)+$/i', $host);
+        $hostnameRegex = 
'/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/i';
+        return preg_match($hostnameRegex, $host);
     }
 }
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php 
b/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php
index c5aaf6a..601b86a 100644
--- a/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php
+++ b/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php
@@ -9,6 +9,8 @@
 
 namespace JsonSchema\Constraints;
 
+use JsonSchema\Entity\JsonPointer;
+
 /**
  * The NumberConstraint Constraints, validates an number against a given schema
  *
@@ -20,20 +22,20 @@
     /**
      * {@inheritDoc}
      */
-    public function check($element, $schema = null, $path = null, $i = null)
+    public function check($element, $schema = null, JsonPointer $path = null, 
$i = null)
     {
         // Verify minimum
         if (isset($schema->exclusiveMinimum)) {
             if (isset($schema->minimum)) {
                 if ($schema->exclusiveMinimum && $element <= $schema->minimum) 
{
                     $this->addError($path, "Must have a minimum value of " . 
$schema->minimum, 'exclusiveMinimum', array('minimum' => $schema->minimum,));
-                } else if ($element < $schema->minimum) {
+                } elseif ($element < $schema->minimum) {
                     $this->addError($path, "Must have a minimum value of " . 
$schema->minimum, 'minimum', array('minimum' => $schema->minimum,));
                 }
             } else {
                 $this->addError($path, "Use of exclusiveMinimum requires 
presence of minimum", 'missingMinimum');
             }
-        } else if (isset($schema->minimum) && $element < $schema->minimum) {
+        } elseif (isset($schema->minimum) && $element < $schema->minimum) {
             $this->addError($path, "Must have a minimum value of " . 
$schema->minimum, 'minimum', array('minimum' => $schema->minimum,));
         }
 
@@ -42,13 +44,13 @@
             if (isset($schema->maximum)) {
                 if ($schema->exclusiveMaximum && $element >= $schema->maximum) 
{
                     $this->addError($path, "Must have a maximum value of " . 
$schema->maximum, 'exclusiveMaximum', array('maximum' => $schema->maximum,));
-                } else if ($element > $schema->maximum) {
+                } elseif ($element > $schema->maximum) {
                     $this->addError($path, "Must have a maximum value of " . 
$schema->maximum, 'maximum', array('maximum' => $schema->maximum,));
                 }
             } else {
-                $this->addError($path, "Use of exclusiveMaximum requires 
presence of maximum", 'missingMinimum');
+                $this->addError($path, "Use of exclusiveMaximum requires 
presence of maximum", 'missingMaximum');
             }
-        } else if (isset($schema->maximum) && $element > $schema->maximum) {
+        } elseif (isset($schema->maximum) && $element > $schema->maximum) {
             $this->addError($path, "Must have a maximum value of " . 
$schema->maximum, 'maximum', array('maximum' => $schema->maximum,));
         }
 
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php 
b/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php
index 0e5cf1b..5a12b87 100644
--- a/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php
+++ b/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php
@@ -9,6 +9,8 @@
 
 namespace JsonSchema\Constraints;
 
+use JsonSchema\Entity\JsonPointer;
+
 /**
  * The ObjectConstraint Constraints, validates an object against a given schema
  *
@@ -20,7 +22,7 @@
     /**
      * {@inheritDoc}
      */
-    function check($element, $definition = null, $path = null, $additionalProp 
= null, $patternProperties = null)
+    public function check($element, $definition = null, JsonPointer $path = 
null, $additionalProp = null, $patternProperties = null)
     {
         if ($element instanceof UndefinedConstraint) {
             return;
@@ -40,7 +42,7 @@
         $this->validateElement($element, $matches, $definition, $path, 
$additionalProp);
     }
 
-    public function validatePatternProperties($element, $path, 
$patternProperties)
+    public function validatePatternProperties($element, JsonPointer $path = 
null, $patternProperties)
     {
         $try = array('/','#','+','~','%');
         $matches = array();
@@ -71,17 +73,16 @@
     /**
      * Validates the element properties
      *
-     * @param \stdClass $element          Element to validate
-     * @param array     $matches          Matches from patternProperties (if 
any)
-     * @param \stdClass $objectDefinition ObjectConstraint definition
-     * @param string    $path             Path to test?
-     * @param mixed     $additionalProp   Additional properties
+     * @param \stdClass        $element          Element to validate
+     * @param array            $matches          Matches from 
patternProperties (if any)
+     * @param \stdClass        $objectDefinition ObjectConstraint definition
+     * @param JsonPointer|null $path             Path to test?
+     * @param mixed            $additionalProp   Additional properties
      */
-    public function validateElement($element, $matches, $objectDefinition = 
null, $path = null, $additionalProp = null)
+    public function validateElement($element, $matches, $objectDefinition = 
null, JsonPointer $path = null, $additionalProp = null)
     {
+        $this->validateMinMaxConstraint($element, $objectDefinition, $path);
         foreach ($element as $i => $value) {
-
-            $property = $this->getProperty($element, $i, new 
UndefinedConstraint());
             $definition = $this->getProperty($objectDefinition, $i);
 
             // no additional properties allowed
@@ -108,20 +109,25 @@
                 // normal property verification
                 $this->checkUndefined($value, new \stdClass(), $path, $i);
             }
+
+            $property = $this->getProperty($element, $i, new 
UndefinedConstraint());
+            if (is_object($property)) {
+                $this->validateMinMaxConstraint(!($property instanceof 
UndefinedConstraint) ? $property : $element, $definition, $path);
+            }
         }
     }
 
     /**
      * Validates the definition properties
      *
-     * @param \stdClass $element          Element to validate
-     * @param \stdClass $objectDefinition ObjectConstraint definition
-     * @param string    $path             Path?
+     * @param \stdClass         $element          Element to validate
+     * @param \stdClass         $objectDefinition ObjectConstraint definition
+     * @param JsoinPointer|null $path             Path?
      */
-    public function validateDefinition($element, $objectDefinition = null, 
$path = null)
+    public function validateDefinition($element, $objectDefinition = null, 
JsonPointer $path = null)
     {
         foreach ($objectDefinition as $i => $value) {
-            $property = $this->getProperty($element, $i, new 
UndefinedConstraint());
+            $property = $this->getProperty($element, $i, 
$this->getFactory()->createInstanceFor('undefined'));
             $definition = $this->getProperty($objectDefinition, $i);
             $this->checkUndefined($property, $definition, $path, $i);
         }
@@ -146,4 +152,26 @@
 
         return $fallback;
     }
+
+    /**
+     * validating minimum and maximum property constraints (if present) 
against an element
+     *
+     * @param \stdClass        $element          Element to validate
+     * @param \stdClass        $objectDefinition ObjectConstraint definition
+     * @param JsonPointer|null $path             Path to test?
+     */
+    protected function validateMinMaxConstraint($element, $objectDefinition, 
JsonPointer $path = null) {
+        // Verify minimum number of properties
+        if (isset($objectDefinition->minProperties) && 
!is_object($objectDefinition->minProperties)) {
+            if ($this->getTypeCheck()->propertyCount($element) < 
$objectDefinition->minProperties) {
+                $this->addError($path, "Must contain a minimum of " . 
$objectDefinition->minProperties . " properties", 'minProperties', 
array('minProperties' => $objectDefinition->minProperties,));
+            }
+        }
+        // Verify maximum number of properties
+        if (isset($objectDefinition->maxProperties) && 
!is_object($objectDefinition->maxProperties)) {
+            if ($this->getTypeCheck()->propertyCount($element) > 
$objectDefinition->maxProperties) {
+                $this->addError($path, "Must contain no more than " . 
$objectDefinition->maxProperties . " properties", 'maxProperties', 
array('maxProperties' => $objectDefinition->maxProperties,));
+            }
+        }
+    }
 }
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php 
b/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php
index b856a11..071cd12 100644
--- a/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php
+++ b/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php
@@ -10,6 +10,7 @@
 namespace JsonSchema\Constraints;
 
 use JsonSchema\Exception\InvalidArgumentException;
+use JsonSchema\Entity\JsonPointer;
 
 /**
  * The SchemaConstraint Constraints, validates an element against a given 
schema
@@ -22,16 +23,20 @@
     /**
      * {@inheritDoc}
      */
-    public function check($element, $schema = null, $path = null, $i = null)
+    public function check($element, $schema = null, JsonPointer $path = null, 
$i = null)
     {
         if ($schema !== null) {
             // passed schema
-            $this->checkUndefined($element, $schema, '', '');
-        } elseif (property_exists($element, $this->inlineSchemaProperty)) {
+            $this->checkUndefined($element, $schema, $path, $i);
+        } elseif ($this->getTypeCheck()->propertyExists($element, 
$this->inlineSchemaProperty)) {
+            $inlineSchema = $this->getTypeCheck()->propertyGet($element, 
$this->inlineSchemaProperty);
+            if (is_array($inlineSchema)) {
+                $inlineSchema = json_decode(json_encode($inlineSchema));
+            }
             // inline schema
-            $this->checkUndefined($element, 
$element->{$this->inlineSchemaProperty}, '', '');
+            $this->checkUndefined($element, $inlineSchema, $path, $i);
         } else {
             throw new InvalidArgumentException('no schema found to verify 
against');
         }
     }
-}
\ No newline at end of file
+}
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php 
b/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php
index f57f64c..44313cb 100644
--- a/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php
+++ b/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php
@@ -9,6 +9,8 @@
 
 namespace JsonSchema\Constraints;
 
+use JsonSchema\Entity\JsonPointer;
+
 /**
  * The StringConstraint Constraints, validates an string against a given schema
  *
@@ -20,7 +22,7 @@
     /**
      * {@inheritDoc}
      */
-    public function check($element, $schema = null, $path = null, $i = null)
+    public function check($element, $schema = null, JsonPointer $path = null, 
$i = null)
     {
         // Verify maxLength
         if (isset($schema->maxLength) && $this->strlen($element) > 
$schema->maxLength) {
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/LooseTypeCheck.php
 
b/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/LooseTypeCheck.php
new file mode 100644
index 0000000..7499c2e
--- /dev/null
+++ 
b/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/LooseTypeCheck.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace JsonSchema\Constraints\TypeCheck;
+
+class LooseTypeCheck implements TypeCheckInterface
+{
+    public static function isObject($value)
+    {
+        return
+            is_object($value) ||
+            (is_array($value) && (count($value) == 0 || 
self::isAssociativeArray($value)));
+    }
+
+    public static function isArray($value)
+    {
+        return
+            is_array($value) &&
+            (count($value) == 0 || !self::isAssociativeArray($value));
+    }
+
+    public static function propertyGet($value, $property)
+    {
+        if (is_object($value)) {
+            return $value->{$property};
+        }
+
+        return $value[$property];
+    }
+
+    public static function propertyExists($value, $property)
+    {
+        if (is_object($value)) {
+            return property_exists($value, $property);
+        }
+
+        return array_key_exists($property, $value);
+    }
+
+    public static function propertyCount($value)
+    {
+        if (is_object($value)) {
+            return count(get_object_vars($value));
+        }
+
+        return count($value);
+    }
+
+    /**
+     * Check if the provided array is associative or not
+     *
+     * @param array $arr
+     *
+     * @return bool
+     */
+    private static function isAssociativeArray($arr)
+    {
+        return (array_keys($arr) !== range(0, count($arr) - 1));
+    }
+}
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/StrictTypeCheck.php
 
b/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/StrictTypeCheck.php
new file mode 100644
index 0000000..73bbc38
--- /dev/null
+++ 
b/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/StrictTypeCheck.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace JsonSchema\Constraints\TypeCheck;
+
+class StrictTypeCheck implements TypeCheckInterface
+{
+    public static function isObject($value)
+    {
+        return is_object($value);
+    }
+
+    public static function isArray($value)
+    {
+        return is_array($value);
+    }
+
+    public static function propertyGet($value, $property)
+    {
+        return $value->{$property};
+    }
+
+    public static function propertyExists($value, $property)
+    {
+        return property_exists($value, $property);
+    }
+
+    public static function propertyCount($value)
+    {
+        return count(get_object_vars($value));
+    }
+}
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/TypeCheckInterface.php
 
b/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/TypeCheckInterface.php
new file mode 100644
index 0000000..5fd68ac
--- /dev/null
+++ 
b/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/TypeCheckInterface.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace JsonSchema\Constraints\TypeCheck;
+
+interface TypeCheckInterface
+{
+    public static function isObject($value);
+
+    public static function isArray($value);
+
+    public static function propertyGet($value, $property);
+
+    public static function propertyExists($value, $property);
+
+    public static function propertyCount($value);
+}
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php 
b/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php
index 837cfd8..d082f6a 100644
--- a/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php
+++ b/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php
@@ -10,6 +10,7 @@
 namespace JsonSchema\Constraints;
 
 use JsonSchema\Exception\InvalidArgumentException;
+use JsonSchema\Entity\JsonPointer;
 use UnexpectedValueException as StandardUnexpectedValueException;
 
 /**
@@ -38,51 +39,102 @@
     /**
      * {@inheritDoc}
      */
-    public function check($value = null, $schema = null, $path = null, $i = 
null)
+    public function check($value = null, $schema = null, JsonPointer $path = 
null, $i = null)
     {
         $type = isset($schema->type) ? $schema->type : null;
-        $isValid = true;
+        $isValid = false;
+        $wording = array();
 
         if (is_array($type)) {
-            // @TODO refactor
-            $validatedOneType = false;
-            $errors = array();
-            foreach ($type as $tp) {
-                $validator = new TypeConstraint($this->checkMode);
-                $subSchema = new \stdClass();
-                $subSchema->type = $tp;
-                $validator->check($value, $subSchema, $path, null);
-                $error = $validator->getErrors();
-
-                if (!count($error)) {
-                    $validatedOneType = true;
-                    break;
-                }
-
-                $errors = $error;
-            }
-
-            if (!$validatedOneType) {
-                $this->addErrors($errors);
-
-                return;
-            }
+            $this->validateTypesArray($value, $type, $wording, $isValid, 
$path);
         } elseif (is_object($type)) {
             $this->checkUndefined($value, $type, $path);
+            return;
         } else {
             $isValid = $this->validateType($value, $type);
         }
 
         if ($isValid === false) {
-            if (!isset(self::$wording[$type])) {
-                throw new StandardUnexpectedValueException(
-                    sprintf(
-                        "No wording for %s available, expected wordings are: 
[%s]",
-                        var_export($type, true),
-                        implode(', ', array_filter(self::$wording)))
-                );
+            if (!is_array($type)) {
+                $this->validateTypeNameWording($type);
+                $wording[] = self::$wording[$type];
             }
-            $this->addError($path, ucwords(gettype($value)) . " value found, 
but " . self::$wording[$type] . " is required", 'type');
+            $this->addError($path, ucwords(gettype($value)) . " value found, 
but " .
+                $this->implodeWith($wording, ', ', 'or') . " is required", 
'type');
+        }
+    }
+
+    /**
+     * Validates the given $value against the array of types in $type. Sets 
the value
+     * of $isValid to true, if at least one $type mateches the type of $value 
or the value
+     * passed as $isValid is already true.
+     *
+     * @param mixed $value Value to validate
+     * @param array $type TypeConstraints to check agains
+     * @param array $wording An array of wordings of the valid types of the 
array $type
+     * @param boolean $isValid The current validation value
+     */
+    protected function validateTypesArray($value, array $type, 
&$validTypesWording, &$isValid,
+                                          $path) {
+        foreach ($type as $tp) {
+            // $tp can be an object, if it's a schema instead of a simple 
type, validate it
+            // with a new type constraint
+            if (is_object($tp)) {
+                if (!$isValid) {
+                    $validator = 
$this->getFactory()->createInstanceFor('type');
+                    $subSchema = new \stdClass();
+                    $subSchema->type = $tp;
+                    $validator->check($value, $subSchema, $path, null);
+                    $error = $validator->getErrors();
+                    $isValid = !(bool)$error;
+                    $validTypesWording[] = self::$wording['object'];
+                }
+            } else {
+                $this->validateTypeNameWording( $tp );
+                $validTypesWording[] = self::$wording[$tp];
+                if (!$isValid) {
+                    $isValid = $this->validateType( $value, $tp );
+                }
+            }
+        }
+    }
+
+    /**
+     * Implodes the given array like implode() with turned around parameters 
and with the
+     * difference, that, if $listEnd isn't false, the last element delimiter 
is $listEnd instead of
+     * $delimiter.
+     *
+     * @param array $elements The elements to implode
+     * @param string $delimiter The delimiter to use
+     * @param bool $listEnd The last delimiter to use (defaults to $delimiter)
+     * @return string
+     */
+    protected function implodeWith(array $elements, $delimiter = ', ', 
$listEnd = false) {
+        if ($listEnd === false || !isset($elements[1])) {
+            return implode(', ', $elements);
+        }
+        $lastElement  = array_slice($elements, -1);
+        $firsElements = join(', ', array_slice($elements, 0, -1));
+        $implodedElements = array_merge(array($firsElements), $lastElement);
+        return join(" $listEnd ", $implodedElements);
+    }
+
+    /**
+     * Validates the given $type, if there's an associated self::$wording. If 
not, throws an
+     * exception.
+     *
+     * @param string $type The type to validate
+     *
+     * @throws StandardUnexpectedValueException
+     */
+    protected function validateTypeNameWording( $type) {
+        if (!isset(self::$wording[$type])) {
+            throw new StandardUnexpectedValueException(
+                sprintf(
+                    "No wording for %s available, expected wordings are: [%s]",
+                    var_export($type, true),
+                    implode(', ', array_filter(self::$wording)))
+            );
         }
     }
 
@@ -116,18 +168,17 @@
         }
 
         if ('object' === $type) {
-            return is_object($value);
-            //return ($this::CHECK_MODE_TYPE_CAST == $this->checkMode) ? 
is_array($value) : is_object($value);
+            return $this->getTypeCheck()->isObject($value);
         }
 
         if ('array' === $type) {
-            return is_array($value);
+            return $this->getTypeCheck()->isArray($value);
         }
 
         if ('string' === $type) {
             return is_string($value);
         }
-        
+
         if ('email' === $type) {
             return is_string($value);
         }
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php 
b/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php
index c033720..7815e24 100644
--- 
a/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php
+++ 
b/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php
@@ -9,8 +9,8 @@
 
 namespace JsonSchema\Constraints;
 
-use JsonSchema\Exception\InvalidArgumentException;
 use JsonSchema\Uri\UriResolver;
+use JsonSchema\Entity\JsonPointer;
 
 /**
  * The UndefinedConstraint Constraints
@@ -23,21 +23,13 @@
     /**
      * {@inheritDoc}
      */
-    public function check($value, $schema = null, $path = null, $i = null)
+    public function check($value, $schema = null, JsonPointer $path = null, $i 
= null)
     {
-        if (is_null($schema)) {
+        if (is_null($schema) || !is_object($schema)) {
             return;
         }
 
-        if (!is_object($schema)) {
-            throw new InvalidArgumentException(
-                'Given schema must be an object in ' . $path
-                . ' but is a ' . gettype($schema)
-            );
-        }
-
-        $i = is_null($i) ? "" : $i;
-        $path = $this->incrementPath($path, $i);
+        $path = $this->incrementPath($path ?: new JsonPointer(''), $i);
 
         // check special properties
         $this->validateCommonProperties($value, $schema, $path);
@@ -52,23 +44,23 @@
     /**
      * Validates the value against the types
      *
-     * @param mixed  $value
-     * @param mixed  $schema
-     * @param string $path
-     * @param string $i
+     * @param mixed       $value
+     * @param mixed       $schema
+     * @param JsonPointer $path
+     * @param string      $i
      */
-    public function validateTypes($value, $schema = null, $path = null, $i = 
null)
+    public function validateTypes($value, $schema = null, JsonPointer $path, 
$i = null)
     {
         // check array
-        if (is_array($value)) {
+        if ($this->getTypeCheck()->isArray($value)) {
             $this->checkArray($value, $schema, $path, $i);
         }
 
         // check object
-        if (is_object($value) && (isset($schema->properties) || 
isset($schema->patternProperties) || isset($schema->additionalProperties))) {
+        if ($this->getTypeCheck()->isObject($value)) {
             $this->checkObject(
                 $value,
-                isset($schema->properties) ? $schema->properties : null,
+                isset($schema->properties) ? $schema->properties : $schema,
                 $path,
                 isset($schema->additionalProperties) ? 
$schema->additionalProperties : null,
                 isset($schema->patternProperties) ? $schema->patternProperties 
: null
@@ -94,12 +86,12 @@
     /**
      * Validates common properties
      *
-     * @param mixed  $value
-     * @param mixed  $schema
-     * @param string $path
-     * @param string $i
+     * @param mixed       $value
+     * @param mixed       $schema
+     * @param JsonPointer $path
+     * @param string      $i
      */
-    protected function validateCommonProperties($value, $schema = null, $path 
= null, $i = "")
+    protected function validateCommonProperties($value, $schema = null, 
JsonPointer $path, $i = "")
     {
         // if it extends another schema, it must pass that schema as well
         if (isset($schema->extends)) {
@@ -116,17 +108,21 @@
         }
 
         // Verify required values
-        if (is_object($value)) {
-            if (!($value instanceof UndefinedConstraint) && 
isset($schema->required) && is_array($schema->required) ) {
+        if ($this->getTypeCheck()->isObject($value)) {
+            if (!($value instanceof UndefinedConstraint) && 
isset($schema->required) && is_array($schema->required)) {
                 // Draft 4 - Required is an array of strings - e.g. 
"required": ["foo", ...]
                 foreach ($schema->required as $required) {
-                    if (!property_exists($value, $required)) {
-                        $this->addError((!$path) ? $required : 
"$path.$required", "The property " . $required . " is required", 'required');
+                    if (!$this->getTypeCheck()->propertyExists($value, 
$required)) {
+                        $this->addError(
+                            $this->incrementPath($path ?: new JsonPointer(''), 
$required),
+                            "The property " . $required . " is required",
+                            'required'
+                        );
                     }
                 }
-            } else if (isset($schema->required) && 
!is_array($schema->required)) {
+            } elseif (isset($schema->required) && 
!is_array($schema->required)) {
                 // Draft 3 - Required attribute - e.g. "foo": {"type": 
"string", "required": true}
-                if ( $schema->required && $value instanceof 
UndefinedConstraint) {
+                if ($schema->required && $value instanceof 
UndefinedConstraint) {
                     $this->addError($path, "Is missing and it is required", 
'required');
                 }
             }
@@ -165,22 +161,8 @@
             }
         }
 
-        // Verify minimum and maximum number of properties
-        if (is_object($value)) {
-            if (isset($schema->minProperties)) {
-                if (count(get_object_vars($value)) < $schema->minProperties) {
-                    $this->addError($path, "Must contain a minimum of " . 
$schema->minProperties . " properties", 'minProperties', array('minProperties' 
=> $schema->minProperties,));
-                }
-            }
-            if (isset($schema->maxProperties)) {
-                if (count(get_object_vars($value)) > $schema->maxProperties) {
-                    $this->addError($path, "Must contain no more than " . 
$schema->maxProperties . " properties", 'maxProperties', array('maxProperties' 
=> $schema->maxProperties,));
-                }
-            }
-        }
-
         // Verify that dependencies are met
-        if (is_object($value) && isset($schema->dependencies)) {
+        if (isset($schema->dependencies) && 
$this->getTypeCheck()->isObject($value)) {
             $this->validateDependencies($value, $schema->dependencies, $path);
         }
     }
@@ -188,12 +170,12 @@
     /**
      * Validate allOf, anyOf, and oneOf properties
      *
-     * @param mixed  $value
-     * @param mixed  $schema
-     * @param string $path
-     * @param string $i
+     * @param mixed       $value
+     * @param mixed       $schema
+     * @param JsonPointer $path
+     * @param string      $i
      */
-    protected function validateOfProperties($value, $schema, $path, $i = "")
+    protected function validateOfProperties($value, $schema, JsonPointer 
$path, $i = "")
     {
         // Verify type
         if ($value instanceof UndefinedConstraint) {
@@ -242,17 +224,8 @@
                 $allErrors = array_merge($allErrors, 
array_values($this->getErrors()));
             }
             if ($matchedSchemas !== 1) {
-                $this->addErrors(
-                    array_merge(
-                        $allErrors,
-                        array(array(
-                            'property' => $path,
-                            'message' => "Failed to match exactly one schema",
-                            'constraint' => 'oneOf',
-                        ),),
-                        $startErrors
-                    )
-                );
+                $this->addErrors(array_merge($allErrors, $startErrors));
+                $this->addError($path, "Failed to match exactly one schema", 
'oneOf');
             } else {
                 $this->errors = $startErrors;
             }
@@ -262,28 +235,28 @@
     /**
      * Validate dependencies
      *
-     * @param mixed  $value
-     * @param mixed  $dependencies
-     * @param string $path
-     * @param string $i
+     * @param mixed       $value
+     * @param mixed       $dependencies
+     * @param JsonPointer $path
+     * @param string      $i
      */
-    protected function validateDependencies($value, $dependencies, $path, $i = 
"")
+    protected function validateDependencies($value, $dependencies, JsonPointer 
$path, $i = "")
     {
         foreach ($dependencies as $key => $dependency) {
-            if (property_exists($value, $key)) {
+            if ($this->getTypeCheck()->propertyExists($value, $key)) {
                 if (is_string($dependency)) {
                     // Draft 3 string is allowed - e.g. "dependencies": 
{"bar": "foo"}
-                    if (!property_exists($value, $dependency)) {
+                    if (!$this->getTypeCheck()->propertyExists($value, 
$dependency)) {
                         $this->addError($path, "$key depends on $dependency 
and $dependency is missing", 'dependencies');
                     }
-                } else if (is_array($dependency)) {
+                } elseif (is_array($dependency)) {
                     // Draft 4 must be an array - e.g. "dependencies": {"bar": 
["foo"]}
                     foreach ($dependency as $d) {
-                        if (!property_exists($value, $d)) {
+                        if (!$this->getTypeCheck()->propertyExists($value, 
$d)) {
                             $this->addError($path, "$key depends on $d and $d 
is missing", 'dependencies');
                         }
                     }
-                } else if (is_object($dependency)) {
+                } elseif (is_object($dependency)) {
                     // Schema - e.g. "dependencies": {"bar": {"properties": 
{"foo": {...}}}}
                     $this->checkUndefined($value, $dependency, $path, $i);
                 }
diff --git a/justinrainbow/json-schema/src/JsonSchema/Entity/JsonPointer.php 
b/justinrainbow/json-schema/src/JsonSchema/Entity/JsonPointer.php
new file mode 100644
index 0000000..00e14e0
--- /dev/null
+++ b/justinrainbow/json-schema/src/JsonSchema/Entity/JsonPointer.php
@@ -0,0 +1,129 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Entity;
+
+/**
+ * @package JsonSchema\Entity
+ * @author Joost Nijhuis <jnijhui...@gmail.com>
+ */
+class JsonPointer
+{
+    /** @var string */
+    private $filename;
+
+    /** @var string[] */
+    private $propertyPaths = array();
+
+    /**
+     * @param string $value
+     * @throws \InvalidArgumentException when $value is not a string
+     */
+    public function __construct($value)
+    {
+        if (!is_string($value)) {
+            throw new \InvalidArgumentException('Ref value must be a string');
+        }
+
+        $splitRef = explode('#', $value, 2);
+        $this->filename = $splitRef[0];
+        if (array_key_exists(1, $splitRef)) {
+            $this->propertyPaths = $this->decodePropertyPaths($splitRef[1]);
+        }
+    }
+
+    /**
+     * @param string $propertyPathString
+     * @return string[]
+     */
+    private function decodePropertyPaths($propertyPathString)
+    {
+        $paths = array();
+        foreach (explode('/', trim($propertyPathString, '/')) as $path) {
+            $path = $this->decodePath($path);
+            if (is_string($path) && '' !== $path) {
+                $paths[] = $path;
+            }
+        }
+
+        return $paths;
+    }
+
+    /**
+     * @return array
+     */
+    private function encodePropertyPaths()
+    {
+        return array_map(
+            array($this, 'encodePath'),
+            $this->getPropertyPaths()
+        );
+    }
+
+    /**
+     * @param string $path
+     * @return string
+     */
+    private function decodePath($path)
+    {
+        return strtr($path, array('~1' => '/', '~0' => '~', '%25' => '%'));
+    }
+
+    /**
+     * @param string $path
+     * @return string
+     */
+    private function encodePath($path)
+    {
+        return strtr($path, array('/' => '~1', '~' => '~0', '%' => '%25'));
+    }
+
+    /**
+     * @return string
+     */
+    public function getFilename()
+    {
+        return $this->filename;
+    }
+
+    /**
+     * @return string[]
+     */
+    public function getPropertyPaths()
+    {
+        return $this->propertyPaths;
+    }
+
+    /**
+     * @param array $propertyPaths
+     * @return JsonPointer
+     */
+    public function withPropertyPaths(array $propertyPaths)
+    {
+        $new = clone $this;
+        $new->propertyPaths = $propertyPaths;
+        return $new;
+    }
+
+    /**
+     * @return string
+     */
+    public function getPropertyPathAsString()
+    {
+        return rtrim('#/' . implode('/', $this->encodePropertyPaths()), '/');
+    }
+
+    /**
+     * @return string
+     */
+    public function __toString()
+    {
+        return $this->getFilename() . $this->getPropertyPathAsString();
+    }
+}
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Exception/ExceptionInterface.php 
b/justinrainbow/json-schema/src/JsonSchema/Exception/ExceptionInterface.php
new file mode 100644
index 0000000..14d532a
--- /dev/null
+++ b/justinrainbow/json-schema/src/JsonSchema/Exception/ExceptionInterface.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace JsonSchema\Exception;
+
+interface ExceptionInterface
+{
+
+}
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.php
 
b/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.php
index ec702a7..ac37135 100644
--- 
a/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.php
+++ 
b/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.php
@@ -12,6 +12,6 @@
 /**
  * Wrapper for the InvalidArgumentException
  */
-class InvalidArgumentException extends \InvalidArgumentException
+class InvalidArgumentException extends \InvalidArgumentException implements 
ExceptionInterface
 {
 }
\ No newline at end of file
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.php
 
b/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.php
index 2e94677..93cc97e 100644
--- 
a/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.php
+++ 
b/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.php
@@ -12,6 +12,6 @@
 /**
  * Wrapper for the InvalidSchemaMediaType
  */
-class InvalidSchemaMediaTypeException extends \RuntimeException
+class InvalidSchemaMediaTypeException extends RuntimeException
 {    
 }
\ No newline at end of file
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php 
b/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php
index 2c22881..a755626 100644
--- 
a/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php
+++ 
b/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php
@@ -12,7 +12,7 @@
 /**
  * Wrapper for the JsonDecodingException
  */
-class JsonDecodingException extends \RuntimeException
+class JsonDecodingException extends RuntimeException
 {
     public function __construct($code = JSON_ERROR_NONE, \Exception $previous 
= null)
     {
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.php
 
b/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.php
index 87b4ac1..3341a90 100644
--- 
a/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.php
+++ 
b/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.php
@@ -12,6 +12,6 @@
 /**
  * Wrapper for the ResourceNotFoundException
  */
-class ResourceNotFoundException extends \RuntimeException
+class ResourceNotFoundException extends RuntimeException
 {
 }
\ No newline at end of file
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Exception/RuntimeException.php 
b/justinrainbow/json-schema/src/JsonSchema/Exception/RuntimeException.php
new file mode 100644
index 0000000..3a4d3f9
--- /dev/null
+++ b/justinrainbow/json-schema/src/JsonSchema/Exception/RuntimeException.php
@@ -0,0 +1,17 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Exception;
+
+/**
+ * Wrapper for the RuntimeException
+ */
+class RuntimeException extends \RuntimeException implements ExceptionInterface
+{
+}
\ No newline at end of file
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Exception/UnresolvableJsonPointerException.php
 
b/justinrainbow/json-schema/src/JsonSchema/Exception/UnresolvableJsonPointerException.php
new file mode 100644
index 0000000..44c562e
--- /dev/null
+++ 
b/justinrainbow/json-schema/src/JsonSchema/Exception/UnresolvableJsonPointerException.php
@@ -0,0 +1,18 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Exception;
+
+/**
+ * @package JsonSchema\Exception
+ * @author Joost Nijhuis <jnijhui...@gmail.com>
+ */
+class UnresolvableJsonPointerException extends InvalidArgumentException
+{
+}
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.php 
b/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.php
index 6d0b094..f9e7f28 100644
--- 
a/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.php
+++ 
b/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.php
@@ -12,6 +12,6 @@
 /**
  * Wrapper for the UriResolverException
  */
-class UriResolverException extends \RuntimeException
+class UriResolverException extends RuntimeException
 {
 }
\ No newline at end of file
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Iterator/ObjectIterator.php 
b/justinrainbow/json-schema/src/JsonSchema/Iterator/ObjectIterator.php
new file mode 100644
index 0000000..61bf5be
--- /dev/null
+++ b/justinrainbow/json-schema/src/JsonSchema/Iterator/ObjectIterator.php
@@ -0,0 +1,147 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema\Iterator;
+
+/**
+ * @package JsonSchema\Iterator
+ * @author Joost Nijhuis <jnijhui...@gmail.com>
+ */
+class ObjectIterator implements \Iterator, \Countable
+{
+    /** @var object */
+    private $object;
+
+    /** @var int */
+    private $position = 0;
+
+    /** @var array */
+    private $data = array();
+
+    /** @var bool */
+    private $initialized = false;
+
+    /**
+     * @param object $object
+     */
+    public function __construct($object)
+    {
+        $this->object = $object;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function current()
+    {
+        $this->initialize();
+
+        return $this->data[$this->position];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function next()
+    {
+        $this->initialize();
+        $this->position++;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function key()
+    {
+        $this->initialize();
+
+        return $this->position;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function valid()
+    {
+        $this->initialize();
+
+        return isset($this->data[$this->position]);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function rewind()
+    {
+        $this->initialize();
+        $this->position = 0;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function count()
+    {
+        $this->initialize();
+
+        return count($this->data);
+    }
+
+    /**
+     * Initializer
+     */
+    private function initialize()
+    {
+        if (!$this->initialized) {
+            $this->data = $this->buildDataFromObject($this->object);
+            $this->initialized = true;
+        }
+    }
+
+    /**
+     * @param object $object
+     * @return array
+     */
+    private function buildDataFromObject($object)
+    {
+        $result = array();
+
+        $stack = new \SplStack();
+        $stack->push($object);
+
+        while (!$stack->isEmpty()) {
+
+            $current = $stack->pop();
+            if (is_object($current)) {
+                array_push($result, $current);
+            }
+
+            foreach ($this->getDataFromItem($current) as $propertyName => 
$propertyValue) {
+                if (is_object($propertyValue) || is_array($propertyValue)) {
+                    $stack->push($propertyValue);
+                }
+            }
+        }
+
+        return $result;
+    }
+
+    /**
+     * @param object|array $item
+     * @return array
+     */
+    private function getDataFromItem($item)
+    {
+        if (!is_object($item) && !is_array($item)) {
+            return array();
+        }
+
+        return is_object($item) ? get_object_vars($item) : $item;
+    }
+}
diff --git a/justinrainbow/json-schema/src/JsonSchema/RefResolver.php 
b/justinrainbow/json-schema/src/JsonSchema/RefResolver.php
deleted file mode 100644
index ea0fafd..0000000
--- a/justinrainbow/json-schema/src/JsonSchema/RefResolver.php
+++ /dev/null
@@ -1,277 +0,0 @@
-<?php
-
-/*
- * This file is part of the JsonSchema package.
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace JsonSchema;
-
-use JsonSchema\Exception\JsonDecodingException;
-use JsonSchema\Uri\Retrievers\UriRetrieverInterface;
-use JsonSchema\Uri\UriRetriever;
-
-/**
- * Take in an object that's a JSON schema and take care of all $ref references
- *
- * @author Tyler Akins <fid...@rumkin.com>
- * @see    README.md
- */
-class RefResolver
-{
-    /**
-     * HACK to prevent too many recursive expansions.
-     * Happens e.g. when you want to validate a schema against the schema
-     * definition.
-     *
-     * @var integer
-     */
-    protected static $depth = 0;
-
-    /**
-     * maximum references depth
-     * @var integer
-     */
-    public static $maxDepth = 7;
-
-    /**
-     * @var UriRetrieverInterface
-     */
-    protected $uriRetriever = null;
-
-    /**
-     * @var object
-     */
-    protected $rootSchema = null;
-
-    /**
-     * @param UriRetriever $retriever
-     */
-    public function __construct($retriever = null)
-    {
-        $this->uriRetriever = $retriever;
-    }
-
-    /**
-     * Retrieves a given schema given a ref and a source URI
-     *
-     * @param  string $ref       Reference from schema
-     * @param  string $sourceUri URI where original schema was located
-     * @return object            Schema
-     */
-    public function fetchRef($ref, $sourceUri)
-    {
-        $retriever  = $this->getUriRetriever();
-        $jsonSchema = $retriever->retrieve($ref, $sourceUri);
-        $this->resolve($jsonSchema);
-
-        return $jsonSchema;
-    }
-
-    /**
-     * Return the URI Retriever, defaulting to making a new one if one
-     * was not yet set.
-     *
-     * @return UriRetriever
-     */
-    public function getUriRetriever()
-    {
-        if (is_null($this->uriRetriever)) {
-            $this->setUriRetriever(new UriRetriever);
-        }
-
-        return $this->uriRetriever;
-    }
-
-    /**
-     * Resolves all $ref references for a given schema.  Recurses through
-     * the object to resolve references of any child schemas.
-     *
-     * The 'format' property is omitted because it isn't required for
-     * validation.  Theoretically, this class could be extended to look
-     * for URIs in formats: "These custom formats MAY be expressed as
-     * an URI, and this URI MAY reference a schema of that format."
-     *
-     * The 'id' property is not filled in, but that could be made to happen.
-     *
-     * @param object $schema    JSON Schema to flesh out
-     * @param string $sourceUri URI where this schema was located
-     */
-    public function resolve($schema, $sourceUri = null)
-    {
-        if (self::$depth > self::$maxDepth) {
-            self::$depth = 0;
-            throw new JsonDecodingException(JSON_ERROR_DEPTH);
-        }
-        ++self::$depth;
-
-        if (! is_object($schema)) {
-            --self::$depth;
-            return;
-        }
-
-        if (null === $sourceUri && ! empty($schema->id)) {
-            $sourceUri = $schema->id;
-        }
-
-        if (null === $this->rootSchema) {
-            $this->rootSchema = $schema;
-        }
-
-        // Resolve $ref first
-        $this->resolveRef($schema, $sourceUri);
-
-        // These properties are just schemas
-        // eg.  items can be a schema or an array of schemas
-        foreach (array('additionalItems', 'additionalProperties', 'extends', 
'items') as $propertyName) {
-            $this->resolveProperty($schema, $propertyName, $sourceUri);
-        }
-
-        // These are all potentially arrays that contain schema objects
-        // eg.  type can be a value or an array of values/schemas
-        // eg.  items can be a schema or an array of schemas
-        foreach (array('disallow', 'extends', 'items', 'type', 'allOf', 
'anyOf', 'oneOf') as $propertyName) {
-            $this->resolveArrayOfSchemas($schema, $propertyName, $sourceUri);
-        }
-
-        // These are all objects containing properties whose values are schemas
-        foreach (array('dependencies', 'patternProperties', 'properties') as 
$propertyName) {
-            $this->resolveObjectOfSchemas($schema, $propertyName, $sourceUri);
-        }
-
-        --self::$depth;
-    }
-
-    /**
-     * Given an object and a property name, that property should be an
-     * array whose values can be schemas.
-     *
-     * @param object $schema       JSON Schema to flesh out
-     * @param string $propertyName Property to work on
-     * @param string $sourceUri    URI where this schema was located
-     */
-    public function resolveArrayOfSchemas($schema, $propertyName, $sourceUri)
-    {
-        if (! isset($schema->$propertyName) || ! 
is_array($schema->$propertyName)) {
-            return;
-        }
-
-        foreach ($schema->$propertyName as $possiblySchema) {
-            $this->resolve($possiblySchema, $sourceUri);
-        }
-    }
-
-    /**
-     * Given an object and a property name, that property should be an
-     * object whose properties are schema objects.
-     *
-     * @param object $schema       JSON Schema to flesh out
-     * @param string $propertyName Property to work on
-     * @param string $sourceUri    URI where this schema was located
-     */
-    public function resolveObjectOfSchemas($schema, $propertyName, $sourceUri)
-    {
-        if (! isset($schema->$propertyName) || ! 
is_object($schema->$propertyName)) {
-            return;
-        }
-
-        foreach (get_object_vars($schema->$propertyName) as $possiblySchema) {
-            $this->resolve($possiblySchema, $sourceUri);
-        }
-    }
-
-    /**
-     * Given an object and a property name, that property should be a
-     * schema object.
-     *
-     * @param object $schema       JSON Schema to flesh out
-     * @param string $propertyName Property to work on
-     * @param string $sourceUri    URI where this schema was located
-     */
-    public function resolveProperty($schema, $propertyName, $sourceUri)
-    {
-        if (! isset($schema->$propertyName)) {
-            return;
-        }
-
-        $this->resolve($schema->$propertyName, $sourceUri);
-    }
-
-    /**
-     * Look for the $ref property in the object.  If found, remove the
-     * reference and augment this object with the contents of another
-     * schema.
-     *
-     * @param object $schema    JSON Schema to flesh out
-     * @param string $sourceUri URI where this schema was located
-     */
-    public function resolveRef($schema, $sourceUri)
-    {
-        $ref = '$ref';
-
-        if (empty($schema->$ref)) {
-            return;
-        }
-
-        $splitRef = explode('#', $schema->$ref, 2);
-
-        $refDoc = $splitRef[0];
-        $refPath = null;
-        if (count($splitRef) === 2) {
-            $refPath = explode('/', $splitRef[1]);
-            array_shift($refPath);
-        }
-
-        if (empty($refDoc) && empty($refPath)) {
-            // TODO: Not yet implemented - root pointer ref, causes recursion 
issues
-            return;
-        }
-
-        if (!empty($refDoc)) {
-            $refSchema = $this->fetchRef($refDoc, $sourceUri);
-        } else {
-            $refSchema = $this->rootSchema;
-        }
-
-        if (null !== $refPath) {
-            $refSchema = $this->resolveRefSegment($refSchema, $refPath);
-        }
-
-        unset($schema->$ref);
-
-        // Augment the current $schema object with properties fetched
-        foreach (get_object_vars($refSchema) as $prop => $value) {
-            $schema->$prop = $value;
-        }
-    }
-
-    /**
-     * Set URI Retriever for use with the Ref Resolver
-     *
-     * @param UriRetriever $retriever
-     * @return $this for chaining
-     */
-    public function setUriRetriever(UriRetriever $retriever)
-    {
-        $this->uriRetriever = $retriever;
-
-        return $this;
-    }
-
-    protected function resolveRefSegment($data, $pathParts)
-    {
-        foreach ($pathParts as $path) {
-            $path = strtr($path, array('~1' => '/', '~0' => '~', '%25' => 
'%'));
-
-            if (is_array($data)) {
-                $data = $data[$path];
-            } else {
-                $data = $data->{$path};
-            }
-        }
-
-        return $data;
-    }
-}
diff --git a/justinrainbow/json-schema/src/JsonSchema/Rfc3339.php 
b/justinrainbow/json-schema/src/JsonSchema/Rfc3339.php
new file mode 100644
index 0000000..5afdaed
--- /dev/null
+++ b/justinrainbow/json-schema/src/JsonSchema/Rfc3339.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace JsonSchema;
+
+class Rfc3339
+{
+    const REGEX = 
'/(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})(\.\d+)?(Z|([+-]\d{2}):?(\d{2}))/';
+
+    /**
+     * Try creating a DateTime instance
+     *
+     * @param string $string
+     * @return \DateTime|null
+     */
+    public static function createFromString($string)
+    {
+        if (!preg_match(self::REGEX, strtoupper($string), $matches)) {
+            return null;
+        }
+
+        $dateAndTime = $matches[1];
+        $microseconds = $matches[2] ?: '.000000';
+        $timeZone = 'Z' !== $matches[3] ? $matches[4] . ':' . $matches[5] : 
'+00:00';
+
+        $dateTime = \DateTime::createFromFormat('Y-m-d\TH:i:s.uP', 
$dateAndTime . $microseconds . $timeZone, new \DateTimeZone('UTC'));
+
+        return $dateTime ?: null;
+    }
+}
diff --git a/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php 
b/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php
new file mode 100644
index 0000000..97f88eb
--- /dev/null
+++ b/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php
@@ -0,0 +1,109 @@
+<?php
+
+namespace JsonSchema;
+
+use JsonSchema\Entity\JsonPointer;
+use JsonSchema\Exception\UnresolvableJsonPointerException;
+use JsonSchema\Iterator\ObjectIterator;
+use JsonSchema\Uri\UriResolver;
+use JsonSchema\Uri\UriRetriever;
+
+class SchemaStorage
+{
+    protected $uriRetriever;
+    protected $uriResolver;
+    protected $schemas = array();
+
+    public function __construct(
+        UriRetrieverInterface $uriRetriever = null,
+        UriResolverInterface $uriResolver = null
+    ) {
+        $this->uriRetriever = $uriRetriever ?: new UriRetriever;
+        $this->uriResolver = $uriResolver ?: new UriResolver;
+    }
+
+    /**
+     * @return UriRetrieverInterface
+     */
+    public function getUriRetriever()
+    {
+        return $this->uriRetriever;
+    }
+
+    /**
+     * @return UriResolverInterface
+     */
+    public function getUriResolver()
+    {
+        return $this->uriResolver;
+    }
+
+    /**
+     * @param string $id
+     * @param object $schema
+     */
+    public function addSchema($id, $schema = null)
+    {
+        if (is_null($schema)) {
+            $schema = $this->uriRetriever->retrieve($id);
+        }
+        $objectIterator = new ObjectIterator($schema);
+        foreach ($objectIterator as $toResolveSchema) {
+            if (property_exists($toResolveSchema, '$ref') && 
is_string($toResolveSchema->{'$ref'})) {
+                $jsonPointer = new 
JsonPointer($this->uriResolver->resolve($toResolveSchema->{'$ref'}, $id));
+                $toResolveSchema->{'$ref'} = (string)$jsonPointer;
+            }
+        }
+        $this->schemas[$id] = $schema;
+    }
+
+    /**
+     * @param string $id
+     * @return object
+     */
+    public function getSchema($id)
+    {
+        if (!array_key_exists($id, $this->schemas)) {
+            $this->addSchema($id);
+        }
+
+        return $this->schemas[$id];
+    }
+
+    public function resolveRef($ref)
+    {
+        $jsonPointer = new JsonPointer($ref);
+        $refSchema = $this->getSchema($jsonPointer->getFilename());
+
+        foreach ($jsonPointer->getPropertyPaths() as $path) {
+            if (is_object($refSchema) && property_exists($refSchema, $path)) {
+                $refSchema = $this->resolveRefSchema($refSchema->{$path});
+            } elseif (is_array($refSchema) && array_key_exists($path, 
$refSchema)) {
+                $refSchema = $this->resolveRefSchema($refSchema[$path]);
+            } else {
+                throw new UnresolvableJsonPointerException(sprintf(
+                    'File: %s is found, but could not resolve fragment: %s',
+                    $jsonPointer->getFilename(),
+                    $jsonPointer->getPropertyPathAsString()
+                ));
+            }
+        }
+
+        return $refSchema;
+    }
+
+    /**
+     * @param $refSchema
+     * @return object
+     */
+    public function resolveRefSchema($refSchema)
+    {
+        if (is_object($refSchema) && property_exists($refSchema, '$ref')) {
+            $newSchema = $this->resolveRef($refSchema->{'$ref'});
+            $refSchema = (object) (get_object_vars($refSchema) + 
get_object_vars($newSchema));
+            unset($refSchema->{'$ref'});
+        }
+
+        return $refSchema;
+    }
+}
diff --git 
a/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php 
b/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php
index bc43de6..0c4d54a 100644
--- 
a/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php
+++ 
b/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php
@@ -14,51 +14,51 @@
 
 /**
  * Tries to retrieve JSON schemas from a URI using file_get_contents()
- * 
- * @author Sander Coolen <san...@jibber.nl> 
+ *
+ * @author Sander Coolen <san...@jibber.nl>
  */
 class FileGetContents extends AbstractRetriever
 {
     protected $messageBody;
-    
+
     /**
      * {@inheritDoc}
      * @see \JsonSchema\Uri\Retrievers\UriRetrieverInterface::retrieve()
      */
     public function retrieve($uri)
     {
-        $context = stream_context_create(array(
-            'http' => array(
-                'method' => 'GET',
-                'header' => "Accept: " . Validator::SCHEMA_MEDIA_TYPE
-            )));
-
-        set_error_handler(function() use ($uri) {
-            throw new ResourceNotFoundException('JSON schema not found at ' . 
$uri);
+        $errorMessage = null;
+        set_error_handler(function ($errno, $errstr) use (&$errorMessage) {
+            $errorMessage = $errstr;
         });
         $response = file_get_contents($uri);
         restore_error_handler();
 
-        if (false === $response) {
-            throw new ResourceNotFoundException('JSON schema not found at ' . 
$uri);
+        if ($errorMessage) {
+            throw new ResourceNotFoundException($errorMessage);
         }
+
+        if (false === $response) {
+            throw new ResourceNotFoundException('JSON schema not found at 
'.$uri);
+        }
+
         if ($response == ''
             && substr($uri, 0, 7) == 'file://' && substr($uri, -1) == '/'
         ) {
-            throw new ResourceNotFoundException('JSON schema not found at ' . 
$uri);
+            throw new ResourceNotFoundException('JSON schema not found at 
'.$uri);
         }
 
         $this->messageBody = $response;
-        if (! empty($http_response_header)) {
+        if (!empty($http_response_header)) {
             $this->fetchContentType($http_response_header);
         } else {
             // Could be a "file://" url or something else - fake up the 
response
             $this->contentType = null;
         }
-        
+
         return $this->messageBody;
     }
-    
+
     /**
      * @param array $headers HTTP Response Headers
      * @return boolean Whether the Content-Type header was found or not
@@ -70,10 +70,10 @@
                 return true;
             }
         }
-        
+
         return false;
     }
-    
+
     /**
      * @param string $header
      * @return string|null
diff --git a/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php 
b/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php
index 9784114..a4a6323 100644
--- a/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php
+++ b/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php
@@ -10,13 +10,14 @@
 namespace JsonSchema\Uri;
 
 use JsonSchema\Exception\UriResolverException;
+use JsonSchema\UriResolverInterface;
 
 /**
  * Resolves JSON Schema URIs
  * 
  * @author Sander Coolen <san...@jibber.nl> 
  */
-class UriResolver
+class UriResolver implements UriResolverInterface
 {
     /**
      * Parses a URI into five main components
@@ -69,11 +70,7 @@
     }
     
     /**
-     * Resolves a URI
-     * 
-     * @param string $uri Absolute or relative
-     * @param string $baseUri Optional base URI
-     * @return string Absolute URI
+     * {@inheritdoc}
      */
     public function resolve($uri, $baseUri = null)
     {
diff --git a/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php 
b/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php
index c723cd9..b2445a7 100644
--- a/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php
+++ b/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php
@@ -11,6 +11,7 @@
 
 use JsonSchema\Uri\Retrievers\FileGetContents;
 use JsonSchema\Uri\Retrievers\UriRetrieverInterface;
+use JsonSchema\UriRetrieverInterface as BaseUriRetrieverInterface;
 use JsonSchema\Validator;
 use JsonSchema\Exception\InvalidSchemaMediaTypeException;
 use JsonSchema\Exception\JsonDecodingException;
@@ -21,7 +22,7 @@
  *
  * @author Tyler Akins <fid...@rumkin.com>
  */
-class UriRetriever
+class UriRetriever implements BaseUriRetrieverInterface
 {
     /**
      * @var null|UriRetrieverInterface
@@ -50,7 +51,7 @@
             return;
         }
 
-        if (Validator::SCHEMA_MEDIA_TYPE === $contentType) {
+        if (in_array($contentType, array(Validator::SCHEMA_MEDIA_TYPE, 
'application/json'))) {
             return;
         }
 
@@ -128,11 +129,7 @@
     }
 
     /**
-     * Retrieve a URI
-     *
-     * @param string $uri JSON Schema URI
-     * @param string|null $baseUri
-     * @return object JSON Schema contents
+     * {@inheritdoc}
      */
     public function retrieve($uri, $baseUri = null)
     {
diff --git a/justinrainbow/json-schema/src/JsonSchema/UriResolverInterface.php 
b/justinrainbow/json-schema/src/JsonSchema/UriResolverInterface.php
new file mode 100644
index 0000000..1386c18
--- /dev/null
+++ b/justinrainbow/json-schema/src/JsonSchema/UriResolverInterface.php
@@ -0,0 +1,25 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema;
+
+/**
+ * @package JsonSchema
+ */
+interface UriResolverInterface
+{
+    /**
+     * Resolves a URI
+     *
+     * @param string $uri Absolute or relative
+     * @param null|string $baseUri Optional base URI
+     * @return string Absolute URI
+     */
+    public function resolve($uri, $baseUri = null);
+}
diff --git a/justinrainbow/json-schema/src/JsonSchema/UriRetrieverInterface.php 
b/justinrainbow/json-schema/src/JsonSchema/UriRetrieverInterface.php
new file mode 100644
index 0000000..3b683f9
--- /dev/null
+++ b/justinrainbow/json-schema/src/JsonSchema/UriRetrieverInterface.php
@@ -0,0 +1,25 @@
+<?php
+
+/*
+ * This file is part of the JsonSchema package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace JsonSchema;
+
+/**
+ * @package JsonSchema
+ */
+interface UriRetrieverInterface
+{
+    /**
+     * Retrieve a URI
+     *
+     * @param string $uri JSON Schema URI
+     * @param null|string $baseUri
+     * @return object JSON Schema contents
+     */
+    public function retrieve($uri, $baseUri = null);
+}
diff --git a/justinrainbow/json-schema/src/JsonSchema/Validator.php 
b/justinrainbow/json-schema/src/JsonSchema/Validator.php
index 14dbb60..b627d78 100644
--- a/justinrainbow/json-schema/src/JsonSchema/Validator.php
+++ b/justinrainbow/json-schema/src/JsonSchema/Validator.php
@@ -11,6 +11,7 @@
 
 use JsonSchema\Constraints\SchemaConstraint;
 use JsonSchema\Constraints\Constraint;
+use JsonSchema\Entity\JsonPointer;
 
 /**
  * A JsonSchema Constraint
@@ -30,7 +31,7 @@
      *
      * {@inheritDoc}
      */
-    public function check($value, $schema = null, $path = null, $i = null)
+    public function check($value, $schema = null, JsonPointer $path = null, $i 
= null)
     {
         $validator = $this->getFactory()->createInstanceFor('schema');
         $validator->check($value, $schema);

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I5687286da9f7fa2bb2b84699fa43ab3c2547fe03
Gerrit-PatchSet: 3
Gerrit-Project: mediawiki/vendor
Gerrit-Branch: master
Gerrit-Owner: Florianschmidtwelzow <florian.schmidt.stargatewis...@gmail.com>
Gerrit-Reviewer: Legoktm <legoktm.wikipe...@gmail.com>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to