iReport - sub relatórios aninhados

Pessoal, eu tenho as seguintes classes:

public class Cidade {
	
	private String cidade;

	// get e set
	
}
public class Estado {

	private String estado;
	private Collection<Cidade> cidades;
	
	public Estado (String estado, Collection<Cidade> cidades) {
		this.estado = estado;
		this.cidades = cidades;
	}

	// get e set
	
}
public class Pais {

	private String pais;
	private Collection<Estado> estados;
	
	public Pais(String pais, Collection<Estado> estados) {
		tthis.pais = pais;
		this.estados = estados;
	}

	// get e set
}

Estou tentando gerar um relatório de países que tem um sub-relatório de estados e este por sua vez possui um sub-relatório de cidades. Para popular os dados no relatório estou usando JRBeanCollectionDataSource. O problema é que não estou conseguindo passar as listas como parâmetro para os sub-relatórios. Quando crio um field para o atributo estados da classe Pais dá uma ClassCastException, mesmo eu mapeando esse field como java.lang.Object. Alguém poderia me dar uma dica de como passar as listas para o sub-relatório de estados e depois de como recuperar a lista de cidade e passar para o outro sub-relatório?

O meu código para criar e exibir o relatório é o seguinte:

package paises;

import java.util.ArrayList;
import java.util.HashMap;

import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.view.JasperViewer;

public class Run {

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		ArrayList<Pais> paises = new ArrayList<Pais>();
		
		
		ArrayList<Estado> estados = new ArrayList<Estado>();
		
		ArrayList<Cidade> cidades = new ArrayList<Cidade>();
		cidades.add(new Cidade("Florianópolis"));
		cidades.add(new Cidade("São José"));
		estados.add(new Estado("Santa Catarina", cidades));
		
		cidades = new ArrayList<Cidade>();
		cidades.add(new Cidade("Curitiba"));
		cidades.add(new Cidade("Londrina"));
		estados.add(new Estado("Paraná", cidades));
		
		cidades = new ArrayList<Cidade>();
		cidades.add(new Cidade("São Paulo"));
		cidades.add(new Cidade("Campinas"));
		estados.add(new Estado("São Paulo", cidades));
		
		paises.add(new Pais("Brasil", estados));
		
		
		estados = new ArrayList<Estado>();
		
		cidades = new ArrayList<Cidade>();
		cidades.add(new Cidade("New York"));
		estados.add(new Estado("N. Y.", cidades));
		
		cidades = new ArrayList<Cidade>();
		cidades.add(new Cidade("San Diego"));
		estados.add(new Estado("California", cidades));
		
		paises.add(new Pais("Estados Unidos", estados));
		
		String arquivoRelatorio = "/home/thiago/testeireport/TesteSub_Principal";
		
		JasperPrint relatorio = JasperFillManager.fillReport(arquivoRelatorio + ".jasper", new HashMap(), new JRBeanCollectionDataSource(paises));
		JasperViewer.viewReport(relatorio, false);

	}

}

Muito obrigado pela atenção

Você deve passar tudo para o relatório principal e mapear todos os atributos neste relatório principal. Depois você passa como parâmetro para os sub-relatórios e daí pode dar o nome que quiser, já não estará preso nos atributos que chegaram no relatório principal.

Por exemplo:

class Pais { String nome; ArrayList<Estado> estado; }

class Estado { String nome; }

Digamos que exista o relatório principal main.jrxml e sub.jrxml. No main.jrxml você mapeia um field String nome e outro Object estado. Ainda no main.jrxml, vá nas propriedades do sub relatório e passe o Object estado pra ele como um datasource.

Já no sub.jrxml você cria o field String nome, que é o nome do estado… Entendeu?

Entendi. É isso que eu estou fazendo. Passo meus objetos para relatório principal através de um JRBeanCollectionDataSource. O problema é que quando vou recuparar o field estados no relatório principal ocorre uma ClassCastException, mesmo eu mapeando o field como java.lang.Object. Veja:

Exception in thread "main" java.lang.ClassCastException: java.lang.String
	at TesteSub_Principal_1203531791727_875794.evaluate(TesteSub_Principal_1203531791727_875794:167)
	at net.sf.jasperreports.engine.fill.JREvaluator.evaluate(JREvaluator.java:186)
	at net.sf.jasperreports.engine.fill.JRCalculator.evaluate(JRCalculator.java:537)
	at net.sf.jasperreports.engine.fill.JRCalculator.evaluate(JRCalculator.java:505)
	at net.sf.jasperreports.engine.fill.JRFillElement.evaluateExpression(JRFillElement.java:806)
	at net.sf.jasperreports.engine.fill.JRFillSubreport.evaluateSubreport(JRFillSubreport.java:335)
	at net.sf.jasperreports.engine.fill.JRFillSubreport.evaluate(JRFillSubreport.java:260)
	at net.sf.jasperreports.engine.fill.JRFillElementContainer.evaluate(JRFillElementContainer.java:274)
	at net.sf.jasperreports.engine.fill.JRFillBand.evaluate(JRFillBand.java:403)
	at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillColumnBand(JRVerticalFiller.java:1346)
	at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillDetail(JRVerticalFiller.java:662)
	at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillReportStart(JRVerticalFiller.java:232)
	at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillReport(JRVerticalFiller.java:113)
	at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:763)
	at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:688)
	at net.sf.jasperreports.engine.fill.JRFiller.fillReport(JRFiller.java:89)
	at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.java:601)
	at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.java:517)
	at masterdetail.Principal.main(Principal.java:76)

NESTED BY :
net.sf.jasperreports.engine.fill.JRExpressionEvalException: Error evaluating expression : 
	Source text : new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource((java.util.Collection) $F{estados})
	at net.sf.jasperreports.engine.fill.JREvaluator.evaluate(JREvaluator.java:197)
	at net.sf.jasperreports.engine.fill.JRCalculator.evaluate(JRCalculator.java:537)
	at net.sf.jasperreports.engine.fill.JRCalculator.evaluate(JRCalculator.java:505)
	at net.sf.jasperreports.engine.fill.JRFillElement.evaluateExpression(JRFillElement.java:806)
	at net.sf.jasperreports.engine.fill.JRFillSubreport.evaluateSubreport(JRFillSubreport.java:335)
	at net.sf.jasperreports.engine.fill.JRFillSubreport.evaluate(JRFillSubreport.java:260)
	at net.sf.jasperreports.engine.fill.JRFillElementContainer.evaluate(JRFillElementContainer.java:274)
	at net.sf.jasperreports.engine.fill.JRFillBand.evaluate(JRFillBand.java:403)
	at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillColumnBand(JRVerticalFiller.java:1346)
	at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillDetail(JRVerticalFiller.java:662)
	at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillReportStart(JRVerticalFiller.java:232)
	at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillReport(JRVerticalFiller.java:113)
	at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:763)
	at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:688)
	at net.sf.jasperreports.engine.fill.JRFiller.fillReport(JRFiller.java:89)
	at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.java:601)
	at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.java:517)
	at masterdetail.Principal.main(Principal.java:76)
Caused by: java.lang.ClassCastException: java.lang.String
	at TesteSub_Principal_1203531791727_875794.evaluate(TesteSub_Principal_1203531791727_875794:167)
	at net.sf.jasperreports.engine.fill.JREvaluator.evaluate(JREvaluator.java:186)
	... 17 more

Anexei os arquivos, quem sabe ajuda.

Eu não testei os arquivos, mas agora acho que irão funcionar.

Funcionou do jeito que te passei… O erro estava que o iReport não estava compilando os relatórios denovo…