from gen.javaLabeled.JavaLexer import JavaLexer

try:
    import understand as und
except ImportError as e:
    print(e)

from antlr4 import *
from antlr4.TokenStreamRewriter import TokenStreamRewriter

from gen.javaLabeled.JavaParserLabeled import JavaParserLabeled
from gen.javaLabeled.JavaParserLabeledListener import JavaParserLabeledListener


class IncreaseFieldVisibilityRefactoringListener(JavaParserLabeledListener):
    """
    ## Introduction
    # TODO: Change name to decrease
    1. Private
    2. Protected
    3. Package (no modifier)
    4. Public

    Increase the visibility of a field from private to package, package to protected or protected to public.

    ## Pre and Post Conditions

    ### Pre Conditions:

    1. User must enter the field's name, and the source class's name for the refactoring
       in order to increase the target field's visibility.

    ### Post Conditions:

    No specific Post Condition
    """

    def __init__(self, common_token_stream: CommonTokenStream = None, source_class=None, field_name: str = None):
        """To implement Increase Field Visibility refactoring based on its actors.
           Detects the required field and increases/changes its visibility status.

           Args:
                common_token_stream (CommonTokenStream): A stream of tokens generated by parsing the main file using the ANTLR parser generator

                source_class (str): Name of the class in which the refactoring has to be done

                field_name (str): Name of the field whose visibility status has to be changed

           Returns:
                No returns
        """
        if field_name is None:
            self.field_name = ""
        else:
            self.field_name = field_name

        if source_class is None:
            self.source_class = ""
        else:
            self.source_class = source_class
        if common_token_stream is None:
            raise ValueError('common_token_stream is None')
        else:
            self.token_stream_rewriter = TokenStreamRewriter(common_token_stream)

        self.is_source_class = False
        self.detected_field = None
        self.detected_method = None
        self.TAB = "\t"
        self.NEW_LINE = "\n"
        self.code = ""
        self.temp_declaration_code = ""

    def enterClassDeclaration(self, ctx: JavaParserLabeled.ClassDeclarationContext):

        class_identifier = ctx.IDENTIFIER().getText()
        if class_identifier == self.source_class:
            self.is_source_class = True
        else:
            self.is_source_class = False

    def exitFieldDeclaration(self, ctx: JavaParserLabeled.FieldDeclarationContext):
        if not self.is_source_class:
            return None
        grand_parent_ctx = ctx.parentCtx.parentCtx
        # field_identifier = ctx.variableDeclarators().getText().split(",")
        field_identifier = ctx.variableDeclarators().variableDeclarator(0).variableDeclaratorId().IDENTIFIER().getText()
        if self.field_name in field_identifier:
            if not grand_parent_ctx.modifier():
                self.token_stream_rewriter.replaceRange(
                    from_idx=ctx.typeType().start.tokenIndex,
                    to_idx=ctx.typeType().stop.tokenIndex,
                    text='private ' + ctx.typeType().getText()
                )
            elif grand_parent_ctx.modifier(0).getText() == 'public':
                self.token_stream_rewriter.replaceRange(
                    from_idx=grand_parent_ctx.modifier(0).start.tokenIndex,
                    to_idx=grand_parent_ctx.modifier(0).stop.tokenIndex,
                    text='private')
            elif grand_parent_ctx.modifier(0).getText() != 'private':
                self.token_stream_rewriter.replaceRange(
                    from_idx=grand_parent_ctx.modifier(0).start.tokenIndex,
                    to_idx=grand_parent_ctx.modifier(0).stop.tokenIndex,
                    text='private ' + grand_parent_ctx.modifier(0).getText())
            # generate accessor and mutator methods
            # Accessor body
            new_code = '\n\t'
            new_code += 'public ' + ctx.typeType().getText() + ' get' + str.capitalize(self.field_name)
            new_code += '() { \n\t\t return this.' + self.field_name + ';' + '\n\t}'

            # Mutator body
            new_code += '\n\t'
            new_code += 'public void set' + str.capitalize(self.field_name)
            new_code += '(' + ctx.typeType().getText() + ' ' + self.field_name + ') { \n\t\t'
            new_code += 'this.' + self.field_name + ' = ' + self.field_name + ';' + '\n\t}\n'

            self.token_stream_rewriter.insertAfter(ctx.stop.tokenIndex, new_code)


