Jasper Report: acessando atributos de uma coleção dentro de outra coleção?

Olá pessoal!

estou usando o o Jasper Report para gerar relatórios sem o uso de Query e sem o uso de XML

dessa forma eu faço todo o design no código java e a lista de elementos a serem exibidos no relatório é passada como parametro na forma de um JRBeanCollectionDataSource para o preenchimento do conteúdo no corpo do relatório.

só que tenho uma situação em particular que não estou conseguindo resolver:

tenho uma classe Usuário mostrada abaixo:

public class Usuario  {

	/**
	 * O código do usuário.
	 */	
	private int codigo;

	/**
	 * A matrícula do usuário.
	 */
	private String matricula;

	/**
	 * O nome completo do usuário.
	 */
	private String nomeCompleto;

	/**
	 * Os grupos que este usuario pertence.
	 */
	private Collection<GrupoUsuario> gruposUsuario;

	/**
	 * Inicializa Usuario como uma entidade parametrizada.
	 */	
	public Usuario() {
		setGruposUsuario(new ArrayList<GrupoUsuario>());
	}

	// métodos get e set ...

	/**
	 * Adiciona um elemento ao atributo gruposUsuario.
	 * 
	 * @param grupoUsuario
	 *            O elemento grupoUsuario.
	 */
	public void addGrupoUsuario(GrupoUsuario grupoUsuario) {
		this.gruposUsuario.add(grupoUsuario);
	}

}
public class GrupoUsuario {
	
	private int codigo;

	private String nome;

	/**
	 * Inicializa GrupoUsuario.
	 */
	public GrupoUsuario() {
	}

	// métodos get e set ...

        @Override
	public String toString() {
		return String.format("%-3d\t%s", getCodigo(), getNome());
	}
	
}

Tenho que gerar um relatório com todos os usuário agrupados por cada grupo
então, como Usuário pode estar em vários grupos, o usuário pode repetir na listagem!

ok!

meu código da geração de relatório está assim:

import java.awt.Color;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.jasperreports.engine.JRAlignment;
import net.sf.jasperreports.engine.JRElement;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRVariable;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.design.JRDesignBand;
import net.sf.jasperreports.engine.design.JRDesignExpression;
import net.sf.jasperreports.engine.design.JRDesignField;
import net.sf.jasperreports.engine.design.JRDesignGroup;
import net.sf.jasperreports.engine.design.JRDesignLine;
import net.sf.jasperreports.engine.design.JRDesignParameter;
import net.sf.jasperreports.engine.design.JRDesignRectangle;
import net.sf.jasperreports.engine.design.JRDesignStaticText;
import net.sf.jasperreports.engine.design.JRDesignStyle;
import net.sf.jasperreports.engine.design.JRDesignTextField;
import net.sf.jasperreports.engine.design.JRDesignVariable;
import net.sf.jasperreports.engine.design.JasperDesign;
import br.com.construtorasucesso.sistemas.m001.bean.GrupoUsuario;
import br.com.construtorasucesso.sistemas.m001.bean.Usuario;

public class Relatorio {

