浏览代码

refactor: move DocumentCache into reference manager

Sam Jaffe 1 年之前
父节点
当前提交
563e97d788

+ 1 - 3
include/jvalidate/detail/parser_context.h

@@ -4,7 +4,6 @@
 
 #include <jvalidate/detail/reference.h>
 #include <jvalidate/forward.h>
-#include <jvalidate/reference_handler.h>
 
 namespace jvalidate::detail {
 template <Adapter A> struct ParserContext {
@@ -15,7 +14,6 @@ template <Adapter A> struct ParserContext {
 
   schema::Version version;
   ConstraintFactory<A> const & factory;
-  DocumentCache<A> & external;
   ReferenceManager<A> & ref;
 
   std::optional<Object> parent = std::nullopt;
@@ -24,7 +22,7 @@ template <Adapter A> struct ParserContext {
 
   ParserContext rebind(A const & new_schema, Reference const & new_loc, Reference const & new_dyn,
                        std::optional<Object> parent = std::nullopt) const {
-    return {root, new_schema, version, factory, external, ref, parent, new_loc, new_dyn};
+    return {root, new_schema, version, factory, ref, parent, new_loc, new_dyn};
   }
 
   ParserContext child(A const & child, std::string const & key) const {

+ 1 - 0
include/jvalidate/forward.h

@@ -139,6 +139,7 @@ concept RegexEngine = std::constructible_from<std::string> && requires(R const r
 namespace jvalidate {
 template <Adapter A> class ConstraintFactory;
 template <Adapter A> class DocumentCache;
+template <Adapter A> class ReferenceManager;
 template <Adapter A, RegexEngine RE> class ValidationVisitor;
 
 template <RegexEngine RE> class ValidatorT;

+ 29 - 4
include/jvalidate/reference_handler.h

@@ -6,9 +6,11 @@
 #include <unordered_map>
 
 #include <jvalidate/detail/anchor.h>
+#include <jvalidate/detail/parser_context.h>
 #include <jvalidate/detail/pointer.h>
 #include <jvalidate/detail/reference.h>
 #include <jvalidate/detail/reference_cache.h>
+#include <jvalidate/document_cache.h>
 #include <jvalidate/enum.h>
 #include <jvalidate/forward.h>
 #include <jvalidate/uri.h>
@@ -19,15 +21,16 @@ public:
   using Keywords = std::unordered_map<std::string_view, std::set<schema::Wraps>>;
 
 private:
-  std::map<detail::RootReference, A> roots_;
-
+  DocumentCache<A> & external_;
   detail::ReferenceCache references_;
 
+  std::map<detail::RootReference, A> roots_;
   std::multimap<URI, detail::Anchor> dynamic_anchors_;
 
 public:
-  ReferenceManager(A const & root, schema::Version version, Keywords const & keywords)
-      : roots_{{{}, root}} {
+  ReferenceManager(DocumentCache<A> & external, A const & root, schema::Version version,
+                   Keywords const & keywords)
+      : external_(external), roots_{{{}, root}} {
     prime_impl(root, {}, version, keywords);
   }
 
@@ -47,6 +50,28 @@ public:
     return std::nullopt;
   }
 
+  std::optional<A> load(detail::Reference const & ref, detail::ParserContext<A> const & context) {
+    if (std::optional<A> in_cache = root(ref.root())) {
+      return ref.pointer().walk(*in_cache);
+    }
+
+    std::optional<A> external = external_.try_load(ref.uri());
+    if (not external) {
+      return std::nullopt;
+    }
+
+    // TODO(samjaffe): Change Versions if needed...
+    prime(*external, ref.uri(), context.version, context.factory.keywords(context.version));
+
+    // May have a sub-id that we map to
+    if (std::optional<A> in_cache = root(ref.root())) {
+      return ref.pointer().walk(*in_cache);
+    }
+
+    // Will get called if the external schema does not declare a root document id?
+    return ref.pointer().walk(*external);
+  }
+
   detail::Reference canonicalize(detail::Reference const & ref,
                                  detail::Reference const & parent) const {
     // Relative URI, not in the HEREDOC (or we set an $id)

+ 6 - 18
include/jvalidate/schema.h

@@ -159,8 +159,8 @@ public:
       return;
     }
 
-    ReferenceManager<A> ref(json, version, factory.keywords(version));
-    detail::ParserContext<A> root{*this, json, version, factory, external, ref};
+    ReferenceManager<A> ref(external, json, version, factory.keywords(version));
+    detail::ParserContext<A> root{*this, json, version, factory, ref};
 
     root.where = root.dynamic_where = ref.canonicalize({}, {});
     construct(root);
@@ -243,24 +243,12 @@ private:
     }
 
     // Special case if the root-level document does not have an $id property
-    if (std::optional root = context.ref.root(lexical.root())) {
-      return fetch_schema(context.rebind(lexical.pointer().walk(*root), lexical, dynamic));
+    if (std::optional root = context.ref.load(lexical, context)) {
+      return fetch_schema(context.rebind(*root, lexical, dynamic));
     }
 
-    std::optional schema = context.external.try_load(lexical.uri());
-    if (not schema.has_value()) {
-      std::string error = "URIResolver could not resolve " + std::string(lexical.uri());
-      return alias(dynamic, &cache_.try_emplace(dynamic, error).first->second);
-    }
-
-    context.ref.prime(*schema, lexical.uri(), context.version,
-                      context.factory.keywords(context.version));
-
-    if (std::optional root = context.ref.root(lexical.root())) {
-      return fetch_schema(context.rebind(lexical.pointer().walk(*root), lexical, dynamic));
-    }
-
-    return fetch_schema(context.rebind(lexical.pointer().walk(*schema), lexical, dynamic));
+    std::string error = "URIResolver could not resolve " + std::string(lexical.uri());
+    return alias(dynamic, &cache_.try_emplace(dynamic, error).first->second);
   }
 
   template <Adapter A> schema::Node const * fetch_schema(detail::ParserContext<A> const & context) {