Neste artigo iremos criar um converter padrão para trabalhar com o PickList do Primefaces. Antes de mais nada é importante saber o que é o PickList e como podemos usufruir deste recurso. Na figura 1 você consegue ver um Picklist básico.

PickList Básico
Figura 1. PickList Básico

Quando estamos trabalhando com valores simples como inteiros, double, strings e outros, o trabalho fica fácil pois não precisamos de um “Converter” para realizar a conversão de objeto para String e vice-versa, mas na maioria dos casos isso não acontece, pois precisamos usar um PickList ligado diretamente a “beans” prontos, por exemplo: Na lista do lado esquerdo podemos ter uma lista de funcionários que não estão de férias e do lado direito podemos ter os funcionários que estão de férias (um exemplo simples e prático).

A picklist nos ajudará a transferir de forma fácil e rápido valores da lista do lado esquerdo para a lista do lado direito e vice-versa, com várias funcionalidades como: adicionar todos, remover todos e etc.

Definindo nosso PickList no ManagedBean

Vamos primeiro definir como será nosso PickList em nosso ManagedBean.


private DualListModel<Funcionario> dualListModelFuncionarios;
private List<Funcionario> funcionariosFerias;
private List<Funcionario> funcionariosTrabalhando;
...

dualListModelFuncionarios = new DualListModel<Funcionario>(
				funcionariosTrabalhando,
				funcionariosFerias);
.. .

public DualListModel<Funcionario> getDualListModelFuncionarios() {
	return dualListModelFuncionarios;
} 
Listagem 1. Definindo o PickList no ManagedBean

Bom, na primeira parte definimos 3 listas importantes: A DualListModel que terá a lista de funcionários que estão trabalhando (vamos dizer que seja a lista do lado esquerdo) e os funcionários que estão de férias (vamos dizer que seja a lista do lado direito), além disso temos as listas que serão gerenciadas pelo DualListModel.

Na segunda parte iremos inicializar o DualListModel, em nosso caso estamos inicializando ela colocando os funcionários de férias do lado direito e os funcionários trabalhando do lado esquerdo.

Obviamente que estes são apenas trechos de códigos maiores, você precisa definir onde colocar cada trecho, e ainda definir os getters e setters para trabalhar com o xhtml e o managedBean.

Vamos agora definir um pickList usando o primefaces.


<p:pickList id="myPickList"
	value="#{meuManagedBeanMB.dualListModelfuncionarios}"
	var="funcionario" required="true"
	converter="primeFacesPickListConverter"
	requiredMessage="Pelo menos 1 funcionário deve ser selecionado"
	itemValue="#{funcionario}" itemLabel="#{funcionario}"
	showSourceControls="true" showTargetControls="true">

	<p:ajax event="transfer"
		listener="#{meuManagedBeanMB.onTransfer}" />

	<f:facet name="sourceCaption">Disponíveis</f:facet>
	<f:facet name="targetCaption">Selecionados</f:facet>

	<p:column style="width:75%;">
		<h:outputText value="#{funcionario.nome}" />
	</p:column>
</p:pickList>
Listagem 2. Definindo o picklist do xhtml

Acima temos diversas opções, temos ainda um evento “transfer” que é disparado sempre que um registro é transferido de uma lista para a outra, assim sendo, sempre que essa transferência ocorre disparamos um evento onTransfer no nosso ManagedBean que fará alguma ação. Podemos, por exemplo, verifica se o usuário que está sendo transferindo tem permissão para entrar de férias antes de concluir a transferência.

Você deve ter percebido que usamos um converter chamado primeFacesPickListConverter e é exatamente nele que iremos focar a partir daqui, pois este nosso Converter deve servir para qualquer Bean que você precise aplicar mais a frente. Imagine se você tivesse que criar um novo Converter para cada novo PickList que for usar ? Provavelmente você optaria por utilizar esse poderoso recurso menos vezes, e não é isso que queremos.

Enfim, na listagem 3 você verá um exemplo de um PickList Converter padrão.


import java.util.Iterator; 
import java.util.List; 
import javax.faces.component.UIComponent; 
import javax.faces.context.FacesContext; 
import javax.faces.convert.Converter; 
import javax.faces.convert.FacesConverter; 

import org.primefaces.component.picklist.PickList; 
import org.primefaces.model.DualListModel; 

@FacesConverter(value = "primeFacesPickListConverter") 
public class PrimeFacesPickListConverter implements Converter { 