	public static void main(String[] args) {

		String fileName = "Report";

		try {
			long start = System.currentTimeMillis();

			JasperDesign jasperDesign = getJasperDesign();
			JasperCompileManager.compileReportToFile(jasperDesign, fileName);
			System.err.println("Compile time : "
					+ (System.currentTimeMillis() - start));

			// Preparing parameters
			Map<String, Object> parameters = new HashMap<String, Object>();
			parameters.put("ReportTitle", "Relatório de Usuários");

			List<?> lista = loadUsuarios();
			JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(
					lista);

			JasperFillManager
					.fillReportToFile(fileName, parameters, dataSource);
			System.err.println("Filling time : "
					+ (System.currentTimeMillis() - start));

			JasperExportManager.exportReportToPdfFile(fileName + ".jrprint");
			System.err.println("PDF creation time : "
					+ (System.currentTimeMillis() - start));

		} catch (JRException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static List<?> loadUsuarios() {

		GrupoUsuario grupoUsuario1 = new GrupoUsuario();
		grupoUsuario1.setCodigo(1);
		grupoUsuario1.setDescricao("grupo1");
		grupoUsuario1.setNome("g1");

		GrupoUsuario grupoUsuario2 = new GrupoUsuario();
		grupoUsuario2.setCodigo(2);
		grupoUsuario2.setDescricao("grupo2");
		grupoUsuario2.setNome("g2");

		List<Usuario> usuarios = new ArrayList<Usuario>();

		Usuario usuario = null;

		usuario = new Usuario();
		usuario.setCodigo(1);
		usuario.setNomeCompleto("usuario1");
		usuario.setMatricula("matUsuario1");
		usuario.addGrupoUsuario(grupoUsuario1);

		usuarios.add(usuario);

		usuario = new Usuario();
		usuario.setCodigo(2);
		usuario.setNomeCompleto("usuario2");
		usuario.setMatricula("matUsuario2");
		usuario.addGrupoUsuario(grupoUsuario2);

		usuarios.add(usuario);

		usuario = new Usuario();
		usuario.setCodigo(3);
		usuario.setNomeCompleto("usuario3");
		usuario.setMatricula("matUsuario3");
		usuario.addGrupoUsuario(grupoUsuario1);
		usuario.addGrupoUsuario(grupoUsuario2);

		usuarios.add(usuario);

		return usuarios;
	}

	/**
	 * 
	 */
	private static JasperDesign getJasperDesign() throws JRException {
		// JasperDesign
		JasperDesign jasperDesign = new JasperDesign();
		jasperDesign.setName("Report");
		jasperDesign.setPageWidth(595);
		jasperDesign.setPageHeight(842);
		jasperDesign.setColumnWidth(515);
		jasperDesign.setColumnSpacing(0);
		jasperDesign.setLeftMargin(40);
		jasperDesign.setRightMargin(40);
		jasperDesign.setTopMargin(50);
		jasperDesign.setBottomMargin(50);

		// Fonts
		JRDesignStyle normalStyle = new JRDesignStyle();
		normalStyle.setName("Arial_Normal");
		normalStyle.setDefault(true);
		normalStyle.setFontName("Arial");
		normalStyle.setFontSize(12);
		normalStyle.setPdfFontName("Helvetica");
		normalStyle.setPdfEncoding("Cp1252");
		normalStyle.setPdfEmbedded(false);
		jasperDesign.addStyle(normalStyle);

		JRDesignStyle boldStyle = new JRDesignStyle();
		boldStyle.setName("Arial_Bold");
		boldStyle.setFontName("Arial");
		boldStyle.setFontSize(12);
		boldStyle.setBold(true);
		boldStyle.setPdfFontName("Helvetica-Bold");
		boldStyle.setPdfEncoding("Cp1252");
		boldStyle.setPdfEmbedded(false);
		jasperDesign.addStyle(boldStyle);

		JRDesignStyle italicStyle = new JRDesignStyle();
		italicStyle.setName("Arial_Italic");
		italicStyle.setFontName("Arial");
		italicStyle.setFontSize(12);
		italicStyle.setItalic(true);
		italicStyle.setPdfFontName("Helvetica-Oblique");
		italicStyle.setPdfEncoding("Cp1252");
		italicStyle.setPdfEmbedded(false);
		jasperDesign.addStyle(italicStyle);

		// Parameters
		JRDesignParameter parameter = null;

		parameter = new JRDesignParameter();
		parameter.setName("ReportTitle");
		parameter.setValueClass(java.lang.String.class);
		jasperDesign.addParameter(parameter);

		parameter = new JRDesignParameter();
		parameter.setName("ImgLogo");
		parameter.setValueClass(File.class);
		jasperDesign.addParameter(parameter);

		// Fields
		JRDesignField field = null;

		field = new JRDesignField();
		field.setName("codigo");
		field.setValueClass(java.lang.Integer.class);
		jasperDesign.addField(field);

		field = new JRDesignField();
		field.setName("matricula");
		field.setValueClass(java.lang.String.class);
		jasperDesign.addField(field);

		field = new JRDesignField();
		field.setName("nomeCompleto");
		field.setValueClass(java.lang.String.class);
		jasperDesign.addField(field);

		field = new JRDesignField();
		field.setName("gruposUsuario");
		field.setValueClass(List.class);
		jasperDesign.addField(field);

		// Variables
		JRDesignVariable variable = null;

		JRDesignExpression expression = null;

		JRDesignGroup group = null;

		// // Primeira alternativa
		// variable = new JRDesignVariable();
		// variable.setValueClass(GrupoUsuario.class); // Ocorre erro pois não
		// // pode ser feito um cast do tipo para GrupoUsuario
		// variable.setName("grupoUsuario");
		// variable.setResetType(JRVariable.RESET_TYPE_GROUP);
		// variable.setCalculation(JRVariable.CALCULATION_SYSTEM);
		// group = new JRDesignGroup();
		// group.setName("grupoUsuario");
		// variable.setResetGroup(group);
		// expression = new JRDesignExpression();
		// expression.setValueClass(GrupoUsuario.class);
		//
		// expression.setText("$F{gruposUsuario}");
		//
		// variable.setInitialValueExpression(expression);
		// jasperDesign.addVariable(variable);

		// // Segunda alternativa
		// variable = new JRDesignVariable();
		// variable.setValueClass(java.lang.Object.class);
		// variable.setName("grupoUsuario");
		// variable.setResetType(JRVariable.RESET_TYPE_GROUP);
		// variable.setCalculation(JRVariable.CALCULATION_SYSTEM);
		// group = new JRDesignGroup();
		// group.setName("grupoUsuario");
		// variable.setResetGroup(group);
		// expression = new JRDesignExpression();
		// expression.setValueClass(java.lang.Object.class);
		//
		// expression.setText("$F{gruposUsuario}");
		// // A linha acima dá erro, mas
		// // tenho que setar na expressão o Grupo atual
		//
		// variable.setInitialValueExpression(expression);
		// jasperDesign.addVariable(variable);

		// Terceira alternativa, essa alternativa não atende aos objetivos
		variable = new JRDesignVariable();
		variable.setValueClass(Object.class);
		variable.setName("grupoUsuario");
		variable.setResetType(JRVariable.RESET_TYPE_GROUP);
		variable.setCalculation(JRVariable.CALCULATION_SYSTEM);
		group = new JRDesignGroup();
		group.setName("grupoUsuario");
		variable.setResetGroup(group);
		expression = new JRDesignExpression();
		expression.setValueClass(Object.class);

		expression.setText("$F{gruposUsuario}");

		variable.setInitialValueExpression(expression);
		jasperDesign.addVariable(variable);

		// Groups
		group.setMinHeightToStartNewPage(60);
		expression = new JRDesignExpression();
		expression.setValueClass(java.lang.Object.class);
		expression.setText("$V{grupoUsuario}");
		group.setExpression(expression);

		JRDesignBand band = new JRDesignBand();
		band.setHeight(20);
		JRDesignRectangle rectangle = new JRDesignRectangle();
		rectangle.setX(0);
		rectangle.setY(4);
		rectangle.setWidth(515);
		rectangle.setHeight(15);
		rectangle.setForecolor(new Color(0xC0, 0xC0, 0xC0));
		rectangle.setBackcolor(new Color(0xC0, 0xC0, 0xC0));
		band.addElement(rectangle);
		JRDesignTextField textField = new JRDesignTextField();
		textField.setX(0);
		textField.setY(4);
		textField.setWidth(515);
		textField.setHeight(15);
		textField.setBackcolor(new Color(0xC0, 0xC0, 0xC0));
		textField.setMode(JRElement.MODE_OPAQUE);
		textField.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_LEFT);
		textField.setStyle(boldStyle);
		expression = new JRDesignExpression();
		expression.setValueClass(String.class);
		expression.setText("String.valueOf($V{grupoUsuario})");
		// O objetivo da linha acima seria mostrar o código e o nome do grupo.
		// Mas como $V{grupoUsuario} origina-se de uma Collection, o toString
		// exibe todos os grupos de determinado usuario
		// Alinha abaixo ilustra um pouco do que na verdade deve ser mostrado se
		// a conversão de cada elemento da lista para GrupoUsuario funcionar
		// expression.setText("$V{grupoUsuario}.getCodigo()\t"
		// + "$V{grupoUsuario}.getNome()");
		textField.setExpression(expression);
		band.addElement(textField);
		JRDesignLine line = new JRDesignLine();
		line.setX(0);
		line.setY(19);
		line.setWidth(515);
		line.setHeight(0);
		band.addElement(line);
		group.setGroupHeader(band);

		JRDesignStaticText staticText = null;

		jasperDesign.addGroup(group);

		// Title
		band = new JRDesignBand();
		band.setHeight(50);
		line = new JRDesignLine();
		line.setX(0);
		line.setY(0);
		line.setWidth(515);
		line.setHeight(0);
		band.addElement(line);
		textField = new JRDesignTextField();
		textField.setBlankWhenNull(true);
		textField.setX(0);
		textField.setY(10);
		textField.setWidth(515);
		textField.setHeight(30);
		textField.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_CENTER);
		textField.setStyle(normalStyle);
		textField.setFontSize(22);
		expression = new JRDesignExpression();
		expression.setValueClass(java.lang.String.class);
		expression.setText("$P{ReportTitle}");
		textField.setExpression(expression);
		band.addElement(textField);
		jasperDesign.setTitle(band);

		// Page header
		band = new JRDesignBand();
		band.setHeight(20);
		rectangle = new JRDesignRectangle();
		rectangle.setX(0);
		rectangle.setY(5);
		rectangle.setWidth(515);
		rectangle.setHeight(15);
		rectangle.setForecolor(new Color(0x33, 0x33, 0x33));
		rectangle.setBackcolor(new Color(0x33, 0x33, 0x33));
		band.addElement(rectangle);
		staticText = new JRDesignStaticText();
		staticText.setX(0);
		staticText.setY(5);
		staticText.setWidth(55);
		staticText.setHeight(15);
		staticText.setForecolor(Color.white);
		staticText.setBackcolor(new Color(0x33, 0x33, 0x33));
		staticText.setMode(JRElement.MODE_OPAQUE);
		staticText.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_CENTER);
		staticText.setStyle(boldStyle);
		staticText.setText("Código");
		band.addElement(staticText);
		staticText = new JRDesignStaticText();
		staticText.setX(55);
		staticText.setY(5);
		staticText.setWidth(205);
		staticText.setHeight(15);
		staticText.setForecolor(Color.white);
		staticText.setBackcolor(new Color(0x33, 0x33, 0x33));
		staticText.setMode(JRElement.MODE_OPAQUE);
		staticText.setStyle(boldStyle);
		staticText.setText("Matrícula");
		band.addElement(staticText);
		staticText = new JRDesignStaticText();
		staticText.setX(260);
		staticText.setY(5);
		staticText.setWidth(255);
		staticText.setHeight(15);
		staticText.setForecolor(Color.white);
		staticText.setBackcolor(new Color(0x33, 0x33, 0x33));
		staticText.setMode(JRElement.MODE_OPAQUE);
		staticText.setStyle(boldStyle);
		staticText.setText("Nome de Usuário");
		band.addElement(staticText);
		jasperDesign.setPageHeader(band);

