Add ModeXMLGenerator class
authorJinWang An <jinwang.an@samsung.com>
Fri, 21 Jun 2019 04:11:23 +0000 (13:11 +0900)
committerYoungjae Shin <yj99.shin@samsung.com>
Wed, 18 Mar 2020 08:53:50 +0000 (17:53 +0900)
13 files changed:
supervisor/Mode.cpp
supervisor/Mode.h
supervisor/ModeTag.cpp [new file with mode: 0644]
supervisor/ModeTag.h [new file with mode: 0644]
supervisor/ModeXMLParser.cpp
supervisor/ModeXMLParser.h
supervisor/Req.h
supervisor/TReq.h
supervisor/XMLGenerator.cpp [new file with mode: 0644]
supervisor/XMLGenerator.h [new file with mode: 0644]
unittest/CMakeLists.txt
unittest/modes-gtest-run.sh
unittest/modes_test_generator.cpp [new file with mode: 0644]

index b20b4cd..eb23373 100644 (file)
@@ -55,3 +55,7 @@ void Mode::apply()
        for (it = reqList.begin(); it != reqList.end(); it++)
                (*it)->apply();
 }
+
+std::list<Req*> Mode::getReqList(){
+       return reqList;
+}
index 3fe4b93..7c73a06 100644 (file)
@@ -32,7 +32,10 @@ public:
        std::string getModeType();
 
        void addRequirement(Req *req);
+       std::list<Req*> getReqList();
+
        void apply();
+
 private:
        std::string name;
        std::string type;
diff --git a/supervisor/ModeTag.cpp b/supervisor/ModeTag.cpp
new file mode 100644 (file)
index 0000000..55c3b7b
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ModeTag.h"
+
+MODES_NAMESPACE_USE;
+
+const xmlChar* const ModeTag::XML_VERSION = (xmlChar*)"1.0";
+const xmlChar* const ModeTag::XML_ENCODING = (xmlChar*)"utf-8";
+const xmlChar* const ModeTag::TIZENMODES = (xmlChar*)"tizenModes";
+const xmlChar* const ModeTag::XMLNS = (xmlChar*)"xmlns";
+const xmlChar* const ModeTag::XMLNS_STR = (xmlChar*)"http://www.tizen.org";
+const xmlChar* const ModeTag::VERSION = (xmlChar*)"version";
+const xmlChar* const ModeTag::VERSION_STR = (xmlChar*)"5.5";
+const xmlChar* const ModeTag::MODE = (xmlChar*)"mode";
+const xmlChar* const ModeTag::NAME = (xmlChar*)"name";
+const xmlChar* const ModeTag::TYPE = (xmlChar*)"type";
+const xmlChar* const ModeTag::REQ = (xmlChar*)"req";
+const xmlChar* const ModeTag::ACTION = (xmlChar*)"action";
+const xmlChar* const ModeTag::RESTICT = (xmlChar*)"restrict";
+const xmlChar* const ModeTag::ID = (xmlChar*)"ID";
+const xmlChar* const ModeTag::PRIORITY = (xmlChar*)"priority";
+const xmlChar* const ModeTag::BEFORE = (xmlChar*)"before";
+const xmlChar* const ModeTag::AFTER = (xmlChar*)"after";
+const char* const ModeTag::RESTICT_LOCK = "lock";
diff --git a/supervisor/ModeTag.h b/supervisor/ModeTag.h
new file mode 100644 (file)
index 0000000..c651432
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <libxml/tree.h>
+#include "mdss.h"
+
+MODES_NAMESPACE_BEGIN
+
+struct ModeTag {
+       static const xmlChar* const XML_VERSION;
+       static const xmlChar* const XML_ENCODING;
+       static const xmlChar* const TIZENMODES;
+       static const xmlChar* const XMLNS;
+       static const xmlChar* const XMLNS_STR;
+       static const xmlChar* const VERSION;
+       static const xmlChar* const VERSION_STR;
+       static const xmlChar* const MODE;
+       static const xmlChar* const NAME;
+       static const xmlChar* const TYPE;
+       static const xmlChar* const REQ;
+       static const xmlChar* const ACTION;
+       static const xmlChar* const RESTICT;
+       static const xmlChar* const ID;
+       static const xmlChar* const PRIORITY;
+       static const xmlChar* const BEFORE;
+       static const xmlChar* const AFTER;
+       static const char* const RESTICT_LOCK;
+};
+
+MODES_NAMESPACE_END
index cd6d24f..193c2b7 100644 (file)
 #include "Mode.h"
 #include "ModesEx.h"
 #include "TReq.h"
