Busca recursiva e geração de menus dinâmicos HTML

Meus Caros,

estou atualmente portando uma aplicação PHP para JavaEE utilizando Vraptor + Hibernate como framework.
Como sou ainda iniciante no framework Hibernate, não estou encontrando uma saída para a geração de um menu dinâmico. Em PHP fiz uma função recursiva, que hoje atende muito bem, porem, na nova plataforma (como as entidades estão sendo carregadas automáticas - LAZY) estou tendo algumas dificuldades.

Segue a entidade Menu, o relacional é muito simples, muito pra muitos Perfil -> Menu. Na entidade Menu há uma ressalva, há uma ligação recursiva ID -> IDREF, onde o primeiro nível (raiz) representa por valor 0:

Menu.java

package br.com.internetsistemas.nucleo.model.entity;

import java.io.Serializable;
import javax.persistence.*;

/**
 * Entidade com os menus, submenus e páginas linkadas com o controller.
 */
@Entity
@org.hibernate.annotations.Proxy(lazy=false)
@Table(name="Menu")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class Menu implements Serializable {
	private static final long serialVersionUID = 1L;

	@Column(name="ID", nullable=false)	
	@Id	
	@GeneratedValue(generator="V7F00010112B65A686FC0112F")	
	@org.hibernate.annotations.GenericGenerator(name="V7F00010112B65A686FC0112F", strategy="identity")	
	private int ID;
	
	@Column(name="nome", nullable=false, length=255)	
	private String nome;
	
	@Column(name="tipo", nullable=false, length=30)	
	@Enumerated(EnumType.STRING)
	private MenuType tipo;
	
	@Column(name="icone", nullable=true, length=100)	
	private String icone;
	
	@Column(name="url", nullable=true, length=100)	
	private String url;
	
	@Column(name="ordem", nullable=false, length=10)	
	private int ordem;
	
	@Column(name="ativo", nullable=false, length=1)	
	private boolean ativo;
	
	@Column(name="idRef", nullable=true, length=10)	
	private Integer idRef;
	
	@OneToOne(targetEntity=br.com.internetsistemas.nucleo.model.entity.Permissao.class)	
	@org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.LOCK})	
	@JoinColumns({ @JoinColumn(name="PermissaoID") })	
	@Basic(fetch=FetchType.LAZY)	
	private br.com.internetsistemas.nucleo.model.entity.Permissao permissao;
	
	@ManyToMany(mappedBy="menu", targetEntity=br.com.internetsistemas.nucleo.model.entity.Perfil.class)	
	@org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.LOCK})	
	@org.hibernate.annotations.LazyCollection(org.hibernate.annotations.LazyCollectionOption.EXTRA)	
	private java.util.Set<br.com.internetsistemas.nucleo.model.entity.Perfil> perfil = new java.util.HashSet<br.com.internetsistemas.nucleo.model.entity.Perfil>();
	
	public void setID(int value) {
		this.ID = value;
	}
	
	public int getID() {
		return ID;
	}
	
	public int getORMID() {
		return getID();
	}
	
	public void setNome(String value) {
		this.nome = value;
	}
	
	public String getNome() {
		return nome;
	}
	
	public void setTipo(MenuType value) {
		this.tipo = value;
	}
	
	public MenuType getTipo() {
		return tipo;
	}
	
	public void setIcone(String value) {
		this.icone = value;
	}
	
	public String getIcone() {
		return icone;
	}
	
	public void setUrl(String value) {
		this.url = value;
	}
	
	public String getUrl() {
		return url;
	}
	
	public void setAtivo(boolean value) {
		this.ativo = value;
	}
	
	public boolean getAtivo() {
		return ativo;
	}
	
	public void setIdRef(int value) {
		setIdRef(new Integer(value));
	}
	
	public void setIdRef(Integer value) {
		this.idRef = value;
	}
	
	public Integer getIdRef() {
		return idRef;
	}
	
	public void setOrdem(int value) {
		this.ordem = value;
	}
	
	public int getOrdem() {
		return ordem;
	}
	
	public void setPerfil(java.util.Set<br.com.internetsistemas.nucleo.model.entity.Perfil> value) {
		this.perfil = value;
	}
	
	public java.util.Set<br.com.internetsistemas.nucleo.model.entity.Perfil> getPerfil() {
		return perfil;
	}
	
	
	public void setPermissao(br.com.internetsistemas.nucleo.model.entity.Permissao value) {
		this.permissao = value;
	}
	
	public br.com.internetsistemas.nucleo.model.entity.Permissao getPermissao() {
		return permissao;
	}
	
	public String toString() {
		return toString(false);
	}
	
	public String toString(boolean idOnly) {
		if (idOnly) {
			return String.valueOf(getID());
		}
		else {
			StringBuffer sb = new StringBuffer();
			sb.append("Menu[ ");
			sb.append("ID=").append(getID()).append(" ");
			sb.append("Nome=").append(getNome()).append(" ");
			sb.append("Tipo=").append(getTipo()).append(" ");
			sb.append("Icone=").append(getIcone()).append(" ");
			sb.append("Url=").append(getUrl()).append(" ");
			sb.append("Ordem=").append(getOrdem()).append(" ");
			sb.append("Ativo=").append(getAtivo()).append(" ");
			sb.append("IdRef=").append(getIdRef()).append(" ");
			if (getPermissao() != null)
				sb.append("Permissao.Persist_ID=").append(getPermissao().toString(true)).append(" ");
			else
				sb.append("Permissao=null ");
			sb.append("Perfil.size=").append(getPerfil().size()).append(" ");
			sb.append("]");
			return sb.toString();
		}
	}
	
}

