]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Template plugin for performance test implementation.
authorsbh <sergey.belash@opencascade.com>
Mon, 22 Dec 2014 06:53:08 +0000 (09:53 +0300)
committersbh <sergey.belash@opencascade.com>
Mon, 22 Dec 2014 06:53:08 +0000 (09:53 +0300)
15 files changed:
CMakeLists.txt
src/Config/plugins.xml
src/Config/plugins.xml.template [new file with mode: 0644]
src/ModuleBase/ModuleBase_IModule.cpp
src/TemplatePlugin/CMakeLists.txt [new file with mode: 0644]
src/TemplatePlugin/TemplatePlugin.h [new file with mode: 0644]
src/TemplatePlugin/TemplatePlugin_Plugin.cpp [new file with mode: 0644]
src/TemplatePlugin/TemplatePlugin_Plugin.h [new file with mode: 0644]
src/TemplatePlugin/TemplatePlugin_TemplateFeature.cpp [new file with mode: 0644]
src/TemplatePlugin/TemplatePlugin_TemplateFeature.h [new file with mode: 0644]
src/TemplatePlugin/Test/TestPluginLoading.py [new file with mode: 0644]
src/TemplatePlugin/features.xml.template [new file with mode: 0644]
src/TemplatePlugin/plugin-Template_1.xml [new file with mode: 0644]
src/TemplatePlugin/template_widget.xml [new file with mode: 0644]
src/TemplatePlugin/xmlGenerator.py [new file with mode: 0644]

index 1d1120f84a40d7c0abae8c6ef2db6be0075ab990..a1b6e4d634a9bb7811200f26d4400700e18f15be 100644 (file)
@@ -60,6 +60,7 @@ ADD_SUBDIRECTORY (src/XGUI)
 ADD_SUBDIRECTORY (src/GeomApp)
 ADD_SUBDIRECTORY (src/ExchangePlugin)
 ADD_SUBDIRECTORY (src/GeomValidators)
+ADD_SUBDIRECTORY (src/TemplatePlugin)
 
 IF(${HAVE_SALOME})
        ADD_SUBDIRECTORY (src/NewGeom)
index ede1536faa9eec813a6ea9f488021cf691e33760..9dbb286b243e6d523136e93fc26141838cc8c0d0 100644 (file)
@@ -6,7 +6,8 @@
   <plugin library="ConstructionPlugin" configuration="plugin-Construction.xml"/>
   <plugin library="FeaturesPlugin" configuration="plugin-Features.xml"/>
   <plugin library="ExchangePlugin" configuration="plugin-Exchange.xml"/>
+  <plugin library="TemplatePlugin_1" configuration="plugin-Template_1.xml"/>
   <plugin library="SketchSolver"/>
   <plugin library="GeomValidators"/>
   <plugin library="DFBrowser"/>
-</plugins>
+</plugins>
\ No newline at end of file
diff --git a/src/Config/plugins.xml.template b/src/Config/plugins.xml.template
new file mode 100644 (file)
index 0000000..2070f3b
--- /dev/null
@@ -0,0 +1,15 @@
+<!-- Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+<plugins module="PartSet">
+  <plugin library="PartSetPlugin" configuration="plugin-PartSet.xml"/>
+  <plugin library="SketchPlugin" configuration="plugin-Sketch.xml"/>
+  <plugin library="ConstructionPlugin" configuration="plugin-Construction.xml"/>
+  <plugin library="FeaturesPlugin" configuration="plugin-Features.xml"/>
+  <plugin library="ExchangePlugin" configuration="plugin-Exchange.xml"/>
+  <template>
+  <plugin library="TemplatePlugin_{nplugin}" configuration="plugin-Template_{nplugin}.xml"/>
+  </template>
+  <plugin library="SketchSolver"/>
+  <plugin library="GeomValidators"/>
+  <plugin library="DFBrowser"/>
+</plugins>
\ No newline at end of file
index 0e2ce8d7f6bc7545a1c204fd6d6f2e670bdd8bcb..ea4cfc640c5a79662b036f35c7e46936c5a702af 100644 (file)
 
 #include <QAction>
 