+#include "ModeTag.h"
 
 MODES_NAMESPACE_USE;
 
-const xmlChar* const ModeXMLParser::MODE_TAG_XMLNS = (xmlChar*)"xmlns";
-const xmlChar* const ModeXMLParser::MODE_TAG_VERSION = (xmlChar*)"version";
-const xmlChar* const ModeXMLParser::MODE_TAG_MODE = (xmlChar*)"mode";
-const xmlChar* const ModeXMLParser::MODE_TAG_NAME = (xmlChar*)"name";
-const xmlChar* const ModeXMLParser::MODE_TAG_TYPE = (xmlChar*)"type";
-const xmlChar* const ModeXMLParser::MODE_TAG_REQ = (xmlChar*)"req";
-const xmlChar* const ModeXMLParser::MODE_TAG_ACTION = (xmlChar*)"action";
-const xmlChar* const ModeXMLParser::MODE_TAG_RESTICT = (xmlChar*)"restrict";
-const char* const ModeXMLParser::MODE_RESTICT_LOCK = "lock";
-
 ModeXMLParser::ModeXMLParser(const std::string &modeFile, ActionSchemaManager &asMgr, PluginManager &piMgr)
        :ModeParser(asMgr), pluginManager(piMgr), parser(modeFile)
 {
@@ -45,20 +36,20 @@ void ModeXMLParser::parseMode(xmlNodePtr node, Mode &modedesc)
 {
        char *tmp;
 
-       tmp = (char*)xmlGetProp(node, MODE_TAG_NAME);
+       tmp = (char*)xmlGetProp(node, ModeTag::NAME);
        if (tmp) {
                modedesc.setName(tmp);
                xmlFree(tmp);
        } else {
-               ERR("Mode : No %s", MODE_TAG_NAME);
+               ERR("Mode : No %s", ModeTag::NAME);
        }
 
-       tmp = (char*)xmlGetProp(node, MODE_TAG_TYPE);
+       tmp = (char*)xmlGetProp(node, ModeTag::TYPE);
        if (tmp) {
                modedesc.setModeType(tmp);
                xmlFree(tmp);
        } else {
-               ERR("Mode : No %s", MODE_TAG_TYPE);
+               ERR("Mode : No %s", ModeTag::TYPE);
        }
 }
 
@@ -75,7 +66,7 @@ void ModeXMLParser::parseReq(xmlNodePtr node, Mode &modedesc)
        char *tmp;
        Req *req = NULL;
 
-       tmp = (char*)xmlGetProp(node, MODE_TAG_ACTION);
+       tmp = (char*)xmlGetProp(node, ModeTag::ACTION);
        if (tmp) {
                req = schemaMgr.createAction(tmp);
                if (nullptr == req) {
@@ -86,21 +77,27 @@ void ModeXMLParser::parseReq(xmlNodePtr node, Mode &modedesc)
 
                xmlFree(tmp);
        } else {
-               ERR("Req : No %s", MODE_TAG_ACTION);
+               ERR("Req : No %s", ModeTag::ACTION);
        }
        if (NULL == req) {
                ERR("req is NULL");
                throw ModesEx(ModesEx::PARSER_ERROR, "No req");
        }
 
-       tmp = (char*)xmlGetProp(node, MODE_TAG_RESTICT);
-       if (tmp && MDS_EQUAL == strcmp(tmp, MODE_RESTICT_LOCK)) {
+       tmp = (char*)xmlGetProp(node, ModeTag::RESTICT);
+       if (tmp && MDS_EQUAL == strcmp(tmp, ModeTag::RESTICT_LOCK)) {
                req->setRestrict(Req::REQ_LOCK);
        } else {
                req->setRestrict(Req::REQ_NONE);
        }
        xmlFree(tmp);
 
+       tmp = (char*)xmlGetProp(node, ModeTag::ID);
+       if (tmp) {
+               req->setID(tmp);
+               xmlFree(tmp);
+       }
+
        tmp = (char*)xmlNodeGetContent(node);
        if (tmp) {
                req->setValue(tmp);
@@ -116,9 +113,9 @@ void ModeXMLParser::parseReq(xmlNodePtr node, Mode &modedesc)
 
 void ModeXMLParser::getDatafromNode(xmlNodePtr node, Mode &modedesc)
 {
-       if (MDS_EQUAL == xmlStrcmp(node->name, MODE_TAG_MODE)) {
+       if (MDS_EQUAL == xmlStrcmp(node->name, ModeTag::MODE)) {
                parseMode(node, modedesc);
-       } else if (MDS_EQUAL == xmlStrcmp(node->name, MODE_TAG_REQ)) {
+       } else if (MDS_EQUAL == xmlStrcmp(node->name, ModeTag::REQ)) {
                parseReq(node, modedesc);
        } else {
                DBG("Unhandled node : %s", node->name);
@@ -158,8 +155,8 @@ std::string ModeXMLParser::getModeName()
                if (xmlIsBlankNode(cur))
                        continue;
 
-               if (MDS_EQUAL == xmlStrcmp(cur->name, MODE_TAG_MODE)) {
-                       char *name = (char*)xmlGetProp(cur, MODE_TAG_NAME);
+               if (MDS_EQUAL == xmlStrcmp(cur->name, ModeTag::MODE)) {
+                       char *name = (char*)xmlGetProp(cur, ModeTag::NAME);
                        modeName = name;
                        xmlFree(name);
                }
index dd3ac10..ce86552 100644 (file)
@@ -31,17 +31,8 @@ public:
        Mode getMode() override;
        std::string getModeName() override;
        void validateMode(const std::string &xsd) override;
-private:
-       static const xmlChar* const MODE_TAG_XMLNS;
-       static const xmlChar* const MODE_TAG_VERSION;
-       static const xmlChar* const MODE_TAG_MODE;
-       static const xmlChar* const MODE_TAG_NAME;
-       static const xmlChar* const MODE_TAG_REQ;
-       static const xmlChar* const MODE_TAG_ACTION;
-       static const xmlChar* const MODE_TAG_TYPE;
-       static const xmlChar* const MODE_TAG_RESTICT;
-       static const char* const MODE_RESTICT_LOCK;
 
+private:
        void parseMode(xmlNodePtr node, Mode &modedesc);
        void parseReq(xmlNodePtr node, Mode &modedesc);
        void getDatafromNode(xmlNodePtr node, Mode &modedesc);
index 9de2061..036d6d4 100644 (file)
@@ -41,10 +41,13 @@ public:
        ReqRestrict getRestrict();
        void setPlugin(Plugin *pi);
        virtual void setValue(const std::string &val) = 0;
+       virtual std::string getStringOfValue() = 0;
        virtual void apply() = 0;
+
 protected:
        std::string actionName;
        Plugin *plugin;
+
 private:
        std::string id;
        ReqRestrict restriction;
index 804cd13..4527e10 100644 (file)
@@ -41,6 +41,16 @@ public:
                return value;
        }
 
+       std::string getStringOfValue()
+       {
+               std::string val;
+               std::ostringstream ostr;
+
+               ostr << value;
+               val = ostr.str();
+               return val;
+       }
+
        void setValue(const std::string &val) override
        {
                auto it = valueAliases.find(val);
diff --git a/supervisor/XMLGenerator.cpp b/supervisor/XMLGenerator.cpp
new file mode 100644 (file)
index 0000000..f10c8d7
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <libxml/tree.h>
+#include <libxml/xmlschemas.h>
+#include "Req.h"
+#include "ModeTag.h"
+#include "ModesEx.h"
+#include "XMLGenerator.h"
+
+MODES_NAMESPACE_USE;
+
+XMLGenerator::XMLGenerator()
+       :doc(NULL), rootNode(NULL), modeNode(NULL)
+{
+}
+
+XMLGenerator::~XMLGenerator()
+{
+}
+
+void XMLGenerator::createRootNode()
+{
+       doc = xmlNewDoc(ModeTag::XML_VERSION);
+       doc->encoding = ModeTag::XML_ENCODING;
+       doc->charset = 1;
+
+       rootNode = xmlNewNode(NULL, ModeTag::TIZENMODES);
+       xmlSetProp(rootNode, ModeTag::XMLNS, ModeTag::XMLNS_STR);
+       xmlSetProp(rootNode, ModeTag::VERSION, ModeTag::VERSION_STR);
+       xmlDocSetRootElement(doc, rootNode);
+       return;
+}
+
+void XMLGenerator::write(const std::string &filename)
+{
+       int ret = xmlSaveFormatFile(filename.c_str(), doc, 1);
+       if (-1 == ret) {
+               ERR("xmlSaveFormatFile(%s) Fail()", filename.c_str());
+               throw ModesEx(ModesEx::INVALID_ARG);
+       }
+
+       return;
+}
+
+void XMLGenerator::makeMode(const std::string &filename, Mode &mode)
+{
+       if (filename.empty()) {
+               ERR("filename empty!!");
+               throw ModesEx(ModesEx::INVALID_ARG);
+       }
+
+       createRootNode();
+
+       std::string modeType = mode.getModeType();
+       std::string modeName = mode.getName();
+
+       modeNode = xmlNewNode(NULL, ModeTag::MODE);
+
+       xmlSetProp(modeNode, ModeTag::NAME, (xmlChar*)modeName.c_str());
+       xmlSetProp(modeNode, ModeTag::TYPE, (xmlChar*)modeType.c_str());
+       xmlAddChild(rootNode, modeNode);
+
+       std::list<Req*> reqList = mode.getReqList();
+       std::list<Req*>::iterator it;
+       for (it = reqList.begin(); it != reqList.end(); it++) {
+               xmlNodePtr reqNode;
+               Req::ReqRestrict restriction = (*it)->getRestrict();
+
+               reqNode = xmlNewNode(NULL, ModeTag::REQ);
+
+               if (!(*it)->getID().empty())
+                       xmlSetProp(reqNode, ModeTag::ID, (xmlChar*)(*it)->getID().c_str());
+
+               xmlSetProp(reqNode, ModeTag::ACTION, (xmlChar*)(*it)->getName().c_str());
+
+               if (restriction == Req::ReqRestrict::REQ_LOCK)
+                       xmlSetProp(reqNode, ModeTag::RESTICT, (xmlChar*)ModeTag::RESTICT_LOCK);
+
+               xmlNodeSetContent(reqNode, (xmlChar*)(*it)->getStringOfValue().c_str());
+
+               xmlAddChild(modeNode, reqNode);
+       }
+
+       write(filename);
+
+       doc->encoding = NULL;
+       xmlFreeDoc(doc);
+       return;
+}
diff --git a/supervisor/XMLGenerator.h b/supervisor/XMLGenerator.h
new file mode 100644 (file)
index 0000000..91b5757
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <string>
+#include <libxml/tree.h>
+#include "mdss.h"
+#include "Mode.h"
+
+MODES_NAMESPACE_BEGIN
+
+class XMLGenerator {
+public:
+       XMLGenerator();
+       ~XMLGenerator();
+
+       void makeMode(const std::string &filename, Mode &mode);
+
+private:
+       void createRootNode();
+       void write(const std::string &filename);
+
+       xmlDocPtr doc;
+       xmlNodePtr rootNode;
+       xmlNodePtr modeNode;
+};
+
+MODES_NAMESPACE_END
index a2a365f..55f81d8 100644 (file)
@@ -15,6 +15,7 @@ FILE(GLOB SRC "modes_test_main.cpp")
 #=======================================================================================#
 SET(GTEST_MODEMGR "modes-gtest-modemgr")
 FILE(GLOB GTEST_MODEMGR_SRCS
+               ${SUPERVISOR_DIR}/ModeTag.cpp
                ${SUPERVISOR_DIR}/XMLParser.cpp
                ${SUPERVISOR_DIR}/ModeManager.cpp
                ${SUPERVISOR_DIR}/ModeXMLParser.cpp
@@ -53,6 +54,7 @@ FILE(GLOB GTEST_PARSER_SRCS
                ${SUPERVISOR_DIR}/ModesEx.cpp
                ${SUPERVISOR_DIR}/Action.cpp
                ${SUPERVISOR_DIR}/Mode.cpp
+               ${SUPERVISOR_DIR}/ModeTag.cpp
                "modes_test_parser.cpp"
        )
 ADD_EXECUTABLE(${GTEST_PARSER} ${SRC} ${GTEST_PARSER_SRCS})
@@ -72,3 +74,23 @@ SET(TEST_APPLY_MODE_SRC "modes_apply_mode.c")
 ADD_EXECUTABLE(${TEST_APPLY_MODE} ${TEST_APPLY_MODE_SRC})
 TARGET_LINK_LIBRARIES(${TEST_APPLY_MODE} ${CLIENT})
 INSTALL(TARGETS ${TEST_APPLY_MODE} DESTINATION ${TEST_INSTALL_DIR})
+
+#=======================================================================================#
+SET(GTEST_PARSER "modes-gtest-generator")
+FILE(GLOB GTEST_PARSER_SRCS
+               ${SUPERVISOR_DIR}/ModeTag.cpp
+               ${SUPERVISOR_DIR}/XMLParser.cpp
+               ${SUPERVISOR_DIR}/PluginManager.cpp
+               ${SUPERVISOR_DIR}/Req.cpp
+               ${SUPERVISOR_DIR}/ActionSchema.cpp
+               ${SUPERVISOR_DIR}/ActionSchemaManager.cpp
+               ${SUPERVISOR_DIR}/ModeXMLParser.cpp
+               ${SUPERVISOR_DIR}/ModesEx.cpp
+               ${SUPERVISOR_DIR}/Action.cpp
+               ${SUPERVISOR_DIR}/Mode.cpp
+               ${SUPERVISOR_DIR}/XMLGenerator.cpp
+               "modes_test_generator.cpp"
+       )
+ADD_EXECUTABLE(${GTEST_PARSER} ${SRC} ${GTEST_PARSER_SRCS})
+TARGET_LINK_LIBRARIES(${GTEST_PARSER} ${gtest_pkgs_LIBRARIES} dl)
+INSTALL(TARGETS ${GTEST_PARSER} DESTINATION ${TEST_INSTALL_DIR})
index c0dc5a4..0adcc17 100755 (executable)
@@ -21,6 +21,7 @@ then
        $WORKING_DIR/modes-gtest-modemgr
        $WORKING_DIR/modes-gtest-plugin
        $WORKING_DIR/modes-gtest-parser
+       $WORKING_DIR/modes-gtest-generator
 else
        cp $DATA_DIR/mode/*_mode.xml $WORKING_DIR
        cp $DATA_DIR/action/*_schema.xml $WORKING_DIR
@@ -32,6 +33,7 @@ else
        ./modes-gtest-client
        ./modes-gtest-modemgr
        ./modes-gtest-parser
+       ./modes-gtest-generator
        ./modes-gtest-plugin
        popd
 fi
diff --git a/unittest/modes_test_generator.cpp b/unittest/modes_test_generator.cpp
new file mode 100644 (file)
index 0000000..b2f2d63
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <memory.h>
+#include <iostream>
+#include <gtest/gtest.h>
+#include "supervisor/Mode.h"
+#include "supervisor/ModesEx.h"
+#include "supervisor/ModeXMLParser.h"
+#include "supervisor/XMLGenerator.h"
+#include "supervisor/ActionSchemaManager.h"
+
+MODES_NAMESPACE_USE;
+using namespace std;
+
+TEST(XMLGenerator, makeMode) {
+       PluginManager pluginManager;
+       ActionSchemaManager schemaMgr;
+
+       ModeXMLParser modeparser("tizen_ex1_mode.xml", schemaMgr, pluginManager);
+       Mode mode = modeparser.getMode();
+
+       try {
+               XMLGenerator xmlGenerator;
+               xmlGenerator.makeMode("tizen_gen_ex1_mode.xml", mode);
+       } catch (ModesEx &e) {
+               ERR("XMLGenerator(tizen_gen_ex1_mode.xml) Fail(%s)", e.what());
+               FAIL();
+       }
+
+       ModeXMLParser genmodeparser("tizen_gen_ex1_mode.xml", schemaMgr, pluginManager);
+       Mode genMode = genmodeparser.getMode();
+
+       EXPECT_EQ("ex1", genmodeparser.getModeName());
+       list<Req*> reqList = mode.getReqList();
+       EXPECT_FALSE(reqList.empty());
+
+       for (list<Req*>::iterator it = reqList.begin(); it != reqList.end(); ++it) {
+               cout << "* Req : " << (*it)->getName() << endl;
+               cout << "\t\t- Restrict : " << (*it)->getRestrict() << endl;
+               cout << "\t\t- Content : " << (*it)->getStringOfValue() << endl;
+       }
+}
+
+TEST(XMLGenerator, exFileName) {
+       EXPECT_THROW({
+               PluginManager pluginManager;
+               ActionSchemaManager schemaMgr;
+
+               ModeXMLParser modeparser("tizen_ex1_mode.xml", schemaMgr, pluginManager);
+               Mode mode = modeparser.getMode();
+
+               XMLGenerator xmlGenerator;
+               xmlGenerator.makeMode("", mode);
+       }, ModesEx);
+}