• Nenhum resultado encontrado

Uma das funcionalidades mais importantes da aplicação OD@UA é a criação de reports a partir dos dados obtidos pelas queries escolhidas pelo utilizador. Por esta razão, importa conhecer mais detalhadamente o componente “Reports Operator” do diagrama da Figura 29, uma vez que esta responsabilidade lhe está atribuída.

Numa fase inicial deste trabalho procurou-se, para além de representar os dados nos reports na forma tabelar, permitir também a inclusão de visualizações gráficas dos mesmos. Para se conseguir isso utilizou-se a ferramenta Google Image Charts [102], mas devido às grandes limitações da mesma, nomeadamente na quantidade de dados que era possível conter em cada visualização, optou-se por abandonar esta funcionalidade.

O componente “Reports Operator” engloba diversas classes, estando estas relacionadas entre si recorrendo a “composições” e “agregações”. Segundo Fowler [103] uma “agregação” é uma relação do tipo “parte de”, ou seja, por exemplo, uma pessoa faz “parte de” um clube. Também a “composição” diz respeito a uma relação “parte de”. No entanto, ao contrário da “agregação”, numa relação de “composição” [103], apesar de uma classe poder ser um componente de várias classes distintas, qualquer instância desta deve pertencer a apenas um dono.

67

6 Aplicação para representação dinâmica de dados de fontes heterogéneas

Figura 31: Diagrama de classes do componente “Reports Operator” da aplicação OD@UA

Para que melhor se perceba qual a forma utilizada pela aplicação OD@UA na criação de reports, será aqui descrita de forma sucinta esse processo.

Após o utilizador ter criado uma representação dos dados retornados pelas queries simples ou compostas que seleccionou, é-lhe dada a possibilidade de criar um report sobre a mesma, por meio de uma operação específica para esse efeito. Ao fazê-lo, o portal cria uma estrutura de dados servindo-se da notação JSON, estrutura essa que irá armazenar toda a informação sobre a representação de dados em questão. Essa estrutura será depois encaminhada para o handler HTTP “InformationRetriever” que, servindo-se de funcionalidades da componente “General Methods” da aplicação, irá converter a estrutura JSON num objecto C#, utilizado pelo componente “Reports Operator” para criar o report.

Inicialmente, servindo-se do objecto contendo as informações relativas à representação dos dados, o handler “InformationRetriever” irá criar um array de objectos instâncias da classe “ReportQueryInfo” representada na Figura 31, contendo informações sobre cada uma das queries, caso os dados sejam relativos a uma query composta, ou sobre a query simples à qual

68 6 Aplicação para representação dinâmica de dados de fontes heterogéneas

correspondem os dados. Seguidamente, é também criado um array de objectos instâncias da classe “QueryLineResult” da Figura 31, que por sua vez vão ter agregados, a cada um deles, um array de objectos instâncias da classe “QueryLineResultData”.

As informações contidas em cada objecto do tipo “ReportQueryInfo” são respeitantes ao título e índice, caso a query seja composta, de cada uma das queries simples no universo da query composta. Caso os dados provenham de apenas uma query simples o índice da mesma será 0. Já cada objecto do tipo “QueryLineResult” contém informações sobre cada uma das linhas da representação de dados resultante da query simples ou composta, sendo que é nos objectos “QueryLineResultData” associados a cada objecto “QueryLineResult” que estão os valores dos dados, ou seja, o nome da coluna e o seu valor. Importa compreender que a representação de uma query composta se faz utilizando uma nested table. No entanto, os dados são passados do “Portal” ao handler “InformationRetriever” por linha, em que cada uma das linhas pertence a uma tabela, sendo que essa tabela não é a nested table da representação final dos dados, mas sim uma de entre as tabelas resultantes do output de cada uma das queries tendo por input cada uma das linhas do output da query anterior. Desta forma, cada objecto “QueryLineResult” vai conter informação sobre a linha pai que deu origem à linha à qual o objecto diz respeito, conforme se pode ver na Figura 31.

Depois de criados os arrays de objectos dos tipos “QueryLineResult” e “ReportQueryInfo” será criado um objecto que irá agregar estes dois arrays, contendo assim todos os dados necessários à criação de um report. Esse objecto será do tipo “ReportData”, conforme a Figura 31.