class PropagationIncreaseFieldVisibilityRefactoringListener(JavaParserLabeledListener):
    def __init__(self, common_token_stream: CommonTokenStream = None, using_field_name=None, object_name=None,
                 propagated_class_name=None, action_to_do=None):
        """
        Used for propagation purposes in the other classes of the project: implement the propagation

        Args:
            common_token_stream (CommonTokenStream): A stream of tokens generated by parsing the main file using the ANTLR parser generator

            using_field_name (str): Name of the field which has to be propagated

            object_name (str): Name of the objects that need to be changed with the propagation operation

            propagated_class_name (str): Name of the class in which the propagation operation needs to be implemented

        Returns: No returns
        """

        if using_field_name is None:
            self.using_field_name = []
        else:
            self.using_field_name = using_field_name

        if action_to_do is None:
            self.action_to_do = []
        else:
            self.action_to_do = action_to_do

        if object_name is None:
            self.object_name = []
        else:
            self.object_name = object_name

        if propagated_class_name is None:
            self.propagated_class_name = []
        else:
            self.propagated_class_name = propagated_class_name

        if common_token_stream is None:
            raise ValueError('common_token_stream is None')
        else:
            self.token_stream_rewriter = TokenStreamRewriter(common_token_stream)

        self.is_class = False

    def enterClassDeclaration(self, ctx: JavaParserLabeled.ClassDeclarationContext):
        # print("Propagation started, please wait...")
        class_identifier = ctx.IDENTIFIER().getText()

        if class_identifier in self.propagated_class_name:
            self.is_class = True
            print("Propagation   started, please wait......")
        else:
            self.is_class = False

    def is_before_equal(self, parent_ctx):
        try:
            if str(type(
                    parent_ctx)) == "<class 'gen.javaLabeled.JavaParserLabeled.JavaParserLabeled.Expression21Context'>":
                if str(type(parent_ctx.children[
                                0])) == "<class 'gen.javaLabeled.JavaParserLabeled.JavaParserLabeled.Expression1Context'>":
                    return True
                return False
        except:
            return False

    def getoperator(self, str):
        return (str[0:1])

    def check_is_expression_obj_and_field(self, ctx):
        if str(ctx.children[0].getText()) in self.object_name and str(
                ctx.children[2].getText()) == self.using_field_name:
            return True
        else:
            return False
        # print(ctx.children[0].getText())
        # print(ctx.children[1].getText())
        # print(ctx.children[2].getText())

    def enterExpression1(self, ctx: JavaParserLabeled.Expression1Context):
        if not self.is_class: return
        parent_ctx = ctx.parentCtx;
        if self.is_before_equal(parent_ctx):

            # print("going to set")
            if self.action_to_do == "Get":
                return None
            # {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{

            if isinstance(parent_ctx, JavaParserLabeled.Expression21Context):
                # print("parent_ctx.children[1]:", str(parent_ctx.children[1]))
                if (str(parent_ctx.children[1]) in ["+=", "-=", "*=", "/=", "&=", "|=", "^=", ">>=", ">>>=", "<<=",
                                                    "%="]):
                    if self.action_to_do == "Get":
                        return None
                    if ctx.expression() is not None:
                        if ctx.expression().primary() is not None:
                            if ctx.expression().primary().IDENTIFIER().getText() in self.object_name:
                                parent_ctx = ctx.parentCtx
                                count = parent_ctx.getChildCount()
                                if count == 3:
                                    expression_text = parent_ctx.children[2].getText()

                                    self.token_stream_rewriter.replaceRange(
                                        from_idx=parent_ctx.start.tokenIndex,
                                        to_idx=parent_ctx.stop.tokenIndex,
                                        text=ctx.expression().primary().IDENTIFIER().getText() + '.' + 'set' + str.capitalize(
                                            ctx.IDENTIFIER().getText()) + '(' + ctx.expression().primary().IDENTIFIER().getText() + '.get' + str.capitalize(
                                            ctx.IDENTIFIER().getText()) + '() ' + self.getoperator(
                                            str(parent_ctx.children[1])) + "( " + expression_text + ') )'
                                    )
                                    return True

            # }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}

            if ctx.expression() is not None:
                if ctx.expression().primary() is not None:
                    if ctx.expression().primary().IDENTIFIER().getText() in self.object_name:
                        # print("ctx.expression().primary().IDENTIFIER().getText()=",ctx.expression().primary().IDENTIFIER().getText())
                        parent_ctx = ctx.parentCtx
                        count = parent_ctx.getChildCount()
                        if count == 3:
                            expression_text = parent_ctx.children[2].getText()

                            self.token_stream_rewriter.replaceRange(
                                from_idx=parent_ctx.start.tokenIndex,
                                to_idx=parent_ctx.stop.tokenIndex,
                                text=ctx.expression().primary().IDENTIFIER().getText() + '.' + 'set' + str.capitalize(
                                    ctx.IDENTIFIER().getText()) + '(' + expression_text + ')'
                            )
        else:  # expression is after =
            if self.action_to_do == "Set":
                return None
            if self.check_is_expression_obj_and_field(ctx):
                if ctx.expression() is not None:
                    if ctx.expression().primary() is not None:
                        if (
                                ctx.expression().primary().IDENTIFIER().getText() in self.object_name and ctx.IDENTIFIER().getText() == self.using_field_name):
                            self.token_stream_rewriter.replaceRange(
                                from_idx=ctx.start.tokenIndex,
                                to_idx=ctx.stop.tokenIndex,
                                text=ctx.expression().primary().IDENTIFIER().getText() + '.' + 'get' + str.capitalize(
                                    ctx.IDENTIFIER().getText()) + '()'
                            )
            # if ctx.expression() != None:
            #     print("ctx.getText()===============",ctx.getText())
            #     self.check_is_exprresion_obj_and_field(ctx)
    # TODO: Check or remove this comments
    # def enterVariableDeclarator(self, ctx: JavaParserLabeled.VariableDeclaratorContext):
    #     if self.action_to_do == "Set":
    #         return None
    #
    #     if not self.is_class:
    #         return None
    #
    #     grand_child_ctx = ctx.variableInitializer().expression()
    #     if (str(type(
    #             grand_child_ctx)) == "<class 'gen.javaLabeled.JavaParserLabeled.JavaParserLabeled.Expression1Context'>"):
    #         usingfieldidentifier = grand_child_ctx.IDENTIFIER().getText()
    #
    #         if usingfieldidentifier == self.using_field_name:
    #             objectidentifier = grand_child_ctx.expression().primary().IDENTIFIER().getText()
    #
    #             if objectidentifier in self.object_name:
    #                 self.token_stream_rewriter.replaceRange(
    #                     from_idx=grand_child_ctx.start.tokenIndex,
    #                     to_idx=grand_child_ctx.stop.tokenIndex,
    #                     text=grand_child_ctx.expression().primary().IDENTIFIER().getText() + '.' + 'get' + str.capitalize(
    #                         grand_child_ctx.IDENTIFIER().getText()) + '()'
    #                 )