Pelo código abaixo até consigo retornar todos os menus, porem fica “complicado” fazer a recursão, pois todos os dados já estão carregados no List e fazer um filtro por IF fica “estranho”, pelo próprio motivo da ligação recursiva na entidade Menu:

UsuarioServiceImpl.java

@Override
	public String calcularMenu(Usuario usuario) {
		Perfil perfil = usuario.getPerfil();
		
	
		if(perfil != null)
		{
			for (Menu menu : new ArrayList<Menu>(perfil.getMenu())) {
				System.out.println(menu);
			}
		}
		
		// retorna o menu fixo por enquanto
		return "<ul class=\"menuh\"><li class=\"menuv\"><a href=\"home\">Home</a></li><li class=\"menuv\"><a href=\"#\">Administração</a><ul class=\"menu\"><li class=\"topo\"></li><li class=\"menu\"><a href=\"cad_categorias.php\">Categorias</a></li><li class=\"menu\"><a href=\"index.php\">Produtos</a></li></ul></li></ul>";
	}

Só para vocês entenderem um pouco da função implementada em PHP que estou utilizando no outro sistema (aqui a tabela paginas são os menus):

menu.php

/**

 * Imprime o menu de topo de acordo com o perfil do usuário logado.

 *

 * @todo Alterar para carregar na session.

 * 

 * @param int $cod Código inicial do menu pai

 */

function imprimir_menu_topo ($cod)

