segunda-feira, 24 de agosto de 2009

JSP e Oracle - Para apresentar uma Treeview

Olá pessoal!

Dando manutenção em um sistema java web com interface jsp precisei usar uma treeview para apresentar as categorias de produtos para o usuário. Vou relatar aqui a experiência.


As categorias estão modeladas no banco em uma tabela com autorelacionamento.



No oracle para consultar uma table com autorelacionamento podemos utilizar a seguinte query:

select id, LEVEL, SYS_CONNECT_BY_PATH(nome, '@') as caminho
from categoria CONNECT BY parent_id = PRIOR id START WITH id = categoria_inicial


A categoria_inicial é a primeira categoria de uma árvore, nesse sistemas existem várias árvores de categorias.

O resultado fica assim para a categoria_inicial igual a 30:
id  level caminho
30  1     @Material de escritório
31  2     @Material de escritório@Informática
34  3     @Material de escritório@Informática@Tinta
55  4     @Material de escritório@Informática@Tinta@Tinta Impressoras
60  3     @Material de escritório@Informática@Armazenamento
63  4     @Material de escritório@Informática@Armazenamento@DAT/DLT/DVD/DDS
64  4     @Material de escritório@Informática@Armazenamento@Disquetes
92  3     @Material de escritório@Informática@Teste
93  4     @Material de escritório@Informática@Teste@Teste1
113 4     @Material de escritório@Informática@Teste@Teste2
120 4     @Material de escritório@Informática@Teste@Test3

Ai no java criei uma classe para representar a estrutura da categoria, ficou assim:
public class CategoriaTreeView {
 public String id;
 public int level;
 public String path;

 public CategoriaTreeView(String id, int level, String path){
  this.id = id;
  this.level = level;
  this.path = path;
 }
}


Como essa classe vai ser utilizada somente como uma estrutura de dados para representar o dado que será exibido na tela ela não tem gets e sets. Nem toda classe java precisa ter gets e sets. Gets e sets aqui são desnecessários e não acresentam nada. Acredite. Mas isso é assunto para outro post.

Também tenho um DAO que acessa o banco e entrega um List com os objetos CategoriaTreeView.

Antes disso fiz uma pesquisa na internet sobre como criar uma treeview no jsp (ou html) e encontrei o jQuery plugin: Treeview que transforma uma lista não ordenada do html <ul> em uma árvore.

Agora o problema é transformar a minha coleção de CategoriaTreeView em uma lista não ordenada com <ul> e <li>. Para isso eu criei a seguinte função recursiva que retorna uma String que será utilizada dentro do html:

private String processa(int atual, List<CategoriaTreeView> lista){
 if(lista == null) return "";
 String out = "";
 if(lista.size() == 0) {
  if(atual > 0){
   out += "</li>\n";
   out += "</ul>\n";
   out += processa(atual - 1, lista);
  }
 }else if(lista.size()>0){
  CategoriaTreeView item = lista.remove(0);
  if(item.level == atual){
   out += "</li>\n";
   out += "<li><span>" + subString(item.level, item.path) + "</span>\n";
   out += processa(item.level, lista);
  }else if(item.level > atual){
   out += "<ul>\n";
   out += "<li><span>" + subString(item.level, item.path) + "</span>\n";
   out += processa(item.level, lista);
  }else if(item.level < atual){
   out += "</li>\n";
   out += "</ul>\n";
   // adiciono o cara de volta na lista pois ainda não foi processado. estou voltando um nivel na árvore.
   lista.add(0, item);
   out += processa(atual - 1, lista);
  }
 }
 return out;
}

Também temos a função para retornar a categoria de dentro do caminho:

private String subString(int i, String s){
 String[] ss = s.split("@");
 return ss[i];
}


Dentro do meu servlet eu tenho o seguinte código:
ArrayList categorias = dao.categorias(categoria_inicial);
String treeView = processa(0, categorias);
treeView = treeView.replaceFirst("<ul>", "<ul id=\"browser\">");
request.setAttribute("treeView", treeView);

Para exibir a treeview no jsp eu utilizei o exemplo simple.html que vem no download do jQuery plugin: Treeview. A única mudança foi que eu fiz o download do jquery ao invés de usar o link direto do ajax.googleapis.com.

Adicionei o seguinte ao jsp:

<link rel="stylesheet" href="../jquery.treeview.css" />
<link rel="stylesheet" href="../red-treeview.css" />
<link rel="stylesheet" href="screen.css" />

<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
<script src="../lib/jquery.cookie.js" type="text/javascript"></script>
<script src="../jquery.treeview.js" type="text/javascript"></script>

<script type="text/javascript">
$(document).ready(function(){
 $("#browser").treeview({control: "#treecontrol", animated:"normal", persist: "cookie"});
});
</script>

<%
String s = (String)request.getAttribute("treeView");
if(s != null && !s.trim().equals("")){
%>
<tr>
 <td>
 <br>
  <div id="treecontrol">
   <a title="Collapse the entire tree below" href="#">Fechar Tudo</a>
   <a title="Expand the entire tree below" href="#">Abrir Tudo</a>
  </div>

 </td>
</tr>
<tr>
 <td>
 <br>
 <div><%= s %></div>
 </td>
</tr>
<%
}
%>


O resultado fica parecido com esse demo que está no site.



Abraços, Rodrigo Alencar.

Um comentário:

 
BlogBlogs.Com.Br