text: from soccminer.parse_source_files import SourceFiles
  from soccminer.java_ast_parsing import XmlParsing
  from soccminer.project_meta import JavaProjectMeta
  from soccminer.exception_monitoring import ExceptionStack
  from soccminer.performance_time import APIPerformanceTime
  from soccminer.soccminer_logger import SoCCMinerLogger
  from soccminer.environment import Platform
  from soccminer.java_project_meta_attributes import JavaMetaAttribute
  from soccminer.proj_comments_main_attr import CommentsMetaAttribute
  from soccminer.proj_comments_comprehensive_attr import ComprehensiveCommentsAttribute
  from soccminer.java_proj_miner import JavaMiner
  from soccminer.parse_source_files import validate_loc
  from soccminer.source_code_details import PackageInfo, ClassInfo, MethodInfo, InterfaceInfo, StaticBlockInfo, EnumInfo, FileInfo
  from soccminer.comments import CommentInfo
  from soccminer.json_serialization import SerializeSoCCMiner
  from soccminer.helper import RepoDownloader, TrackProgress, Utility
  import sys
  import traceback
  import os
  import logging
  import time
  import gc
  from multiprocessing import Process
  import shutil
  from datetime import datetime
  
  
  class CommentsMiner:
      mining_level = None
      log = None
      lang = None
      proj_url = None
      load_project = None
      output_path = None
      mode = None
      soccminer_cfg_file = None
  
      @staticmethod
      def save_program_parameters():
          try:
              params = [CommentsMiner.proj_url, CommentsMiner.lang, str(CommentsMiner.mining_level),
                        str(CommentsMiner.load_project), str(CommentsMiner.log)]
              with open(CommentsMiner.soccminer_cfg_file, 'w', encoding='utf-8') as fh:
                  fh.write("\n".join(params))
          except IOError as ioexception:
              if CommentsMiner.log != 0:
                  logging.error("Unable to save miner config parameters. Exiting the program.".format(ioexception.strerror))
              print("Unable to save miner config parameters. Exiting the program.".format(ioexception.strerror))
  
      @staticmethod
      def set_mining_level_inp(m_level):
          CommentsMiner.mining_level = m_level
  
      @staticmethod
      def set_log_inp(log):
          CommentsMiner.log = log
  
      @staticmethod
      def set_output_inp(output_dir):
          CommentsMiner.output_path = output_dir
  
      @staticmethod
      def set_lang_inp(lang):
          CommentsMiner.lang = lang
  
      @staticmethod
      def set_source_url(proj_url):
          CommentsMiner.proj_url = proj_url
  
      @staticmethod
      def set_load_project(load_project):
          CommentsMiner.load_project = load_project
  
      @staticmethod
      def set_mode(mode):
          CommentsMiner.mode = mode
  
      @staticmethod
      def validate_soccminer_dir_structure(proj_dir):
          soccminer_dir = [type(PackageInfo()).__name__, type(ClassInfo()).__name__, type(MethodInfo()).__name__,
                          type(InterfaceInfo()).__name__, type(StaticBlockInfo()).__name__]
          empty_folders = False
          empty_folder_count = 0
          soccminer_entity_dir_count = 0
          attr_dir = 'attributes'
          comment_dir = 'comments'
          for folder in os.listdir(proj_dir):
              if CommentsMiner.is_dir(folder):
                  if folder in soccminer_dir:
                      soccminer_entity_dir_count += 1
                      folder_content = None
                      attr_folder = None
                      comment_folder = None
                      if Platform.is_unix_platform():
                          folder_content = proj_dir + '/' + folder
                          attr_folder = folder_content + '/' + attr_dir
                          comment_folder = folder_content + '/' + comment_dir
                      elif Platform.is_windows_platform():
                          folder_content = proj_dir + '\\' + folder
                      # supposed to be 2 (attributes and comments) or either 1 of them empty or can be 0.
                      soccminer_subfolder_count = 0
                      attr_dir_file_count = None
                      comment_dir_file_count = None
                      for sub_folder in os.listdir(folder_content):
                          if sub_folder == attr_dir:
                              if CommentsMiner.is_dir(attr_folder):
                                  soccminer_subfolder_count += 1
                                  src_file_obj = SourceFiles(attr_folder)
                                  src_file_obj.fetch_source_files(attr_folder, 'json')
                                  attr_dir_file_count = len(src_file_obj.get_files())
                                  del src_file_obj
                          elif sub_folder == comment_dir:
                              if CommentsMiner.is_dir(comment_folder):
                                  soccminer_subfolder_count += 1
                                  src_file_obj = SourceFiles(attr_folder)
                                  src_file_obj.fetch_source_files(comment_folder, 'json')
                                  comment_dir_file_count = len(src_file_obj.get_files())
                                  del src_file_obj
                      if soccminer_subfolder_count == 1:
                          if attr_dir_file_count is not None and attr_dir_file_count == 0:
                              empty_folder_count += 1
                          elif comment_dir_file_count is not None and comment_dir_file_count == 0:
                              empty_folder_count += 1
                      if soccminer_subfolder_count == 2:
                          if attr_dir_file_count == 0 and comment_dir_file_count == 0:
                              empty_folder_count += 1
                      if soccminer_subfolder_count == 0:
                          empty_folder_count += 1
          if empty_folder_count == 5:
              empty_folders = True
          return empty_folders
  
      @staticmethod
      def validate_mining_input_dir(input_dir):
          #  source files are expected to be present inside project directory.
          #  input_dir contains one or more project directories and project
          #                directory contains one or more source code files.
          for item in os.listdir(input_dir):
              if item.endswith('.java'):
                  print("Input directory cannot contain file but only project folders as sub-directories in multiple mode")
                  return False
              if Platform.is_unix_platform():
                  if os.path.isfile(input_dir + '/' + item):
                      print(
                          "Input directory cannot contain file but only project folders as sub-directories in multiple mode")
                      return False
              elif Platform.is_windows_platform():
                  if os.path.isfile(input_dir + '\\' + item):
                      print(
                          "Input directory cannot contain file but only project folders as sub-directories in multiple mode")
                      return False
          return True
  
      def __init__(self, source_url, lang: str='java', m_level: str ='comment', direct_load=False, log: str = "nolog", output_dir: str =os.getcwd(), mode: str ='single'):
          self.url = source_url
          if Platform.is_unix_platform():
              CommentsMiner.soccminer_cfg_file = os.getcwd() + '/' + 'soccminer.cfg'
          elif Platform.is_windows_platform():
              CommentsMiner.soccminer_cfg_file = os.getcwd() + '\\' + 'soccminer.cfg'
          self.lang = lang
          self.mining_level = m_level
          self.load_project = direct_load
          self.log = log
          self.output_dir = output_dir
          self.mode = mode
          self.invalid_ing_arg_flag = False
          if not self.validate_args(self.url, lang, m_level, direct_load, log, output_dir, mode):
              print("Exiting due to invalid arguments.")
              logging.info("Exiting due to invalid arguments.")
              self.invalid_ing_arg_flag = True
              return
  
          if not self.load_project and not Utility.validate_srcml():
              print("Exiting due to inadequate environment. srcML is either not installed or installed incorrectly. SoCCMiner unable to utilize srcML.")
              logging.info("Exiting due to inadequate environment. srcML is either not installed or installed incorrectly. SoCCMiner unable to utilize srcML.")
              self.miner_status_flag = False
              return
  
          self.project = None
          self.project_details_mstr_dict = {}
          self.exception_obj = ExceptionStack()
          self.proj_comments_main_attr_obj_list = []  # Contains basic comment attribute objects (CommentMetaAttributes)
          self.proj_comments_all_attr_obj_list = []  # Contains all comment attributes objects (ComprehensiveCommentsAttribute)
          self.proj_meta_attr_obj_list = []  # Contains MetaAttribute objects (JavaMetaAttribute)
          self.proj_comments_and_attr_obj_list = []  # Contains MinerObjects (JavaMiner)
          self.proj_directories = []  # Contains project directories for mining project source code
          self.soccminer_proj_directories = []  # Contains soccminer tool mined project entities for later use suching loading project
          self.miner_status_flag = False
          self.load_status = False  # If Proj has been loaded from json successfully
          self.project_directory = ""
          self.empty_proj_flag = []  # Contains boolean indicating if a project is empty, i.e., no source code file
          self.soccminer_cfg_file = None
          self.log_dir = SoCCMinerLogger.log_dir
          self.mined_entity_dir = []
          self.log_file_obj = None
  
          logging.debug("Setting soccminer parameters")
          # set params
          CommentsMiner.set_source_url(self.url)
          CommentsMiner.set_mining_level_inp(self.mining_level)
          CommentsMiner.set_lang_inp(self.lang)
          CommentsMiner.set_load_project(self.load_project)
          CommentsMiner.set_log_inp(self.log)
          CommentsMiner.set_output_inp(self.output_dir)
          CommentsMiner.set_mode(self.mode)
          CommentsMiner.save_program_parameters()
          logging.debug("Config file created with program parameters")
  
          if self.log == 1 or self.log == 2:
              if SoCCMinerLogger.main_logger is None:
                  self.log_file_obj = SoCCMinerLogger(self.log, "")
  
          logging.debug("Mining_Level and Load_Project in Comments_Miner initialization: {} , {}".format(self.mining_level, self.load_project))
          if self.mining_level != 0 and not self.load_project:
              logging.debug("SoCCMiner initiated")
              print("SoCCMiner initiated")
              self.initiate_mining()
              if self.miner_status_flag:
                  if not self.invalid_ing_arg_flag:
                      logging.info("Project mining successful")
                      print("Project mining successful")
                      self.load_after_mining()
                  else:
                      print("Mining unsuccessful")
          elif self.mining_level != 0 and self.load_project:
              logging.debug("Load project from json initiated")
              print("Load project from json initiated {}".format(self.url))
              self.load_soccminer_entities()
              if self.load_status:
                  logging.info("Project load successful")
                  print("Project load successful")
              else:
                  print("Loading unsuccessful")
          if os.path.exists(CommentsMiner.soccminer_cfg_file):
              os.remove(CommentsMiner.soccminer_cfg_file)
          Utility.clear_temp_folders()
  
      def load_after_mining(self):
          print("", sep='', end='', flush=True)
          entity_dir = []
          # resetting input directory to mined entities directory
          entity_dir = self.mined_entity_dir
  
          #for proj in entity_dir:
          #    print("Initiating loading. Preparing data pipelines with mined attributes from {} ".format(proj))
  
              #if Platform.is_unix_platform():
              #    if self.mode == 'multiple':
              #        proj = proj[:-1] if proj.endswith('/') else proj
              #        proj = proj[:proj.rindex('/')]
              #elif Platform.is_windows_platform():
              #    if self.mode == 'multiple':
              #        proj = proj[:-1] if proj.endswith('/') else proj
              #        proj = proj[:proj.rindex('/')]
          #    self.url = proj
  
          self.load_soccminer_entities()
          if self.load_status:
              logging.info("Project/s load successful")
              print("Project/s load successful")
  
      def get_log(self):
          return self.log
  
      def get_mining_level(self):
          return self.mining_level
  
      def get_language(self):
          return self.lang
  
      @staticmethod
      def is_dir(dir_loc):
          # validate if dir
          return os.path.exists(dir_loc) and os.path.isdir(dir_loc)
  
      @staticmethod
      def is_empty_dir(dir_loc):
          # validate if empty dir
          return os.listdir(dir_loc)
  
      @staticmethod
      def get_repo_folders_to_process(local_loc):
          proj_dirs = None
          logging.debug("get_repo_folders_to_process() begins for {}".format(local_loc))
          validate_dir_rc = Utility.validate_inp_dir(local_loc)
          if validate_dir_rc:
              proj_dirs = os.listdir(local_loc)
              for proj in proj_dirs:
                  logging.debug("Folders to be processed: {}".format(proj))
          else:
              logging.debug(
                  "Input directory {} is either empty or does not contain with return value {}".format(local_loc,
                                                                                                       validate_dir_rc))
          return proj_dirs
  
      @staticmethod
      def validate_inp_dir(dir_loc):
          # validate if dir exists and not empty
          if CommentsMiner.is_dir(dir_loc):
              if CommentsMiner.is_empty_dir(dir_loc):  # if returned list has file entry items allow process
                  return True
              else:
                  print("Empty input directory {}".format(dir_loc))
                  return False
          else:
              print("Input {} is not a directory".format(dir_loc))
              return False
  
      @classmethod
      def usage_warning(cls):
          print("input - Defines the input to the tool. Can be 'local_dir' containing project repositories as sub-directories or 'Git Repo URL'")
          print("language - The programming language of the project, for now only java project is handled by soccminer")
          print("mining_level - Defines the mining/project entity loading level. \n"
                " Can be 'comment' to mine/load basic comment info, \n"
                " 'comprehensive_comment' to mine/load comprehensive comment attributes, \n"
                " 'project' to mine/load project attributes), \n"
                " 'all' (for project and comprehensive attributes), \n"
                " NOTE: While loading entities with load_project input argument set to True, SoCCMiner expects the same mining level with which the project was mined. \n")
          print("load_project - If True, loads project entities from the mined entities directory containing the soccminer serialized json files.  "
                "If False, mines source code projects for comments, source code entities and their attributes according to the mining level input")
          print("log - Defines the logging level. Can be one of none(NOLOG), info(INFO), debug(DEBUG)")
          print("output - Defines the output directory where the mined entities will be stored by default it is current working directory")
          if CommentsMiner.log != 0:
              logging.error("inp - Defines the input to the tool. Can be 'local_dir' containing project repositories as sub-directories or 'Git Repo URL'")
              logging.error("language - The programming language of the project, for now only java project are handled by soccminer")
              logging.error("mining_level - Defines the mining/project entity loading level. \n"
                    " Can be 'comment' to mine/load basic comment info, \n"
                    " 'comprehensive_comment' to mine/load comprehensive comment attributes, \n"
                    " 'project' to mine/load project attributes), \n"
                    " 'all' (for project and comprehensive attributes), \n"
                    " 'none' (for loading mined soccminer project entities but not mining), \n")
              logging.error("load_project - If True, loads project entities from the soccminer serialized json files from the mined entities directory of "
                    "respective projects.  "
                    "If False, mines source code projects for comments, source code entities and their attributes according to the mining level input")
              logging.error("log - Defines the logging level. Can be one of none(NOLOG), info(INFO), debug(DEBUG)")
  
      @staticmethod
      def validate_multiple_mode_input(input):
          if not CommentsMiner.validate_mining_input_dir(input):
              return False
          else:
              return True
  
      @classmethod
      def mining_warning_msg(cls, mining_status):
          if not mining_status:
              logging.warning("Encountered issue with SoCCMiner, probably incorrect attribute invoked for the chosen mining level. Please invoke the appropriate attribute for the chosen mining level")
  
      def fetch_load_status(self):
          load_status = True
          for project in self.exception_obj.exception_dict:
              for exception in self.exception_obj.exception_dict[project]:
                  print("{} - Exception: {}".format(project, exception))
                  load_status = False
          for project in self.exception_obj.warning_dict:
              for warning in self.exception_obj.warning_dict[project]:
                  print("{} - Warning: {}".format(project, warning))
                  load_status = False
          return load_status
  
      def fetch_mining_status(self, proj_directories):
          proj_counter = 0
          failed_projects = 0
          project_name = ""
          tot_proj_entities_mined = 0
          total_project_repositories = len(proj_directories)
          for project_dict_ind in self.project_details_mstr_dict:
              try:
                  project_name = self.project_details_mstr_dict[project_dict_ind].project_name
  
                  if project_name in self.exception_obj.exception_dict:
                      failed_projects += 1 if len(self.exception_obj.exception_dict[project_name]) > 0 else 0
                  proj_counter += 1
                  if self.empty_proj_flag[project_dict_ind]:
                      #  Project does not contain any source code flag, problem with input not with mining process.
                      #  self.miner_status_flag = True
                      continue
  
                  print("")
                  print("Project #: {}, Project Name: {}".format(project_dict_ind + 1, project_name))
                  perf_obj = self.project_details_mstr_dict[project_dict_ind]
                  exception_msg_list = Utility.check_exception_directory(perf_obj.mined_entity_directory)
  
                  ast_exception_count = exception_msg_list[0]
                  if ast_exception_count > 0:
                      self.exception_obj.update_exception_message(project_name,
                                                                  "{} Exception occured while mining source files. "
                                                                  "Please check detailed exception message at {}"
                                                                  "".format(ast_exception_count, exception_msg_list[1]))
                  if project_name in self.exception_obj.exception_dict:
                      issue = ",".join(self.exception_obj.exception_dict[project_name]) if \
                      self.exception_obj.exception_dict[project_name] \
                          else ",".join(self.exception_obj.warning_dict[project_name])
                      if issue:
                          self.miner_status_flag = False
                          logging.info("Issue with input Project {} with error: {}".format(project_name, issue))
                      else:
                          self.miner_status_flag = True
  
                      mining_level_dict = Utility.fetch_mining_level_mapping()
                      attributes_count = 0
                      if self.mining_level == 1:
                          attributes_count = 3
                      elif self.mining_level == 2:
                          attributes_count = 17
                      elif self.mining_level == 3:
                          attributes_count = 30
                      elif self.mining_level == 4:
                          attributes_count = 47
  
                      print("Project mined at '{}' level for {} attributes".format(mining_level_dict[self.mining_level], attributes_count))
                      print("Project SOURCE_FILE_PREPARATION_OVERHEAD ----: {} seconds".format(str(round(perf_obj.xml_conv_overhead_time, 2))))
                      print("Project ATTR_PROCESSING_TIME ----------------: {} seconds".format(str(round(perf_obj.tot_attr_processing_time, 2))))
                      print("Project TOTAL MINING_TIME -------------------: {} seconds".format(str(round(perf_obj.mining_time,2))))
                      print("Project TOTAL_SRC_FILES_PROCESSED -----------: {} source files".format(perf_obj.tot_src_files_processed))
                      print("Project PROJECT_SIZE ------------------------: {} KLOC".format(perf_obj.tot_kloc_processed))
                      logging.info("Project SOURCE_FILE_PREPARATION_OVERHEAD: {} seconds".format(str(round(perf_obj.xml_conv_overhead_time, 2))))
                      logging.info("Project MINING_TIME: {} seconds".format(str(round(perf_obj.mining_time, 2))))
                      logging.info("Project ATTR_PROCESSING_TIME: {} seconds".format(str(round(perf_obj.tot_attr_processing_time, 2))))
                      logging.info("Project TOTAL_SRC_FILES_PROCESSED: {} source files".format(perf_obj.tot_src_files_processed))
                      logging.info("Project PROJECT_KLOC: {}".format(perf_obj.tot_kloc_processed))
  
                      if self.mining_level != 3:
                          print("Project TOTAL_COMMENTS_MINED ----------------: {}".format(perf_obj.tot_comments_processed))
                          logging.info("Project TOTAL_COMMENTS_MINED: {}".format(perf_obj.tot_comments_processed))
  
  
                      if self.mining_level == 3 or self.mining_level == 4:
                          print("Project Entity Mining Stats: ")
                          if perf_obj.tot_packages_processed > 0:
                              tot_proj_entities_mined += perf_obj.tot_packages_processed
                              print("\t TOTAL_PACKAGES_MINED -------------------: {}".format(perf_obj.tot_packages_processed))
                          if perf_obj.tot_classes_processed > 0:
                              tot_proj_entities_mined += perf_obj.tot_classes_processed
                              print("\t TOTAL_CLASSES_MINED --------------------: {}".format(perf_obj.tot_classes_processed))
                          if perf_obj.tot_enums_processed > 0:
                              tot_proj_entities_mined += perf_obj.tot_enums_processed
                              print("\t TOTAL_ENUMS_MINED ----------------------: {}".format(perf_obj.tot_enums_processed))
                          if perf_obj.tot_methods_processed > 0:
                              tot_proj_entities_mined += perf_obj.tot_methods_processed
                              print("\t TOTAL_METHODS_MINED --------------------: {}".format(perf_obj.tot_methods_processed))
                          if perf_obj.tot_interfaces_processed > 0:
                              tot_proj_entities_mined += perf_obj.tot_interfaces_processed
                              print("\t TOTAL_INTERFACES_MINED -----------------: {}".format(perf_obj.tot_interfaces_processed))
                          if perf_obj.tot_static_blocks_processed > 0:
                              tot_proj_entities_mined += perf_obj.tot_static_blocks_processed
                              print("\t TOTAL_STATIC_BLOCKS_MINED --------------: {}".format(perf_obj.tot_static_blocks_processed))
                          print("TOTAL_JAVA_PROJECT_SOURCE_ENTITIES_MINED ----: {}".format(tot_proj_entities_mined))
                      tot_attr_mined = 0
                      if self.mining_level == 1:
                          tot_attr_mined = perf_obj.tot_comments_processed * 3
                      elif self.mining_level == 2:
                          tot_attr_mined = perf_obj.tot_comments_processed * 17
                      elif self.mining_level == 3:
                          tot_attr_mined = (tot_proj_entities_mined * 30)
                      elif self.mining_level == 4:
                          tot_attr_mined = (tot_proj_entities_mined * 30) + (perf_obj.tot_comments_processed * 17)
                      print("SoCCMiner Performance: ")
                      print("\t TOTAL ATTRIBUTE INFO MINED -----------------: {}".format(tot_attr_mined))
                      print("\t ATTRIBUTE MINING PERFORMANCE -----------: {} attributes/sec for mining level {}({})"
                            "".format(str(round((tot_attr_mined/perf_obj.mining_time))), self.mining_level, mining_level_dict[self.mining_level]))
                      print("\t SOURCE CODE MINING PERFORMANCE (LOC)----: {} KLOC/sec for mining level {}({})"
                            "".format(str(round((perf_obj.tot_kloc_processed / perf_obj.mining_time), 2)), self.mining_level, mining_level_dict[self.mining_level]))
                      print("\t SOURCE CODE MINING PERFORMANCE ---------: {} files/sec for mining level {}({})".format(
                          str(round((perf_obj.tot_src_files_processed / perf_obj.mining_time), 2)), self.mining_level, mining_level_dict[self.mining_level]))
                      print("\t AVG SOURCE FILE LOC PER SOURCE FILE ----: {} LOC ".format(str(round((perf_obj.avg_source_file_loc), 2))))
                      logging.info("Project TOTAL_PACKAGES_PROCESSED: {}".format(perf_obj.tot_packages_processed))
                      logging.info("Project TOTAL_CLASSES_PROCESSED: {}".format(perf_obj.tot_classes_processed))
                      logging.info("Project TOTAL_ENUMS_PROCESSED: {}".format(perf_obj.tot_enums_processed))
                      logging.info("Project TOTAL_METHODS_PROCESSED: {}".format(perf_obj.tot_methods_processed))
                      logging.info("Project TOTAL_INTERFACES_PROCESSED: {}".format(perf_obj.tot_interfaces_processed))
                      logging.info("Project TOTAL_STATIC_BLOCKS_PROCESSED: {}".format(perf_obj.tot_static_blocks_processed))
  
                  for proj_dir in self.soccminer_proj_directories:
  
                      project_label = ''
                      if Platform.is_unix_platform():
                          project_label = 'SoCCMiner_Mined_Entities' + '/' + project_name
                      elif Platform.is_windows_platform():
                          project_label = 'SoCCMiner_Mined_Entities' + '\\' + project_name
                      try:
                          proj_entry_ind = proj_dir.index(project_label)
                      except ValueError:
                          logging.debug("Skipping entry {} as it is not the mined project url".format(proj_dir))
                      else:
                          self.mined_entity_dir.append(proj_dir)
                          print("Mined Entities for project {} are stored at {}".format(project_name, proj_dir))
                          logging.info("Mined Entities for project {} are stored at {}".format(project_name, proj_dir))
  
                      if project_name in self.exception_obj.warning_dict:
                          if self.exception_obj.warning_dict[project_name]:
                              logging.warning("Potential Invalid Source Code Files for project {}"
                                           "".format(project_name, len(self.exception_obj.exception_dict[project_name])))
                  project_name = None
              except Exception as project_exception:
                  if self.log != 0:
                      logging.error("Fetch_Mining_Status: - Unexpected error: {}".format(project_exception))
                  error_message = traceback.format_exc()
                  self.exception_obj.update_exception_message(project_name, error_message)
                  continue
  
      def validate_args(self, input, programming_language, mining_level, load_proj_flag, log, output_dir, mode):
          # level 'comment' - Basic Comment attributes
          # level 'comprehensive_comment' - Comprehensive Comment Attributes
          # level 'project' - Project Meta Attributes,
          # level 'all' - Project and Comprehensive Comment attributes
          # log can be none/nolog(0), info (1), debug(2)
          if type(load_proj_flag) == str:
              if load_proj_flag.lower() == 'true':
                  load_proj_flag = True
              elif load_proj_flag.lower() == 'false':
                  load_proj_flag = False
          programming_language = programming_language.lower()
          mining_level = str(mining_level).lower()
  
          if load_proj_flag not in [0, 1]:
              load_proj_flag = str(load_proj_flag).lower()
              if load_proj_flag == "true" or load_proj_flag:
                  load_proj_flag = 1
              if load_proj_flag == "false" or not load_proj_flag:
                  load_proj_flag = 0
          self.load_project = load_proj_flag
  
          if 'http' in input and 'github.com' in input:
              if RepoDownloader.validate_repo_url(input):
                  cloned_folder = RepoDownloader.clone_repo(input)
                  if not cloned_folder:
                      print("Issue with input url, please check input url: {}".format(input))
                      self.invalid_ing_arg_flag = True
                      return False
                  else:
                      self.url = cloned_folder
                      if Platform.is_unix_platform():
                          self.url = self.url[:-1] if self.url.endswith('/') else self.url
                      elif Platform.is_windows_platform():
                          self.url = self.url[:-1] if self.url.endswith('\\') else self.url
                      print("after repo download:",self.url)
                      if mode != 'single':
                          print("Mode cannot be multiple/files for GitHub project repository, forcing it to 'single'")
                          self.mode = 'single'
              else:
                  print("Issue with input url, please check input url: {}".format(input))
                  return False
          elif CommentsMiner.validate_inp_dir(input):
              self.url = input
              if mode == 'multiple' and not load_proj_flag:
                  mode_validation_status = CommentsMiner.validate_multiple_mode_input(self.url)
                  if not mode_validation_status:
                      return False
  
          else:
              print("Issue with input ({})".format(input))
              self.invalid_ing_arg_flag = True
              return False
  
          if not CommentsMiner.is_dir(output_dir):
              print("Invalid output directory ({})".format(output_dir))
              self.invalid_ing_arg_flag = True
              return False
  
          if load_proj_flag not in [0, 1]:
              print("Incorrect value for load_project. Can be either True/False, {},{}".format(load_proj_flag, type(load_proj_flag)))
              self.invalid_ing_arg_flag = True
              return False
  
          if not mining_level.strip().lower() in ["comment", "comprehensive_comment", "project", "all"]:  # , "none"]:
              print("Issue with mining level input {}".format(mining_level.strip().lower()))
              self.invalid_ing_arg_flag = True
              return False
          else:
              if mining_level.strip().lower() == "comment":
                  self.mining_level = 1
              elif mining_level.strip().lower() == "comprehensive_comment":
                  self.mining_level = 2
              elif mining_level.strip().lower() == "project":
                  self.mining_level = 3
              elif mining_level.strip().lower() == "all":
                  self.mining_level = 4
  
          if log is not None:
              if log.strip().lower() not in ['nolog', "false", "info", "debug"]:
                  print("Issue with log level input {}".format(log))
                  self.invalid_ing_arg_flag = True
                  return False
              else:
                  # default nolog --> 0
                  self.log = 0
                  if str(log).strip().lower() == "false" or str(log).strip().lower() == "nolog":
                      self.log = 0
                  elif str(log).strip().lower() == "debug":
                      self.log = 2
                  elif str(log).strip().lower() == "info":
                      self.log = 1
          else:
              self.log = 0
  
          if programming_language not in ['java']:
              print("Issue with programming language input {}".format(programming_language))
              self.invalid_ing_arg_flag = True
              return False
          else:
              self.lang = programming_language
  
          if Platform.is_unix_platform():
              self.output_dir = output_dir[:-1] if output_dir.endswith('/') else output_dir
          elif Platform.is_windows_platform():
              self.output_dir = output_dir[:-1] if output_dir.endswith('\\') else output_dir
          return True
  
      def initiate_mining(self):
          project_instance = None
          mining_objects_list = []
          single_mode_inp_dir_path = None
  
          logging.debug("initiate_mining() begins for {} containing {} programs".format(self.url, self.lang))
          proj_dirs = None
          if self.mode != 'multiple':
              if '.' in self.url or '..' in self.url:
                  (single_mode_inp_dir_path, proj_dirs) = Utility.fetch_inp_dir(Utility.fetch_absolute_inp_dir(self.url))
                  proj_dirs = [proj_dirs]
              else:
                  (single_mode_inp_dir_path, proj_dirs) = Utility.fetch_inp_dir(self.url)
                  proj_dirs = [proj_dirs]
          else:
              self.url = Utility.fetch_absolute_inp_dir(self.url)
              if Platform.is_unix_platform():
                  self.url = self.url+'/' if not self.url.endswith('/') else self.url
              elif Platform.is_windows_platform():
                  self.url = self.url+'\\' if not self.url.endswith('\\') else self.url
              proj_dirs = CommentsMiner.get_repo_folders_to_process(self.url)
          project_name = None
          logging.debug("Input directory path {}".format(self.url))
          for ind, proj_dir in enumerate(proj_dirs):
              try:
                  project_name = ""
                  if self.mode == 'single':
                      absolute_dir = single_mode_inp_dir_path + proj_dir
                  else:
                      absolute_dir = self.url + proj_dir
                  self.proj_directories.append(absolute_dir)
                  logging.debug("absolute_dir: {}".format(absolute_dir))
  
                  if CommentsMiner.validate_inp_dir(absolute_dir):
                      logging.debug(" validated absolute_dir ".format(absolute_dir))
                      if Platform.is_unix_platform():
                          project_name = proj_dir.replace("/", "_")
                          SoCCMinerLogger.log_dir = SoCCMinerLogger.log_dir + '/' + project_name
                      elif Platform.is_windows_platform():
                          project_name = proj_dir.replace("\\", "_")
                          SoCCMinerLogger.log_dir = SoCCMinerLogger.log_dir + '\\' + project_name
                      self.project = project_name
                      self.exception_obj.set_project_stack(project_name)
                      logging.info("Project to be initiated for {},{} ".format(proj_dir, absolute_dir))
                      if self.lang.lower() == "java":
                          project_instance = JavaProjectMeta(absolute_dir)
                      perf_obj = APIPerformanceTime()
  
                      mining_objects_list.append(project_instance)
                      src_files = SourceFiles(absolute_dir)
                      mining_objects_list.append(src_files)
                      src_files.fetch_source_files(src_files.loc, self.lang)
                      conv_start_time = time.time()
                      process_start_time = time.time()
                      src_files.convert_srcfiles_to_xmlfiles(project_name, self.exception_obj)
                      project_instance.set_source_file_info(src_files)
                      logging.debug("Source file count for project {} is {}".format(project_name, len(src_files.get_files())))
  
                      if len(src_files.get_files()) != 0:
                          file_cntr = 0
                          empty_file_count = 0
                          logging.info("Total source code files: {} for project {}".format(len(src_files.get_files()), project_name))
                          conv_end_time = time.time()
                          perf_obj.xml_conv_overhead_time = conv_end_time - conv_start_time
                          attr_and_meta_attr_proc_start_time = time.time()
  
                          if Platform.is_unix_platform():
                              self.project_directory = self.output_dir + '/SoCCMiner_Mined_Entities/' + project_instance.get_project_name()
                          elif Platform.is_windows_platform():
                              self.project_directory = self.output_dir + '\\SoCCMiner_Mined_Entities\\' + project_instance.get_project_name()
                          perf_obj.mined_entity_directory = self.project_directory
                          self.soccminer_proj_directories.append(self.project_directory)
                          # remove if already exists
                          if validate_loc(self.project_directory):
                              shutil.rmtree(self.project_directory)
  
                          empty_file_count = 0
                          for xml_file in src_files.cd_file_xml_mapping_dict:
                              if os.path.getsize(xml_file) == 0:
                                  logging.warning(
                                      "Potential invalid source code file or failed xml conversion for {} whose file size is 0 "
                                      "".format(xml_file))
                                  empty_file_count += 1
  
                          valid_file_count = len(src_files.get_files()) - empty_file_count - self.exception_obj.failed_ast_conv_dict[project_name]
                          logging.info('Source files successfully prepared for {}/{}'.format(valid_file_count, len(src_files.files)))
  
                          processed_source_file_dir = ''
                          exception_dir = ''
                          if Platform.is_unix_platform():
                              processed_source_file_dir = self.project_directory + '/' + type(
                                  FileInfo()).__name__ + '/' + 'attributes'
                              exception_dir = self.project_directory + '/' + 'exceptions' + '/'
                          elif Platform.is_windows_platform():
                              processed_source_file_dir = self.project_directory + '\\' + type(
                                  FileInfo()).__name__ + '\\' + 'attributes'
                              exception_dir = self.project_directory + '\\' + 'exceptions' + '\\'
  
                          logging.info("proj dir before tracking ast parsing progress: {}, {}".format(processed_source_file_dir, exception_dir))
                          tracking_process = Process(target=TrackProgress.track_ast_parsing_progress,
                                            args=(valid_file_count, processed_source_file_dir, exception_dir, project_name, self.mining_level))
                          tracking_process.daemon = True
                          tracking_process.start()
  
                          for xml_file in src_files.cd_file_xml_mapping_dict:
                              try:
                                  file_cntr += 1
                                  # Source Code Parsing
                                  process = Process(target=XmlParsing.ast_parsing_multiprocessing,
                                                    args=(xml_file, src_files.cd_file_xml_mapping_dict[xml_file],
                                                          self.project_directory, file_cntr, self.exception_obj, self.log))
                                  process.start()
                                  process.join()
  
                              except Exception as proc_files_ex:
                                  if self.log != 0:
                                      logging.error(
                                          "CM: Error while processing source code file {} {} {}".format(xml_file, sys.exc_info()[0],
                                                                                                   proc_files_ex))
                                  error_message = traceback.format_exc()
                                  self.exception_obj.update_exception_message(project_name, error_message)
  
                                  error_file = ''
                                  if Platform.is_unix_platform():
                                      error_file = exception_dir + xml_file.split("/")[-1].replace(".java", ".error")
                                  elif Platform.is_windows_platform():
                                      error_file = exception_dir + xml_file.split("\\")[-1].replace(".java", ".error")
                                  with open(error_file, 'w') as writer:
                                      writer.write("{}".format(error_message))
                                  continue
                          tracking_process.join()
                          TrackProgress.track_ast_parsing_progress(valid_file_count, processed_source_file_dir, exception_dir, project_name, self.mining_level)
                          load_msg = project_instance.load_project_from_json(self.project_directory, "package")
                          if load_msg != "success":
                              print("Encountered issue while loading for {}".format(project_name))
                              logging.info("Encountered issue while loading for {}".format(project_name))
                          logging.debug("Type, # of packages from loaded project instance from json: {}, {}".format(type(project_instance).__name__,
                                                                                                                    len(project_instance.get_packages())))
                          project_instance.set_project_loc(project_instance.fetch_project_loc() / 1000)
  
                          load_msg = project_instance.load_project_from_json(self.project_directory, "file")
                          perf_obj.avg_source_file_loc = project_instance.fetch_avg_file_loc()
                          entity_count_dict = project_instance.populate_entity_stats(self.project_directory)
                          if empty_file_count != 0:
                              self.exception_obj.update_warning_message(project_name,
                                                                        "Potential invalid source code or failed AST conversion, "
                                                                        "with {} empty files".format(empty_file_count))
  
                          process_end_time = time.time()
                          perf_obj.mining_time = process_end_time - process_start_time
                          perf_obj.tot_src_files_processed = file_cntr
                          perf_obj.tot_comments_processed = entity_count_dict[type(CommentInfo()).__name__]
                          perf_obj.tot_kloc_processed = project_instance.get_project_loc()
  
                          #  Serialize project source file info and project meta
                          src_file_proj_info = {}
  
                          file_list = src_files.get_files()
                          proj_path = ''
                          proj_name_str = ''
                          updated_file_list=[]
                          if Platform.is_unix_platform():
                              proj_name_str = '/' + project_name + '/'
                              proj_path = file_list[0].split(proj_name_str)[0]
                              updated_file_list = [file.replace(proj_path, '').replace("/", ".")[1:] for file in file_list]
                          elif Platform.is_windows_platform():
                              proj_name_str = '\\' + project_name + '\\'
                              proj_path = file_list[0].split(proj_name_str)[0]
                              updated_file_list = [file.replace(proj_path, '').replace("\\", ".")[1:] for file in file_list]
                          src_files.files = updated_file_list
                          file_list = None
                          updated_file_list = []
  
                          src_file_proj_info['src_file_obj'] = src_files
                          src_file_proj_info['proj_name'] = project_name
                          src_file_proj_info['proj_loc'] = project_instance.get_project_loc()
                          src_file_proj_info['platform'] = Platform.fetch_platform()
                          src_file_proj_info['mining_level'] = self.mining_level
                          SerializeSoCCMiner.serialize_project_source_file_info(project_name, self.project_directory, src_file_proj_info)
                          src_file_proj_info = {}
  
                          if self.mining_level > 2:
                              perf_obj.tot_packages_processed += entity_count_dict[type(PackageInfo()).__name__]
                              perf_obj.tot_classes_processed += entity_count_dict[type(ClassInfo()).__name__]
                              perf_obj.tot_enums_processed += entity_count_dict[type(EnumInfo()).__name__]
                              perf_obj.tot_methods_processed += entity_count_dict[type(MethodInfo()).__name__]
                              perf_obj.tot_interfaces_processed += entity_count_dict[type(InterfaceInfo()).__name__]
                              perf_obj.tot_static_blocks_processed += entity_count_dict[type(StaticBlockInfo()).__name__]
  
                          attr_and_meta_attr_proc_end_time = time.time()
                          perf_obj.tot_attr_processing_time += attr_and_meta_attr_proc_end_time - attr_and_meta_attr_proc_start_time
                          perf_obj.project_name = project_name
  
                          self.project_details_mstr_dict[ind] = perf_obj
                          self.empty_proj_flag.append(False)
                          logging.info("Mining Ends for Project {},{} ".format(proj_dir, absolute_dir))
                      else:
                          self.exception_obj.update_warning_message(project_name,
                                                                    "Project {} does not contain any .java source code file".format(
                                                                        project_name))
                          perf_obj.project_name = project_name
                          self.project_details_mstr_dict[ind] = perf_obj
                          print("Project {} does not contain any .java source code file".format(project_name))
                          self.empty_proj_flag.append(True)
                  else:
                      print("Invalid input project directory {}.  Please check your input.".format(absolute_dir))
                      #self.usage_warning()
                      self.miner_status_flag = True
                      self.invalid_ing_arg_flag = True
              except Exception as proc_dir_ex:
                  error_message = traceback.format_exc()
                  self.exception_obj.update_exception_message(project_name, error_message)
                  if self.log != 0:
                      logging.error("Unexpected error {} {}".format(sys.exc_info()[0], proc_dir_ex))
                      logging.error("Error Trace Details: {}".format(error_message))
                  continue
              else:
                  if 1 in self.empty_proj_flag:
                      logging.warning("One or more project has empty source code files")
                  else:
                      self.miner_status_flag = True
  
              # Releasing processed objects
              for processed_mining_object in mining_objects_list:
                  logging.info("Releasing processed object {}".format(type(processed_mining_object).__name__))
                  self.release_obj(processed_mining_object)
              mining_objects_list = []
  
          tot_src_files_processed = 0
          tot_packages_processed = 0
          tot_classes_processed = 0
          tot_enums_processed = 0
          tot_methods_processed = 0
          tot_interfaces_processed = 0
          tot_static_blocks_processed = 0
          tot_comments_processed = 0
          tot_kloc_processed = 0
          tot_xml_conv_overhead_time = 0.0
          tot_attr_processing_time = 0.0
  
          for project_ind in self.project_details_mstr_dict:
              perf_obj = self.project_details_mstr_dict[project_ind]
              tot_src_files_processed += perf_obj.tot_src_files_processed
              tot_packages_processed += perf_obj.tot_packages_processed
              tot_classes_processed += perf_obj.tot_classes_processed
              tot_enums_processed += perf_obj.tot_enums_processed
              tot_methods_processed += perf_obj.tot_methods_processed
              tot_interfaces_processed += perf_obj.tot_interfaces_processed
              tot_static_blocks_processed += perf_obj.tot_static_blocks_processed
              tot_comments_processed += perf_obj.tot_comments_processed
              tot_kloc_processed += perf_obj.tot_kloc_processed
              tot_xml_conv_overhead_time += perf_obj.xml_conv_overhead_time
              tot_attr_processing_time += perf_obj.tot_attr_processing_time
  
          self.fetch_mining_status(self.proj_directories)
  
          if self.miner_status_flag:
              logging.info("-------------------")
              logging.info("Total XML Conversion overhead time : {}".format(tot_xml_conv_overhead_time))
              logging.info("Total ATTR and META-ATTR processing time: {}".format(tot_attr_processing_time))
              logging.info("Total Source files processed: {}".format(tot_src_files_processed))
              logging.info("Total Packages processed: {}".format(tot_packages_processed))
              logging.info("Total Classes processed: {}".format(tot_classes_processed))
              logging.info("Total Methods processed: {}".format(tot_methods_processed))
              logging.info("Total Interfaces processed: {}".format(tot_interfaces_processed))
              logging.info("Total Static Blocks processed: {}".format(tot_static_blocks_processed))
              logging.info("Total Comments processed: {}".format(tot_comments_processed))
              logging.info("Total KLOC processed: {}".format(tot_kloc_processed))
          else:
              issue = ",".join(self.exception_obj.exception_dict[project_name]) if self.exception_obj.exception_dict[project_name] \
                  else ",".join(self.exception_obj.warning_dict[project_name])
              print("Encountered issues while mining Project {} issue: {}".format(project_name, issue))
              Utility.clear_temp_folders()
  
      def release_obj(self, obj):
          del obj
          logging.info("comments_miner - GC status: {}".format(gc.isenabled()))
          gc.collect()
  
      def validate_soccminer_entity_input_dir(self, proj_entity_dir):
          soccminer_entity_dir_list = [type(PackageInfo()).__name__, type(ClassInfo()).__name__, type(MethodInfo()).__name__,
                                      type(InterfaceInfo()).__name__, type(StaticBlockInfo()).__name__, 'attributes', 'comments', 'exceptions']
          proj_name = ''
          if Platform.is_unix_platform():
              proj_entity_dir = proj_entity_dir[:-1] if proj_entity_dir.endswith('/') else proj_entity_dir
              proj_name = proj_entity_dir.split('/')[-1]
          elif Platform.is_windows_platform():
              proj_entity_dir = proj_entity_dir[:-1] if proj_entity_dir.endswith('\\') else proj_entity_dir
              proj_name = proj_entity_dir.split('\\')[-1]
  
          for dir_item in os.listdir(proj_entity_dir):
              if os.path.isfile(dir_item):
                  if dir_item != proj_name + '.json':
                      print(
                          "Cannot contain any file other than project json file {} for loading_project but directory contains {}.".format(
                              {proj_name + '.json'}, dir_item))
                      return False
              elif os.path.isdir(dir_item):
                  if dir_item not in soccminer_entity_dir_list:
                      print(
                          "Cannot contain any directory other than soccminer generated entity directory for loading_project but contains {}".format(
                              dir_item))
                      return False
          return True
  
      def load_soccminer_entities(self):
          project_name = None
          proj_directory = ''
  
          if self.mode == 'single':
              if not self.load_project:
                  # for direct load project set as false, there is supposed to be only one mined entity dir in single mode
                  # validating for project json at the first level, for direct_load true, self.url should contain the entities.
                  self.url = self.mined_entity_dir[0]
  
              if not Utility.validate_entity_folder(self.url):
                  print("Project JSON not found in the input folder {}. Not a valid SoCC-Miner Mined Entity folder. Exiting SoCCMiner.".format(self.url))
                  print("Please check the input folder or use the appropriate input mode single/multiple.")
                  self.load_status = False
                  return
              self.url = Utility.create_temp_dir_for_loading(self.url, self.mode)
          elif self.mode == 'multiple':
              # copy the newly created project dir for single mode
              # self.url = inner_proj_directory
              # loading after mining for multiple projects, mined_entity_dir will contain
              # successfully mined directories
              if not self.load_project:
                  for proj_dir in self.mined_entity_dir:
                      self.url = Utility.create_temp_dir_for_loading(proj_dir, self.mode)
              elif self.load_project:
                  self.url = Utility.multiple_mode_projects_for_loading(self.url)
  
  
          logging.debug("load_soccminer_entities(): Validating dir: {}".format(self.url))
          if self.validate_inp_dir(self.url):
              proj_entity_dirs = CommentsMiner.get_repo_folders_to_process(self.url)
              project_name = ""
              for ind, proj_dir in enumerate(proj_entity_dirs):
                  try:
                      if Platform.is_unix_platform():
                          if not self.url.endswith("/"):
                              self.url = self.url + '/'
                      if Platform.is_windows_platform():
                          if not self.url.endswith("\\"):
                              self.url = self.url + '\\'
                      project_name = ""
                      absolute_dir = self.url + proj_dir
  
                      if os.path.isfile(absolute_dir):
                          logging.info(
                              "Files cannot be present at this level while loading project, hence skipping {}".format(
                                  absolute_dir))
                          print(
                              "Encountered file instead of directory for project loading, hence skipping {}".format(
                                  absolute_dir))
                          continue
  
                      if Platform.is_unix_platform():
                          project_name = proj_dir.replace("/", "_")
                      elif Platform.is_windows_platform():
                          project_name = proj_dir.replace("\\", "_")
  
                      self.exception_obj.set_project_stack(project_name)
                      if not self.validate_soccminer_entity_input_dir(absolute_dir):
                          print("Encountered issue while loading source file meta for {}".format(project_name))
                          self.exception_obj.update_exception_message(project_name, "Invalid input folder for loading project")
                          continue
  
                      if CommentsMiner.validate_inp_dir(absolute_dir):
                          if not CommentsMiner.validate_soccminer_dir_structure(absolute_dir):
                              self.proj_directories.append(absolute_dir)
                              project_instance = JavaProjectMeta(absolute_dir)
                              #  load source file info object and project meta before loading other serialized entities
                              load_msg = project_instance.load_project_from_json(absolute_dir, "source_file")
                              if load_msg != "success":
                                  print("Encountered issue while loading source file meta for {}".format(project_name))
                                  self.exception_obj.update_exception_message(project_name, load_msg)
                                  continue
  
                              #  load entire project attributes and comments
                              load_msg = project_instance.load_project_from_json(absolute_dir, "project")
                              if load_msg != "success":
                                  print("Encountered issue while loading source file meta for {}".format(project_name))
                                  self.exception_obj.update_exception_message(project_name, load_msg)
                                  continue
  
                              if self.mining_level == 1:  # comment level
                                  self.proj_comments_main_attr_obj_list.append(CommentsMetaAttribute(project_instance))
                                  print("{} pipeline is ready and can be used further containing {}'s comment details".format('CommentsMetaAttribute', project_name))
                              elif self.mining_level == 2:  # comprehensive_comment level
                                  self.proj_comments_all_attr_obj_list.append(ComprehensiveCommentsAttribute(project_instance))
                                  print("{} pipeline is ready and can be used further containing {}'s comprehensive comment context details".format('ComprehensiveCommentsAttribute',
                                                                                                 project_name))
                              elif self.mining_level == 3:  # project level
                                  self.proj_meta_attr_obj_list.append(JavaMetaAttribute(project_instance))
                                  print("{} pipeline is ready and can be used further containing {}'s source code entity details".format('JavaMetaAttribute',
                                                                                                 project_name))
                              elif self.mining_level == 4:  # all level
                                  self.proj_comments_and_attr_obj_list.append(JavaMiner(project_instance))
                                  print("{} pipeline is ready and can be used further containing {}'s comprehensive comment context and source code entity details".format('JavaMiner',
                                                                                                 project_name))
                              self.release_obj(project_instance)
                          else:
                              self.exception_obj.update_warning_message(project_name,
                                                                        "Unable to load SoCCMiner entities from empty directory {}".format(absolute_dir))
                      else:
                          self.exception_obj.update_warning_message(project_name,
                                                                        "Unable to load SoCCMiner entities from invalid input directory {}".format(
                                                                            absolute_dir))
                  except Exception as load_soccminer_entity:
                      error_message = traceback.format_exc()
                      self.exception_obj.update_exception_message(project_name, error_message)
                      if self.log != 0:
                          logging.error("load_soccminer_entity: Encountered error {} {}".format(sys.exc_info()[0],
                                                                                            load_soccminer_entity))
                          logging.error("Error Trace Details: {}".format(error_message))
                      continue
              self.load_status = self.fetch_load_status()
          else:
              if self.log != 0:
                  logging.error(
                      "Incorrect input folder hierarchy for loading project. \n"
                      "Expected: Folder --> soccminer_project_entity_folder1, soccminer_project_entity_folderN, etc.,  containing  attributes/comments sub-directories \n"
                      "Given input project load folder is: soccminer_project_entity \n"
                      "Input Directory for project load: {} \n".format(self.url))
              print(
                  "Incorrect input folder hierarchy for loading project. \n"
                  "Expected: Folder --> soccminer_project_entity_folder1, soccminer_project_entity_folderN, etc.,  containing  attributes/comments sub-directories \n"
                  "Given input project load folder is: soccminer_project_entity \n"
                  "Input Directory for project load: {} \n".format(self.url))
  
      def fetch_mined_project_meta(self):
          """
          Fetches Project Meta Attributes specific to programming language,
          for example (Java): Class Name, Signature, Nested Level, Method Name, Signature, etc.,
          Works for mining level Project(Module input argument), else returns empty list.
                  :param: None
                  :returns: List of returned :class: JavaMetaAttr objects
                  :rtype: list
          """
          proj_meta_attr_obj_list = []
          if len(self.proj_meta_attr_obj_list) > 0 and CommentsMiner.mining_level == 3:
              if CommentsMiner.lang == 'java':
                  return self.proj_meta_attr_obj_list
          else:
              CommentsMiner.mining_warning_msg(False)
              return proj_meta_attr_obj_list
  
      def fetch_mined_comments(self):
          """
          Fetches Mined Comments.  i.e., text, line no and source file name
          Works for mining level comment(Module input argument), default mining level argument.
          Returns CommentsMetaAttribute objects in a list.
  
                  :param: None
                  :returns: List of returned :class: ProjCommentsMainAttr objects
                  :rtype: list
          """
          proj_comments_main_attr_obj_list = []
          if len(self.proj_comments_main_attr_obj_list) > 0 and (CommentsMiner.mining_level == 1):
              if CommentsMiner.lang == 'java':
                  return self.proj_comments_main_attr_obj_list
          else:
              CommentsMiner.mining_warning_msg(False)
              return proj_comments_main_attr_obj_list
  
      def fetch_mined_comment_attributes(self):
          """
          Fetches Project comments and comprehensive comment attributes, i.e., all attributes
          Works for mining level comprehensive_comment(Module input argument), else returns empty list.
          Returns ComprehensiveCommentsAttribute objects in a list.
                  :param: None
                  :returns: List of returned :class: ProjectMetaAttribute objects (JavaMetaAttribute for Java)
                  :rtype: list
          """
          proj_comments_all_attr_obj_list = []
          if len(self.proj_comments_all_attr_obj_list) > 0 and (CommentsMiner.mining_level == 2):
              if CommentsMiner.lang == 'java':
                  return self.proj_comments_all_attr_obj_list
          else:
              CommentsMiner.mining_warning_msg(False)
              return proj_comments_all_attr_obj_list
  
      def fetch_mined_project_meta_and_comments(self):
          """
          Fetches all Project comments with their attributes, Project attributes (file count, etc.,) and
          Meta-attributes (for java: package/class/interface/method/static block attributes)
          Works only for mining level all(Module input argument), else returns empty list.
          Returns ProjectMiner objects in a list (for Java programs JavaProjectMiner objects)
                  :param: None
                  :returns: List of returned :class: JavaProjectMiner objects
                  :rtype: list
          """
          proj_all_comments_attr_obj_list = []
          if len(self.proj_comments_and_attr_obj_list) > 0 and (CommentsMiner.mining_level == 4):
              if CommentsMiner.lang == 'java':
                  return self.proj_comments_and_attr_obj_list
          else:
              CommentsMiner.mining_warning_msg(False)
              return proj_all_comments_attr_obj_list
  
  