{

    $SqlBuscaPaginas = "SELECT * FROM paginas p INNER JOIN paginas_perfis pg ON (p.cod_paginas = pg.cod_paginas) WHERE p.cod_paginas_pai = $cod AND p.habilitado = TRUE AND pg.cod_perfis = " . $cod_perfil_usuario_logado . " ORDER BY ordem, menu";

    $resBuscaPaginas = mysql_query($SqlBuscaPaginas);

    

    while ($objBuscaPaginas = mysql_fetch_object($resBuscaPaginas))

    {

        if ($objBuscaPaginas->tipo == 'MENU')

        {

            if ($objBuscaPaginas->menu != 'Sistema')

            {

                echo '<li class="menuvertical lado">' . "\n";

            }

            else

            {

                echo '<li class="menuvertical">' . "\n";

            }

            

            echo '<a href="#">' . $objBuscaPaginas->menu . '</a>' . "\n";

            echo '<ul class="menu">' . "\n";

        }

        else if ($objBuscaPaginas->tipo == 'SUBMENU')

        {

            echo '<li class="submenu">' . "\n";

            echo '<a href="#">' . $objBuscaPaginas->menu . '</a>' . "\n";

            echo '<ul>' . "\n";

        }

        else

        {

            echo '<li class="menu"><a href="' . $objBuscaPaginas->arquivo . '">' . $objBuscaPaginas->menu . '</a></li>' . "\n";

        }

        

        imprimir_menu_topo($objBuscaPaginas->cod_paginas);

        

        if ($objBuscaPaginas->tipo != 'PAGINA')

        {

            echo '</ul>' . "\n";

            echo '</li>' . "\n";

        }

    }

}



$conexao = conectar_bd();

imprimir_menu_topo(0);

desconectar_bd($conexao);

Se vocês tiverem sugestões com outra abordagem serão bem vindas. Já pensei até em grafo (juro! rs), mas visto a “simplicidade” do problema deixei um pouco de lado.

Abraço a todos!

Oi ffontouras,

Está complicado montar o menu pq vc muda a estrutura dele. Enquanto um menu de verdade está estruturado como uma árvore, você está usando uma lista para representá-lo :frowning:
Seu código está um pouco confuso tbm… Teria como vc mostrar apenas as partes relevantes? Precisava ver a entidade Usuario, Menu, Perfil, o método getMenu que você utiliza e assim por diante.
Fazer a montagem do menu recursivamente não é difícil, mas preciso dar uma olhada melhor no que você já fez.
Se puder dar uma comentada no código tbm, facilita.

[]´s

Oi David!

Primeiramente obrigado pela sua resposta! Realmente, acredito que eu tenha sido muito sucinto na apresentação do código.

Sobre a montagem do código menu realmente não é difícil, tanto é que na função PHP acima isso é feito em poucas linhas, e sem utilizar nenhuma estrutura de armazenamento intermediária, eu só estou me perdendo um pouco na maneira Hibernate de pensar (retorno de listas das entidades).

Sobre a lista, estou recuperando como Lista porque são os métodos possíveis (get) que a Entidade me permite. E que terei que utilizar para depois programar os CRUDs.

Segue códigos das entidades Usuario, Perfil e Menu respectivamente:

Usuario.java

package br.com.internetsistemas.nucleo.model.entity;

import java.io.Serializable;
import javax.persistence.*;
/**
 * Entidade de usuários do sistema.
 */
