From 733ef3a952e2cd2d5df92667569eb9096200da27 Mon Sep 17 00:00:00 2001 From: Sergey Belash Date: Fri, 21 Mar 2014 14:38:24 +0400 Subject: [PATCH] To customize processing of various XML files: * Config_XMLReader became abstract, two inhereted "readers" added * "Module" reader for plugins.xml files. * "Features" reader for plugin-*.xml files. --- src/Config/CMakeLists.txt | 13 ++- src/Config/Config_FeatureReader.cpp | 78 ++++++++++++++ src/Config/Config_FeatureReader.h | 27 +++++ src/Config/Config_ModuleReader.cpp | 70 ++++++++++++ src/Config/Config_ModuleReader.h | 39 +++++++ src/Config/Config_XMLReader.cpp | 161 +++++++++++++--------------- src/Config/Config_XMLReader.h | 26 ++--- src/Config/plugins.xml | 4 +- src/PartSet/PartSet_Module.cpp | 11 +- src/PartSet/PartSet_Module.h | 2 +- 10 files changed, 321 insertions(+), 110 deletions(-) create mode 100644 src/Config/Config_FeatureReader.cpp create mode 100644 src/Config/Config_FeatureReader.h create mode 100644 src/Config/Config_ModuleReader.cpp create mode 100644 src/Config/Config_ModuleReader.h diff --git a/src/Config/CMakeLists.txt b/src/Config/CMakeLists.txt index 95bcd8f53..63f5a9631 100644 --- a/src/Config/CMakeLists.txt +++ b/src/Config/CMakeLists.txt @@ -7,13 +7,17 @@ INCLUDE_DIRECTORIES (${PROJECT_SOURCE_DIR}/src/Event) SET(PROJECT_HEADERS Config.h - Config_XMLReader.h Config_Message.h + Config_XMLReader.h + Config_ModuleReader.h + Config_FeatureReader.h ) SET(PROJECT_SOURCES - Config_XMLReader.cpp Config_Message.cpp + Config_XMLReader.cpp + Config_ModuleReader.cpp + Config_FeatureReader.cpp ) SET(XML_RESOURCES @@ -26,9 +30,12 @@ SET(PROJECT_LIBRARIES ${LIBXML2_LIBRARIES} ) +SOURCE_GROUP ("Resource Files" FILES ${XML_RESOURCES}) + ADD_DEFINITIONS(-DCONFIG_EXPORTS) -ADD_LIBRARY(Config SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS}) +ADD_LIBRARY(Config SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${XML_RESOURCES}) TARGET_LINK_LIBRARIES(Config ${PROJECT_LIBRARIES}) +INSTALL(TARGETS Config DESTINATION bin) INSTALL(FILES ${XML_RESOURCES} DESTINATION plugins) diff --git a/src/Config/Config_FeatureReader.cpp b/src/Config/Config_FeatureReader.cpp new file mode 100644 index 000000000..0eb2bfdaa --- /dev/null +++ b/src/Config/Config_FeatureReader.cpp @@ -0,0 +1,78 @@ +/* + * Config_FeatureReader.cpp + * + * Created on: Mar 20, 2014 + * Author: sbh + */ + +#include + +#include + +#include +#include + +#ifdef _DEBUG +#include +#endif + +//Hardcoded xml entities +// * Nodes + +// * Properties +const static char* FEATURE_ID = "id"; +const static char* FEATURE_TEXT = "text"; +const static char* FEATURE_TOOLTIP = "tooltip"; +const static char* FEATURE_ICON = "icon"; +const static char* FEATURE_KEYSEQUENCE = "keysequence"; +const static char* FEATURE_GROUP_NAME = "name"; + + + + +Config_FeatureReader::Config_FeatureReader(const std::string& theXmlFile) + : Config_XMLReader(theXmlFile) +{ + #ifdef _DEBUG + if(!Event_Loop::Loop()) { + std::cout << "Config_FeatureReader::importWorkbench: " + << "No event loop registered" << std::endl; + } + #endif +} + +Config_FeatureReader::~Config_FeatureReader() +{ +} + +void Config_FeatureReader::processNode(xmlNodePtr theNode) +{ + if(isNode(theNode,"feature")) { + Event_Loop* aEvLoop = Event_Loop::Loop(); + Config_FeatureMessage aMessage(aEvLoop->EventByName("Feature"), this); + fillFeature(theNode, aMessage); + xmlNodePtr aGroupNode = theNode->parent; + if(aGroupNode) { + std::string aGroupName = getProperty(aGroupNode, FEATURE_GROUP_NAME); + aMessage.m_group = aGroupName; + } + aEvLoop->Send(aMessage); + } +} + +bool Config_FeatureReader::processChildren(xmlNodePtr theNode) +{ + return isNode(theNode, "workbench") + || isNode(theNode, "group"); +// || isNode(theNode, "feature"); +} + +void Config_FeatureReader::fillFeature(xmlNodePtr theRoot, + Config_FeatureMessage& outFtMessage) +{ + outFtMessage.m_id = getProperty(theRoot, FEATURE_ID); + outFtMessage.m_text = getProperty(theRoot, FEATURE_TEXT); + outFtMessage.m_tooltip = getProperty(theRoot, FEATURE_TOOLTIP); + outFtMessage.m_icon = getProperty(theRoot, FEATURE_ICON); + outFtMessage.m_keysequence = getProperty(theRoot, FEATURE_KEYSEQUENCE); +} diff --git a/src/Config/Config_FeatureReader.h b/src/Config/Config_FeatureReader.h new file mode 100644 index 000000000..76d7635c0 --- /dev/null +++ b/src/Config/Config_FeatureReader.h @@ -0,0 +1,27 @@ +/* + * Config_FeatureReader.h + * + * Created on: Mar 20, 2014 + * Author: sbh + */ + +#ifndef CONFIG_FEATUREREADER_H_ +#define CONFIG_FEATUREREADER_H_ + +#include + +class CONFIG_EXPORT Config_FeatureReader: public Config_XMLReader +{ +public: + Config_FeatureReader(const std::string& theXmlFile); + virtual ~Config_FeatureReader(); + +protected: + void processNode(xmlNodePtr aNode); + bool processChildren(xmlNodePtr aNode); + + void fillFeature(xmlNodePtr theRoot, Config_FeatureMessage& outFeatureMessage); + +}; + +#endif /* CONFIG_FEATUREREADER_H_ */ diff --git a/src/Config/Config_ModuleReader.cpp b/src/Config/Config_ModuleReader.cpp new file mode 100644 index 000000000..e09904422 --- /dev/null +++ b/src/Config/Config_ModuleReader.cpp @@ -0,0 +1,70 @@ +/* + * Config_ModuleReader.cpp + * + * Created on: Mar 20, 2014 + * Author: sbh + */ + +#include +#include + +#include +#include + +#ifdef _DEBUG +#include +#endif + +Config_ModuleReader::Config_ModuleReader() + : Config_XMLReader("plugins.xml"), + m_isAutoImport(false) +{ +} + +Config_ModuleReader::~Config_ModuleReader() +{ +} + +/* + * Get module name from plugins.xml + * (property "module") + */ +std::string Config_ModuleReader::getModuleName() +{ + xmlNodePtr aRoot = findRoot(); + return getProperty(aRoot, "module"); +} + +/* + * + */ +void Config_ModuleReader::processNode(xmlNodePtr theNode) +{ + if(isNode(theNode, "plugin")) { + std::string aPluginName = getProperty(theNode, "configuration"); + if(m_isAutoImport) + importPlugin(aPluginName); + m_pluginsList.push_back(aPluginName); + } +} + +bool Config_ModuleReader::processChildren(xmlNodePtr theNode) +{ + return isNode(theNode, "plugins"); +} + +void Config_ModuleReader::importPlugin(const std::string& thePluginName) +{ + Config_FeatureReader aReader(thePluginName); + aReader.readAll(); +} + +void Config_ModuleReader::setAutoImport(bool enabled) +{ + m_isAutoImport = enabled; +} + +const std::list& Config_ModuleReader::pluginsList() const +{ + return m_pluginsList; +} diff --git a/src/Config/Config_ModuleReader.h b/src/Config/Config_ModuleReader.h new file mode 100644 index 000000000..4bd958f51 --- /dev/null +++ b/src/Config/Config_ModuleReader.h @@ -0,0 +1,39 @@ +/* + * Config_XMLModuleReader.h + * + * Created on: Mar 20, 2014 + * Author: sbh + */ + +#ifndef CONFIG_MODULEREADER_H_ +#define CONFIG_MODULEREADER_H_ + +#include + +#include + +class CONFIG_EXPORT Config_ModuleReader: public Config_XMLReader +{ + +public: + Config_ModuleReader(); + virtual ~Config_ModuleReader(); + + void setAutoImport(bool enabled); + const std::list& pluginsList() const; + + std::string getModuleName(); + +protected: + void processNode(xmlNodePtr aNode); + bool processChildren(xmlNodePtr aNode); + + void importPlugin(const std::string& thePluginName); + +private: + bool m_isAutoImport; + std::list m_pluginsList; + +}; + +#endif /* CONFIG_XMLMODULEREADER_H_ */ diff --git a/src/Config/Config_XMLReader.cpp b/src/Config/Config_XMLReader.cpp index 658d62478..adce851dc 100644 --- a/src/Config/Config_XMLReader.cpp +++ b/src/Config/Config_XMLReader.cpp @@ -8,9 +8,9 @@ #include #include - #include #include + #ifdef WIN32 //For GetModuleFileNameW #include @@ -20,36 +20,11 @@ #include #endif -static bool IsNode(xmlNodePtr theNode, const char* theNodeName) -{ - return theNode->type == XML_ELEMENT_NODE - && !xmlStrcmp(theNode->name, (const xmlChar *) theNodeName); -} - -const static char* FEATURE_ID = "id"; -const static char* FEATURE_TEXT = "text"; -const static char* FEATURE_TOOLTIP = "tooltip"; -const static char* FEATURE_ICON = "icon"; -const static char* FEATURE_KEYSEQUENCE = "keysequence"; -const static char* FEATURE_GROUP_NAME = "name"; - -Config_XMLReader::Config_XMLReader(const std::string& theXmlFile) -{ - setDocumentPath(theXmlFile); -} - -Config_XMLReader::~Config_XMLReader() -{ -} - -std::string Config_XMLReader::documentPath() const -{ - return m_DocumentPath; -} -void Config_XMLReader::setDocumentPath(std::string documentPath) +Config_XMLReader::Config_XMLReader(const std::string& theXmlFileName) { std::string prefix; + //Get path to *.xml files (typically ./bin/../plugins/) #ifdef WIN32 HMODULE hModule = GetModuleHandleW(NULL); WCHAR wchar_path[MAX_PATH]; @@ -66,20 +41,51 @@ void Config_XMLReader::setDocumentPath(std::string documentPath) //TODO(sbh): Find full path to binary on linux prefix = "../plugins/"; #endif - m_DocumentPath = prefix + documentPath; + + m_DocumentPath = prefix + theXmlFileName; +} + + +Config_XMLReader::~Config_XMLReader() +{ } +/* + * Read all nodes (recursively if processChildren() is true + * for a node). For each read node the processNode will be + * called. + */ void Config_XMLReader::readAll() { - import(); + xmlNodePtr aRoot = findRoot(); + readRecursively(aRoot); +} + +/* + * Allows to customize reader's behavior for a node. Virtual. + * The default implementation does nothing. (In debug mode prints + * some info) + */ +void Config_XMLReader::processNode(xmlNodePtr aNode) +{ + #ifdef _DEBUG + std::cout << "Config_XMLReader::processNode: " + << aNode->name << " content: " + << aNode->content << std::endl; + #endif } /* - * TODO: make virtual as beforeImport + * Defines which nodes should be processed recursively. Virtual. + * The default implementation to read all nodes. */ -bool Config_XMLReader::import() +bool Config_XMLReader::processChildren(xmlNodePtr aNode) +{ + return true; +} + +xmlNodePtr Config_XMLReader::findRoot() { - bool result = false; xmlDocPtr aDoc; aDoc = xmlParseFile(m_DocumentPath.c_str()); if(aDoc == NULL) { @@ -87,81 +93,62 @@ bool Config_XMLReader::import() std::cout << "Config_XMLReader::import: " << "Document " << m_DocumentPath << " is not parsed successfully." << std::endl; #endif - return result; + return NULL; } xmlNodePtr aRoot = xmlDocGetRootElement(aDoc); + #ifdef _DEBUG if(aRoot == NULL) { - #ifdef _DEBUG std::cout << "Config_XMLReader::import: " << "Error: empty document"; - #endif - return result; } - xmlNodePtr aWbSec; - for(aWbSec = aRoot->xmlChildrenNode; aWbSec; aWbSec = aWbSec->next) { // searching for higher level element "workbench" - if(IsNode(aWbSec, "workbench")) { - result = importWorkbench(aWbSec); - } else { - #ifdef _DEBUG - std::cout << "Config_XMLReader::import: " - << "Found strange section, should be workbench" << std::endl; - #endif - continue; - } - } - return result; + #endif + return aRoot; } /* - * TODO(sbh): make virtual as doImport + * Calls processNode() for each child (for some - recursively) + * of the given node. + * \sa ReadAll() */ -bool Config_XMLReader::importWorkbench(void* theRoot) +void Config_XMLReader::readRecursively(xmlNodePtr theParent) { - xmlNodePtr aGroupNode = (static_cast(theRoot))->xmlChildrenNode; - Event_Loop* aEvLoop = Event_Loop::Loop(); - if(!aEvLoop) { - #ifdef _DEBUG - std::cout << "Config_XMLReader::importWorkbench: " - << "No event loop registered" << std::endl; - #endif - return false; - } - for(; aGroupNode; aGroupNode = aGroupNode->next) { // searching for record - if(!IsNode(aGroupNode, "group")) - continue; - std::string aGroupName = getProperty(aGroupNode, FEATURE_GROUP_NAME); - if(aGroupName.empty()) - continue; - xmlNodePtr aFtNode = aGroupNode->xmlChildrenNode; - for(; aFtNode; aFtNode = aFtNode->next) { - if(!IsNode(aFtNode, "feature")) - continue; - //Create feature... - Config_FeatureMessage aMessage(aEvLoop->EventByName("Feature"), this); - fillFeature(aFtNode, aMessage); - aMessage.m_group = aGroupName; - aEvLoop->Send(aMessage); + if(!theParent) + return; + xmlNodePtr aNode = theParent->xmlChildrenNode; + for(; aNode; aNode = aNode->next) { + processNode(aNode); + if(processChildren(aNode)) { + readRecursively(aNode); } } - return true; } -void Config_XMLReader::fillFeature(void *theRoot, - Config_FeatureMessage& outFeatureMessage) +/* + * void* -> xmlNodePtr + */ +xmlNodePtr Config_XMLReader::node(void* theNode) { - outFeatureMessage.m_id = getProperty(theRoot, FEATURE_ID); - outFeatureMessage.m_text = getProperty(theRoot, FEATURE_TEXT); - outFeatureMessage.m_tooltip = getProperty(theRoot, FEATURE_TOOLTIP); - outFeatureMessage.m_icon = getProperty(theRoot, FEATURE_ICON); - outFeatureMessage.m_keysequence = getProperty(theRoot, FEATURE_KEYSEQUENCE); + return static_cast(theNode); } -std::string Config_XMLReader::getProperty(void *theRoot, const char* name) +/* + * Returns named property for a given node as std::string. + */ +std::string Config_XMLReader::getProperty(xmlNodePtr theNode, const char* name) { std::string result = ""; - xmlNodePtr aNode = (static_cast(theRoot)); - char* aPropChars = (char*) xmlGetProp(aNode, BAD_CAST name); + char* aPropChars = (char*) xmlGetProp(theNode, BAD_CAST name); if(!aPropChars || aPropChars[0] == 0) return result; result = std::string(aPropChars); return result; } + +/* + * Returns true if theNode is XML node with a given name. + */ +bool Config_XMLReader::isNode(xmlNodePtr theNode, const char* theNodeName) +{ + const char* emptyLine = ""; + return theNode->type == XML_ELEMENT_NODE + && !xmlStrcmp(theNode->name, (const xmlChar *) theNodeName); +} diff --git a/src/Config/Config_XMLReader.h b/src/Config/Config_XMLReader.h index 25637fd49..9761ada43 100644 --- a/src/Config/Config_XMLReader.h +++ b/src/Config/Config_XMLReader.h @@ -12,27 +12,29 @@ #include "Config_Message.h" #include -#include + +//Forward declaration for xmlNodePtr. +typedef struct _xmlNode xmlNode; +typedef xmlNode *xmlNodePtr; +struct _xmlNode; class CONFIG_EXPORT Config_XMLReader { public: Config_XMLReader(const std::string& theXmlFile); virtual ~Config_XMLReader(); - std::string documentPath() const; - void setDocumentPath(std::string documentName); - void readAll(); protected: - //! Performs the real import of the given xml file, return false if file is not found - //! or generates an algo error if file content is bad - //! \param theFile name of the imported XML file - //! \returns true if file exists and not corrupted - bool import(); - bool importWorkbench(void*); - void fillFeature(void *theRoot, Config_FeatureMessage& outFeatureMessage); - std::string getProperty(void *theRoot, const char* name); + virtual void processNode(xmlNodePtr aNode); + virtual bool processChildren(xmlNodePtr aNode); + + xmlNodePtr findRoot(); + void readRecursively(xmlNodePtr theParent); + + xmlNodePtr node(void* theNode); + std::string getProperty(xmlNodePtr theNode, const char* property); + bool isNode(xmlNodePtr theNode, const char* name); private: std::string m_DocumentPath; diff --git a/src/Config/plugins.xml b/src/Config/plugins.xml index 2931524ea..4af6b07db 100644 --- a/src/Config/plugins.xml +++ b/src/Config/plugins.xml @@ -1,3 +1,3 @@ - + - \ No newline at end of file + diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index 2121a26a6..26d8b7243 100644 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -1,6 +1,6 @@ #include "PartSet_Module.h" -#include +#include #include #include @@ -24,10 +24,11 @@ PartSet_Module::~PartSet_Module() { } - void PartSet_Module::createFeatures() { - Config_XMLReader* aReader = - new Config_XMLReader("plugin-PartSet.xml"); - aReader->readAll(); + Config_ModuleReader* aXMLReader = new Config_ModuleReader(); + aXMLReader->getModuleName(); + aXMLReader->setAutoImport(true); + aXMLReader->readAll(); + delete aXMLReader; } diff --git a/src/PartSet/PartSet_Module.h b/src/PartSet/PartSet_Module.h index b9f6ee913..3f792d21f 100644 --- a/src/PartSet/PartSet_Module.h +++ b/src/PartSet/PartSet_Module.h @@ -6,7 +6,7 @@ #include -class Config_XMLReader; +class Config_FeatureReader; class PARTSET_EXPORT PartSet_Module : public XGUI_Module { -- 2.39.2