+//#ifdef _DEBUG
+#include <ctime>
+//#endif
+
 ModuleBase_IModule::ModuleBase_IModule(ModuleBase_IWorkshop* theParent)
   : QObject(theParent), myWorkshop(theParent) 
 {
@@ -97,7 +101,17 @@ void ModuleBase_IModule::createFeatures()
   registerFilters();
 
   Config_ModuleReader aXMLReader = Config_ModuleReader();
+//  #ifdef _DEBUG
+  std::cout << "ModuleBase_IModule::createFeatures: start loading libraries" << std::endl;
+  clock_t spent_time;
+  spent_time = clock();
+//  #endif
   aXMLReader.readAll();
+//  #ifdef _DEBUG
+  spent_time = clock() - spent_time;
+  std::cout << "ModuleBase_IModule::createFeatures: loading finished, took: "
+            << ((float) spent_time) / CLOCKS_PER_SEC << "s" << std::endl;
+//  #endif
   myFeaturesInFiles = aXMLReader.featuresInFiles();
 }
 
@@ -127,4 +141,4 @@ void ModuleBase_IModule::editFeature(FeaturePtr theFeature)
   ModuleBase_Operation* anOperation = createOperation(aFeatureId);
   anOperation->setFeature(theFeature);
   sendOperation(anOperation);
