Skip to content

Instantly share code, notes, and snippets.

@wakim
Last active August 29, 2015 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wakim/e118e515fccbc787b73b to your computer and use it in GitHub Desktop.
Save wakim/e118e515fccbc787b73b to your computer and use it in GitHub Desktop.
Implementação do VisitCallback que notifica com todos os componentes de uma determinada linha de um UIData
package br.com.wakim.teste_jsf.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import javax.faces.component.UIColumn;
import javax.faces.component.UIComponent;
import javax.faces.component.UIData;
import javax.faces.component.visit.VisitCallback;
import javax.faces.component.visit.VisitContext;
import javax.faces.component.visit.VisitResult;
import javax.faces.context.FacesContext;
/***
* Classe que implementa o comportamento de visitar um UIData
* e notificar apenas ao termino de visitacao de uma linha
* @author wakim
*/
public class LineVisitor implements VisitCallback {
int lastRowIndex = -1;
LineVisitorCallback lineVisitor;
UIDataLine line = new UIDataLine();
UIData ancestor;
private LineVisitor(LineVisitorCallback lineVisitor){
this.lineVisitor = lineVisitor;
}
public static void visit(FacesContext context, UIData data, LineVisitorCallback callback) {
VisitContext vc = VisitContext.createVisitContext(context);
LineVisitor lv = new LineVisitor(callback);
lv.ancestor = data;
data.visitTree(vc, lv);
lv.doLastVisitIfNeeded();
}
@Override
public VisitResult visit(VisitContext context, UIComponent target) {
if(target == ancestor) {
return VisitResult.ACCEPT;
}
int rowIndex = ancestor.getRowIndex();
// Adiciono os componentes da linha na lista
line.add(target);
// Se houve mudanca na linha atual
// Entao podemos notificar o callback
// com todos os componentes da linha
if(lastRowIndex != rowIndex) {
// Caso especial onde a primeira linha vem com os UIColumn's e as Facets.
// Precisamos recuperar todos os filhos dos UIColumns e notificar o callback
if(lastRowIndex == -1) {
line = transferColumnsViews(line, new UIDataLine());
}
// Notifico, se ele retornar false
// Pode parar o Visitor
if(! lineVisitor.visit(ancestor, line, lastRowIndex)) {
return VisitResult.COMPLETE;
}
// O callback foi notificado, entao podemos
// limpar a lista para a proxima linha
line.clear();
}
// Atualizo a ultima linha visitada
lastRowIndex = rowIndex;
return VisitResult.ACCEPT;
}
/***
* Transfere todos componentes de todas as UIColumn's
* da lista source para a lista target
* @param source
* @param target
*/
UIDataLine transferColumnsViews(UIDataLine source, UIDataLine target) {
for(UIComponent component : source) {
if(component instanceof UIColumn) {
target.addAll(((UIColumn) component).getChildren());
}
}
return target;
}
/***
* Faz uma visita apos ter terminado o visit, para notificar sobre a ultima linha
*/
public void doLastVisitIfNeeded() {
if(lastRowIndex != -1) {
lineVisitor.visit(ancestor, line, lastRowIndex);
}
}
public static interface LineVisitorCallback {
public boolean visit(UIData ancestor, UIDataLine line, int row);
}
/***
* Implementacao de lista que guarda uma estrutura de indice
* A chave do indice e o ID do componente
* @author wakim
*
*/
public static class UIDataLine extends ArrayList<UIComponent> {
private static final long serialVersionUID = -3522555822357988347L;
private HashMap<String, UIComponent> index = new HashMap<String, UIComponent>();
public UIComponent findComponentById(String id) {
return index.get(id);
}
@Override
public void add(int index, UIComponent element) {
super.add(index, element);
this.index.put(element.getId(), element);
}
@Override
public boolean add(UIComponent element) {
this.index.put(element.getId(), element);
return super.add(element);
}
@Override
public boolean addAll(Collection<? extends UIComponent> collection) {
for(UIComponent element : collection) {
this.index.put(element.getId(), element);
}
return super.addAll(collection);
}
@Override
public boolean addAll(int index, Collection<? extends UIComponent> collection) {
for(UIComponent element : collection) {
this.index.put(element.getId(), element);
}
return super.addAll(index, collection);
}
@Override
public UIComponent remove(int index) {
this.index.remove(get(index).getId());
return super.remove(index);
}
@Override
public boolean remove(Object element) {
this.index.remove(((UIComponent) element).getId());
return super.remove(element);
}
@Override
public boolean removeAll(Collection<?> collection) {
for(Object element : collection) {
this.index.remove(((UIComponent) element).getId());
}
return super.removeAll(collection);
}
@Override
protected void removeRange(int arg0, int arg1) {
for(int i = arg0; i < arg1; ++i) {
this.index.remove(get(i).getId());
}
super.removeRange(arg0, arg1);
}
@Override
public void clear() {
this.index.clear();
super.clear();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment