77#include < sourcemeta/blaze/evaluator.h>
88#include < sourcemeta/blaze/output.h>
99
10- #include < cassert> // assert
10+ #include < cassert> // assert
11+ #include < filesystem>
1112#include < iostream> // std::cerr
1213#include < map> // std::map
13- #include < string> // std::string
14+ #include < optional>
15+ #include < sstream>
16+ #include < string> // std::string
17+ #include < string_view>
18+ #include < vector>
1419
1520#include " command.h"
1621#include " configuration.h"
@@ -29,31 +34,43 @@ auto sourcemeta::jsonschema::metaschema(
2934 sourcemeta::blaze::Evaluator evaluator;
3035
3136 std::map<std::string, sourcemeta::blaze::Template> cache;
37+ const auto current_path{std::filesystem::current_path ()};
38+ const auto remote_configuration_path{find_configuration (current_path)};
39+ const auto &remote_configuration{
40+ read_configuration (options, remote_configuration_path)};
3241
33- for (const auto &entry : for_each_json (options)) {
34- if (!sourcemeta::core::is_schema (entry.second )) {
35- throw NotSchemaError{entry.first };
36- }
37-
38- const auto configuration_path{find_configuration (entry.first )};
39- const auto &configuration{
40- read_configuration (options, configuration_path, entry.first )};
41- const auto default_dialect_option{default_dialect (options, configuration)};
42+ const auto process_schema =
43+ [&](const sourcemeta::core::JSON &schema,
44+ const sourcemeta::core::PointerPositionTracker &positions,
45+ const std::optional<std::filesystem::path> &schema_path,
46+ const std::string_view schema_display,
47+ const sourcemeta::jsonschema::CustomResolver &custom_resolver,
48+ const std::string_view default_dialect_option) -> void {
49+ if (!sourcemeta::core::is_schema (schema)) {
50+ if (schema_path.has_value ()) {
51+ throw NotSchemaError{schema_path.value ()};
52+ }
4253
43- const auto &custom_resolver{resolver (options, options.contains (" http" ),
44- default_dialect_option,
45- configuration)};
54+ throw RemoteSchemaNotSchemaError{std::string{schema_display}};
55+ }
4656
4757 try {
4858 const auto dialect{
49- sourcemeta::core::dialect (entry. second , default_dialect_option)};
59+ sourcemeta::core::dialect (schema , default_dialect_option)};
5060 if (dialect.empty ()) {
51- throw FileError<sourcemeta::core::SchemaUnknownBaseDialectError>(
52- entry.first );
61+ if (schema_path.has_value ()) {
62+ throw FileError<sourcemeta::core::SchemaUnknownBaseDialectError>(
63+ schema_path.value ());
64+ }
65+
66+ std::ostringstream error;
67+ error << " Could not resolve the metaschema of the schema\n at uri "
68+ << schema_display;
69+ throw std::runtime_error (error.str ());
5370 }
5471
5572 const auto metaschema{sourcemeta::core::metaschema (
56- entry. second , custom_resolver, default_dialect_option)};
73+ schema , custom_resolver, default_dialect_option)};
5774 const sourcemeta::core::JSON bundled{
5875 sourcemeta::core::bundle (metaschema, sourcemeta::core::schema_walker,
5976 custom_resolver, default_dialect_option)};
@@ -74,16 +91,16 @@ auto sourcemeta::jsonschema::metaschema(
7491 sourcemeta::blaze::TraceOutput output{
7592 sourcemeta::core::schema_walker, custom_resolver,
7693 sourcemeta::core::empty_weak_pointer, frame};
77- result = evaluator.validate (cache.at (std::string{dialect}),
78- entry. second , std::ref (output));
79- print (output, entry. positions , std::cout);
94+ result = evaluator.validate (cache.at (std::string{dialect}), schema,
95+ std::ref (output));
96+ print (output, positions, std::cout);
8097 } else if (json_output) {
8198 // Otherwise its impossible to correlate the output
8299 // when validating i.e. a directory of schemas
83- std::cerr << entry. first . string () << " \n " ;
100+ std::cerr << schema_display << " \n " ;
84101 const auto output{sourcemeta::blaze::standard (
85- evaluator, cache.at (std::string{dialect}), entry. second ,
86- sourcemeta::blaze::StandardOutput::Basic, entry. positions )};
102+ evaluator, cache.at (std::string{dialect}), schema ,
103+ sourcemeta::blaze::StandardOutput::Basic, positions)};
87104 assert (output.is_object ());
88105 assert (output.defines (" valid" ));
89106 assert (output.at (" valid" ).is_boolean ());
@@ -94,29 +111,56 @@ auto sourcemeta::jsonschema::metaschema(
94111 sourcemeta::core::prettify (output, std::cout);
95112 std::cout << " \n " ;
96113 } else {
97- sourcemeta::blaze::SimpleOutput output{entry. second };
98- if (evaluator.validate (cache.at (std::string{dialect}), entry. second ,
114+ sourcemeta::blaze::SimpleOutput output{schema };
115+ if (evaluator.validate (cache.at (std::string{dialect}), schema ,
99116 std::ref (output))) {
100117 LOG_VERBOSE (options)
101- << " ok: "
102- << sourcemeta::core::weakly_canonical (entry.first ).string ()
103- << " \n matches " << dialect << " \n " ;
118+ << " ok: " << schema_display << " \n matches " << dialect << " \n " ;
104119 } else {
105- std::cerr << " fail: "
106- << sourcemeta::core::weakly_canonical (entry.first ).string ()
107- << " \n " ;
108- print (output, entry.positions , std::cerr);
120+ std::cerr << " fail: " << schema_display << " \n " ;
121+ print (output, positions, std::cerr);
109122 result = false ;
110123 }
111124 }
112125 } catch (const sourcemeta::core::SchemaRelativeMetaschemaResolutionError
113126 &error) {
114- throw FileError<
115- sourcemeta::core::SchemaRelativeMetaschemaResolutionError>(
116- entry.first , error);
127+ if (schema_path.has_value ()) {
128+ throw FileError<
129+ sourcemeta::core::SchemaRelativeMetaschemaResolutionError>(
130+ schema_path.value (), error);
131+ }
132+
133+ throw ;
117134 } catch (const sourcemeta::core::SchemaResolutionError &error) {
118- throw FileError<sourcemeta::core::SchemaResolutionError>(entry.first ,
119- error);
135+ if (schema_path.has_value ()) {
136+ throw FileError<sourcemeta::core::SchemaResolutionError>(
137+ schema_path.value (), error);
138+ }
139+
140+ throw ;
141+ }
142+ };
143+
144+ for (const auto &entry : for_each_json (options)) {
145+ if (entry.path .has_value ()) {
146+ const auto configuration_path{find_configuration (entry.path .value ())};
147+ const auto &configuration{
148+ read_configuration (options, configuration_path, entry.path .value ())};
149+ const auto default_dialect_option{
150+ default_dialect (options, configuration)};
151+ const auto &custom_resolver{resolver (options, options.contains (" http" ),
152+ default_dialect_option,
153+ configuration)};
154+ process_schema (entry.second , entry.positions , entry.path , entry.first ,
155+ custom_resolver, default_dialect_option);
156+ } else {
157+ const auto remote_default_dialect_option{
158+ default_dialect (options, remote_configuration)};
159+ const auto &remote_resolver{resolver (options, options.contains (" http" ),
160+ remote_default_dialect_option,
161+ remote_configuration)};
162+ process_schema (entry.second , entry.positions , std::nullopt , entry.first ,
163+ remote_resolver, remote_default_dialect_option);
120164 }
121165 }
122166
0 commit comments