@Entity
@org.hibernate.annotations.Proxy(lazy=false)
@Table(name="Usuario")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class Usuario implements Serializable {
	private static final long serialVersionUID = 1L;

	@Column(name="ID", nullable=false)	
	@Id	
	@GeneratedValue(generator="V7F00010112B65A686F00112C")	
	@org.hibernate.annotations.GenericGenerator(name="V7F00010112B65A686F00112C", strategy="identity")	
	private int ID;
	
	@Column(name="login", nullable=false, unique=true, length=30)	
	private String login;
	
	@Column(name="senha", nullable=false, length=65)	
	private String senha;
	
	@Column(name="email", nullable=true, length=100)	
	private String email;
	
	@Column(name="ultimoLogin", nullable=true)	
	private java.sql.Timestamp ultimoLogin;
	
	@Column(name="admin", nullable=false, length=1)	
	private boolean admin;
	
	@Column(name="ativo", nullable=false, length=1)	
	private boolean ativo;
	
	@ManyToOne(targetEntity=br.com.internetsistemas.nucleo.model.entity.Perfil.class)	
	@org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.LOCK})	
	@JoinColumns({ @JoinColumn(name="PerfilID", referencedColumnName="ID") })	
	@Basic(fetch=FetchType.LAZY)	
	private br.com.internetsistemas.nucleo.model.entity.Perfil perfil;
	
	public void setID(int value) {
		this.ID = value;
	}
	
	public int getID() {
		return ID;
	}
	
	public int getORMID() {
		return getID();
	}
	
	public void setLogin(String value) {
		this.login = value;
	}
	
	public String getLogin() {
		return login;
	}
	
	public void setSenha(String value) {
		this.senha = value;
	}
	
	public String getSenha() {
		return senha;
	}
	
	public void setEmail(String value) {
		this.email = value;
	}
	
	public String getEmail() {
		return email;
	}
	
	public void setUltimoLogin(java.sql.Timestamp value) {
		this.ultimoLogin = value;
	}
	
	public java.sql.Timestamp getUltimoLogin() {
		return ultimoLogin;
	}
	
	public void setAdmin(boolean value) {
		this.admin = value;
	}
	
	public boolean getAdmin() {
		return admin;
	}
	
	public void setAtivo(boolean value) {
		this.ativo = value;
	}
	
	public boolean getAtivo() {
		return ativo;
	}
	
	public void setPerfil(br.com.internetsistemas.nucleo.model.entity.Perfil value) {
		this.perfil = value;
	}
	
	public br.com.internetsistemas.nucleo.model.entity.Perfil getPerfil() {
		return perfil;
	}
	
	public String toString() {
		return toString(false);
	}
	
	public String toString(boolean idOnly) {
		if (idOnly) {
			return String.valueOf(getID());
		}
		else {
			StringBuffer sb = new StringBuffer();
			sb.append("Usuario[ ");
			sb.append("ID=").append(getID()).append(" ");
			sb.append("Login=").append(getLogin()).append(" ");
			sb.append("Senha=").append(getSenha()).append(" ");
			sb.append("Email=").append(getEmail()).append(" ");
			sb.append("UltimoLogin=").append(getUltimoLogin()).append(" ");
			sb.append("Admin=").append(getAdmin()).append(" ");
			sb.append("Ativo=").append(getAtivo()).append(" ");
			if (getPerfil() != null)
				sb.append("Perfil.Persist_ID=").append(getPerfil().toString(true)).append(" ");
			else
				sb.append("Perfil=null ");
			sb.append("]");
			return sb.toString();
		}
	}
	
}

Perfil.java

package br.com.internetsistemas.nucleo.model.entity;

import java.io.Serializable;
import javax.persistence.*;
/**
 * Entidade de perfil de usuários.
 */