class PropagationIncreaseFieldVisibilityGetObjectsRefactoringListener(JavaParserLabeledListener):
    def __init__(self, common_token_stream: CommonTokenStream = None, source_class=None,
                 propagated_class_name=None):
        """Used for propagation purposes in the other classes of the project:
           Detect the objects which have to be propagated

           Args:
                common_token_stream (CommonTokenStream): A stream of tokens generated by parsing the main file using the ANTLR parser generator

                source_class (str): Name of the class in which the propagation has to be implemented

                propagated_class_name (str): Name of the class which has to be propagated

           Returns: No returns
        """
        if source_class is None:
            self.source_class = []
        else:
            self.source_class = source_class

        if propagated_class_name is None:
            self.propagated_class_name = []
        else:
            self.propagated_class_name = propagated_class_name

        if common_token_stream is None:
            raise ValueError('common_token_stream is None')
        else:
            self.token_stream_rewriter = TokenStreamRewriter(common_token_stream)

        self.is_class = False
        self.current_class = ''
        self.objects = list()

    def enterClassDeclaration(self, ctx: JavaParserLabeled.ClassDeclarationContext):
        class_identifier = ctx.IDENTIFIER().getText()
        if class_identifier in self.propagated_class_name:
            self.is_class = True
            print("Propagation get object started, please wait...")
            self.current_class = class_identifier
        else:
            self.is_class = False

    def enterVariableDeclarator(self, ctx: JavaParserLabeled.VariableDeclaratorContext):
        if not self.is_class:
            return None
        grand_parent_ctx = ctx.parentCtx.parentCtx
        if grand_parent_ctx.typeType().classOrInterfaceType() is not None:
            class_name = grand_parent_ctx.typeType().classOrInterfaceType().IDENTIFIER(0).getText()
            if class_name in self.source_class:
                object_name = ctx.variableDeclaratorId().IDENTIFIER().getText()
                self.objects.append(object_name)


def main():
    print("Increase Field Visibility")

    # Note: If a class is not in a package -> package_name=(Unnamed_Package)

    udb_path = "/data/Dev/JavaSample/JavaSample.udb"
    package_name = "my_package"
    class_name = "Source"
    field_name = "number3"

    file_list_to_be_propagate = set()
    propagate_classes = set()
    file_list_to_be_propagate_for_setby = set()
    propagate_classes_for_setby = set()
    file_list_to_be_propagate_for_getby = set()
    propagate_classes_for_getby = set()

    file_list_include_file_name_that_edited = ""
    main_file = ""
    db = und.open(udb_path)
    # TODO: Check filter
    for field in db.ents("public variable"):

        if (str(field) == str(class_name + "." + field_name) and str(
                field.parent().ref("Java Containin").ent()) == package_name):

            print(field)
            if field.parent().parent().relname() is not None:
                main_file = field.parent().parent().longname(True)
                print("mainfile=", main_file)

            else:
                for ref in field.refs("Definein"):
                    main_file = (ref.file().longname())

            for ref in field.refs("Setby , Modifyby"):
                if not (str(ref.ent()) == str(field.parent())
                        or str(ref.ent().parent()) == str(field.parent())):
                    propagate_classes_for_setby.add(str(ref.ent().parent().simplename()))

                    file_list_to_be_propagate_for_setby.add(ref.file().longname(True))
            for ref in field.refs("Useby"):
                if not str(ref.ent()) == str(field.parent() or str(ref.ent().parent()) == str(field.parent())):
                    propagate_classes_for_getby.add(str(ref.ent().parent().simplename()))

                    file_list_to_be_propagate_for_getby.add(ref.file().longname(True))

    file_list_to_be_propagate = list(file_list_to_be_propagate)
    propagate_classes = list(propagate_classes)

    if main_file == "":
        print("main file not found!!!")
        return False

    stream = FileStream(main_file, encoding='utf8')
    # Step 2: Create an instance of AssignmentStLexer
    lexer = JavaLexer(stream)
    # Step 3: Convert the input source into a list of tokens
    token_stream = CommonTokenStream(lexer)
    # Step 4: Create an instance of the AssignmentStParser
    parser = JavaParserLabeled(token_stream)
    parser.getTokenStream()
    parse_tree = parser.compilationUnit()
    my_listener = IncreaseFieldVisibilityRefactoringListener(common_token_stream=token_stream,
                                                             source_class=class_name,
                                                             field_name=field_name)
    walker = ParseTreeWalker()
    walker.walk(t=parse_tree, listener=my_listener)
    print("my_listener is walked")
    # print(my_listener.token_stream_rewriter.getDefaultText())
    with open(main_file, mode='w', encoding="utf-8", newline='') as f:
        f.write(my_listener.token_stream_rewriter.getDefaultText())

    print("file_list_to_be_propagate:", file_list_to_be_propagate)

    for file in file_list_to_be_propagate_for_getby:
        print("file_list_to_be_propagate_for_Getby:", file)
        stream = FileStream(file, encoding='utf8')
        # input_stream = StdinStream()
        # Step 2: Create an instance of AssignmentStLexer
        lexer = JavaLexer(stream)
        # Step 3: Convert the input source into a list of tokens
        token_stream = CommonTokenStream(lexer)
        # Step 4: Create an instance of the AssignmentStParser
        parser = JavaParserLabeled(token_stream)
        parser.getTokenStream()
        parse_tree = parser.compilationUnit()
        my_listener_get_object = PropagationIncreaseFieldVisibilityGetObjectsRefactoringListener(token_stream,
                                                                                                 source_class=class_name,
                                                                                                 propagated_class_name=propagate_classes_for_getby)
        walker = ParseTreeWalker()
        walker.walk(t=parse_tree, listener=my_listener_get_object)
        print("my_listener_get_object.objects:", my_listener_get_object.objects)

        my_listener = PropagationIncreaseFieldVisibilityRefactoringListener(common_token_stream=token_stream,
                                                                            using_field_name=field_name,
                                                                            object_name=my_listener_get_object.objects,
                                                                            propagated_class_name=propagate_classes_for_getby,
                                                                            action_to_do="Get")
        walker = ParseTreeWalker()
        walker.walk(t=parse_tree, listener=my_listener)
        # print(my_listener.token_stream_rewriter.getDefaultText())
        with open(file, mode='w', encoding="utf-8", newline='') as f:
            f.write(my_listener.token_stream_rewriter.getDefaultText())

    for file in file_list_to_be_propagate_for_setby:
        print("file_list_to_be_propagate_for_setby:", file)
        stream = FileStream(file, encoding='utf8')
        # Step 2: Create an instance of AssignmentStLexer
        lexer = JavaLexer(stream)
        # Step 3: Convert the input source into a list of tokens
        token_stream = CommonTokenStream(lexer)
        # Step 4: Create an instance of the AssignmentStParser
        parser = JavaParserLabeled(token_stream)
        parser.getTokenStream()
        parse_tree = parser.compilationUnit()
        my_listener_get_object = PropagationIncreaseFieldVisibilityGetObjectsRefactoringListener(token_stream,
                                                                                                 source_class=class_name,
                                                                                                 propagated_class_name=propagate_classes_for_setby)
        walker = ParseTreeWalker()
        walker.walk(t=parse_tree, listener=my_listener_get_object)
        print("my_listener_get_object.objects:", my_listener_get_object.objects)

        my_listener = PropagationIncreaseFieldVisibilityRefactoringListener(common_token_stream=token_stream,
                                                                            using_field_name=field_name,
                                                                            object_name=my_listener_get_object.objects,
                                                                            propagated_class_name=propagate_classes_for_setby,
                                                                            action_to_do="Set")
        walker = ParseTreeWalker()
        walker.walk(t=parse_tree, listener=my_listener)
        with open(file, mode='w', encoding="utf-8", newline='') as f:
            f.write(my_listener.token_stream_rewriter.getDefaultText())


if __name__ == '__main__':
    main()

from gen.javaLabeled.JavaLexer import JavaLexer

try:
    import understand as und
except ImportError as e:
    print(e)

from antlr4 import *
from antlr4.TokenStreamRewriter import TokenStreamRewriter

from gen.javaLabeled.JavaParserLabeled import JavaParserLabeled
from gen.javaLabeled.JavaParserLabeledListener import JavaParserLabeledListener


class IncreaseFieldVisibilityRefactoringListener(JavaParserLabeledListener):
    """
    ## Introduction
    # TODO: Change name to decrease
    1. Private
    2. Protected
    3. Package (no modifier)
    4. Public

    Increase the visibility of a field from private to package, package to protected or protected to public.

    ## Pre and Post Conditions

    ### Pre Conditions:

    1. User must enter the field's name, and the source class's name for the refactoring
       in order to increase the target field's visibility.

    ### Post Conditions:

    No specific Post Condition
    """

    def __init__(self, common_token_stream: CommonTokenStream = None, source_class=None, field_name: str = None):
        """To implement Increase Field Visibility refactoring based on its actors.
           Detects the required field and increases/changes its visibility status.

           Args:
                common_token_stream (CommonTokenStream): A stream of tokens generated by parsing the main file using the ANTLR parser generator

                source_class (str): Name of the class in which the refactoring has to be done

                field_name (str): Name of the field whose visibility status has to be changed

           Returns:
                No returns
        """
        if field_name is None:
            self.field_name = ""
        else:
            self.field_name = field_name

        if source_class is None:
            self.source_class = ""
        else:
            self.source_class = source_class
        if common_token_stream is None:
            raise ValueError('common_token_stream is None')
        else:
            self.token_stream_rewriter = TokenStreamRewriter(common_token_stream)

        self.is_source_class = False
        self.detected_field = None
        self.detected_method = None
        self.TAB = "\t"
        self.NEW_LINE = "\n"
        self.code = ""
        self.temp_declaration_code = ""

    def enterClassDeclaration(self, ctx: JavaParserLabeled.ClassDeclarationContext):

        class_identifier = ctx.IDENTIFIER().getText()
        if class_identifier == self.source_class:
            self.is_source_class = True
        else:
            self.is_source_class = False

    def exitFieldDeclaration(self, ctx: JavaParserLabeled.FieldDeclarationContext):
        if not self.is_source_class:
            return None
        grand_parent_ctx = ctx.parentCtx.parentCtx
        # field_identifier = ctx.variableDeclarators().getText().split(",")
        field_identifier = ctx.variableDeclarators().variableDeclarator(0).variableDeclaratorId().IDENTIFIER().getText()
        if self.field_name in field_identifier:
            if not grand_parent_ctx.modifier():
                self.token_stream_rewriter.replaceRange(
                    from_idx=ctx.typeType().start.tokenIndex,
                    to_idx=ctx.typeType().stop.tokenIndex,
                    text='private ' + ctx.typeType().getText()
                )
            elif grand_parent_ctx.modifier(0).getText() == 'public':
                self.token_stream_rewriter.replaceRange(
                    from_idx=grand_parent_ctx.modifier(0).start.tokenIndex,
                    to_idx=grand_parent_ctx.modifier(0).stop.tokenIndex,
                    text='private')
            elif grand_parent_ctx.modifier(0).getText() != 'private':
                self.token_stream_rewriter.replaceRange(
                    from_idx=grand_parent_ctx.modifier(0).start.tokenIndex,
                    to_idx=grand_parent_ctx.modifier(0).stop.tokenIndex,
                    text='private ' + grand_parent_ctx.modifier(0).getText())
            # generate accessor and mutator methods
            # Accessor body
            new_code = '\n\t'
            new_code += 'public ' + ctx.typeType().getText() + ' get' + str.capitalize(self.field_name)
            new_code += '() { \n\t\t return this.' + self.field_name + ';' + '\n\t}'

            # Mutator body
            new_code += '\n\t'
            new_code += 'public void set' + str.capitalize(self.field_name)
            new_code += '(' + ctx.typeType().getText() + ' ' + self.field_name + ') { \n\t\t'
            new_code += 'this.' + self.field_name + ' = ' + self.field_name + ';' + '\n\t}\n'

            self.token_stream_rewriter.insertAfter(ctx.stop.tokenIndex, new_code)


