Mount recursive function for Treetable

Asked

Viewed 146 times

0

I’m trying to build a tree of folders and questions with Java, Jsf and Primefaces. I have two lists, one is the one that saves the folders and subfolders, and another list is the one that assembles the questions of these folders or subfolders. Follows image of how this mounted up to the moment. inserir a descrição da imagem aqui

In the folder outside, if selected, the folder is saved to the root, as shown in the image. In the column actions I have another folder icon, and a question icon that if clicked is added a question inside the line that was clicked.It follows methods that I was able to mount until the moment to mount the recursion. If anyone could shed some light on how to ride I’d be grateful.

public TreeNode montaTreeNode() {

    TreeNode pasta = null;
    TreeNode root = new DefaultTreeNode(new BancoPerguntaView(null, null, null), null);

    if(this.listaBancoPasta != null || !this.listaBancoPasta.isEmpty()){

        try {

            for (BancoPastas bdPasta : this.listaBancoPasta) {

                pasta = new DefaultTreeNode(new BancoPerguntaView(bdPasta.getIdBancoPasta(), bdPasta.getNomePasta(), bdPasta.getTipoPasta()), root);

                this.adicionarFilhos(pasta, bdPasta, null);

            }

        } catch (Exception e) {
            System.out.println("Erro treeNode: " + e.getMessage());
        }
    }

    return root;
}

public void adicionarFilhos(TreeNode nodePai, BancoPastas bdPasta, BancoPerguntas pergunta) {

    if(this.listaBancoPerguntas!= null || !this.listaBancoPerguntas.isEmpty()){

        try {

            for (BancoPerguntas bdPergunta : this.listaBancoPerguntas) {

                TreeNode nodeFilho = new DefaultTreeNode(new BancoPerguntaView(bdPergunta.getFkIdPasta(), bdPergunta.getNomePergunta(), bdPergunta.getTipoPergunta()), nodePai);

                this.adicionarFilhos(nodeFilho, null , bdPergunta);
            }

        } catch (Exception e) {
            System.out.println("Erro adicionarFilhos: " + e.getMessage());
        }
    }
}

But when I click to add a subfolder or a question, loop the line that calls the recursion

this.adicionarFilhos(nodeFilho, null , bdPergunta);

Subfolders going to the root, instead of entering the parent folder

inserir a descrição da imagem aqui

Follow refactored methods as suggested by Weslley

public TreeNode montaTreeNode() {

    TreeNode pasta = null;
    TreeNode root = new DefaultTreeNode(new BancoPerguntaView(null, null, null), null);

    if (this.listaBancoPasta != null || !this.listaBancoPasta.isEmpty()) {

        try {

            for (BancoPastas bdPasta : this.listaBancoPasta) {

                pasta = new DefaultTreeNode(new BancoPerguntaView(bdPasta.getIdBancoPasta(), bdPasta.getNomePasta(), bdPasta.getTipoPasta()), root);

                this.adicionarFilhos(pasta, bdPasta, null);

            }

        } catch (Exception e) {
            System.out.println("Erro treeNode: " + e.getMessage());
        }
    }

    return root;

}

public void adicionarFilhos(TreeNode nodePai, BancoPastas bdPasta, List<BancoPerguntas> perguntas) {

    if (Objects.nonNull(perguntas) && !perguntas.isEmpty()) {

        BancoPerguntas bdPergunta = perguntas.get(0);

        perguntas.remove(bdPergunta); 

        for (BancoPerguntas pergunta : perguntas) {

            TreeNode nodeFilho = new DefaultTreeNode(new BancoPerguntaView(pergunta.getFkIdPasta(), pergunta.getNomePergunta(), pergunta.getTipoPergunta()), nodePai);

            this.adicionarFilhos(nodeFilho, null, perguntas);
        }
    }
}

1 answer

1

Your problem is occurring due to the use of the parameter listaBancoPerguntas in his for.

Note that every time you enter the call from the stretch:

for (BancoPerguntas bdPergunta : this.listaBancoPerguntas) {
    TreeNode nodeFilho = new DefaultTreeNode(new BancoPerguntaView(bdPergunta.getFkIdPasta(), bdPergunta.getNomePergunta(), bdPergunta.getTipoPergunta()), nodePai);
    this.adicionarFilhos(nodeFilho, null , bdPergunta);
}

your code will return to the same state as before, since the list has not undergone any changes yet.

One of the possible solutions would be to pass the list itself as a parameter for calling your method adicionarFilhos() and perform the validation (removal of current record perhaps?) necessary to eliminate the loop infinite in its code.

Correction proposal

One possibility would be to refactor your method to:

public void adicionarFilhos(TreeNode nodePai, BancoPastas bdPasta, List<BancoPerguntas> perguntas) {
    if (Objects.nonNull(perguntas) && !perguntas.isEmpty()) {
        BancoPerguntas bdPergunta = perguntas.get(0);
        perguntas.remove(bdPergunta); // Assumindo que a classe BancoPerguntas implementa o equals(). Caso não implemente, utilize o índice, que será o 0
        for (BancoPerguntas bdPergunta : perguntas) {
            TreeNode nodeFilho = new DefaultTreeNode(new BancoPerguntaView(bdPergunta.getFkIdPasta(), bdPergunta.getNomePergunta(), bdPergunta.getTipoPergunta()), nodePai);
            this.adicionarFilhos(nodeFilho, null , perguntas);
        }
    }
}
  • Weslley, passing as parameter the entire list Oce says? or only bdPergunta that is the option of the moment? and the validation that Voce is talking about is verifying what exactly?

  • 1

    Your problem is using the list listaBancoPerguntas as a parameter in your repeat loop. Note that if you use a class parameter within a recursive method and use this attribute for control in your recursion, the infinite loop probability is enormous (which is your case). To avoid this behavior, your method adicionarFilhos() shall use a method domain parameter. And the validation would be related to the current state of its implementation, since at no point does the list change (a removal, for example).

  • 1

    I edited the answer to include a correction proposal. It solves the problem with the loop, now need to validate if it is suitable to your business rule.

  • Weslley, I’ve refactored the code on your instructions. When adding a folder to the root, it is adding correctly, but when trying to add a subfolder, it goes to the root, not into the parent folder. I edited the publication by placing the modifications as indicated. Detail that if I try to add a question, it is not taking any action, and does not generate any error too

  • Now it gets a little more complex to help, since I can’t simulate the scenario without all the flow of your application. Another thing that made me curious was the use of the parameter BancoPastas bdPasta in his method adicionarFilhos, and it has no function at all in the.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.