@Entity
@org.hibernate.annotations.Proxy(lazy=false)
@Table(name="Perfil")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class Perfil implements Serializable {
	private static final long serialVersionUID = 1L;

	@Column(name="ID", nullable=false)	
	@Id	
	@GeneratedValue(generator="V7F00010112B65A686F70112D")	
	@org.hibernate.annotations.GenericGenerator(name="V7F00010112B65A686F70112D", strategy="identity")	
	private int ID;
	
	@Column(name="nome", nullable=false, length=45)	
	private String nome;
	
	@ManyToMany(targetEntity=br.com.internetsistemas.nucleo.model.entity.Permissao.class)	
	@org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.LOCK})	
	@JoinTable(name="Perfil_Permissao", joinColumns={ @JoinColumn(name="PerfilID") }, inverseJoinColumns={ @JoinColumn(name="PermissaoID") })	
	@org.hibernate.annotations.LazyCollection(org.hibernate.annotations.LazyCollectionOption.EXTRA)	
	private java.util.Set<br.com.internetsistemas.nucleo.model.entity.Permissao> permissao = new java.util.HashSet<br.com.internetsistemas.nucleo.model.entity.Permissao>();
	
	@ManyToMany(targetEntity=br.com.internetsistemas.nucleo.model.entity.Menu.class)	
	@org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.LOCK})	
	@JoinTable(name="Perfil_Menu", joinColumns={ @JoinColumn(name="PerfilID") }, inverseJoinColumns={ @JoinColumn(name="MenuID") })	
	@org.hibernate.annotations.LazyCollection(org.hibernate.annotations.LazyCollectionOption.EXTRA)	
	private java.util.Set<br.com.internetsistemas.nucleo.model.entity.Menu> menu = new java.util.HashSet<br.com.internetsistemas.nucleo.model.entity.Menu>();
	
	@OneToMany(mappedBy="perfil", targetEntity=br.com.internetsistemas.nucleo.model.entity.Usuario.class)	
	@org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.LOCK})	
	@org.hibernate.annotations.LazyCollection(org.hibernate.annotations.LazyCollectionOption.EXTRA)	
	private java.util.Set<br.com.internetsistemas.nucleo.model.entity.Usuario> usuario = new java.util.HashSet<br.com.internetsistemas.nucleo.model.entity.Usuario>();
	
	public void setID(int value) {
		this.ID = value;
	}
	
	public int getID() {
		return ID;
	}
	
	public int getORMID() {
		return getID();
	}
	
	public void setNome(String value) {
		this.nome = value;
	}
	
	public String getNome() {
		return nome;
	}
	
	public void setPermissao(java.util.Set<br.com.internetsistemas.nucleo.model.entity.Permissao> value) {
		this.permissao = value;
	}
	
	public java.util.Set<br.com.internetsistemas.nucleo.model.entity.Permissao> getPermissao() {
		return permissao;
	}
	
	
	public void setMenu(java.util.Set<br.com.internetsistemas.nucleo.model.entity.Menu> value) {
		this.menu = value;
	}
	
	public java.util.Set<br.com.internetsistemas.nucleo.model.entity.Menu> getMenu() {
		return menu;
	}
	
	
	public void setUsuario(java.util.Set<br.com.internetsistemas.nucleo.model.entity.Usuario> value) {
		this.usuario = value;
	}
	
	public java.util.Set<br.com.internetsistemas.nucleo.model.entity.Usuario> getUsuario() {
		return usuario;
	}
	
	
	public String toString() {
		return toString(false);
	}
	
	public String toString(boolean idOnly) {
		if (idOnly) {
			return String.valueOf(getID());
		}
		else {
			StringBuffer sb = new StringBuffer();
			sb.append("Perfil[ ");
			sb.append("ID=").append(getID()).append(" ");
			sb.append("Nome=").append(getNome()).append(" ");
			sb.append("Permissao.size=").append(getPermissao().size()).append(" ");
			sb.append("Menu.size=").append(getMenu().size()).append(" ");
			sb.append("Usuario.size=").append(getUsuario().size()).append(" ");
			sb.append("]");
			return sb.toString();
		}
	}
	
}

Menu.java

package br.com.internetsistemas.nucleo.model.entity;

import java.io.Serializable;
import javax.persistence.*;

/**
 * Entidade com os menus, submenus e páginas linkadas com o controller.
 */
