diff --git a/.github/workflows/CMake.yml b/.github/workflows/CMake.yml index d566fac..dd84586 100644 --- a/.github/workflows/CMake.yml +++ b/.github/workflows/CMake.yml @@ -13,6 +13,9 @@ jobs: with: submodules: recursive + - name: Update + run: sudo apt-get update + - name: Install Requried Libs for FERS run: sudo apt-get install libboost-all-dev libfftw3-dev libhdf5-dev libhdf5-serial-dev build-essential cmake cmake-qt-gui python-all-dev libtinyxml-dev diff --git a/config_validators/validator.cpp b/config_validators/validator.cpp index d046d12..0cd46ca 100644 --- a/config_validators/validator.cpp +++ b/config_validators/validator.cpp @@ -1,6 +1,6 @@ // FERS input Validator Function // Makes calls to xml_validator.cpp and kml_visualiser.cpp -// Script written by Michael Altshuler +// Script written by Michael Altshuler // University of Cape Town: ALTMIC003 // The following implementation makes use of the Document Object Model (DOM) and a custom XSD Schema. @@ -9,6 +9,7 @@ #include #include #include +#include // Including necessary Xerces-C++ header files: #include @@ -24,18 +25,32 @@ using namespace xercesc; using namespace std; +void printUsage(const std::string &programName) +{ + std::cout << "Usage: " << programName << " [options] ...\n" + << "Options:\n" + << " -h, --help Show this help message\n" + << " -p, --path fersxml file path (required)\n" + << " -s, --schema fersxml.xsd schema location (requried)" + << " -v, --verbose run with verbose outputs (optional)\n"; +} + // Error handler that catches validation errors and further provides information about the errors. -class MyErrorHandler : public ErrorHandler { +class MyErrorHandler : public ErrorHandler +{ public: - void warning(const SAXParseException& e) { + void warning(const SAXParseException &e) + { cerr << "Warning: " << XMLString::transcode(e.getMessage()) << " at line " << e.getLineNumber() << ", column " << e.getColumnNumber() << endl; } - void error(const SAXParseException& e) { + void error(const SAXParseException &e) + { cerr << "Error: " << XMLString::transcode(e.getMessage()) << " at line " << e.getLineNumber() << ", column " << e.getColumnNumber() << endl; } - void fatalError(const SAXParseException& e) { + void fatalError(const SAXParseException &e) + { cerr << "Fatal Error: " << XMLString::transcode(e.getMessage()) << " at line " << e.getLineNumber() << ", column " << e.getColumnNumber() << endl; } @@ -43,45 +58,66 @@ class MyErrorHandler : public ErrorHandler { }; // Function to extract the file name from a given path -std::string getFileNameFromPath(const std::string &filePath) { +std::string getFileNameFromPath(const std::string &filePath) +{ size_t lastSlash = filePath.find_last_of("/\\"); size_t lastDot = filePath.find_last_of("."); - if (lastSlash == std::string::npos) { + if (lastSlash == std::string::npos) + { lastSlash = 0; - } else { + } + else + { lastSlash++; } return filePath.substr(lastSlash, lastDot - lastSlash); } - -int main(int argc, char* argv[]) { - - try { - - // Check if the user provided the mode argument - std::string mode = "non-verbose"; // Default mode - std::string file_path; - - if (argc == 2) { - file_path = argv[1]; - } else if (argc == 3) { - std::string mode_arg = argv[1]; - if (mode_arg == "-v" || mode_arg == "--verbose") { - mode = "verbose"; - } else if (mode_arg == "-q" || mode_arg == "--quiet" || mode_arg == "--non-verbose") { - mode = "non-verbose"; - } else { - std::cerr << "Invalid mode argument. Please provide '-v' or '--verbose' for verbose mode, or '-q', '--quiet', or '--non-verbose' for non-verbose mode." << std::endl; - return 1; +int main(int argc, char *argv[]) +{ + + try + { + std::string strFilePath = ""; + std::string strFerXMLSchemaPath = ""; + bool bRunAsVerbose = false; + + // Parse command-line arguments + for (int i = 1; i < argc; ++i) + { + std::string arg(argv[i]); + if (arg == "-h" || arg == "--help") + { + printUsage(argv[0]); + return 0; + } + else if (arg == "-c" || arg == "--config") + { + strFilePath = argv[++i]; + std::cout << "ferxml path set to: " << strFilePath << std::endl; + } + else if (arg == "-s" || arg == "--schema") + { + strFerXMLSchemaPath = argv[++i]; + std::cout << "ferxml xsd path set to: " << strFerXMLSchemaPath << std::endl; + } + else if (arg == "-v" || arg == "--verbose") + { + std::cerr << "Running in verbose configuration\n"; + bRunAsVerbose = true; } - file_path = argv[2]; - } else { - std::cerr << "Invalid number of arguments. Please provide a file path and an optional mode (-v for verbose)." << std::endl; - return 1; } - + if (strFilePath.empty()) + { + std::cerr << "Error: no fersxml file given, run with -h\n"; + return 1; + } + if (strFerXMLSchemaPath.empty()) + { + std::cerr << "Error: no fersxml.xsd schema file given, run with -h\n"; + return 1; + } // Initializing Xerces-C++ library: xercesc::XMLPlatformUtils::Initialize(); @@ -96,146 +132,163 @@ int main(int argc, char* argv[]) { parser.setDoSchema(true); // Set the custom XSD file for the parser by specifying the XSD file path and XSD file name - parser.setExternalNoNamespaceSchemaLocation("/Users/michaelaltshuler/Documents/5th Year/EEE4022F:Thesis/FERS Features/FERS Validator/FERS-schema/fers-xml.xsd"); + std::cout << "Attempting to set xsd namespace: " + strFerXMLSchemaPath << std::endl; + parser.setExternalNoNamespaceSchemaLocation(strFerXMLSchemaPath.c_str()); + std::cout << "Wohoo! Success!" << std::endl; // error handler instance created and set on the parser. MyErrorHandler errorHandler; parser.setErrorHandler(&errorHandler); // Establish a DOMDocument object and parse the input FERSXML file: - parser.parse(file_path.c_str()); + std::cout << "Attempting to parse" + strFilePath << std::endl; + parser.parse(strFilePath.c_str()); + if (parser.getErrorCount() == 0) + std::cout << "Wohoo! Success!" + strFilePath << std::endl; + else + { + // error should have been printed by parser + std::cout << "XML parsing encountered errors - see above" << std::endl; + return 1; + } - cout<< endl; + std::cout << "XML document is valid" << std::endl; - if(parser.getErrorCount() == 0) { - std::cout << "User is in " << mode << " mode." << std::endl; - cout << endl; + // Command to run xml_validator_output with mode and strFilePath as argument + std::string command = "./xml_validator_output " + strFilePath; + // Run the command using system() function + int result = std::system(command.c_str()); - std::cout << "XML document is valid" << std::endl; + if (result == -1) + { + std::cerr << "Failed to run xml_validator_output." << std::endl; + return 1; + } - // Command to run xml_validator_output with mode and file_path as argument - std::string command = "./xml_validator_output " + file_path + " " + mode; - // Run the command using system() function - int result = std::system(command.c_str()); + std::cout << endl; - if (result == -1) { - std::cerr << "Failed to run xml_validator_output." << std::endl; - return 1; - } + // Prompting user whether they want to run the kml_visualiser + char run_kml_visualiser = 'n'; + char custom_coordinates; + double referenceLatitude = -33.9545; + double referenceLongitude = 18.4563; + double referenceAltitude = 0; + std::string outputName; + std::string input; + + std::cout << "Do you want to run the kml_visualiser program? (y/N): "; + std::getline(std::cin, input); + + if (!input.empty()) + { + run_kml_visualiser = input[0]; + } + + if (run_kml_visualiser == 'y' || run_kml_visualiser == 'Y') + { + std::cout << "Name a KML output file (defualt file name = file name of fersxml): "; + std::getline(std::cin, outputName); - std::cout << endl; + if (outputName.empty()) + { + outputName = getFileNameFromPath(strFilePath); + } + + std::cout << "Do you want to enter custom referenceLatitude, referenceLongitude, and referenceAltitude? (y/N): "; + input.clear(); + std::getline(std::cin, input); + custom_coordinates = input.empty() ? 'n' : input[0]; + std::cout << "Default coordinates set to University of Cape Town: <133.9577° S, 18.4612° E, 0>" << std::endl; - // Prompting user whether they want to run the kml_visualiser - char run_kml_visualiser = 'n'; - char custom_coordinates; - double referenceLatitude = -33.9545; - double referenceLongitude = 18.4563; - double referenceAltitude = 0; - std::string outputName; + if (custom_coordinates == 'y' || custom_coordinates == 'Y') + { std::string input; - std::cout << "Do you want to run the kml_visualiser program? (y/N): "; - std::getline(std::cin, input); + std::cout << "Enter referenceLatitude (default: -33.9545): "; + std::cin >> input; + std::istringstream iss_latitude(input); + if (!(iss_latitude >> referenceLatitude)) + { + std::cerr << "Invalid input. Please enter a valid number for referenceLatitude." << std::endl; + return 1; + } - if (!input.empty()) { - run_kml_visualiser = input[0]; + std::cout << "Enter referenceLongitude (default: 18.4563): "; + std::cin >> input; + std::istringstream iss_longitude(input); + if (!(iss_longitude >> referenceLongitude)) + { + std::cerr << "Invalid input. Please enter a valid number for referenceLongitude." << std::endl; + return 1; } - if (run_kml_visualiser == 'y' || run_kml_visualiser == 'Y') { - std::cout << "Name a KML output file (defualt file name = file name of fersxml): "; - std::getline(std::cin, outputName); - - if (outputName.empty()) { - outputName = getFileNameFromPath(file_path); - } - - std::cout << "Do you want to enter custom referenceLatitude, referenceLongitude, and referenceAltitude? (y/N): "; - input.clear(); - std::getline(std::cin, input); - custom_coordinates = input.empty() ? 'n' : input[0]; - std::cout << "Default coordinates set to University of Cape Town: <133.9577° S, 18.4612° E, 0>" << std::endl; - - if (custom_coordinates == 'y' || custom_coordinates == 'Y') { - std::string input; - - std::cout << "Enter referenceLatitude (default: -33.9545): "; - std::cin >> input; - std::istringstream iss_latitude(input); - if (!(iss_latitude >> referenceLatitude)) { - std::cerr << "Invalid input. Please enter a valid number for referenceLatitude." << std::endl; - return 1; - } - - std::cout << "Enter referenceLongitude (default: 18.4563): "; - std::cin >> input; - std::istringstream iss_longitude(input); - if (!(iss_longitude >> referenceLongitude)) { - std::cerr << "Invalid input. Please enter a valid number for referenceLongitude." << std::endl; - return 1; - } - - std::cout << "Enter referenceAltitude (default: 0): "; - std::cin >> input; - std::istringstream iss_altitude(input); - if (!(iss_altitude >> referenceAltitude)) { - std::cerr << "Invalid input. Please enter a valid number for referenceAltitude." << std::endl; - return 1; - } - } - - std::string kml_visualiser_command = "./kml_visualiser"; - - if (custom_coordinates == 'y' || custom_coordinates == 'Y') { - kml_visualiser_command += " " + file_path + " " + outputName + ".kml" + " " + std::to_string(referenceLatitude) + " " + std::to_string(referenceLongitude) + " " + std::to_string(referenceAltitude); - - int kml_visualiser_result = std::system(kml_visualiser_command.c_str()); - - if (kml_visualiser_result == -1) { - std::cerr << "Failed to run kml_visualiser." << std::endl; - return 1; - } - } else { - kml_visualiser_command += " " + file_path + " " + outputName + ".kml"; - int kml_visualiser_result = std::system(kml_visualiser_command.c_str()); - - if (kml_visualiser_result == -1) { - std::cerr << "Failed to run kml_visualiser." << std::endl; - return 1; - } - } - - std::cout << outputName + ".kml" + " outputted to current working directory." << std::endl; - - } else if (run_kml_visualiser != 'n' && run_kml_visualiser != 'N') { - std::cerr << "Invalid input. Please enter 'y' for yes or 'n' for no." << std::endl; + std::cout << "Enter referenceAltitude (default: 0): "; + std::cin >> input; + std::istringstream iss_altitude(input); + if (!(iss_altitude >> referenceAltitude)) + { + std::cerr << "Invalid input. Please enter a valid number for referenceAltitude." << std::endl; return 1; } + } - } + std::string kml_visualiser_command = "./kml_visualiser"; - else { - std::cout << "FERSXML invalid: Take note of given errors and warnings above." << std::endl; - } + if (custom_coordinates == 'y' || custom_coordinates == 'Y') + { + kml_visualiser_command += " " + strFilePath + " " + outputName + ".kml" + " " + std::to_string(referenceLatitude) + " " + std::to_string(referenceLongitude) + " " + std::to_string(referenceAltitude); + + int kml_visualiser_result = std::system(kml_visualiser_command.c_str()); + + if (kml_visualiser_result == -1) + { + std::cerr << "Failed to run kml_visualiser." << std::endl; + return 1; + } + } + else + { + kml_visualiser_command += " " + strFilePath + " " + outputName + ".kml"; + int kml_visualiser_result = std::system(kml_visualiser_command.c_str()); + + if (kml_visualiser_result == -1) + { + std::cerr << "Failed to run kml_visualiser." << std::endl; + return 1; + } + } - // Function call deallocates memory associated with he parsed FERSXML document. - //parser.resetDocumentPool(); - // Shuts down and deallocates any memory associated with the Xerces-C++ library. - //xercesc::XMLPlatformUtils::Terminate(); - return 0; + std::cout << outputName + ".kml" + " outputted to current working directory." << std::endl; + } + else if (run_kml_visualiser != 'n' && run_kml_visualiser != 'N') + { + std::cerr << "Invalid input. Please enter 'y' for yes or 'n' for no." << std::endl; + return 1; + } - } catch (const xercesc::XMLException& e) { + // Function call deallocates memory associated with he parsed FERSXML document. + // parser.resetDocumentPool(); + // Shuts down and deallocates any memory associated with the Xerces-C++ library. + // xercesc::XMLPlatformUtils::Terminate(); + return 0; + } + catch (const xercesc::XMLException &e) + { std::cerr << "Error parsing XML document: " << e.getMessage() << std::endl; return 1; - - } catch (const xercesc::DOMException& e) { + } + catch (const xercesc::DOMException &e) + { std::cerr << "Error parsing XML document: " << e.getMessage() << std::endl; return 1; - - } catch (const xercesc::SAXParseException& e) { + } + catch (const xercesc::SAXParseException &e) + { std::cerr << "Error parsing XML document: " << e.getMessage() << " at line " << e.getLineNumber() << std::endl; return 1; - - } catch (...) { + } + catch (...) + { std::cerr << "Error parsing XML document: unknown exception" << std::endl; return 1; } diff --git a/test/regressionsuite/test1.fersxml b/test/regressionsuite/test1.fersxml index cbbf556..0e671f5 100644 --- a/test/regressionsuite/test1.fersxml +++ b/test/regressionsuite/test1.fersxml @@ -1,6 +1,6 @@ - + 0 diff --git a/test/regressionsuite/test2.fersxml b/test/regressionsuite/test2.fersxml index 9545d61..dbda54c 100644 --- a/test/regressionsuite/test2.fersxml +++ b/test/regressionsuite/test2.fersxml @@ -1,6 +1,6 @@ - + 0 diff --git a/test/regressionsuite/test3.fersxml b/test/regressionsuite/test3.fersxml index 2c609de..76c85c5 100644 --- a/test/regressionsuite/test3.fersxml +++ b/test/regressionsuite/test3.fersxml @@ -1,6 +1,6 @@ - + 0 diff --git a/test/regressionsuite/test4.fersxml b/test/regressionsuite/test4.fersxml index 7effa43..0824d24 100644 --- a/test/regressionsuite/test4.fersxml +++ b/test/regressionsuite/test4.fersxml @@ -1,6 +1,6 @@ - + 0 diff --git a/test/regressionsuite/test5.fersxml b/test/regressionsuite/test5.fersxml index 386daf5..2175128 100644 --- a/test/regressionsuite/test5.fersxml +++ b/test/regressionsuite/test5.fersxml @@ -2,7 +2,7 @@ - + 0 diff --git a/test/regressionsuite/test6.fersxml b/test/regressionsuite/test6.fersxml index 61b6479..ad8a4ad 100644 --- a/test/regressionsuite/test6.fersxml +++ b/test/regressionsuite/test6.fersxml @@ -2,7 +2,7 @@ - + 0 diff --git a/test/test_cases/test1.fersxml b/test/test_cases/test1.fersxml index 626ca51..cb6e289 100644 --- a/test/test_cases/test1.fersxml +++ b/test/test_cases/test1.fersxml @@ -1,6 +1,6 @@ - + 0 diff --git a/test/test_cases/test2.fersxml b/test/test_cases/test2.fersxml index c64bfb2..7fb87cb 100644 --- a/test/test_cases/test2.fersxml +++ b/test/test_cases/test2.fersxml @@ -1,6 +1,6 @@ - + 0 diff --git a/test/test_cases/test3.fersxml b/test/test_cases/test3.fersxml index 2c609de..76c85c5 100644 --- a/test/test_cases/test3.fersxml +++ b/test/test_cases/test3.fersxml @@ -1,6 +1,6 @@ - + 0 diff --git a/test/test_cases/test4.fersxml b/test/test_cases/test4.fersxml index 7effa43..0824d24 100644 --- a/test/test_cases/test4.fersxml +++ b/test/test_cases/test4.fersxml @@ -1,6 +1,6 @@ - + 0 diff --git a/test/test_cases/test5.fersxml b/test/test_cases/test5.fersxml index 386daf5..2175128 100644 --- a/test/test_cases/test5.fersxml +++ b/test/test_cases/test5.fersxml @@ -2,7 +2,7 @@ - + 0 diff --git a/test/test_cases/test6.fersxml b/test/test_cases/test6.fersxml index 61b6479..ad8a4ad 100644 --- a/test/test_cases/test6.fersxml +++ b/test/test_cases/test6.fersxml @@ -2,7 +2,7 @@ - + 0 diff --git a/test/test_cases/test7.fersxml b/test/test_cases/test7.fersxml index f24d11d..bf6bbb9 100644 --- a/test/test_cases/test7.fersxml +++ b/test/test_cases/test7.fersxml @@ -1,6 +1,6 @@ - + 0 diff --git a/test/test_cases/test8.fersxml b/test/test_cases/test8.fersxml index 61f1936..6cf6830 100644 --- a/test/test_cases/test8.fersxml +++ b/test/test_cases/test8.fersxml @@ -1,6 +1,6 @@ - + 0 diff --git a/xml_schema/README.md b/xml_schema/README.md new file mode 100644 index 0000000..45c2d62 --- /dev/null +++ b/xml_schema/README.md @@ -0,0 +1,6 @@ +# Schema + +- dtd is an older xml descriptor used in the original implementation of unit testing +- xsd is used for xml validation + +note: when chagning xml defenitions - both files should be changed and relevant changes propogated throughout the codebase \ No newline at end of file diff --git a/fers-xml.dtd b/xml_schema/fers-xml.dtd similarity index 100% rename from fers-xml.dtd rename to xml_schema/fers-xml.dtd diff --git a/xml_schema/fers-xml.xsd b/xml_schema/fers-xml.xsd new file mode 100644 index 0000000..b8dc520 --- /dev/null +++ b/xml_schema/fers-xml.xsd @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +