Usando o ponto de extensão do emissor do Projeto BIRT

Estenda sua capacidade de saída

Desenvolvido sobre a estrutura Eclipse, o Projeto Business Intelligence and Reporting Tool (BIRT) Project utiliza a estrutura de plug-in do Eclipse para aprimorar e aumentar seus recursos. Há vários pontos de extensão definidos em BIRT, sendo os maiores: o ponto de acesso a dados aberto para recuperação de dados; o ponto de extensão de item de relatório para incluir novos itens de relatórios na paleta do BIRT; a estrutura de emissor para expandir a capacidade de saída do BIRT; a biblioteca de scripts de função para estender os métodos auxiliares do BIRT em scripts e expressões; e o ponto de extensão de agregação, que permite agregar valores de um conjunto de dados. Este artigo examina como desenvolver emissores de BIRT para estender sua capacidade de saída.

John Ward, Independent consultant

John Ward é consultor independente, especializado em BIRT, GWT e soluções de procura e navegação para e-commerce. John trabalhou por muitos anos como consultor para a Innovent Solutions, desenvolvendo soluções baseadas em BIRT. Antes disso, foi vice-presidente assistente do Citibank América do Norte, gerenciando o grupo de MIS de treinamento e supervisionando o desenvolvimento de novas iniciativas de treinamento baseadas em tecnologia. Ele trabalha e realiza testes com BIRT, incluindo trabalho de desenvolvimento com base em relatórios BIRT e em APIs de BIRT. Ele é autor de Practical Data Analysis and Reporting with BIRT e mantém o blog The Digital Voice.



08/Out/2012

Introdução

BIRT já vem de fábrica com vários formatos de saída. Como ele foi criado para ser uma ferramenta de relatório online, o formato de saída padrão é Linguagem de Marcação de Hipertexto (HTML). Mas é possível gerar arquivos Portable Document Format (PDF) e documentos Word e Excel® do Microsoft® Office, e há emissores no formato OpenDocument na árvore de origem.

Mas pode ser necessário gerar uma saída de relatório em um formato para o qual o BIRT não tenha suporte pronto. Por exemplo, pode ser necessário gerar representações da saída de relatório em Linguagem de Marcação Extensível (XML) para processamento posterior usando Transformação de Linguagem de Folha de Estilo Extensível (XSLT) ou usar para fácil processamento em teste de unidade. Sabendo como trabalhar com o ponto de extensão de emissor, é possível aprimorar os emissores existentes. Por exemplo, é possível incluir segurança ou criptografia no formato de saída PDF, ou incluir suporte a imagens à saída em Excel de software livre existente. Este artigo mostra como criar alguns emissores de BIRT básicos usando duas abordagens diferentes na estrutura de emissor.

O ponto de extensão de emissor do BIRT

Emissores no BIRT são plug-ins de ponto de extensão do Eclipse. Os emissores são chamados apenas no tempo de renderização, após todos os dados de relatório serem recuperados e o arquivo temporário RPTDOCUMENT ser criado. Como indica a Figura 1, isso permite executar um relatório uma vez e renderizar em vários formatos, dispensando o processo caro de recuperar dados e criar o RPTDOCUMENT.

Figura 1. Os emissores de BIRT permitem executar um relatório uma vez e renderizar em vários formatos
Os emissores de BIRT permitem executar um relatório uma vez e renderizar em vários formatos

Há duas interfaces primárias definidas para criação da saída de relatório: ContentEmitter e PageEmitter. A interface mais usada para criar emissores do BIRT é ContentEmitter, que usa um padrão de observador semelhante ao usado pela API simples para XML (SAX). No caso da estrutura de emissor do BIRT, o desenvolvedor é responsável apenas por criar o observador. Portanto, uma tag <report> é encontrada vinda do mecanismo de renderização, e há um método startReport() correspondente para lidar com esse evento. Também definimos um método endReport() para lidar com tags </report>. Isso vale para todos os tipos de item de relatório do BIRT (grades, tabelas, linhas, células, rótulos, dados, texto e tipos de item estendidos). Todos têm um método inicial, e a maioria tem um método final. Há algumas exceções, que o exemplo neste artigo ilustra. Felizmente, a interface já define esses métodos para substituição.

A interface ContentEmitter funciona bem para saída estruturada, como HTML. Mas, quando uma saída perfeita é necessária, usamos a extensão PageEmitter de layout. Os emissores de PDF, Excel e os de Tribix de terceiros funcionam com ela. A ideia básica é que há um objeto IPageDevice que é criado no tempo de renderização pela estrutura de emissor, e que IPageDevice é responsável por criar IPages, que são responsáveis por desenhar a saída usando um sistema de coordenadas X e Y. IPages são observadores, enquanto IPageDevice é um factory para IPages. Há alguns outros objetos de factory que precisam ser criados, mostrados pelo exemplo de uso de PageEmitter.


Exemplo de XML usando o emissor de conteúdo

Esse exemplo explica a criação de um emissor de saída XML básico. A saída XML emite basicamente apenas o tipo de elemento encontrado e seus valores. Isso é útil quando temos algum tipo de processador de XML que cuida da saída, quando queremos fazer algum tipo de transformação XSLT ou quando queremos realizar teste de unidade em designs de relatório.

Para criar um emissor de saída XML básico, é necessário fazer o seguinte:

  1. Criar um projeto de plug-in.
  2. Definir os emissores que o plug-in fornece.
  3. Testar o novo plug-in.

Criando um projeto de plug-in

A primeira etapa para criar um emissor de saída de XML é criar um projeto de plug-in.

  1. No Eclipse, selecione File > New > Other (Figura 2).
    Figura 2. Menu File do Eclipse
    Menu File do Eclipse
  2. Na janela de seleção Wizards, selecione Plug-Development>Plug-In Project (Figura 3).
    Figura 3. Janela de seleção Wizards
    Janela de seleção Wizards
  3. Dê ao projeto um nome na janela New Plug-in Project (Figura 4).
    Figura 4. Janela Plug-in Project
    Janela Plug-in Project
  4. Na janela seguinte (Figura 5), você configura alguns metadados básicos sobre o projeto de plug-in. Desmarque a caixa de seleção This plug-in will make contributions to the UI, pois o emissor não fará alterações na interface com o usuário (UI) e não precisará de componentes de UI do Eclipse.
    Figura 5. Janela Plug-in Project Content
    Janela Plug-in Project Content
  5. Na janela de seleção Templates (Figura 6), desmarque a caixa de seleção Create a plug-in using one of the templates.
    Figura 6. Janela de seleção Templates
    Janela de seleção Templates
  6. Clique em Concluir.
  7. A primeira janela exibida para um projeto de plug-in é do editor de manifesto (Figura 7). É necessário configurar algumas coisas nessa tela para começar a desenvolver o emissor.
    Figura 7. Editor de manifesto
    Editor de manifesto
  8. Primeiro, clique na guia Extensions e clique em Add (Figura 8).
    Figura 8. Guia Extension
    Guia Extension
  9. Na janela Extension Point Selection (Figura 9), use o filtro org.eclipse.birt.report.engine.emitters. Não deixe de desmarcar a caixa de seleção Show only extension points from the required plug-ins.
    Figura 9. Janela Extension Point Selection
    Janela Extension Point Selection
  10. Quando o programa perguntar se você quer incluir a dependência pra org.eclipse.birt.report.engine (Figura 10),clique em Yes.
    Figura 10. Caixa de diálogo New plug-in dependency
    Caixa de diálogo New plug-in dependency

Definindo os emissores que o plug-in fornece

Agora que você criou um projeto de plug-in, pode definir os emissores que ele fornece. Um projeto de plug-in de emissor pode fornecer mais de um tipo de saída de emissor. Por exemplo, um único emissor de imagem pode fornecer saída nos formatos JPEG, Portable Network Graphics (PNG), Graphic Interchange Format (GIF) e bitmap.

  1. Na guia Extensions (Figura 11), clique no emissor recém-incluído e preencha os metadados apropriados. Anote o nome da classe usada nessa seção, pois essa é a classe que lida com todos os eventos de emissor. Além disso, o que você inserir como formato é o que será exibido como tipo de saída para geração em qualquer menu suspenso no BIRT Report Designer ou Sample BIRT Report Viewer. Configure o campo ID para algo exclusivo. Nesse exemplo, eu uso o mesmo nome da classe. Deixe os valores padrão para todos os demais campos.
    Figura 11. Guia Extensions com novo emissor
    Guia Extensions com novo emissor
  2. Crie uma nova classe Java™ com o pacote e o nome correspondendo ao que você inseriu no editor de manifesto (Figura 12).
    Figura 12. Janela New Java Class
    Janela New Java Class
    Essa classe deve implementar a interface org.eclipse.birt.report.engine.emitter.IContentEmitter (Figura 13).
    Figura 13. Caixa de diálogo Implement Interfaces Selection
    Caixa de diálogo Implement Interfaces Selection
  3. Use o código no arquivo com.digiassn.blogspot.birt.emitter.XmlEmitter.java como código de implementação (consulte Download).

Testando o novo plug-in

Agora que você criou o código do emissor, é necessário iniciar uma instância de teste do Eclipse para verificar se tudo está funcionando.

  1. Abra o arquivo Manifest.MF e clique no link Launch an Eclipse Application (Figura 14).
    Figura 14. Guia Overview
    Guia Overview
  2. Se você acessar Run>View Report na instância do Eclipse em execução, uma nova entrada, chamada As XML, estará disponível (Figura 15).
    Figura 15. Nova entrada As XML no menu Run>View Report
    Nova entrada As XML no menu Run>View Report
  3. Usando um relatório simples, com um único elemento de texto dinâmico com 2 + 2 como expressão, a saída é semelhante à Figura 16.
    Figura 16. Saída de exemplo
    Saída de exemplo

Trabalhando com o emissor de página de layout

E se a saída desejada não estiver estruturada como XML, mas sim usar um layout livre? Talvez você queira algo que represente melhor os pixels, como uma tela de imagem ou HTML usando folha de estilo em cascata (CSS) para coordenadas. O emissor estruturado não irá funcionar. A boa notícia é que o terminal de emissor do BIRT tem classes para lidar com essa situação no pacote org.eclipse.birt.report.layout.emitter. A má notícia é que trabalhar com essa estrutura é mais difícil, pois é necessário implementar várias classes diferentes.

O exemplo a seguir explica as classes que precisam ser criadas para implementar um plug-in baseado em PageEmitter para BIRT. Esse plug-in emite uma imagem JPEG renderizada da saída de relatório. Ele usa Abstract Window Toolkit (AWT) para criar uma tela e retirar a saída do BIRT. AWT torna mais fácil trabalhar com as cores e sistema de coordenadas passados do BIRT. No entanto, algumas das técnicas que eu uso neste exemplo são dispendiosas em termos de tempo e memória.

É necessário usar uma configuração de paginação que diz ao BIRT para emitir páginas, quer seja quebra de página ou tamanho de página. A primeira classe que precisa ser implementada é PageEmitter (Listagem 1). Ao contrário da maioria das classes na estrutura de emissor, essa na verdade é uma classe estendida e não uma implementação de uma interface. É uma classe simples, com uma responsabilidade simples. É a classe configurada no manifesto como classe de implementação para a extensão de emissor. Ela é responsável apenas por criar uma classe PageDeviceRender usando seu único método disponível, createRender(IEmitterServices). É possível lidar com as opções de configuração para a saída usando a classe IEmitterServices.

Lista 1. A classe PageEmitter
package com.digiassn.blogspot.birt.layout.emitter;

import org.eclipse.birt.report.engine.api.EngineException;
import org.eclipse.birt.report.engine.emitter.IEmitterServices;
import org.eclipse.birt.report.engine.layout.emitter.PageDeviceRender;
import org.eclipse.birt.report.engine.layout.emitter.PageEmitter;

public class JpegPageEmitter extends PageEmitter {

@Override
public PageDeviceRender createRender(IEmitterServices services)
throws EngineException {
return new JpegPageDeviceRender( services );
	}
}

A próxima classe que precisa ser criada é PageDeviceRender (Listagem 2). Ela também tem responsabilidades simples. Ela cria um IPageDevice quando chamada. Essa classe na verdade é uma implementação de IAreaVisitor, mas não é necessário trabalhar com IAreaVisitor para implementar um emissor. É muito fácil trabalhar estendendo PageDeviceRender.

Lista 2. A classe PageDeviceRender
 package com.digiassn.blogspot.birt.layout.emitter;
 
 import java.io.OutputStream;
 
 import org.eclipse.birt.report.engine.api.EngineException;
 import org.eclipse.birt.report.engine.api.script.IReportContext;
 import org.eclipse.birt.report.engine.content.IReportContent;
 import org.eclipse.birt.report.engine.emitter.EmitterUtil;
 import org.eclipse.birt.report.engine.emitter.IEmitterServices;
 import org.eclipse.birt.report.engine.layout.emitter.IPageDevice;
 import org.eclipse.birt.report.engine.layout.emitter.PageDeviceRender;
 
 public class JpegPageDeviceRender extends PageDeviceRender {
        		
 	private OutputStream output;
        		
        	/**
        	* Setup basic emitter services used throughout
        	* @param services
        	*/
        	public JpegPageDeviceRender(IEmitterServices services) {
        		try {
		this.output = EmitterUtil.getOuputStream( services, "report.jpg" );
        		} catch (EngineException e) {
        			e.printStackTrace();
        		}
        	}
        		
	/**
        	* Called by BIRT to create a page device. 
        	*/
        	@Override
public IPageDevice createPageDevice(String title, String author, String subject,
	String comments, IReportContext reportContext, IReportContent report)
        			throws Exception {
        		this.pageDevice = new JpegLayoutPageDevice(output);
        		return this.pageDevice;
	}
        		
        	/**
* Used to get the output format. This should match what is in the Manifest and Plugin.XML
        	*/
        	@Override
        	public String getOutputFormat() {
        		return "jpg";
        	}
}

A próxima classe que precisa ser criada é IPageDevice (Listagem 3). Essa classe é chamada sempre que uma nova página precisa ser gerada na saída de relatório do BIRT. Essa classe lida com o formato de saída geral e gerencia as páginas individuais a serem incluídas na saída final. No emissor de JPEG criado aqui, apenas uma página será manipulada, portanto é necessário criar apenas um ImageBuffer objeto Graphics. É possível usar outras estratégias, como gravar mais de uma imagem em um diretório de saída e compactar todas ou anexá-las ao final de um arquivo de imagem.

Lista 3. A classe IPageDevice
package com.digiassn.blogspot.birt.layout.emitter;
        		
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.OutputStream;
       		
import javax.imageio.ImageIO;
        		
import org.eclipse.birt.report.engine.layout.emitter.IPage;
import org.eclipse.birt.report.engine.layout.emitter.IPageDevice;
        		
/**
* This class is responsible for creating and managing pages during render.
* Since this is a simple example, this class will only handle a single page.
*
*/
public class JpegLayoutPageDevice implements IPageDevice {
        		
	//the AWT canvas used to draw the image
        	private Graphics2D canvas;
        	//output stream to write to
        	private OutputStream output;
        	//buffered image that will be written to the output
        	private BufferedImage bufferedImage;
        		
        	//set the scale of the image. 
        	double scale = 0.01;
        		
        	/**
        	* Constructor just initializes the output stream read from the 
        	* render options
        	* @param output
        	*/
        	public JpegLayoutPageDevice(OutputStream output) {
        		this.output = output;
        	}
        		
        	/**
        	* Write file on close. 
        	*/
        	@Override
		public void close() throws Exception {
			//use ImageIo to write out the file
        		ImageIO.write(bufferedImage, "jpg", output);
        	}
        		
        	/**
        	* Utility method to calculate the scale size. 
        	* @param size
        	* @return
        	*/
        	private int scale(int size)
        	{
        		return Math.round((float)(size * scale));
        	}
        		
        	/**
        	* Called by BIRT when a new page needs to be created
        	*/
        	@Override
        	public IPage newPage(int width, int height, Color color) {
        		//get the scaled width and height, and create an
        		//image buffer based on that size
        		int scaledWidth = scale(width);
        		int scaledHeight = scale(height);
        		bufferedImage = new BufferedImage(scaledWidth, 
        								scaledHeight, 

BufferedImage.TYPE_INT_RGB);
        		
        		//get the canvas to draw on from the buffered image
        		canvas = bufferedImage.createGraphics();
        		
        		//check the background color. If one is not set, default
        		//to white
        		if (color == null)
        		{
        			canvas.setBackground(Color.WHITE);
        		}
        		else
        		{
        			canvas.setBackground(color);
        		}
        		
        		//clear background color
        canvas.clearRect(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight());
        		
        		//create a new page device
        		return new JpegPage(canvas, scale);
        	}
}

E a última classe que precisa ser implementada é IPage (veja o arquivo com.digiassn.blogspot.birt.layout.emitter.JpegPage.java em Download). Essa classe é responsável por lidar com os eventos de desenho, semelhante a como ContentEmitter funciona. A exceção é que há apenas alguns eventos, como drawLine e drawText. Além de algumas informações de estilo, coordenadas e os valores avaliados finais para a saída, nada mais é fornecido.

A Figura 17 é a saída do emissor de imagem JPEG. Há alguns ajustes que podem ser feitos, mas isso deve dar uma ideia de como tudo funciona.

Figura 17. A imagem de saída do emissor de saída JPEG
A imagem de saída do emissor de saída JPEG

Conclusão

Este artigo tratou dos requisitos básicos para implementar dois tipos diferentes de emissores do BIRT: ContentEmitter e PageEmitter. Você viu como criar um objeto observador para lidar com os eventos que ContentEmitter executa. Esses eventos criam um documento XML contendo os valores da saída de relatório e podem ser usados para qualquer número de rotinas de processamento XML. Você também viu como criar os objetos de factory usados por PageEmitter e como criar o observador para lidar com eventos de renderizador de página. Usando AWT, você criou um emissor simples que criou imagens JPEG de relatórios do BIRT. Você agora deve ter uma base para criar emissores do BIRT.


Download

DescriçãoNomeTamanho
Eclipse plug-in project source for the examplesemitterProjectSource.zip19KB

Recursos

Aprender

Obter produtos e tecnologias

Discutir

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Software livre
ArticleID=839262
ArticleTitle=Usando o ponto de extensão do emissor do Projeto BIRT
publish-date=10082012