@Entity
@org.hibernate.annotations.Proxy(lazy=false)
@Table(name="Menu")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class Menu implements Serializable {
	private static final long serialVersionUID = 1L;

	@Column(name="ID", nullable=false)	
	@Id	
	@GeneratedValue(generator="V7F00010112B65A686FC0112F")	
	@org.hibernate.annotations.GenericGenerator(name="V7F00010112B65A686FC0112F", strategy="identity")	
	private int ID;
	
	@Column(name="nome", nullable=false, length=255)	
	private String nome;
	
	@Column(name="tipo", nullable=false, length=30)	
	@Enumerated(EnumType.STRING)
	private MenuType tipo;
	
	@Column(name="icone", nullable=true, length=100)	
	private String icone;
	
	@Column(name="url", nullable=true, length=100)	
	private String url;
	
	@Column(name="ordem", nullable=false, length=10)	
	private int ordem;
	
	@Column(name="ativo", nullable=false, length=1)	
	private boolean ativo;
	
	@Column(name="idRef", nullable=true, length=10)	
	private Integer idRef;
	
	@OneToOne(targetEntity=br.com.internetsistemas.nucleo.model.entity.Permissao.class)	
	@org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.LOCK})	
	@JoinColumns({ @JoinColumn(name="PermissaoID") })	
	@Basic(fetch=FetchType.LAZY)	
	private br.com.internetsistemas.nucleo.model.entity.Permissao permissao;
	
	@ManyToMany(mappedBy="menu", targetEntity=br.com.internetsistemas.nucleo.model.entity.Perfil.class)	
	@org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.LOCK})	
	@org.hibernate.annotations.LazyCollection(org.hibernate.annotations.LazyCollectionOption.EXTRA)	
	private java.util.Set<br.com.internetsistemas.nucleo.model.entity.Perfil> perfil = new java.util.HashSet<br.com.internetsistemas.nucleo.model.entity.Perfil>();
	
	public void setID(int value) {
		this.ID = value;
	}
	
	public int getID() {
		return ID;
	}
	
	public int getORMID() {
		return getID();
	}
	
	public void setNome(String value) {
		this.nome = value;
	}
	
	public String getNome() {
		return nome;
	}
	
	public void setTipo(MenuType value) {
		this.tipo = value;
	}
	
	public MenuType getTipo() {
		return tipo;
	}
	
	public void setIcone(String value) {
		this.icone = value;
	}
	
	public String getIcone() {
		return icone;
	}
	
	public void setUrl(String value) {
		this.url = value;
	}
	
	public String getUrl() {
		return url;
	}
	
	public void setAtivo(boolean value) {
		this.ativo = value;
	}
	
	public boolean getAtivo() {
		return ativo;
	}
	
	public void setIdRef(int value) {
		setIdRef(new Integer(value));
	}
	
	public void setIdRef(Integer value) {
		this.idRef = value;
	}
	
	public Integer getIdRef() {
		return idRef;
	}
	
	public void setOrdem(int value) {
		this.ordem = value;
	}
	
	public int getOrdem() {
		return ordem;
	}
	
	public void setPerfil(java.util.Set<br.com.internetsistemas.nucleo.model.entity.Perfil> value) {
		this.perfil = value;
	}
	
	public java.util.Set<br.com.internetsistemas.nucleo.model.entity.Perfil> getPerfil() {
		return perfil;
	}
	
	
	public void setPermissao(br.com.internetsistemas.nucleo.model.entity.Permissao value) {
		this.permissao = value;
	}
	
	public br.com.internetsistemas.nucleo.model.entity.Permissao getPermissao() {
		return permissao;
	}
	
	public String toString() {
		return toString(false);
	}
	
	public String toString(boolean idOnly) {
		if (idOnly) {
			return String.valueOf(getID());
		}
		else {
			StringBuffer sb = new StringBuffer();
			sb.append("Menu[ ");
			sb.append("ID=").append(getID()).append(" ");
			sb.append("Nome=").append(getNome()).append(" ");
			sb.append("Tipo=").append(getTipo()).append(" ");
			sb.append("Icone=").append(getIcone()).append(" ");
			sb.append("Url=").append(getUrl()).append(" ");
			sb.append("Ordem=").append(getOrdem()).append(" ");
			sb.append("Ativo=").append(getAtivo()).append(" ");
			sb.append("IdRef=").append(getIdRef()).append(" ");
			if (getPermissao() != null)
				sb.append("Permissao.Persist_ID=").append(getPermissao().toString(true)).append(" ");
			else
				sb.append("Permissao=null ");
			sb.append("Perfil.size=").append(getPerfil().size()).append(" ");
			sb.append("]");
			return sb.toString();
		}
	}
	
}

