26{
27 enum Exitcode : int
28 {
29 SUCCESS,
30 BADCMD,
31 NOFILE,
32 LOADFAIL,
33 BADRELATIONSHIP,
34 UNRESOLVED,
35 MISSING_INCLUDE
36 };
37
39 "Check consistency of OKS schema file\n" +
40 fmt::format("Return codes: {} Success, file is OK\n", Exitcode::SUCCESS) +
41 fmt::format(" {} Bad command line\n", Exitcode::BADCMD) +
42 fmt::format(" {} Failed to find file\n", Exitcode::NOFILE) +
43 fmt::format(" {} Failed to load file -- invalid schema\n", Exitcode::LOADFAIL) +
44 fmt::format(" {} File contains relationship to non loaded class\n", Exitcode::BADRELATIONSHIP) +
45 fmt::format(" {} File contains object with relationship to non loaded class/object\n",
46 Exitcode::UNRESOLVED) +
47 fmt::format(" {} File refers to class in file not directly included\n", Exitcode::MISSING_INCLUDE)
48 };
49
51 app.add_option(
"-f,--file", filename,
"Schema file")->required();
52
53 CLI11_PARSE(app, argc, argv);
54
57 try {
61 return Exitcode::LOADFAIL;
64 return Exitcode::NOFILE;
65 } catch (std::exception& exc) {
66 TLOG() << exc.what() <<
"\n";
67 return Exitcode::LOADFAIL;
68 }
69
70 if (file == nullptr) {
72 return Exitcode::LOADFAIL;
73 }
74
75 std::set<std::string> includes;
76 for (
const auto& ifile :
file->get_include_files()) {
77 includes.insert(ifile);
78 TLOG_DEBUG(2) <<
"direct inserting " << ifile <<
"\n";
79 }
80
81 Exitcode result = Exitcode::SUCCESS;
82
83 if (
filename.ends_with(
".schema.xml")) {
84
85 for (
auto [name, oks_class] : kernel.
classes()) {
86
87 if (
file->get_full_file_name() != oks_class->get_file()->get_full_file_name()) {
88
89 continue;
90 }
91
92 auto cfile = oks_class->get_file()->get_short_file_name();
93 if (cfile !=
file->get_short_file_name() && !includes.contains(cfile)) {
94 TLOG() <<
"Error " <<
filename <<
" misses include of " << cfile <<
" required by " << name;
95 if (result == Exitcode::SUCCESS) {
96 result = Exitcode::MISSING_INCLUDE;
97 }
98 }
99 auto relationships = oks_class->direct_relationships();
100 if (relationships != nullptr) {
101 for (auto rel : *relationships) {
102 auto rel_class = rel->get_class_type();
103 if (rel_class == nullptr) {
104 TLOG() <<
"Error class '" << name <<
"' has relationship '" << rel->get_name() <<
"' to a class '"
105 << rel->get_type() << "' that is not loaded\n";
106 if (result == Exitcode::SUCCESS) {
107 result = Exitcode::BADRELATIONSHIP;
108 }
109 }
110 }
111 }
112
113
114 }
115 }
else if (
filename.ends_with(
".data.xml")) {
116
118 auto relobj =
data->data.OBJECT;
119 if (relobj == nullptr) {
120 return;
121 }
122 auto ofile_name = relobj->get_file()->get_short_file_name();
123 if (
file->get_short_file_name() != ofile_name && !includes.contains(ofile_name)) {
124 TLOG() <<
"Error " <<
filename <<
" misses include of " << ofile_name <<
" required by " << relobj->GetId();
125 if (result == Exitcode::SUCCESS) {
126 result = Exitcode::MISSING_INCLUDE;
127 }
128 }
129 };
130
132 for (auto obj : *data_objs) {
133
134
135 auto oks_class =
obj->GetClass();
136 auto cfile = oks_class->get_file()->get_short_file_name();
137 if (!includes.contains(cfile)) {
138 TLOG() <<
"Error " <<
filename <<
" misses include of " << cfile <<
" required by " <<
obj->GetId()
139 << " of class " << oks_class->get_name();
140 if (result == Exitcode::SUCCESS) {
141 result = Exitcode::MISSING_INCLUDE;
142 }
143 }
144
145
146
147 auto relationships = oks_class->all_relationships();
148 if (relationships != nullptr) {
149 for (auto rel : *relationships) {
150 auto relval =
obj->GetRelationshipValue(rel->get_name());
151 if (relval == nullptr) {
152 continue;
153 }
155 for (OksData::List::iterator iter = relval->data.LIST->begin(); iter != relval->data.LIST->end(); ++iter) {
156 check_relationship(*iter);
157 }
158 } else {
159 check_relationship(relval);
160 }
161 }
162 }
163 }
164 delete data_objs;
165 }
166
169 if (result == Exitcode::SUCCESS) {
170 result = Exitcode::UNRESOLVED;
171 }
172 }
173
174 return result;
175}
Provides interface to the OKS XML schema and data files.
Provides interface to the OKS kernel.
OksFile * load_file(const std::string &name, bool bind=true)
Load OKS database file.
std::list< OksObject * > * create_list_of_data_objects(OksFile *) const
Creates list of objects which belong to given file.
const OksClass::Map & classes() const
Get classes.
const std::string & get_bind_objects_status() const noexcept
Return status of oks objects binding.
virtual const char * what() const noexcept
#define TLOG_DEBUG(lvl,...)