class PropagationIncreaseFieldVisibilityRefactoringListener(JavaParserLabeledListener):
    def __init__(self, common_token_stream: CommonTokenStream = None, using_field_name=None, object_name=None,
                 propagated_class_name=None, action_to_do=None):
        """
        Used for propagation purposes in the other classes of the project: implement the propagation

        Args:
            common_token_stream (CommonTokenStream): A stream of tokens generated by parsing the main file using the ANTLR parser generator

            using_field_name (str): Name of the field which has to be propagated

            object_name (str): Name of the objects that need to be changed with the propagation operation

            propagated_class_name (str): Name of the class in which the propagation operation needs to be implemented

        Returns: No returns
        """

        if using_field_name is None:
            self.using_field_name = []
        else:
            self.using_field_name = using_field_name

        if action_to_do is None:
            self.action_to_do = []
        else:
            self.action_to_do = action_to_do

        if object_name is None:
            self.object_name = []
        else:
            self.object_name = object_name

        if propagated_class_name is None:
            self.propagated_class_name = []
        else:
            self.propagated_class_name = propagated_class_name

        if common_token_stream is None:
            raise ValueError('common_token_stream is None')
        else:
            self.token_stream_rewriter = TokenStreamRewriter(common_token_stream)

        self.is_class = False

    def enterClassDeclaration(self, ctx: JavaParserLabeled.ClassDeclarationContext):
        # print("Propagation started, please wait...")
        class_identifier = ctx.IDENTIFIER().getText()

        if class_identifier in self.propagated_class_name:
            self.is_class = True
            print("Propagation   started, please wait......")
        else:
            self.is_class = False

    def is_before_equal(self, parent_ctx):
        try:
            if str(type(
                    parent_ctx)) == "<class 'gen.javaLabeled.JavaParserLabeled.JavaParserLabeled.Expression21Context'>":
                if str(type(parent_ctx.children[
                                0])) == "<class 'gen.javaLabeled.JavaParserLabeled.JavaParserLabeled.Expression1Context'>":
                    return True
                return False
        except:
            return False

    def getoperator(self, str):
        return (str[0:1])

    def check_is_expression_obj_and_field(self, ctx):
        if str(ctx.children[0].getText()) in self.object_name and str(
                ctx.children[2].getText()) == self.using_field_name:
            return True
        else:
            return False
        # print(ctx.children[0].getText())
        # print(ctx.children[1].getText())
        # print(ctx.children[2].getText())

    def enterExpression1(self, ctx: JavaParserLabeled.Expression1Context):
        if not self.is_class: return
        parent_ctx = ctx.parentCtx;
        if self.is_before_equal(parent_ctx):

            # print("going to set")
            if self.action_to_do == "Get":
                return None
            # {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{

            if isinstance(parent_ctx, JavaParserLabeled.Expression21Context):
                # print("parent_ctx.children[1]:", str(parent_ctx.children[1]))
                if (str(parent_ctx.children[1]) in ["+=", "-=", "*=", "/=", "&=", "|=", "^=", ">>=", ">>>=", "<<=",
                                                    "%="]):
                    if self.action_to_do == "Get":
                        return None
                    if ctx.expression() is not None:
                        if ctx.expression().primary() is not None:
                            if ctx.expression().primary().IDENTIFIER().getText() in self.object_name:
                                parent_ctx = ctx.parentCtx
                                count = parent_ctx.getChildCount()
                                if count == 3:
                                    expression_text = parent_ctx.children[2].getText()

                                    self.token_stream_rewriter.replaceRange(
                                        from_idx=parent_ctx.start.tokenIndex,
                                        to_idx=parent_ctx.stop.tokenIndex,
                                        text=ctx.expression().primary().IDENTIFIER().getText() + '.' + 'set' + str.capitalize(
                                            ctx.IDENTIFIER().getText()) + '(' + ctx.expression().primary().IDENTIFIER().getText() + '.get' + str.capitalize(
                                            ctx.IDENTIFIER().getText()) + '() ' + self.getoperator(
                                            str(parent_ctx.children[1])) + "( " + expression_text + ') )'
                                    )
                                    return True

            # }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}

            if ctx.expression() is not None:
                if ctx.expression().primary() is not None:
                    if ctx.expression().primary().IDENTIFIER().getText() in self.object_name:
                        # print("ctx.expression().primary().IDENTIFIER().getText()=",ctx.expression().primary().IDENTIFIER().getText())
                        parent_ctx = ctx.parentCtx
                        count = parent_ctx.getChildCount()
                        if count == 3:
                            expression_text = parent_ctx.children[2].getText()

                            self.token_stream_rewriter.replaceRange(
                                from_idx=parent_ctx.start.tokenIndex,
                                to_idx=parent_ctx.stop.tokenIndex,
                                text=ctx.expression().primary().IDENTIFIER().getText() + '.' + 'set' + str.capitalize(
                                    ctx.IDENTIFIER().getText()) + '(' + expression_text + ')'
                            )
        else:  # expression is after =
            if self.action_to_do == "Set":
                return None
            if self.check_is_expression_obj_and_field(ctx):
                if ctx.expression() is not None:
                    if ctx.expression().primary() is not None:
                        if (
                                ctx.expression().primary().IDENTIFIER().getText() in self.object_name and ctx.IDENTIFIER().getText() == self.using_field_name):
                            self.token_stream_rewriter.replaceRange(
                                from_idx=ctx.start.tokenIndex,
                                to_idx=ctx.stop.tokenIndex,
                                text=ctx.expression().primary().IDENTIFIER().getText() + '.' + 'get' + str.capitalize(
                                    ctx.IDENTIFIER().getText()) + '()'
                            )
            # if ctx.expression() != None:
            #     print("ctx.getText()===============",ctx.getText())
            #     self.check_is_exprresion_obj_and_field(ctx)
    # TODO: Check or remove this comments
    # def enterVariableDeclarator(self, ctx: JavaParserLabeled.VariableDeclaratorContext):
    #     if self.action_to_do == "Set":
    #         return None
    #
    #     if not self.is_class:
    #         return None
    #
    #     grand_child_ctx = ctx.variableInitializer().expression()
    #     if (str(type(
    #             grand_child_ctx)) == "<class 'gen.javaLabeled.JavaParserLabeled.JavaParserLabeled.Expression1Context'>"):
    #         usingfieldidentifier = grand_child_ctx.IDENTIFIER().getText()
    #
    #         if usingfieldidentifier == self.using_field_name:
    #             objectidentifier = grand_child_ctx.expression().primary().IDENTIFIER().getText()
    #
    #             if objectidentifier in self.object_name:
    #                 self.token_stream_rewriter.replaceRange(
    #                     from_idx=grand_child_ctx.start.tokenIndex,
    #                     to_idx=grand_child_ctx.stop.tokenIndex,
    #                     text=grand_child_ctx.expression().primary().IDENTIFIER().getText() + '.' + 'get' + str.capitalize(
    #                         grand_child_ctx.IDENTIFIER().getText()) + '()'
    #                 )


class PropagationIncreaseFieldVisibilityGetObjectsRefactoringListener(JavaParserLabeledListener):
    def __init__(self, common_token_stream: CommonTokenStream = None, source_class=None,
                 propagated_class_name=None):
        """Used for propagation purposes in the other classes of the project:
           Detect the objects which have to be propagated

           Args:
                common_token_stream (CommonTokenStream): A stream of tokens generated by parsing the main file using the ANTLR parser generator

                source_class (str): Name of the class in which the propagation has to be implemented

                propagated_class_name (str): Name of the class which has to be propagated

           Returns: No returns
        """
        if source_class is None:
            self.source_class = []
        else:
            self.source_class = source_class

        if propagated_class_name is None:
            self.propagated_class_name = []
        else:
            self.propagated_class_name = propagated_class_name

        if common_token_stream is None:
            raise ValueError('common_token_stream is None')
        else:
            self.token_stream_rewriter = TokenStreamRewriter(common_token_stream)

        self.is_class = False
        self.current_class = ''
        self.objects = list()

    def enterClassDeclaration(self, ctx: JavaParserLabeled.ClassDeclarationContext):
        class_identifier = ctx.IDENTIFIER().getText()
        if class_identifier in self.propagated_class_name:
            self.is_class = True
            print("Propagation get object started, please wait...")
            self.current_class = class_identifier
        else:
            self.is_class = False

    def enterVariableDeclarator(self, ctx: JavaParserLabeled.VariableDeclaratorContext):
        if not self.is_class:
            return None
        grand_parent_ctx = ctx.parentCtx.parentCtx
        if grand_parent_ctx.typeType().classOrInterfaceType() is not None:
            class_name = grand_parent_ctx.typeType().classOrInterfaceType().IDENTIFIER(0).getText()
            if class_name in self.source_class:
                object_name = ctx.variableDeclaratorId().IDENTIFIER().getText()
                self.objects.append(object_name)