As entidades utilizo na camada de serviço (UsuarioService), função calcularmenu:

UsuarioServiceImpl.java

package br.com.internetsistemas.nucleo.service.impl;



import java.util.ArrayList;



import org.jgrapht.UndirectedGraph;

import org.jgrapht.graph.DefaultEdge;

import org.jgrapht.graph.SimpleGraph;



import br.com.caelum.vraptor.ioc.Component;

import br.com.internetsistemas.nucleo.model.dao.GenericDao;

import br.com.internetsistemas.nucleo.model.entity.Menu;

import br.com.internetsistemas.nucleo.model.entity.Perfil;

import br.com.internetsistemas.nucleo.model.entity.Usuario;

import br.com.internetsistemas.nucleo.service.UsuarioService;

import br.com.internetsistemas.nucleo.util.db.datetime.DBDateTime;

import br.com.internetsistemas.nucleo.util.db.query.QueryParam;

import br.com.internetsistemas.nucleo.util.sec.Crypt;



@Component

public class UsuarioServiceImpl implements UsuarioService {

	private final GenericDao<Usuario> usuarioDao;

	private final GenericDao<Menu> menuDao;

	private final GenericDao<Perfil> perfilDao;



	public UsuarioServiceImpl(GenericDao<Usuario> usuarioDao,

			GenericDao<Menu> menuDao, GenericDao<Perfil> perfilDao) {

		this.usuarioDao = usuarioDao;

		this.menuDao = menuDao;

		this.perfilDao = perfilDao;

	}



	@Override

	public Usuario verificarLogin(String login, String senha) {

		QueryParam param = new QueryParam();

		param.setParam("login", login);

		param.setParam("senha", Crypt.sha256(senha));

		param.setParam("ativo", true);



		return usuarioDao

				.findUniqueResult(

						"FROM Usuario u WHERE u.login = :login AND u.senha = :senha AND u.ativo = :ativo",

						param);

	}



	@Override

	public String calcularMenu(Usuario usuario) {

                // Apenas para "debug" no console
		Perfil perfil = usuario.getPerfil();

				

		if(perfil != null)

		{

			for (Menu menu : new ArrayList<Menu>(perfil.getMenu())) {

				System.out.println(menu);

			}

		}

		

		//return null;


                // retorna menu fixo por enquanto!
		return "<ul class=\"menuh\"><li class=\"menuv\"><a href=\"home\">Home</a></li><li class=\"menuv\"><a href=\"#\">Administração</a><ul class=\"menu\"><li class=\"topo\"></li><li class=\"menu\"><a href=\"cad_categorias.php\">Categorias</a></li><li class=\"menu\"><a href=\"index.php\">Produtos</a></li></ul></li></ul>";

	}



	private String calcularMenu(Usuario usuario, int idRef) {

		

		

		return null;

	}

	

	@Override

	public void registrarUltimoLogin(Usuario usuario) {

		usuario.setUltimoLogin(DBDateTime.now());

		usuarioDao.merge(usuario);

	}

}

Que por sua vez é chamada no controller do vraptor:

HomeController.java

package br.com.internetsistemas.nucleo.controller;

import javax.servlet.http.HttpServletRequest;

import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Post;
import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.Result;
import br.com.internetsistemas.nucleo.annotation.IgnorarAutenticacao;
import br.com.internetsistemas.nucleo.config.AppConfig;
import br.com.internetsistemas.nucleo.model.entity.Usuario;
import br.com.internetsistemas.nucleo.service.UsuarioService;
import br.com.internetsistemas.nucleo.session.UsuarioSession;

@Resource
public class HomeController {
	private final HttpServletRequest request;
	private final Result result;
	private final UsuarioService usuarioService;
	private final UsuarioSession usuarioSession;

	public HomeController(HttpServletRequest request, Result result,
			UsuarioService usuarioService, UsuarioSession usuarioSession) {
		
		this.request = request;
		this.result = result;
		this.usuarioService = usuarioService;
		this.usuarioSession = usuarioSession;
	}