-}
\ No newline at end of file
+}
diff --git a/src/TemplatePlugin/CMakeLists.txt b/src/TemplatePlugin/CMakeLists.txt
new file mode 100644 (file)
index 0000000..288a0bb
--- /dev/null
@@ -0,0 +1,55 @@
+## Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+INCLUDE(Common)
+
+SET(PROJECT_HEADERS
+    TemplatePlugin.h
+    TemplatePlugin_Plugin.h
+    TemplatePlugin_TemplateFeature.h
+)
+
+SET(PROJECT_SOURCES
+    TemplatePlugin_Plugin.cpp
+    TemplatePlugin_TemplateFeature.cpp
+)
+
+SET(XML_RESOURCES
+    template_widget.xml)
+    
+# Create a list of all generated files
+FILE(GLOB GENERATED_XML_RESOURCES "plugin-Template*.xml")
+
+INCLUDE_DIRECTORIES(
+  ../ModelAPI
+  ../GeomAPI
+  ../GeomAlgoAPI
+  ../Events
+)
+
+SET(PROJECT_LIBRARIES
+    Events
+    ModelAPI 
+    GeomAPI 
+    GeomAlgoAPI
+)
+
+ADD_DEFINITIONS(-DTEMPLATEPLUGIN_EXPORTS)
+
+SET(PLUGINS_COUNT 1)
+
+ADD_CUSTOM_COMMAND(TARGET "${PROJECT_NAME}_Template"
+    PRE_BUILD
+    COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/xmlGenerator.py --plugins=${PLUGINS_COUNT}
+)
+
+WHILE(${PLUGINS_COUNT} GREATER 0)
+  ADD_LIBRARY(TemplatePlugin_${PLUGINS_COUNT} MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${XML_RESOURCES})
+  TARGET_LINK_LIBRARIES(TemplatePlugin_${PLUGINS_COUNT} ${PROJECT_LIBRARIES})
+  INSTALL(TARGETS TemplatePlugin_${PLUGINS_COUNT} DESTINATION plugins)
+  
+  MATH(EXPR PLUGINS_COUNT "${PLUGINS_COUNT} - 1")
+ENDWHILE(${PLUGINS_COUNT} GREATER 0)
+
+INSTALL(FILES ${XML_RESOURCES} DESTINATION plugins)
+INSTALL(FILES ${GENERATED_XML_RESOURCES} DESTINATION plugins)
+#INSTALL(DIRECTORY src/ DESTINATION plugins FILES_MATCHING PATTERN "*Template_*.xml")
diff --git a/src/TemplatePlugin/TemplatePlugin.h b/src/TemplatePlugin/TemplatePlugin.h
new file mode 100644 (file)
index 0000000..e7a2a62
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+#ifndef TEMPLATEPLUGIN_H
+#define TEMPLATEPLUGIN_H
+
+#if defined TEMPLATEPLUGIN_EXPORTS
+#if defined WIN32
+#define TEMPLATEPLUGIN_EXPORT              __declspec( dllexport )
+#else
+#define TEMPLATEPLUGIN_EXPORT
+#endif
+#else
+#if defined WIN32
+#define TEMPLATEPLUGIN_EXPORT              __declspec( dllimport )
+#else
+#define TEMPLATEPLUGIN_EXPORT
+#endif
+#endif
+
+#endif
diff --git a/src/TemplatePlugin/TemplatePlugin_Plugin.cpp b/src/TemplatePlugin/TemplatePlugin_Plugin.cpp
new file mode 100644 (file)
index 0000000..e56f762
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+#include <TemplatePlugin_Plugin.h>
+#include <TemplatePlugin_TemplateFeature.h>
+#include <ModelAPI_Session.h>
+
+#include <string>
+#include <memory>
+
+// the only created instance of this plugin
+static TemplatePlugin_Plugin* MY_FEATURES_INSTANCE = new TemplatePlugin_Plugin();
+
+TemplatePlugin_Plugin::TemplatePlugin_Plugin()
+{
+  // register this plugin
+  ModelAPI_Session::get()->registerPlugin(this);
+}
+
+FeaturePtr TemplatePlugin_Plugin::createFeature(std::string theFeatureID)
+{
+  return FeaturePtr(new TemplatePlugin_TemplateFeature(theFeatureID));
+}
diff --git a/src/TemplatePlugin/TemplatePlugin_Plugin.h b/src/TemplatePlugin/TemplatePlugin_Plugin.h
new file mode 100644 (file)
index 0000000..3dc7d04
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File:        TemplatePlugin_Plugin.hxx
+// Created:     07 July 2014
+// Author:      Vitaly SMETANNIKOV
+
+#ifndef TemplatePlugin_Plugin_H_
+#define TemplatePlugin_Plugin_H_
+
+#include "TemplatePlugin.h"
+#include <ModelAPI_Plugin.h>
+#include <ModelAPI_Feature.h>
+
+class TEMPLATEPLUGIN_EXPORT TemplatePlugin_Plugin : public ModelAPI_Plugin
+{
+ public:
+  /// Creates the feature object of this plugin by the feature string ID
+  virtual FeaturePtr createFeature(std::string theFeatureID);
+
+ public:
+  /// Is needed for python wrapping by swig
+  TemplatePlugin_Plugin();
+};
+
+#endif
diff --git a/src/TemplatePlugin/TemplatePlugin_TemplateFeature.cpp b/src/TemplatePlugin/TemplatePlugin_TemplateFeature.cpp
new file mode 100644 (file)
index 0000000..72e9292
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File:        TemplatePlugin_TemplateFeature.cpp
+// Created:     30 May 2014
+// Author:      Vitaly SMETANNIKOV
+
+#include "TemplatePlugin_TemplateFeature.h"
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeSelection.h>
+#include <ModelAPI_AttributeBoolean.h>
+#include <GeomAlgoAPI_Extrusion.h>
+
+using namespace std;
+#define _LATERAL_TAG 1
+#define _FIRST_TAG 2
+#define _LAST_TAG 3
+#define EDGE 6
+
+TemplatePlugin_TemplateFeature::TemplatePlugin_TemplateFeature(const std::string& theId)
+{
+  myId = theId;
+}
+
+void TemplatePlugin_TemplateFeature::initAttributes()
+{
+  data()->addAttribute(TemplatePlugin_TemplateFeature::FACE_ID(), ModelAPI_AttributeSelection::type());
+  data()->addAttribute(TemplatePlugin_TemplateFeature::SIZE_ID(), ModelAPI_AttributeDouble::type());
+  data()->addAttribute(TemplatePlugin_TemplateFeature::REVERSE_ID(), ModelAPI_AttributeBoolean::type());
+}
+
+void TemplatePlugin_TemplateFeature::execute()
+{
+
+}
+
+//============================================================================
+void TemplatePlugin_TemplateFeature::LoadNamingDS(GeomAlgoAPI_Extrusion& theFeature,
+  std::shared_ptr<ModelAPI_ResultBody> theResultBody, 
+  std::shared_ptr<GeomAPI_Shape> theBasis,
+  std::shared_ptr<GeomAPI_Shape> theContext)
+{  
+
+
+  //load result
+  if(theBasis->isEqual(theContext))
+    theResultBody->store(theFeature.shape());
+  else
+    theResultBody->storeGenerated(theContext, theFeature.shape()); 
+
+  GeomAPI_DataMapOfShapeShape* aSubShapes = new GeomAPI_DataMapOfShapeShape();
+  theFeature.mapOfShapes(*aSubShapes);
+
+    //Insert lateral face : Face from Edge
+  theResultBody->loadAndOrientGeneratedShapes(theFeature.makeShape(), theBasis, EDGE,_LATERAL_TAG, *aSubShapes);
+
+  //Insert bottom face
+  std::shared_ptr<GeomAPI_Shape> aBottomFace = theFeature.firstShape();  
+  if (!aBottomFace->isNull()) {
+       if (aSubShapes->isBound(aBottomFace)) {  
+               aBottomFace = aSubShapes->find(aBottomFace);            
+    }    
+    theResultBody->generated(aBottomFace, _FIRST_TAG);
+  }
+
+
+
+  //Insert top face
+  std::shared_ptr<GeomAPI_Shape> aTopFace = theFeature.lastShape();
+  if (!aTopFace->isNull()) {
+    if (aSubShapes->isBound(aTopFace)) {        
+      aTopFace = aSubShapes->find(aTopFace);   
+    }
+    theResultBody->generated(aTopFace, _LAST_TAG);
+  }
+
+  
+}
diff --git a/src/TemplatePlugin/TemplatePlugin_TemplateFeature.h b/src/TemplatePlugin/TemplatePlugin_TemplateFeature.h
new file mode 100644 (file)
index 0000000..0a8fb7b
--- /dev/null
@@ -0,0 +1,68 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File:        TemplatePlugin_TemplateFeature.h
+// Created:     30 May 2014
+// Author:      Vitaly SMETANNIKOV
+
+#ifndef TemplatePlugin_TemplateFeature_H_
+#define TemplatePlugin_TemplateFeature_H_
+
+#include "TemplatePlugin.h"
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_ResultBody.h>
+#include <GeomAlgoAPI_Extrusion.h>
+#include <GeomAPI_Shape.h>
+
+
+class TemplatePlugin_TemplateFeature : public ModelAPI_Feature
+{
+ public:
+  /// Extrusion kind
+  inline static const std::string& ID()
+  {
+    static const std::string MY_ID("TemplateFeature");
+    return MY_ID;
+  }
+  /// attribute name of referenced face
+  inline static const std::string& FACE_ID()
+  {
+    static const std::string MY_FACE_ID("extrusion_face");
+    return MY_FACE_ID;
+  }
+  /// attribute name of extrusion size
+  inline static const std::string& SIZE_ID()
+  {
+    static const std::string MY_SIZE_ID("extrusion_size");
+    return MY_SIZE_ID;
+  }
+  /// attribute name of reverse direction
+  inline static const std::string& REVERSE_ID()
+  {
+    static const std::string MY_REVERSE_ID("extrusion_reverse");
+    return MY_REVERSE_ID;
+  }
+
+  /// Returns the kind of a feature
+  TEMPLATEPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    return myId;
+  }
+
+  /// Creates a new part document if needed
+  TEMPLATEPLUGIN_EXPORT virtual void execute();
+
+  /// Request for initialization of data model of the feature: adding all attributes
+  TEMPLATEPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Use plugin manager for features creation
+  TemplatePlugin_TemplateFeature(const std::string& theId);
+private:
+  /// Load Naming data structure of the feature to the document
+  void LoadNamingDS(GeomAlgoAPI_Extrusion& theFeature, std::shared_ptr<ModelAPI_ResultBody> theResultBody,
+                       std::shared_ptr<GeomAPI_Shape> theBasis,
+                       std::shared_ptr<GeomAPI_Shape> theContext);
+
+  std::string myId;
+};
+
+#endif
diff --git a/src/TemplatePlugin/Test/TestPluginLoading.py b/src/TemplatePlugin/Test/TestPluginLoading.py
new file mode 100644 (file)
index 0000000..82d22a9
--- /dev/null
@@ -0,0 +1,47 @@
+#=========================================================================
+# Initialization of the test
+#=========================================================================
+import os
+import re
+import time
+
+from ModelAPI import *
+__updated__ = "2014-12-19"
+
+#=========================================================================
+# execfile("D:\NewGEOM\sources\src\TemplatePlugin\Test\TestPluginLoading.py")
+# Before test: trying to figure out how much plugins are generated
+# and how much features they contain
+#=========================================================================
+# self_dir = os.path.dirname(os.path.realpath(__file__))
+# all_plugin_files = os.listdir(os.path.join(self_dir, ".."))
+self_dir = os.path.abspath("D:\\NewGEOM\\sources\\src\\TemplatePlugin")
+all_plugin_files = os.listdir(self_dir)
+reg_exp = re.compile(r"plugin-Template_\d+\.xml")
+all_plugin_files = [x for x in all_plugin_files if reg_exp.match(x)]
+plugins_count = len(all_plugin_files)
+assert (plugins_count > 0)
+features_count = 0
+with open(os.path.join(self_dir, "plugin-Template_1.xml")) as a_plugin_file:
+    reg_exp = re.compile(r"id=\"TemplateFeature_\d+_P_\d+\"")
+    features_count = len(reg_exp.findall(a_plugin_file.read()))
+assert (features_count > 0)
+#=========================================================================
+# Creation all features to load the plugin
+#=========================================================================
+aSession = ModelAPI_Session.get()
+aDocument = aSession.moduleDocument()
+aSession.startOperation()
+print "Starting features creation..."
+t1 = time.time()
+for nplugin in xrange(1, plugins_count + 1):
+    aFeatureId = "TemplateFeature_1_P_{N}".format(N=nplugin)
+    aSketchCommonFeature = aDocument.addFeature(aFeatureId)
+
+t2 = time.time()
+print "Creation fnished, took: ", float(t2 - t1), "s"
+pass
+aSession.finishOperation()
+#=========================================================================
+# End of test
+#=========================================================================
diff --git a/src/TemplatePlugin/features.xml.template b/src/TemplatePlugin/features.xml.template
new file mode 100644 (file)
index 0000000..7eff094
--- /dev/null
@@ -0,0 +1,16 @@
+<!-- Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+<plugin>
+  <workbench id="TemplateWorkbench">
+    <group id="TemplateGroup">
+    <template>
+      <feature
+        id="TemplateFeature_{nfeature}_P_{nplugin}"
+        title="Template_{nfeature} P_{nplugin}"
+        tooltip="Generated feature for performance test"
+        icon=":pictures/wnd_undock.png">
+        <source path="template_widget.xml" />
+      </feature>
+      </template>
+    </group>
+  </workbench>
+</plugin>
\ No newline at end of file
diff --git a/src/TemplatePlugin/plugin-Template_1.xml b/src/TemplatePlugin/plugin-Template_1.xml
new file mode 100644 (file)
index 0000000..825cc8d
--- /dev/null
@@ -0,0 +1,42 @@
+<!-- Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+<plugin>
+  <workbench id="TemplateWorkbench">
+    <group id="TemplateGroup">
+      <feature
+        id="TemplateFeature_1_P_1"
+        title="Template_1 P_1"
+        tooltip="Generated feature for performance test"
+        icon=":pictures/wnd_undock.png">
+        <source path="template_widget.xml" />
+      </feature>
+      <feature
+        id="TemplateFeature_2_P_1"
+        title="Template_2 P_1"
+        tooltip="Generated feature for performance test"
+        icon=":pictures/wnd_undock.png">
+        <source path="template_widget.xml" />
+      </feature>
+      <feature
+        id="TemplateFeature_3_P_1"
+        title="Template_3 P_1"
+        tooltip="Generated feature for performance test"
+        icon=":pictures/wnd_undock.png">
+        <source path="template_widget.xml" />
+      </feature>
+      <feature
+        id="TemplateFeature_4_P_1"
+        title="Template_4 P_1"
+        tooltip="Generated feature for performance test"
+        icon=":pictures/wnd_undock.png">
+        <source path="template_widget.xml" />
+      </feature>
+      <feature
+        id="TemplateFeature_5_P_1"
+        title="Template_5 P_1"
+        tooltip="Generated feature for performance test"
+        icon=":pictures/wnd_undock.png">
+        <source path="template_widget.xml" />
+      </feature>
+    </group>
+  </workbench>
+</plugin>
\ No newline at end of file
diff --git a/src/TemplatePlugin/template_widget.xml b/src/TemplatePlugin/template_widget.xml
new file mode 100644 (file)
index 0000000..84c1fc5
--- /dev/null
@@ -0,0 +1,29 @@
+<!-- Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+<source>
+  <shape_selector
+    id="extrusion_face"
+    label="Select a face"
+    icon=":icons/sketch.png"
+    tooltip="Select a face for extrusion"
+    activate="true"
+    shape_types="face"
+    object_types="construction"
+    use_subshapes="true">
+  </shape_selector>
+  <doublevalue
+    id="extrusion_size"
+    label="Size"
+    min="0"
+    step="1.0"
+    default="1"
+    icon=":icons/dimension_v.png"
+    tooltip="Set size of extrusion">
+    <validator id="GeomValidators_Positive" />
+  </doublevalue>
+  <boolvalue
+    id="extrusion_reverse"
+    label="Reverse"
+    default="false"
+    tooltip="Reverse default direction">
+  </boolvalue>
+</source>
\ No newline at end of file
diff --git a/src/TemplatePlugin/xmlGenerator.py b/src/TemplatePlugin/xmlGenerator.py
new file mode 100644 (file)
index 0000000..bd77bcf
--- /dev/null
@@ -0,0 +1,85 @@
+'''
+Created on Dec 18, 2014
+
+@author: sbh
+'''
+
+import argparse
+import os
+import re
+
+self_dir = os.path.dirname(os.path.realpath(__file__))
+paths = {
+    "FeaturesTemplate": os.path.abspath(os.path.join(self_dir, "features.xml.template")),
+    "PluginsTemplate": os.path.abspath(os.path.join(self_dir, "../Config/", "plugins.xml.template")),
+    "Features": os.path.abspath(os.path.join(self_dir, "plugin-Template_{0}.xml")),
+    "Plugins": os.path.abspath(os.path.join(self_dir, "../Config/", "plugins.xml"))
+}
+
+
+def template(template_file_name):
+    template_file = open(template_file_name)
+    result = ""
+    accumulate = False
+    for line in template_file:
+        if line.strip() == "<template>":
+            accumulate = True
+            continue
+        elif line.strip() == "</template>":
+            break
+        if accumulate:
+            result += line
+    template_file.close()
+    return result
+
+
+def removeFeatureFiles():
+    all_files = os.listdir(self_dir)
+    reg_exp = re.compile(r"plugin-Template_\d+\.xml")
+    all_files = [os.path.join(self_dir, x) for x in all_files if reg_exp.match(x)]
+    for each_file in all_files:
+        os.remove(each_file)
+
+
+def generateFeaturesXml(plugin_number, features_count=1):
+    features_template = template(paths["FeaturesTemplate"])
+    features_template_file = open(paths["FeaturesTemplate"], "r")
+    features_file_name = paths["Features"].format(plugin_number)
+    features_file = open(features_file_name, "w")
+    skip = False
+    for line in features_template_file:
+        if line.strip() == "<template>":
+            skip = True
+            for n in xrange(1, features_count + 1):
+                features_file.write(features_template.format(nplugin=plugin_number, nfeature=n))
+        elif line.strip() == "</template>":
+            skip = False
+            continue
+        elif not skip:
+            features_file.write(line)
+
+
+def generatePluginsXml(plugins_count=1, features_count=1):
+    plugins_template = template(paths["PluginsTemplate"])
+    plugins_template_file = open(paths["PluginsTemplate"], "r")
+    plugins_file = open(paths["Plugins"], "w")
+    skip = False
+    for line in plugins_template_file:
+        if line.strip() == "<template>":
+            skip = True
+            for n in xrange(1, plugins_count + 1):
+                plugins_file.write(plugins_template.format(nplugin=n))
+                generateFeaturesXml(n, 5)
+        elif line.strip() == "</template>":
+            skip = False
+            continue
+        elif not skip:
+            plugins_file.write(line)
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser(description='Process some integers.')
+    parser.add_argument('--plugins', metavar='N', type=int, default=1)
+    args = parser.parse_args()
+    print "Number of plugins: ", args.plugins
+    removeFeatureFiles()
+    generatePluginsXml(args.plugins)