def main():
    print("Increase Field Visibility")

    # Note: If a class is not in a package -> package_name=(Unnamed_Package)

    udb_path = "/data/Dev/JavaSample/JavaSample.udb"
    package_name = "my_package"
    class_name = "Source"
    field_name = "number3"

    file_list_to_be_propagate = set()
    propagate_classes = set()
    file_list_to_be_propagate_for_setby = set()
    propagate_classes_for_setby = set()
    file_list_to_be_propagate_for_getby = set()
    propagate_classes_for_getby = set()

    file_list_include_file_name_that_edited = ""
    main_file = ""
    db = und.open(udb_path)
    # TODO: Check filter
    for field in db.ents("public variable"):

        if (str(field) == str(class_name + "." + field_name) and str(
                field.parent().ref("Java Containin").ent()) == package_name):

            print(field)
            if field.parent().parent().relname() is not None:
                main_file = field.parent().parent().longname(True)
                print("mainfile=", main_file)

            else:
                for ref in field.refs("Definein"):
                    main_file = (ref.file().longname())

            for ref in field.refs("Setby , Modifyby"):
                if not (str(ref.ent()) == str(field.parent())
                        or str(ref.ent().parent()) == str(field.parent())):
                    propagate_classes_for_setby.add(str(ref.ent().parent().simplename()))

                    file_list_to_be_propagate_for_setby.add(ref.file().longname(True))
            for ref in field.refs("Useby"):
                if not str(ref.ent()) == str(field.parent() or str(ref.ent().parent()) == str(field.parent())):
                    propagate_classes_for_getby.add(str(ref.ent().parent().simplename()))

                    file_list_to_be_propagate_for_getby.add(ref.file().longname(True))

    file_list_to_be_propagate = list(file_list_to_be_propagate)
    propagate_classes = list(propagate_classes)

    if main_file == "":
        print("main file not found!!!")
        return False

    stream = FileStream(main_file, encoding='utf8')
    # Step 2: Create an instance of AssignmentStLexer
    lexer = JavaLexer(stream)
    # Step 3: Convert the input source into a list of tokens
    token_stream = CommonTokenStream(lexer)
    # Step 4: Create an instance of the AssignmentStParser
    parser = JavaParserLabeled(token_stream)
    parser.getTokenStream()
    parse_tree = parser.compilationUnit()
    my_listener = IncreaseFieldVisibilityRefactoringListener(common_token_stream=token_stream,
                                                             source_class=class_name,
                                                             field_name=field_name)
    walker = ParseTreeWalker()
    walker.walk(t=parse_tree, listener=my_listener)
    print("my_listener is walked")
    # print(my_listener.token_stream_rewriter.getDefaultText())
    with open(main_file, mode='w', encoding="utf-8", newline='') as f:
        f.write(my_listener.token_stream_rewriter.getDefaultText())

    print("file_list_to_be_propagate:", file_list_to_be_propagate)

    for file in file_list_to_be_propagate_for_getby:
        print("file_list_to_be_propagate_for_Getby:", file)
        stream = FileStream(file, encoding='utf8')
        # input_stream = StdinStream()
        # Step 2: Create an instance of AssignmentStLexer
        lexer = JavaLexer(stream)
        # Step 3: Convert the input source into a list of tokens
        token_stream = CommonTokenStream(lexer)
        # Step 4: Create an instance of the AssignmentStParser
        parser = JavaParserLabeled(token_stream)
        parser.getTokenStream()
        parse_tree = parser.compilationUnit()
        my_listener_get_object = PropagationIncreaseFieldVisibilityGetObjectsRefactoringListener(token_stream,
                                                                                                 source_class=class_name,
                                                                                                 propagated_class_name=propagate_classes_for_getby)
        walker = ParseTreeWalker()
        walker.walk(t=parse_tree, listener=my_listener_get_object)
        print("my_listener_get_object.objects:", my_listener_get_object.objects)

        my_listener = PropagationIncreaseFieldVisibilityRefactoringListener(common_token_stream=token_stream,
                                                                            using_field_name=field_name,
                                                                            object_name=my_listener_get_object.objects,
                                                                            propagated_class_name=propagate_classes_for_getby,
                                                                            action_to_do="Get")
        walker = ParseTreeWalker()
        walker.walk(t=parse_tree, listener=my_listener)
        # print(my_listener.token_stream_rewriter.getDefaultText())
        with open(file, mode='w', encoding="utf-8", newline='') as f:
            f.write(my_listener.token_stream_rewriter.getDefaultText())

    for file in file_list_to_be_propagate_for_setby:
        print("file_list_to_be_propagate_for_setby:", file)
        stream = FileStream(file, encoding='utf8')
        # Step 2: Create an instance of AssignmentStLexer
        lexer = JavaLexer(stream)
        # Step 3: Convert the input source into a list of tokens
        token_stream = CommonTokenStream(lexer)
        # Step 4: Create an instance of the AssignmentStParser
        parser = JavaParserLabeled(token_stream)
        parser.getTokenStream()
        parse_tree = parser.compilationUnit()
        my_listener_get_object = PropagationIncreaseFieldVisibilityGetObjectsRefactoringListener(token_stream,
                                                                                                 source_class=class_name,
                                                                                                 propagated_class_name=propagate_classes_for_setby)
        walker = ParseTreeWalker()
        walker.walk(t=parse_tree, listener=my_listener_get_object)
        print("my_listener_get_object.objects:", my_listener_get_object.objects)

        my_listener = PropagationIncreaseFieldVisibilityRefactoringListener(common_token_stream=token_stream,
                                                                            using_field_name=field_name,
                                                                            object_name=my_listener_get_object.objects,
                                                                            propagated_class_name=propagate_classes_for_setby,
                                                                            action_to_do="Set")
        walker = ParseTreeWalker()
        walker.walk(t=parse_tree, listener=my_listener)
        with open(file, mode='w', encoding="utf-8", newline='') as f:
            f.write(my_listener.token_stream_rewriter.getDefaultText())