	@Path("home")
	public void home() {
	}

	@Get
	@IgnorarAutenticacao
	public void login() {
		String hostname = request.getLocalName();

		// FIXME Adicionar camada de criptografia nas LICS.
		// FIXME Adicionar mais hostnames para camada de LIC.
		boolean licValida = hostname.equals(AppConfig.LIC);

		// Caso a licença não seja válida redireciona para a página de erro de
		// configuração.
		if (!licValida) {
			result.redirectTo(this.getClass()).erroConf();
			//TODO Enviar e-mail ou logar ocorrência de LIC inválida.
		}

		// Caso as tentativas de login estejam excedidas redireciona para página
		// de erro de tentativas.
		if (usuarioSession.isTentativasExcedidas()) {
			result.redirectTo(this.getClass()).erroTentativas();
		}
	}

	@Post
	@IgnorarAutenticacao
	public void login(final String login, final String senha) {
		Usuario usuario = usuarioService.verificarLogin(login, senha);
		
		if (usuario == null) {
			usuarioSession.registrarTentativa();

			if (usuarioSession.isTentativasExcedidas()) {
				result.redirectTo(this.getClass()).erroTentativas();
			} else {
				result.redirectTo(this.getClass()).erroLogin();
			}
		} else {
			usuarioService.registrarUltimoLogin(usuario);
			
			// Logando o usuário e calculando os menus
			usuarioSession.login(usuario, usuarioService.calcularMenu(usuario));
			
			result.redirectTo(this.getClass()).home();
		}
	}

	public void logout() {
		usuarioSession.logout();
		result.redirectTo(this.getClass()).login();
	}

	@IgnorarAutenticacao
	public void erroConf() {
	}

	@IgnorarAutenticacao
	public void erroTentativas() {
	}

	@IgnorarAutenticacao
	public void erroLogin() {
	}
}

Tinha pensado em uma solução de armazenamento tipo árvore (como você citou) para: 1º) armazenar a partir do list (utilizando o Menu.getID() e Menu.getIDRef()) e 2º) recuperar mais facilmente através de um interator ou algo do gênero.

Uma outra opção é utilizar grafos para essa finalidade adicionando e ligando os vértices como exemplifica a biblioteca JGraphT, porem acredito que isso é dar um “tiro de canhão”:

UndirectedGraph<String, DefaultEdge> g =
            new SimpleGraph<String, DefaultEdge>(DefaultEdge.class);

        String v1 = "v1";
        String v2 = "v2";
        String v3 = "v3";
        String v4 = "v4";

        // add the vertices
        g.addVertex(v1);
        g.addVertex(v2);
        g.addVertex(v3);
        g.addVertex(v4);

        // add edges to create a circuit
        g.addEdge(v1, v2);
        g.addEdge(v2, v3);
        g.addEdge(v3, v4);
        g.addEdge(v4, v1);

O que você acha? Não sei se fui mais claro.

PS: Em anexo segue a estrutura relacional.

Abraços!


Olá,

Eu preciso sair agora e provavelmente só volto de noite.
Se ninguém tiver te ajudado ainda e vc ainda não tiver conseguido resolver, de noite dou uma olhada com mais calma no que você fez e vejo no que posso ajudar.

[]´s

[quote=davidbuzatto]Olá,

Eu preciso sair agora e provavelmente só volto de noite.
Se ninguém tiver te ajudado ainda e vc ainda não tiver conseguido resolver, de noite dou uma olhada com mais calma no que você fez e vejo no que posso ajudar.

[]´s[/quote]

David parceiro!

Vc pode me dar um força nesse na resolução deste post: http://www.guj.com.br/posts/list/56401.java
Assunto: Re:Maldito “computing additional info” postei detalhe da situção no ultimo post.

obrigado pela atenção.