		// Column header
		band = new JRDesignBand();
		jasperDesign.setColumnHeader(band);

		// Detail
		band = new JRDesignBand();
		band.setHeight(20);
		textField = new JRDesignTextField();
		textField.setX(0);
		textField.setY(4);
		textField.setWidth(50);
		textField.setHeight(15);
		textField.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_RIGHT);
		textField.setStyle(normalStyle);
		expression = new JRDesignExpression();
		expression.setValueClass(java.lang.Integer.class);
		expression.setText("$F{codigo}");
		textField.setExpression(expression);
		band.addElement(textField);
		textField = new JRDesignTextField();
		textField.setStretchWithOverflow(true);
		textField.setX(55);
		textField.setY(4);
		textField.setWidth(200);
		textField.setHeight(15);
		textField.setPositionType(JRElement.POSITION_TYPE_FLOAT);
		textField.setStyle(normalStyle);
		expression = new JRDesignExpression();
		expression.setValueClass(java.lang.String.class);
		expression.setText("$F{matricula}");
		textField.setExpression(expression);
		band.addElement(textField);

		textField = new JRDesignTextField();
		textField.setStretchWithOverflow(true);
		textField.setX(260);
		textField.setY(4);
		textField.setWidth(255);
		textField.setHeight(15);
		textField.setPositionType(JRElement.POSITION_TYPE_FIX_RELATIVE_TO_TOP);
		textField.setStyle(normalStyle);
		expression = new JRDesignExpression();
		expression.setValueClass(java.lang.String.class);
		expression.setText("$F{nomeCompleto}");
		textField.setExpression(expression);
		band.addElement(textField);

		line = new JRDesignLine();
		line.setX(0);
		line.setY(19);
		line.setWidth(515);
		line.setHeight(0);
		line.setForecolor(new Color(0x80, 0x80, 0x80));
		line.setPositionType(JRElement.POSITION_TYPE_FLOAT);
		band.addElement(line);
		jasperDesign.setDetail(band);

		// Column footer
		band = new JRDesignBand();
		jasperDesign.setColumnFooter(band);

		// Page footer
		band = new JRDesignBand();
		jasperDesign.setPageFooter(band);

		// Summary
		band = new JRDesignBand();
		jasperDesign.setSummary(band);

		return jasperDesign;
	}
}

observem as linhas 203 à 305

Outro problema, é que modificando algumas coisas na teentativa d solucionar os problemas acabei por não conseguir mais agrupar corretamente!

Alguém sabe como resolver estes dois problemas:

1 - Acessar os atributos de cada GrupoUsuario
2 - Agrupar os usuário por GrupoUsurio corretamente (esse prob foi gerado por modificações na tentativa de solucionar o 1º prob)

obrigado!

o 2º problema consegui resolver parcialmente:

a linha 261 estava assim:
expression.setText("$V{grupoUsuario}");

deve ser corrigida assim:

expression.setText("$F{gruposUsuario}");

alguém poderia m ajudar com ess problema!!

obrigado

vc soluciona esse problema da seguinte forma, acredito eu

no IReports vc tem a possibilidade de criar uma banda personalizada
onde vc diz qual o parametro da lista que esta vindo vc quer que seja o filtro…

boa sorte… qq coisa estamos ai…
FLwS