if __name__ == '__main__':
    main()

## Introduction     # TODO: Change name to decrease     1. Private     2. Protected     3. Package (no modifier)     4. Public      Increase the visibility of a field from private to package, package to protected or protected to public.      ## Pre and Post Conditions      ### Pre Conditions:      1. User must enter the field's name, and the source class's name for the refactoring        in order to increase the target field's visibility.      ### Post Conditions:      No specific Post Condition To implement Increase Field Visibility refactoring based on its actors.            Detects the required field and increases/changes its visibility status.             Args:                 common_token_stream (CommonTokenStream): A stream of tokens generated by parsing the main file using the ANTLR parser generator                  source_class (str): Name of the class in which the refactoring has to be done                  field_name (str): Name of the field whose visibility status has to be changed             Returns:                 No returns # field_identifier = ctx.variableDeclarators().getText().split(",") # generate accessor and mutator methods # Accessor body # Mutator body Used for propagation purposes in the other classes of the project: implement the propagation          Args:             common_token_stream (CommonTokenStream): A stream of tokens generated by parsing the main file using the ANTLR parser generator              using_field_name (str): Name of the field which has to be propagated              object_name (str): Name of the objects that need to be changed with the propagation operation              propagated_class_name (str): Name of the class in which the propagation operation needs to be implemented          Returns: No returns # print("Propagation started, please wait...") # print(ctx.children[0].getText()) # print(ctx.children[1].getText()) # print(ctx.children[2].getText()) # print("going to set") # {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ # print("parent_ctx.children[1]:", str(parent_ctx.children[1])) # }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} # print("ctx.expression().primary().IDENTIFIER().getText()=",ctx.expression().primary().IDENTIFIER().getText()) # expression is after = # if ctx.expression() != None: #     print("ctx.getText()===============",ctx.getText()) #     self.check_is_exprresion_obj_and_field(ctx) # TODO: Check or remove this comments # def enterVariableDeclarator(self, ctx: JavaParserLabeled.VariableDeclaratorContext): #     if self.action_to_do == "Set": #         return None # #     if not self.is_class: #         return None # #     grand_child_ctx = ctx.variableInitializer().expression() #     if (str(type( #             grand_child_ctx)) == "<class 'gen.javaLabeled.JavaParserLabeled.JavaParserLabeled.Expression1Context'>"): #         usingfieldidentifier = grand_child_ctx.IDENTIFIER().getText() # #         if usingfieldidentifier == self.using_field_name: #             objectidentifier = grand_child_ctx.expression().primary().IDENTIFIER().getText() # #             if objectidentifier in self.object_name: #                 self.token_stream_rewriter.replaceRange( #                     from_idx=grand_child_ctx.start.tokenIndex, #                     to_idx=grand_child_ctx.stop.tokenIndex, #                     text=grand_child_ctx.expression().primary().IDENTIFIER().getText() + '.' + 'get' + str.capitalize( #                         grand_child_ctx.IDENTIFIER().getText()) + '()' #                 ) Used for propagation purposes in the other classes of the project:            Detect the objects which have to be propagated             Args:                 common_token_stream (CommonTokenStream): A stream of tokens generated by parsing the main file using the ANTLR parser generator                  source_class (str): Name of the class in which the propagation has to be implemented                  propagated_class_name (str): Name of the class which has to be propagated             Returns: No returns # Note: If a class is not in a package -> package_name=(Unnamed_Package) # TODO: Check filter # Step 2: Create an instance of AssignmentStLexer # Step 3: Convert the input source into a list of tokens # Step 4: Create an instance of the AssignmentStParser # print(my_listener.token_stream_rewriter.getDefaultText()) # input_stream = StdinStream() # Step 2: Create an instance of AssignmentStLexer # Step 3: Convert the input source into a list of tokens # Step 4: Create an instance of the AssignmentStParser # print(my_listener.token_stream_rewriter.getDefaultText()) # Step 2: Create an instance of AssignmentStLexer # Step 3: Convert the input source into a list of tokens # Step 4: Create an instance of the AssignmentStParser