	public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) { 
		Object ret = null; 
		if (arg1 instanceof PickList) { 
			Object dualList = ((PickList) arg1).getValue(); 
			DualListModel dl = (DualListModel) dualList; 
			for (Iterator iterator = dl.getSource().iterator(); iterator 
					.hasNext();) { 
				Object o = iterator.next(); 
				String id = (new StringBuilder()).append( 
						((AbstractBean) o).getId()).toString(); 
				if (arg2.equals(id)) { 
					ret = o; 
					break; 
				} 
			} 

			if (ret == null) { 
				for (Iterator iterator1 = dl.getTarget().iterator(); iterator1 
						.hasNext();) { 
					Object o = iterator1.next(); 
					String id = (new StringBuilder()).append( 
							((AbstractBean) o).getId()).toString(); 
					if (arg2.equals(id)) { 
						ret = o; 
						break; 
					} 
				} 

			} 
		} 
		return ret; 
	} 

	public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) { 
		String str = ""; 
		if (arg2 instanceof AbstractBean) 
			str = ((AbstractBean) arg2).getId().toString(); 
		return str; 
	} 
} 
Listagem 3. PrimefacesPickListConverter

Vale ressaltar que para usar um PickListConverter padrão você precisará de um Bean padrão, assim sendo é importante criar um Bean padrão, que chamamos aqui de AbstractBean, veja a listagem 4 como fazemos.


package br.com.odontonew.bean; 

import java.io.Serializable; 

import javax.persistence.GeneratedValue; 
import javax.persistence.Id; 
import javax.persistence.MappedSuperclass; 

@MappedSuperclass 
public abstract class AbstractBean implements Serializable { 

	@Id 
	@GeneratedValue(strategy = javax.persistence.GenerationType.IDENTITY) 
	private Integer id; 

	public Integer getId() { 
		return id; 
	} 

	public void setId(Integer id) { 
		this.id = id; 
	} 

	@Override 
	public int hashCode() { 
		final int prime = 31; 
		int result = 1; 
		result = prime * result + ((id == null) ? 0 : id.hashCode()); 
		return result; 
	} 

	@Override 
	public boolean equals(Object obj) { 
		if (this == obj) 
			return true; 
		if (obj == null) 
			return false; 
		if (getClass() != obj.getClass()) 
			return false; 

		return (obj instanceof AbstractBean) ? (this.getId() == null ? this == obj 
				: this.getId().equals(((AbstractBean) obj).getId())) 
				: false; 
	} 

} 
Listagem 4. Criando um AbstractBean ou Bean Padrão para usar no PickList Converter

O ideal é que qualquer outro bean que você criar estenda do AbstractBean, sendo assim você poderá trabalhar com o AbstractBean e não com um Bean específico como: Funcionario, Categoria e etc.

Veja outro exemplo de como criar um PickList no seu ManagedBean, este foi retirado do próprio ShowCase do Primefaces e ilustra a associação de um Bean chamado “Player” ao seu PickList de forma estática.


//Players  
List<Player> source = new ArrayList<Player>();  
List<Player> target = new ArrayList<Player>();  
  
source.add(new Player("Messi", 10, "messi.jpg"));  
source.add(new Player("Iniesta", 8, "iniesta.jpg"));  
source.add(new Player("Villa", 7, "villa.jpg"));  
source.add(new Player("Alves", 2, "alves.jpg"));  
source.add(new Player("Xavi", 6, "xavi.jpg"));  
source.add(new Player("Puyol", 5, "puyol.jpg"));      
  
players = new DualListModel<Player>(source, target);  
  
//Cities  
List<String> citiesSource = new ArrayList<String>();  
List<String> citiesTarget = new ArrayList<String>();  
  
citiesSource.add("Istanbul");  
citiesSource.add("Ankara");  
citiesSource.add("Izmir");  
citiesSource.add("Antalya");  
citiesSource.add("Bursa");  
  
cities = new DualListModel<String>(citiesSource, citiesTarget); 
Listagem 5. Outra forma de criar um PickList no ManagedBeean

Então veja bem o que foi feito: criamos duas lista uma source e outra target, na source definimos vários Players e na target deixamos vazia, então criamos nosso DualListModel com essas duas listas, o PickList apresentado será 2 tabelas sendo o lado esquerdo preenchido e o lado direito vazio. A mesma coisa é feita com a lista de Cidades.

Este componente é muito útil em muitas situações como as citadas aqui neste artigo. Vale ressaltar que o PickList Converter é apenas uma sugestão para aqueles que não desejam criar inúmeras classes para beans diferentes na sua aplicação, mas é óbvio que você precisará padronizar sua aplicação para usar tal recurso, como é o caso do uso do AbstractBean.

Este artigo teve como principal objetivo demonstrar como criar um PickList Converter padrão para ser usado em todo tipo de Bean, mostramos também como criar um PickList mas este não foi o foco, por isso não foi feito o detalhamento do mesmo.