Update document fetch interface to use underlying document type rather than Adapter

This commit is contained in:
Tristan Penman 2016-02-14 11:10:21 -08:00
parent bee57e1f90
commit 193c58da02
2 changed files with 33 additions and 32 deletions

View File

@ -64,10 +64,10 @@ public:
DocumentType; DocumentType;
/// Templated function pointer type for fetching remote documents /// Templated function pointer type for fetching remote documents
typedef const AdapterType * (*FetchDoc)(const std::string &uri); typedef const DocumentType * (*FetchDoc)(const std::string &uri);
/// Templated function pointer type for freeing fetched documents /// Templated function pointer type for freeing fetched documents
typedef void (*FreeDoc)(const AdapterType *); typedef void (*FreeDoc)(const DocumentType *);
}; };
/** /**
@ -116,7 +116,7 @@ private:
typedef typename adapters::AdapterTraits<AdapterType>::DocumentType typedef typename adapters::AdapterTraits<AdapterType>::DocumentType
DocumentType; DocumentType;
typedef std::map<std::string, const AdapterType*> Type; typedef std::map<std::string, const DocumentType*> Type;
}; };
typedef std::map<std::string, const Subschema *> SchemaCache; typedef std::map<std::string, const Subschema *> SchemaCache;
@ -395,7 +395,7 @@ private:
} }
if (actualDocumentUri) { if (actualDocumentUri) {
const AdapterType *newDoc = NULL; const typename FunctionPtrs<AdapterType>::DocumentType *newDoc = NULL;
// Have we seen this document before? // Have we seen this document before?
typename DocumentCache<AdapterType>::Type::iterator docCacheItr = typename DocumentCache<AdapterType>::Type::iterator docCacheItr =
@ -429,16 +429,18 @@ private:
newDoc = docCacheItr->second; newDoc = docCacheItr->second;
} }
const AdapterType newRootNode(*newDoc);
// Find where we need to be in the document // Find where we need to be in the document
const AdapterType &referencedAdapter = const AdapterType &referencedAdapter =
internal::json_pointer::resolveJsonPointer(*newDoc, internal::json_pointer::resolveJsonPointer(newRootNode,
actualJsonPointer); actualJsonPointer);
newCacheKeys.push_back(queryKey); newCacheKeys.push_back(queryKey);
// Populate the schema, starting from the referenced node, with // Populate the schema, starting from the referenced node, with
// nested JSON References resolved relative to the new root node // nested JSON References resolved relative to the new root node
return makeOrReuseSchema(rootSchema, *newDoc, referencedAdapter, return makeOrReuseSchema(rootSchema, newRootNode, referencedAdapter,
currentScope, actualJsonPointer, fetchDoc, parentSubschema, currentScope, actualJsonPointer, fetchDoc, parentSubschema,
ownName, docCache, schemaCache, newCacheKeys); ownName, docCache, schemaCache, newCacheKeys);
@ -885,7 +887,8 @@ private:
"Fetching of remote JSON References not enabled."); "Fetching of remote JSON References not enabled.");
} }
const AdapterType *newDoc = fetchDoc(*documentUri); const typename DocumentCache<AdapterType>::DocumentType *newDoc =
fetchDoc(*documentUri);
// Can't proceed without the remote document // Can't proceed without the remote document
if (!newDoc) { if (!newDoc) {
@ -900,14 +903,16 @@ private:
docCache.insert(DocCacheValueType(*documentUri, newDoc)); docCache.insert(DocCacheValueType(*documentUri, newDoc));
const AdapterType newRootNode(*newDoc);
const AdapterType &referencedAdapter = const AdapterType &referencedAdapter =
internal::json_pointer::resolveJsonPointer( internal::json_pointer::resolveJsonPointer(
*newDoc, actualJsonPointer); newRootNode, actualJsonPointer);
// TODO: Need to detect degenerate circular references // TODO: Need to detect degenerate circular references
resolveThenPopulateSchema(rootSchema, *newDoc, referencedAdapter, resolveThenPopulateSchema(rootSchema, newRootNode,
schema, boost::none, actualJsonPointer, fetchDoc, referencedAdapter, schema, boost::none, actualJsonPointer,
parentSchema, ownName, docCache, schemaCache); fetchDoc, parentSchema, ownName, docCache, schemaCache);
} else { } else {
const AdapterType &referencedAdapter = const AdapterType &referencedAdapter =

View File

@ -13,43 +13,38 @@ using valijson::SchemaParser;
using valijson::adapters::RapidJsonAdapter; using valijson::adapters::RapidJsonAdapter;
using valijson::Validator; using valijson::Validator;
namespace {
static rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> allocator;
static rapidjson::Value fetchedRoot;
static RapidJsonAdapter fetchedRootAdapter;
}
class TestFetchDocumentCallback : public ::testing::Test class TestFetchDocumentCallback : public ::testing::Test
{ {
}; };
const RapidJsonAdapter * fetchDocument(const std::string &uri) const rapidjson::Document * fetchDocument(const std::string &uri)
{ {
EXPECT_STREQ("http://localhost:1234/", uri.c_str()); EXPECT_STREQ("http://localhost:1234/", uri.c_str());
rapidjson::Document *fetchedRoot = new rapidjson::Document();
fetchedRoot->SetObject();
rapidjson::Value valueOfTypeAttribute; rapidjson::Value valueOfTypeAttribute;
valueOfTypeAttribute.SetString("string", allocator); valueOfTypeAttribute.SetString("string", fetchedRoot->GetAllocator());
rapidjson::Value schemaOfTestProperty; rapidjson::Value schemaOfTestProperty;
schemaOfTestProperty.SetObject(); schemaOfTestProperty.SetObject();
schemaOfTestProperty.AddMember("type", valueOfTypeAttribute, allocator); schemaOfTestProperty.AddMember("type", valueOfTypeAttribute,
fetchedRoot->GetAllocator());
rapidjson::Value propertiesConstraint; rapidjson::Value propertiesConstraint;
propertiesConstraint.SetObject(); propertiesConstraint.SetObject();
propertiesConstraint.AddMember("test", schemaOfTestProperty, allocator); propertiesConstraint.AddMember("test", schemaOfTestProperty,
fetchedRoot->GetAllocator());
fetchedRoot.SetObject(); fetchedRoot->AddMember("properties", propertiesConstraint,
fetchedRoot.AddMember("properties", propertiesConstraint, allocator); fetchedRoot->GetAllocator());
// Have to ensure that fetchedRoot exists for at least as long as the return fetchedRoot;
// shared pointer that we return here
return new RapidJsonAdapter(fetchedRoot);
} }
void freeDocument(const RapidJsonAdapter *adapter) void freeDocument(const rapidjson::Document *adapter)
{ {
delete adapter; delete adapter;
} }
@ -60,7 +55,8 @@ TEST_F(TestFetchDocumentCallback, Basics)
rapidjson::Document schemaDocument; rapidjson::Document schemaDocument;
RapidJsonAdapter schemaDocumentAdapter(schemaDocument); RapidJsonAdapter schemaDocumentAdapter(schemaDocument);
schemaDocument.SetObject(); schemaDocument.SetObject();
schemaDocument.AddMember("$ref", "http://localhost:1234/#/", allocator); schemaDocument.AddMember("$ref", "http://localhost:1234/#/",
schemaDocument.GetAllocator());
// Parse schema document // Parse schema document
Schema schema; Schema schema;
@ -71,7 +67,7 @@ TEST_F(TestFetchDocumentCallback, Basics)
// Test resulting schema with a valid document // Test resulting schema with a valid document
rapidjson::Document validDocument; rapidjson::Document validDocument;
validDocument.SetObject(); validDocument.SetObject();
validDocument.AddMember("test", "valid", allocator); validDocument.AddMember("test", "valid", schemaDocument.GetAllocator());
Validator validator; Validator validator;
EXPECT_TRUE(validator.validate(schema, RapidJsonAdapter(validDocument), EXPECT_TRUE(validator.validate(schema, RapidJsonAdapter(validDocument),
NULL)); NULL));
@ -79,7 +75,7 @@ TEST_F(TestFetchDocumentCallback, Basics)
// Test resulting schema with an invalid document // Test resulting schema with an invalid document
rapidjson::Document invalidDocument; rapidjson::Document invalidDocument;
invalidDocument.SetObject(); invalidDocument.SetObject();
invalidDocument.AddMember("test", 123, allocator); invalidDocument.AddMember("test", 123, schemaDocument.GetAllocator());
EXPECT_FALSE(validator.validate(schema, RapidJsonAdapter(invalidDocument), EXPECT_FALSE(validator.validate(schema, RapidJsonAdapter(invalidDocument),
NULL)); NULL));
} }