O objecto do tipo “ReportData” criado será por sua vez utilizado pelo construtor da classe “FinalQueriesReport”, dando assim origem ao objecto a partir do qual se irá obter o report. A classe “FinalQueriesReport” disponibiliza um método denominado “createReport”, o qual é responsável por criar o report e devolver a localização do mesmo no servidor onde a aplicação está a ser executada.

Para além de agregar a classe “ReportData”, a classe “FinalQueriesReport” é composta por outras quatro classes distintas, como se pode observar na Figura 31. Três destas classes irão compor a “FinalQueriesReport” apenas se a query à qual o report diz respeito for composta. Caso contrário, somente a classe “ReportPage” irá compor a classe “FinalQueriesReport”.

A classe “ReportPage” vai herdar a partir da classe

“iTextSharp.text.pdf.PdfPageEventHelper”, sendo que vai fazer override a dois métodos desta: “onStartPage” e “onEndPage”. Estes dois métodos podem ser vistos como event handlers, sendo que o método “onStartPage” vai ser executado logo que uma página do report começa a ser criada, enquanto que o método “onEndPage” irá ocorrer logo que a mesma página esteja completa. Desta forma, é possível utilizar estes métodos para incluir um cabeçalho e um rodapé em cada página do

69

6 Aplicação para representação dinâmica de dados de fontes heterogéneas

report, sendo essa a razão pela qual a classe “FinalQueriesReport” é composta pela classe “ReportPage”.

A classe “iTextSharp.text.pdf.PdfPageEventHelper”, tal como o seu nome completo indica, pertence à biblioteca iText. Também a classe “FinalQueriesReport” vai ser composta por outras classes desta biblioteca, como por exemplo “iTextSharp.text.pdf.PdfCell” e “iTextSharp.text.pdf.PdfTable” que têm como função a criação de uma célula e de uma tabela, respectivamente, tendo-se optado por não incluir as mesmas no diagrama da Figura 31 por uma questão de simplificação.

A razão pela qual se optou por utilizar a biblioteca iText para auxiliar na criação dos reports é devido ao facto de esta ser simples e intuitiva, oferecendo bastante controlo sobre o processo de criação dos mesmos. Apesar de existir pouca documentação disponível para esta biblioteca, é possível, após um processo de “tentativa e erro”, compreender o funcionamento da mesma por forma a criar os reports que se pretendem.

Importa também conhecer as restantes três classes que compõem a classe “FinalQueriesReport”. Uma dessas classes é a “ReportTable”, utilizada para representar, numa query composta, a tabela resultante da execução de uma query simples integrante do encadeamento, servindo-se do output de uma das linhas da query executada anteriormente como input dos seus parâmetros. Um objecto instanciado a partir desta classe vai armazenar essa mesma tabela e algumas informações a ela relativas, nomeadamente o índice da query que lhe deu origem, bem como informações que possibilitam a identificação de quais os dados que foram utilizados como input. Assim sendo, uma lista contendo objectos deste tipo pode ser vista como uma árvore que contém todas as tabelas resultantes da query composta, sabendo-se qual a linha resultante de cada query simples que serviu de input à query simples seguinte. Uma vez que esta lista armazena todas as informações sobre os resultados da query composta e as relações entre as diversas tabelas, é possível utilizar a mesma para incluir no report, em primeiro lugar, uma nested table com os resutados desta query composta, em segundo lugar, as várias tabelas resultantes de cada uma das queries simples que compõem a query composta.

Para construir a nested table será criada uma lista de objectos do tipo “ReportTableAuxiliar” que vai ser um clone da lista de objectos do tipo “ReportTable” referida anteriormente. Esta lista clonada será então processada até se transformar numa nested table sendo então incluída no report. Já para criação das tabelas resultantes de cada uma as queries simples, a lista de objectos “ReportTable” vai ser processada por forma a ser transformada numa lista de objectos “QueryResultTable”, sendo que cada objecto desta lista corresponderá a uma tabela resultado de cada query simples. Farão parte de cada tabela todos os resultados relativos à mesma

70 6 Aplicação para representação dinâmica de dados de fontes heterogéneas

query, inclusivamente quando os parâmetros que lhe deram origem sejam distintos. Logo que a lista esteja completa estas tabelas serão incluídas no report.

Finalmente, depois de tudo o que foi descrito anteriormente, o método “createReport” retorna a localização do report no servidor, sendo esta devolvida ao browser do utilizador por meio do handler “InformationRetriever” que permitirá então ao utilizador visualizar e, se necessário, salvar o report no seu computador.