26 {
27 enum Exitcode : int {SUCCESS, BADCMD, NOFILE, LOADFAIL,
28 BADRELATIONSHIP, UNRESOLVED,
29 MISSING_INCLUDE};
30
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)
39 };
40
42 app.add_option(
"-f,--file",
filename,
"Schema file")
43 ->required();
44
45 CLI11_PARSE(app, argc, argv);
46
49 try {
51 }
54 return Exitcode::LOADFAIL;
55 }
58 return Exitcode::NOFILE;
59 }
60 catch (std::exception& exc) {
61 TLOG() << exc.what() <<
"\n";
62 return Exitcode::LOADFAIL;
63 }
64
65 if (file == nullptr) {
67 return Exitcode::LOADFAIL;
68 }
69
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";
74 }
75
76 Exitcode result=Exitcode::SUCCESS;
77
78 if (
filename.ends_with(
".schema.xml")) {
79
80 for (
auto [name, oks_class] : kernel.
classes()) {
81
82 if (
file->get_full_file_name() != oks_class->get_file()->get_full_file_name()) {
83
84 continue;
85 }
86
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;
92 }
93 }
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;
105 }
106 }
107
108 }
109 }
110
111
112 }
113 }
else if (
filename.ends_with(
".data.xml")) {
114
116 auto relobj =
data->data.OBJECT;
117 if (relobj == nullptr) {
118 return;
119 }
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;
126 }
127 }
128 };
129
131 for (auto obj : *data_objs) {
132
133
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;
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();
156 iter != relval->data.LIST->end(); ++iter) {
157 check_relationship(*iter);
158 }
159 } else {
160 check_relationship(relval);
161 }
162 }
163 }
164 }
165 delete data_objs;
166 }
167
170 if (result==Exitcode::SUCCESS) {
171 result = Exitcode::UNRESOLVED;
172 }
173 }
174
175 return result;
176}
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,...)
the structure to pass common parameters to various read() methods of OksData and OksObject class