Main method to generate (source code) files from templates.

        See documentation about the directory and file patterns and their possible combinations.

        Args:
            dir_pattern: ``glob`` pattern taken from the root directory. **Only** used for directories.
            file_pattern: ``fnmatch`` pattern taken from all matching directories. **Only** used for files.
            action (char): Denote action to be taken. Can be:
                - g: Generate all files that match both directory and file patterns. This is the default behavior.
                - d: Same as `g` but with doing anything, i.e. dry run.
                - c: Same as `g` but erasing the generated files instead, i.e. clean.
            recursively: Do we do the actions in the sub-directories? Note that in this case **only** the file pattern applies as **all**
                the subdirectories are visited.
            force (boolean): Do we force the generation or not?

def generate(self, dir_pattern, file_pattern, action_ch='g', recursively=False, force=False):
        """
        Main method to generate (source code) files from templates.

        See documentation about the directory and file patterns and their possible combinations.

        Args:
            dir_pattern: ``glob`` pattern taken from the root directory. **Only** used for directories.
            file_pattern: ``fnmatch`` pattern taken from all matching directories. **Only** used for files.
            action (char): Denote action to be taken. Can be:
                - g: Generate all files that match both directory and file patterns. This is the default behavior.
                - d: Same as `g` but with doing anything, i.e. dry run.
                - c: Same as `g` but erasing the generated files instead, i.e. clean.
            recursively: Do we do the actions in the sub-directories? Note that in this case **only** the file pattern applies as **all**
                the subdirectories are visited.
            force (boolean): Do we force the generation or not?

        """
        # directories to visit
        # using heavy machinery to extract absolute cleaned paths... to avoid any problem...
        directories = [os.path.abspath(directory) for directory in glob.glob(os.path.join(self.__root_directory, dir_pattern)) if os.path.isdir(directory)]

        # list of extensions
        extensions = self.__extensions.keys()

        for directory in directories:
            for b, f in find_files(directory, file_pattern, recursively=recursively):
                # test if some template files can be processed
                file_basename, file_ext = os.path.splitext(f)

                if file_ext in extensions:
                    # try to find corresponding action
                    rel_path = os.path.relpath(os.path.join(b,f), self.__root_directory)
                    rel_basename, rel_filename = os.path.split(rel_path)
                    rel_filename_without_ext, rel_ext = os.path.splitext(rel_filename)

                    # template absolute filename
                    in_file_name = os.path.join(b, f)

                    generator_action_container = self.__actions.retrieve_element_or_default(rel_basename, None)
                    action = None

                    if generator_action_container is not None:
                        action = generator_action_container.get_compatible_generator_action(f)

                    # is there a default action if needed?
                    if action is None:
                        action = self.__default_action

                    if action:

                        if action_ch == 'd':
                            print("Process file '%s' with function '%s':" % (rel_path, action.action_function_name()))
                        for filename_end, context in action.run():
                            # generated absolute file name
                            out_file_name = os.path.join(b, rel_filename_without_ext + filename_end + self.__extensions[file_ext])
                            if action_ch == 'g':
                                self.__generate_file(template_filename=in_file_name, context=context, generated_filename=out_file_name, force=force)
                            elif action_ch == 'c':
                                try:
                                    os.remove(out_file_name)
                                    self.log_info("Removed file '%s'" % out_file_name)
                                except OSError:
                                    pass
                            elif action_ch == 'd':
                                # we only print relative path
                                print("   -> %s" % os.path.join(rel_basename, rel_filename_without_ext + filename_end + self.__extensions[file_ext]))