26int main(
int argc,
char **argv) {
27 enum Exitcode :
int {SUCCESS, BADCMD, NOFILE, LOADFAIL,
28 BADRELATIONSHIP, UNRESOLVED,
31 CLI::App app{
"Check consistency of OKS schema file\n"+
32 fmt::format(
"Return codes: {} Success, file is OK\n", Exitcode::SUCCESS)+
33 fmt::format(
" {} Bad command line\n", Exitcode::BADCMD)+
34 fmt::format(
" {} Failed to find file\n", Exitcode::NOFILE)+
35 fmt::format(
" {} Failed to load file -- invalid schema\n", Exitcode::LOADFAIL)+
36 fmt::format(
" {} File contains relationship to non loaded class\n", Exitcode::BADRELATIONSHIP)+
37 fmt::format(
" {} File contains object with relationship to non loaded class/object\n", Exitcode::UNRESOLVED)+
38 fmt::format(
" {} File refers to class in file not directly included\n", Exitcode::MISSING_INCLUDE)
42 app.add_option(
"-f,--file",
filename,
"Schema file")
45 CLI11_PARSE(app, argc, argv);
54 return Exitcode::LOADFAIL;
58 return Exitcode::NOFILE;
60 catch (std::exception& exc) {
61 TLOG() << exc.what() <<
"\n";
62 return Exitcode::LOADFAIL;
65 if (file ==
nullptr) {
67 return Exitcode::LOADFAIL;
70 std::set<std::string> includes;
71 for (
const auto& ifile : file->get_include_files()) {
72 includes.insert(ifile);
73 TLOG_DEBUG(2) <<
"direct inserting " << ifile <<
"\n";
76 Exitcode result=Exitcode::SUCCESS;
78 if (
filename.ends_with(
".schema.xml")) {
80 for (
auto [name, oks_class] : kernel.
classes()) {
82 if (file->get_full_file_name() != oks_class->get_file()->get_full_file_name()) {
87 auto cfile = oks_class->get_file()->get_short_file_name();
88 if (cfile != file->get_short_file_name() && !includes.contains(cfile)) {
89 TLOG() <<
"Error " <<
filename <<
" misses include of " << cfile <<
" required by " << name;
90 if (result==Exitcode::SUCCESS) {
91 result = Exitcode::MISSING_INCLUDE;
94 auto relationships = oks_class->direct_relationships();
95 if (relationships !=
nullptr) {
96 for (
auto rel: *relationships) {
97 auto rel_class = rel->get_class_type();
98 if (rel_class ==
nullptr) {
99 TLOG() <<
"Error class '" << name
100 <<
"' has relationship '" << rel->get_name()
101 <<
"' to a class '" << rel->get_type()
102 <<
"' that is not loaded\n";
103 if (result==Exitcode::SUCCESS) {
104 result = Exitcode::BADRELATIONSHIP;
113 }
else if (
filename.ends_with(
".data.xml")) {
115 auto check_relationship = [&](
OksData* data) {
116 auto relobj = data->data.OBJECT;
117 if (relobj ==
nullptr) {
120 auto ofile_name = relobj->get_file()->get_short_file_name();
121 if (file->get_short_file_name() != ofile_name && !includes.contains(ofile_name)) {
122 TLOG() <<
"Error " <<
filename <<
" misses include of " << ofile_name
123 <<
" required by " << relobj->GetId();
124 if (result==Exitcode::SUCCESS) {
125 result = Exitcode::MISSING_INCLUDE;
131 for (
auto obj : *data_objs) {
134 auto oks_class =
obj->GetClass();
135 auto cfile = oks_class->get_file()->get_short_file_name();
136 if (!includes.contains(cfile)) {
137 TLOG() <<
"Error " <<
filename <<
" misses include of " << cfile
138 <<
" required by " <<
obj->GetId()
139 <<
" of class " << oks_class->get_name();
140 if (result==Exitcode::SUCCESS) {
141 result = Exitcode::MISSING_INCLUDE;
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) {
155 for(OksData::List::iterator iter = relval->data.LIST->begin();
156 iter != relval->data.LIST->end(); ++iter) {
157 check_relationship(*iter);
160 check_relationship(relval);
169 if (!status.empty()) {
170 if (result==Exitcode::SUCCESS) {
171 result = Exitcode::UNRESOLVED;