Nota do editor: Possui muito conhecimento sobre este tópico? Deseja compartilhá-lo? Participe do programa de wiki do software IBM Lotus hoje mesmo.
| wiki do Lotus Quickr |
|---|
As estatísticas específicas de local oferecem informações úteis sobre um local, como o número de documentos no local, o número de documentos modificados no dia atual, o número de documentos de biblioteca, etc. Essas informações são úteis para os proprietários de locais e para o administrador do servidor. As estatísticas também devem ser vistas por meio de uma interface com o usuário (UI) simples que é acessível a partir do tema e também existe em um formato CSV que pode ser transferido por download e importado para uma planilha.
Neste artigo, você torna essas estatísticas mais "consumíveis" para os proprietários de locais. Você fará o seguinte:
- Desenvolverá um servlet para acessar feeds do Place Statistics
- Usará o Abdera para chamar os feeds de adminqcs, construir feeds Atom e analisar o XML
- Usará a API do WebSphere Portal para preparar feeds de JSON
- Protegerá o novo servlet
- Escreverá um widget em Dojo para fornecer uma UI simples e um meio de fazer o download do arquivo CSV
- Integrará o widget ao tema do Lotus Quickr
A UI resultante mostra estatísticas sobre conteúdo, crescimento e funcionamento do local aos proprietários do local em uma forma consumível.
Todos os materiais necessários para implementar o widget Place Statistics estão contidos no arquivo EAR fornecido neste artigo. A seção “Implementação” deste artigo descreve como instalar esse widget e alterar o tema para que o novo recurso possa ser acessado.
Vamos começar construindo o servlet para obter os dados estatísticos do local. O servlet usa o feed \adminqcs já existente, acrescentando a capacidade de fazer a saída dos detalhes no formato JSON. O fato de ter uma saída com o formato JSON facilita a utilização da saída de feed pelos componentes do JavaScript.
A Figura 1 mostra como as partes que formam o servlet funcionam em conjunto. Uma solicitação entra e os dados do feed \adminqcs são obtidos no formato Atom ou CSV, dependendo do formato que será necessário em última análise, usando o FeedRetriever. Em seguida, os dados são passados para o FeedHandler, que faz com que a saída dos dados estatísticos tenha o formato correto; portanto, se queremos o formato JSON, sairá JSON e não Atom ou CSV.
Figura 1. Servlet do Place Statistics
Os dados estatísticos do local podem ser obtidos por qualquer pessoa que tenha função gerencial referente ao local ou qualquer pessoa que tenha uma função com permissão de Manage Membership.
Nenhuma autorização extra é fornecida pelo servlet do Place Statistics descrito neste artigo. A classe PlaceStatisticsRetriever no código de exemplo contém um método authenticateAccess() que pode ser usado para realizar autorizações adicionais. Se o método é implementado, ele lança uma PlaceStatisticsAuthenticationException caso o usuário atual não tenha permissão para visualizar as estatísticas. O método authenticateAccess() é chamado antes da obtenção das estatísticas do local.
Recuperador de feeds: consumindo o feed do Place Statistics
O feed \adminqcs já existente do Place Statistics fornece detalhes no formato Atom ou CSV. O formato Atom é fácil de analisar usando o código Java e fornece uma visualização estruturada das estatísticas do local. O feed em CSV fornece um feed que pode ser transferido por download para um arquivo a partir do navegador, mas é difícil de tratar para qualquer outro propósito.
É necessário um código diferente para recuperar cada uma desses feeds, porque são apresentados em formatos diferentes — o CSV está em um fluxo e o Atom está em um documento XML. O comportamento de que você precisa é o comum, para que possa ser expresso por meio de uma interface que cada recuperador de feed criado por você possa implementar. Essa interface é descrita na Listagem 1.
Listagem 1. Interface #BaseFeedRetriever
package com.ibm.quickr.placestatistics.datahandler;
import javax.servlet.http.Cookie; import
com.ibm.quickr.placestatistics.exceptions.PlaceStatisticsException;
public interface
BaseFeedRetriever
{ public Object getFeed(String feedUrl, Cookie[] cookies) throws
PlaceStatisticsException; } |
O método getFeed() toma como entrada a URL cujo feed você quer obter (incluindo parâmetros como datas de/para) e os cookies necessários para a autenticação; o serviço \adminqcs usa os tokens de LTPA (cookies) que o WebSphere Portal usa para a autenticação.
As classes são criadas estendendo essa interface, que fornece a sua própria implementação do método getFeed(). Para garantir o uso da implementação correta de leitor de feed, você também cria uma classe factory que fornece o leitor de feed adequado com base no formato de saída final desejado. No caso em que a saída necessária é CSV, é usado o CSVFeedRetriever. Em todos os outros casos, o AtomFeedRetriever é usado porque o documento de Atom produzido pode, em seguida, ser analisado de outras formas, como JSON.
Se outros tipos de saída do serviço \adminqcs ficam disponíveis, é possível criar uma classe para tratar esse tipo de feed sem afetar as classes que tratam os feeds Atom e CSV.
A classe AtomFeedRetriever é usada para recuperar a versão em Atom do feed do Place Statistics.
O Apache Abdera é usado para fazer a solicitação de HTTP ao serviço \adminqcs. O Abdera também é usado para tratar os dados retornados e mais algumas coisas no projeto. Uma instância da classe AbderaClient e uma instância da classe RequestOptions — que é usada para passar opções como cookies na solicitação — são necessárias.
Um dos parâmetros do método getFeed é um array de cookies. Alguns dos cookies na solicitação do servlet original são os cookies LTPA que o WebSphere Portal usa para a autenticação. Uma instância da classe org.apache.abdera.protocol.client.RequestOptions é criada e os detalhes dos cookies são configurados. Os cookies devem ser definidos como um array de cadeias de caracteres, uma para cada cookie, com cada cadeia de caractere tendo a seguinte forma:
nome = valor
Você repassa os cookies, forma uma matriz de sequência com um elemento para cada cookie e, em seguida, usa essa matriz para configurar o objeto RequestOptions como se mostra na Listagem 2.
Listagem 2. Configurando cookies para solicitação
RequestOptions options = new RequestOptions(true); //
Put the cookies onto the request options. List<String> cookieStrings =
new ArrayList<String>();; for (int i=0; i<cookies.length;i++) {
String name = cookies[i].getName(); String value = cookies[i].getValue();
cookieStrings.add(name+"="+value); } options.setHeader("Cookie",
(String[])cookieStrings.toArray (new String[cookieStrings.size()])); |
A solicitação propriamente dita é feita usando o método get() na instância AbderaClient, passando a URL da solicitação e o objeto RequestOptions que você configurou. A resposta é uma instância da classe ClientResponse do Abdera que contém detalhes do status da resposta (por exemplo: sucesso ou falha) e os dados enviados na resposta. Nessa instância, pressupondo uma resposta bem-sucedida, a resposta contém o documento XML do Atom. Esse documento pode ser extraído usando o método getResponse() na instância de ClientReponse. Em caso de falha, uma exceção é levantada e tratada.
A resposta obtida é enviada como a saída do recuperador de feed, pronta para ser usada em outro lugar.
A obtenção do feed em CSV é semelhante à obtenção do feed do Atom Place Statistics; a única diferença real é a forma de tratar a saída da solicitação.
Como antes, é necessário definir os cookies em uma tentativa de configurar o objeto RequestOptions e, em seguida, enviar a solicitação.
Dessa vez, você obtém um feed em CSV retornada na forma de uma InputStream, que deve ser lida. Uma boa opção é usar um BufferedReader para ler um bit do fluxo por vez. Cada bit lido é anexado a um objeto StringBuffer até que não haja nada mais para ler. Nesse ponto, é possível retornar o StringBuffer como a saída do recuperador.
Realizando a saída no formato necessário
Agora que você está com os dados do Place Statistics no formato Atom ou CSV, é necessário formar a saída que é enviada ao responsável pela chamada do seu servlet na forma em que foi pedida originalmente.
Para manter as coisas organizadas e flexíveis, é possível usar uma classe separada para tratar cada formato de saída, e cada uma delas fornece a funcionalidade listada na Tabela 1.
Tabela 1. Funções de saída das classes dos dados estatísticos
| Função de saída | Descrição detalhada |
|---|---|
| Tratar o feed de estatísticas | Tomar o feed de estatísticas e gravá-lo no formato necessário, no fluxo de saída determinado. |
| Fornecer o tipo de conteúdo | Fornecer um meio de recuperar o tipo de conteúdo do formato de saída. Depois de criar uma instância de FeedHandler, o tipo de conteúdo do feed pode ser obtido por meio desse método. |
| Gravar a saída da exceção | Realizar a saída dos detalhes de uma exceção no formato determinado. Por exemplo: se ocorre uma exceção no processamento do AtomHandler, ele grava os detalhes da exceção em um formato Atom. |
Já que as operações oferecidas pelas classes são as mesmas, é possível usar uma interface para definir um contrato que todas as suas classes implementam. Um exemplo disso é mostrado na interface BaseFeedHandler, na Listagem 3.
Listagem 3. Interface BaseFeedHandler
public interface BaseFeedHandler
{ // Method to produce feed for an exception. public Object produceExceptionFeed
(Exception ex, PrintWriter writer, String feedId);
public void handleStatsFeed(Object feed,
PrintWriter writer) throws PlaceStatisticsException;
public String getContentType();
} |
O tipo de feed que é passado ao método handleStatsFeed depende do tipo de feed da saída. Por exemplo: se você está tratando um feed Atom, o parâmetro de feed é uma feed Abdera, mas é um StringBuffer se você está tratando um feed em CSV.
O AtomFeedHandler faz a saída do the Place Statistics no formato Atom. Basta tomar o feed Atom recuperado do serviço \adminqcs e passá-lo usando a resposta para o servlet.
O JSONFeedHandler faz a saída do feed do Place Statistics em um formato JSON e requer um pouco mais de trabalho. O feed esperado pela função é o feed Atom produzido pelo serviço adminqcs.
O manipulador faz a saída de uma estrutura JSON capaz de descrever o feed de estatísticas referente a um local; este é um exemplo:
{id : "statistics", fromDate : "2010-05-27", toDate : "2010-05-30",
title: "Lotus Quickr Admin Feed", items: [{"published", statistics:
[{key: "document_totalNum", value: 1}]}]}
A primeira parte do feed contém o ID do feed, as datas de/a referentes ao feed e o título do feed. Depois, vem o array de itens, e um item do array corresponde a um único elemento <entry> no feed Atom.
Cada item tem uma data de publicação, um título e um array. Esse array final contém as informações estatísticas referentes ao local, e cada item tem uma chave e um valor. A chave identifica qual é a estatística; por exemplo: document_size, e o valor indica o valor dessa estatística específica.
Usa-se o Abdera para analisar o feed Atom porque ele oferece tudo o que é necessário para analisar um DOM, ou diretamente ou usando consultas Xpath. Conforme você analisa, pode construir a sua estrutura JSON usando as APIs do WebSphere Portal que tratam os caracteres especiais e problemas de codificação, diminuindo um pouco as suas preocupações.
O Apêndice 1 deste artigo mostra um feed Atom padrão referente às estatísticas de local. Com o Abdera, analisar esse feed no formato JSON é fácil.
A lista de entradas no feed Atom é obtida primeiro; em seguida, é realizada uma procura nessas entradas pelo elemento <statistics> que contém as informações do Place Statistics. Depois que esse elemento é localizado, os elementos dentro dessa entrada sofrem iteração, com pares de JSON sendo formados para cada estatística.
Uma instância da classe JSONHandler é criada e vários métodos dessa instância são usados para construir a estrutura JSON. A Tabela 2 fornece detalhes sobre esses métodos.
Tabela 2. Métodos de manipulação de JSON fornecidos pelo JSONHandler
| Método da API | Descrição |
|---|---|
| startJsonObject | Inicia um objeto JSON. É equivalente a digitar uma chave de abertura ({) na estrutura. |
| jsonPair(chave, principal) | Insere um par de chave/valor na estrutura: fromDate : “2010-05-27” |
| startArray() | Inicia um array na estrutura. É equivalente a digitar um colchete de abertura ([). |
| startPair(pairkey) | Inicia um par de JSON, com a chave sendo passada. |
| endPair() | Termina um par iniciado anteriormente com o método startPair. |
| endArray() | Termina um array iniciado com o método startArray. Insere efetivamente o colchete de fechamento (]) na estrutura. |
| endJsonObject | Termina um objeto JSON iniciado com o método startJsonObject. Insere efetivamente a chave de fechamento (}) na estrutura. |
Às vezes, as coisas dão errado e o usuário precisa obter informações sobre os erros.
Cada um dos FeedHandlers deve ser capaz de enviar detalhes das exceções que ocorreram, em um formato adequado. Por exemplo: O FeedHandler de Atom envia um documento Atom que contém detalhes do erro, o FeedHandler de JSON envia um documento JSON, etc. Se você não fizer isso, é possível que o xhrGet de manipulação de JSON usado para obter o feed do Place Statistics receba um relatório de exceções de Atom e não saiba o que fazer com ele.
O AtomFeedHandler usa o Abdera para construir um feed Atom que contém detalhes da exceção. É usada uma instância da classe FOMFactory para gerar um novo feed, com detalhes da exceção sendo adicionados a essa instância. Finalmente, a coisa toda é enviada de volta ao responsável pela chamada. É mostrado um exemplo na listagem para produzir um feed Atom referente a uma exceção.
Listagem 4. Código de exemplo para produzir um feed Atom referente a uma exceção
public final Object produceExceptionFeed(Exception
ex, PrintWriter writer, String feedId)
{ Feed feed = factory.newFeed();
// Produce the feed header.this.produceFeedHeader(feed, MessageHelper.getMessageFromBundle
("statistics.feed.title"), feedId);
// Add an entry in to show the error. Entry entry = factory.newEntry();
entry.setTitle(MessageHelper.getMessageFromBundle
("statistics.feed.exceptiontitle"));
entry.setContent(ex.getMessage());
feed.insertEntry(entry);
try { this.writeFeed(writer, feed);
} catch (Exception e) {
e.printStackTrace(); } return feed; } |
O JSONFeedHandler faz a saída das informações sobre a exceção no formato JSON. Os objetos de API do WebSphere Portal usados para formar a saída em JSON (que você viu antes) são usados para formar a nova estrutura. É usada uma instância do com.ibm.portal.streaming.json.JSONHandler para criar um documento no qual os pares em JSON são incluídos, como mostra a listagem 5.
Listagem 5. Produzindo um feed em JSON referente a uma exceção
public Object produceExceptionFeed(Exception ex,
PrintWriter writer, String id)
{ // TODO Auto-generated method stub JSONHandler json
= null;
try
{ json = this.getJSONHandler(writer);
json.startDocument();
json.startJSONObject();
json.pair("id",
PlaceStatisticsConstants.FEEDNAME);
json.pair("name",
PlaceStatisticsConstants.JSONERRORID); json.pair("message",
ex.getMessage());
json.endJSONObject(); json.endDocument(); } catch (Exception e) {
e.printStackTrace(); } return null; } |
Lembre-se de que o servlet precisa de detalhes do usuário atual. E, para trabalhar com esses detalhes, o servlet deve ser protegido. Um servlet desprotegido não pode ter acesso aos detalhes do usuário atual.
O arquivo web.xml referente ao servlet contém um elemento <security-constraint> que define a restrição de segurança, os métodos de HTTP aos quais a restrição se aplica e as funções que usam a restrição. A Listagem 6 mostra um exemplo.
Listagem 6. Protegendo o servlet em web.xml
<security-constraint
id="SecurityConstraint_1"> <web-resource-collection
id="WebResourceCollection_1"> <web-resource-name>Statistics
Vault</web-resource-name>
<url-pattern>/placestatistics</url-pattern>
<http-method>GET</http-method>
</web-resource-collection> <auth-constraint
id="AuthConstraint_1"> <description>only for
authenticated</description>
<role-name>Authenticated</role-name>
</auth-constraint> </security-constraint>
<security-role id="SecurityRole_1"> <description>All
authenticated users</description>
<role-name>Authenticated</role-name>
</security-role> |
Em relação à seção<security-constraint>/<web-resource-collection>, as partes interessantes são mostradas na tabela 3.
Tabela 3. Elementos da restrição de segurança
| Elemento de restrição | Descrição |
|---|---|
| <url-pattern> | A URL à qual a segurança se aplica. |
| <http-method> | O método de HTTP ao qual a segurança se aplica. Se esse elemento fica em branco, a segurança é aplicada a todos os métodos de HTTP. Já que o servlet do PlaceStatistics só usa o método GET, você aplica a segurança a todas as operações de GET. |
A próxima etapa é vincular as funções de segurança que têm acesso ao recurso; essa vinculação é feita por meio da seção <auth-constraint>. Em seguida, é necessário colocar usuários e grupos específicos nas funções que você definiu durante a implementação do aplicativo. O arquivo EAR é usado para executar essa tarefa usando o XML contido no arquivo application.xml e nos arquivos ibm-application-bnd.xml.
O arquivo application.xml define o arquivo EAR, detalhando quais arquivos WAR devem ser incluídos. A raiz de contexto do aplicativo (por exemplo: /lotus/PA_Place_Statistics) e detalhes das funções de segurança usadas no aplicativo também são fornecidos. O arquivo ibm-application-bnd.xml liga a função de segurança aos usuários ou grupos adequados; nesse caso, o grupo especial All Authenticated Users.
Esses dois arquivos estão contidos no diretório de nível superior META-INF no arquivo EAR que acompanha este artigo. Agora o servlet está protegido e os detalhes do usuário conectado no momento estão disponíveis a ele.
Para aproveitar totalmente o servlet Place Statistics, é necessário fornecer um meio de:
- Visualizar estatísticas atuais de um local usando uma UI
- Fazer o download de um arquivo CSV que contém as informações do Place Statistics
Pode-se fazer esse download usando um widget em JavaScript desenvolvido usando o Dojo 1.3.2, que está integrado ao tema do Lotus Quickr. Esse widget é implementado como parte do arquivo EAR fornecido neste artigo e é colocado no diretório:
wp_profile/installedApps/<node>/PA_Place_Statistics/js
As técnicas usadas para recuperar dados para a UI e para o arquivo CSV que pode ser transferido por download são diferentes — a UI pode usar uma chamada direta de Ajax, mas o arquivo é acessado por meio de uma tag âncora <a>.
A produção da versão do widget com UI é um processo de duas etapas. A etapa 1 é obter os dados usando uma chamada de Ajax para o servlet do Place Statistics. A segunda etapa é tomar os dados e renderizar dinamicamente uma UI simples a partir deles.
A função getCurrentStats() é usada para recuperar os dados, como mostra a Listagem 7.
Listagem 7. Função em JavaScript para obter o feed de estatísticas
getCurrentStats: function()
{ var self = this; var
content = {"appid": this.placeId, "format": "json"};
dojo.xhrGet({url:
self.serverRoot + "/PA_Place_Statistics/placestatistics",
content: content,
handleAs: "json", load: function(response)
{ self._displayStats(response); }, error:
function(response,ioargs)
{self._displayError(ioargs.xhr.status); } }); }, |
O ID do local cujas estatísticas você quer é mantido como um atributo no widget. Um objeto JavaScript que contém o "conteúdo" da solicitação é configurado; o conteúdo é o placeId e um indicador para informar que você quer que uma estrutura JSON seja retornada.
Em seguida, a solicitação para o servlet do Place Statistics é feita e os retornos de chamada são ligados à carga ou então os manipuladores de erros são chamados, conforme o for adequado.
Supondo-se que a chamada seja bem-sucedida, a função displayStats() é chamada. Essa etapa toma o array de itens declarado no JSON e o usa para construir dinamicamente uma tabela HTML que mostra os detalhes das estatísticas. A Listagem 8 mostra um exemplo.
Listagem 8. Exemplo de código em JavaScript para exibir estatísticas
_displayStats: function(json)
{ dojo.byId(this.id +
"_loading").style.display="none";
// Go through each of the items. Each item
represents a set of statistics. var self = this; var rangeString =
this._labels["rangestring"] + " " + json.fromDate + " - " + json.toDate;
var
statsHolder = dojo.create("div", {id: this.id + "_statsHolder", style:
{height:
"260px", "overflow": "auto"}}, dojo.byId(this.id + "_statsdisplay"));
dojo.create("h3",{},statsHolder).innerHTML = rangeString; // Start a table. var
statTable = dojo.create("table", {className: "lotusTable", border: "0", cellspacing:
"0", cellpadding: "0"}, statsHolder);
if (json.items.length > 0) { var
statsData = json.items[0].statistics;
// Go through each of the statistics and
create a row on the table. dojo.forEach(statsData, function(stat)
{ var newRow =
statTable.insertRow(0); var statDescCell = newRow.insertCell(0);
statDescCell.innerHTML = self._labels[stat.key]; var statValueCell =
newRow.insertCell(1);
statValueCell.innerHTML = stat.value; }); } }, |
Produzindo o CSV que pode ser transferido por download
O widget Place Statistics também fornece um link para obter todas as estatísticas de um local em um arquivo que pode ser transferido por download, fornecido no formato CSV. O link é construído quando o diálogo é aberto; o link usual do PlaceStatistics é usado com os parâmetros mostrados na tabela 4.
Tabela 4. Parâmetros de solicitação para obter o download do CSV
| Parâmetro de URL | Descrição/conteúdo |
|---|---|
| appid | ID do aplicativo |
| formato | “csv” |
| fromDate | Primeira data que tem estatísticas disponíveis |
| toDate | Última data que tem estatísticas disponíveis |
As datas iniciais e finais são obtidas a partir da estrutura JSON retornada como reposta para a chamada de xhrGet na função _getCurrentStats(). Já que a URL é acessada clicando no link (e não por meio de uma chamada de xhrGet), tome cuidado ao codificar cada um dos parâmetros. A resposta do servlet tem o content-type definido como application/x-download, para que o navegador mostre a janela Open/Save.
Renderizando o widget como uma janela
O Place Statistics será apresentado como uma janela quando for acessado por meio de um link. Esse acesso é feito apresentando o widget como uma janela e, em seguida, incluir funções para mostrar e ocultar o widget encapsulado em uma janela.
Primeiro, é possível examinar a estilização, que afeta a forma de exibição da janela. Essa etapa envolve colocar um <div> de agrupamento ao redor do widget e dar a ele a classe lotusDialogBorder e os atributos max-width e width. Também é necessário ter ali um elemento de formulário, com classes de lotusDialog e lotusForm.
O trecho de código HTML mostrado na listagem 9 ilustra a marcação da janela que é necessária.
Listagem 9. HTML para a janela do widget
<div class="lotusDialogBorder"
style="max-width:600px; width:600px;"> <form id="${id}_PlaceStatsForm"
class="lotusDialog lotusForm" action="javascript:;"> <h1>
<a href="javascript:;" class="lotusBtnImg lotusClose" title="Close Dialog"
dojoAttachEvent="onclick: closeStatistics">" <img
src="${commonRes}/css/images/blank.gif"/> </a>Place Statistics
</h1>" <div class="lotusDialogContent">
<div> Main part of widget markup goes in here. </div>
</div> <div class="lotusDialogFooter"> <input
value="Close" class="lotusFormButton" dojoAttachEvent="onclick:
closeStatistics"/> </form> </div> |
Incluir as funções de mostrar/ocultar
Quando se clica no link do Place Statistics, a janela é exibida. A janela também precisa fornecer uma forma de se fechar, o que é feito usando a função closeStatistics() ligada aos botões de fechar por meio das declarações de dojoAttachEvent, como mostra a listagem 9. Uma função de exibição deve criar dinamicamente um objeto de janela de Dojo e colocar o conteúdo de PlaceStatistics nele, como mostra a listagem 10.
Listagem 10. Função em JavaScript para mostrar a janela
…. popup: null, postMixInProperties: function()
{
this.popup = new dijit.Dialog({}); }, …... show: function()
{
this.popup.attr("content",this.domNode);
this.popup.show(); this.getCurrentStats();
}, |
È criada uma janela vazia na função postMixInProperties. Em seguida, a função de exibição coloca o nó superior do DOM do widget (this.domNode) na janela, mostra-o e, finalmente, obtém as estatísticas do local.
A função closeStatistics é ainda mais simples, porque chama o método de ocultar na janela para tirá-la do monitor:
closeStatistics: function()
this.popup.hide();
}
Você criou o servlet, codificou cosias para suportar autenticação, tipos de saída, etc. O widget em Dojo usado para exibir as estatísticas ao usuário também foi codificado. Agora é necessário implementá-lo no servidor e incluir itens no tema para deixar o novo recurso acessível.
As seções a seguir descrevem todo o processo de instalação e as mudanças necessárias no tema.
Instalando o servlet e o widget usando o arquivo EAR
O arquivo EAR que acompanha este artigo contém o servlet e o widget em Dojo que é usado para formar uma UI para os dados do Place Statistics. O arquivo EAR pode ser instalado no servidor do Lotus Quickr por meio do console de administração do WebSphere Application Server. A instalação do arquivo EAR coloca o aplicativo na raiz de contexto /lotus/PA_Place_Statistics (definida no arquivo application.xml). Após a importação do EAR, o aplicativo deve ser iniciado para que o servlet ou o widget em Dojo possa ser usado.
Se você olhar no diretório <server_root>\wp_profile\installedApps\<node>, verá o diretório PA_Place_Statistics.
Agora, a única coisa que falta fazer é alterar o tema para que o usuário tenha uma forma de exibir do widget. Você incorporará o widget ao Lotus Quickr para que ele possa ser acessado por meio de um link contido na navegação lateral do local, como mostra a figura 2.
Figura 2. Navegação lateral que mostra o novo link do Place Statistics
As seguintes tarefas devem ser executadas:
- Atualizar o sideNav.jspf para fornecer acesso ao widget
- Atualizar o js.jsp para carregar o widget em Dojo
Os dois arquivos que alteraremos estão contidos no aplicativo:
<server_root>\wp_profile\installedApps\<node>\QuickrThemeApp.ear
E os arquivos individuais sob esse diretório são:
wp.theme.quickrtheme.war\themes\html\Quickr\js\js.jsp
wp.theme.quickrtheme.war\themes\html\Quickr\sideNav.jspf
Antes de fazer essas mudanças, é recomendável salvar cópias desses arquivos do tema.
Carregue o widget no arquivo js.jsp
O arquivo js.jsp file deve ser alterado para carregar o widget Place Statistics a
partir do aplicativo PA_Place_Statistics. O arquivo js.jsp está localizado em:
installedApps\QuickrThemeApp.ear\wp.theme.quickrtheme.war\themes\html\Quickr\js
Primeiro é necessário registrar um caminho de módulo para que o Dojo saiba onde obter
o visualizador de estatísticas. Já existem várias instruções dojo.registerModulePath
no arquivo js.jsp, e a linha a seguir pode ser adicionada abaixo dessas
instruções:
dojo.registerModulePath('com.ibm.quickr.statistics','/lotus/PA_Place_Statistics/js');
Em seguida, uma linha <c:import> deve ser incluída no arquivo js.jsp
para carregar o widget Place Statistics. Inclua um código como este:
<c:import url="/js/PlaceStatisticsViewer.js"
context="/lotus/PA_Place_Statistics"/>
Deve-se ressaltar que, depois que essa referência é colocada no arquivo JSP, o aplicativo /lotus/PA_Place_Statistics no servidor deve ser iniciado para que o tema funcione corretamente.
Atualize o sideNav.jspf para acessar o widget
Agora é possível examinar a alteração do arquivo sideNav.jspf no tema para incluir o
link para lançar a janela do Place Statistics. Esse arquivo está em:
installedApps\QuickrThemeApp.ear\wp.theme.quickrtheme.war\themes\html\Quickr\sideNav.jspf.
Dois campos principais são necessários:
- Parte da marcação HTML para mostrar o link
- Uma nova função em Javascript para abrir o widget
A amostra de arquivo sideNav.jspf fornecido com este artigo contém exemplos desse código; essas seções são marcadas com comentários que contêm o texto “PLACESTATS”. Essas partes devem ser copiadas e coladas na sua cópia do arquivo sideNav.jspf, em vez de substituir a cópia do arquivo no seu servidor pelo arquivo contido neste artigo.
Uma nova função para exibir o widget é colocada na parte inferior do script. É necessário passar o placeId, a raiz de contexto do tema e a raiz de recurso do tema na função para que possam ser passados ao widget.
A marcação para mostrar o link na UI deve estar contida em uma condição baseada na definição da variável isApplicationManager como true, para que o link só seja exibido se o usuário atual for um gerente. Também é necessário conter um pouco de código para obter a raiz de contexto do tema e a raiz de recurso do tema. Essa tarefa é realizada usando o código mostrado na listagem 11.
Listagem 11. JSP para mostrar o link do Place Statistics no tema do Lotus Quickr
<c:if test="${isApplicationManager}">
<div> <% String themeContextRoot = theme.getContextRoot();
String themeResourceRoot = theme.getResourceRoot(); %> <a
href="javascript:;" onclick='showStatistics("<%=cdoGuid%>",
"<%=themeContextRoot%>","<%=themeResourceRoot%>")'>
Place Statistics</a> </div> </c:if > |
O link para acessar o widget é definido como um elemento <a>. Inclui um manipulador de eventos de onclick que chama a nova função para mostrar o widget, passando o placeID, a raiz de contexto do tema e a raiz de recurso do tema.
Para terminar, é necessário alterar o registro de data no arquivo Default.jsp para
que as mudanças no tema entrem em vigor. Esse arquivo está em:
installedApps\QuickrThemeApp.ear\wp.theme.quickrtheme.war\themes\html\Quickr\Default.jsp
Uma forma de alterar o registro de data e hora é abrir o arquivo em um editor de texto e salvá-lo.
Depois que você faz as mudanças, o novo link é mostrado abaixo do menu de navegação à esquerda, como mostra a figura 3.
Figura 3. Navegação à esquerda com o Place Statistics incluído
Quando se clica no link do Place Statistics, é exibida uma janela que se parece com a janela mostrada na figura 4.
Figura 4. Place Statistics exibido na interface com o usuário da Web para gerentes de local
Quando se clica no link Download Statistics na parte inferior da janela, é exibida a janela usual de download do navegador, dando o nome padrão placestatistics.csv ao arquivo. O arquivo pode ser salvo ou aberto usando um programa que aceite arquivos CSV como entrada, como o IBM Lotus Symphony™.
Usando as estatísticas transferidas por download
Agora que você tem um mecanismo para que os proprietários de locais façam o download das estatísticas sobre os locais, eles se interessarão em saber quais estatísticas estão disponíveis e quais relatórios podem ser executados.
Os proprietários de locais podem acessar dados estatísticos em nível de local:
- Número total de conteúdos
- Tamanho total dos conteúdos (KB)
- Número total dos conteúdos incluídos no dia atual
- Número total de conteúdos atualizados no dia atual
- Número total de conteúdos da Web (posts de blog, página de wiki, comentário)
- Número total de documentos
- Número total de conteúdos da Web incluídos hoje
- Número total de conteúdos da Web atualizados no dia atual
- Número total de documentos incluídos no dia atual
- Número total de documentos atualizados no dia atual
- Número total de posts de blog
- Número total de páginas de wiki
- Número total de comentários
A Figura 5 ilustra uma amostra de estatísticas em nível de local transferidas por download em um arquivo com o formato CSV.
Figura 5. Amostra de estatísticas no formato comma-separated value (CSV)
Place level statistic data. Place Name:
test1 ,"Total number of contents","Total size of contents (KB)", "Total number of
contents added today", ......
2010-06-25,17443,1666,4640,2653,8896,8547,424,4881,4216,2430,1240,4371,2861
2010-06-26,17865,3198,8101,3065,11472,6393,4334,3291,3767,1663,1673,4977,488
2010-06-27,17529,4311,6957,4239,11471,6058,3002,4720,3955,1499,162,4389,3918 ......
...... |
É possível abrir o arquivo CSV transferido por download usando Lotus Symphony Spreadsheets, Microsoft Excel ou o aplicativo de planilha de sua preferência e criar gráficos baseados nos dados estatísticos. As Figuras 6 e 7 são dois gráficos baseados no "Número total de conteúdos" e no "Tamanho total dos conteúdos (KB)" usando o Lotus Symphony Spreadsheets.
Figura 6. Exemplo de gráfico que mostra o número de conteúdos dos locais
Figura 7. Gráfico que mostra o tamanho total dos conteúdos
O arquivo CSV que contém os dados estatísticos referentes a esses gráficos está contido no Apêndice 2 deste documento.
Este artigo mostra como usar os serviços do Place Statistics fornecidos no Lotus Quickr 8.5 para apresentar uma UI que mostra os dados e fornece o recurso de exportar os dados estatísticos para outros aplicativos.
A produção de feeds de vários formatos usando o Abdera e a API do WebSphere Portal foi demonstrada, juntamente com o código que mostra como esses feeds podem ser consumidos.
Este artigo também serve como introdução à inclusão de widgets em Dojo no tema do Lotus Quickr 8.5. A técnica de construir uma janela em Dojo e vincular a uma instância disso no tema pode ser usada em várias situações diferentes.
Apêndice 1: amostra de feed Atom
<feed xmlns:td="urn:ibm.com/td"
xmlns="http://www.w3.org/2005/Atom">
<id>urn:lsid:ibm.com:td:statistics</id> <title
type="text">Lotus Quickr Admin Feed</title> <link
href="/adminqcs/rest/statistics/feed" rel="self"></link>
<link href="/adminqcs/rest/QuickrAdmin"
rel="alternate"></link>
<updated>2010-06-09T15:45:25.984Z</updated>
<author> <name>Quickr Admin</name>
</author> <td:total
xmlns:td="urn:ibm.com/td">1</td:total>
<td:statistic-range xmlns:td="urn:ibm.com/td" from="2010-05-07"
to="2010-06-08"></td:statistic-range> <entry
xmlns:td="urn:ibm.com/td"> <link
rel="self"></link> <link
rel="edit"></link>
<id>1F_18M131M418NA60I2JCM5B51021</id> <title
type="text">Place level statistic data. Place Name: Self Join
Library</title>
<published>2010-06-07T23:00:00.000Z</published>
<updated>2010-06-07T23:00:00.000Z</updated>
<td:statistics xmlns:td="urn:ibm.com/td"> <td:property
xmlns:td="urn:ibm.com/td"
key="document_totalNum">1</td:property> <td:property
xmlns:td="urn:ibm.com/td" key="document_size">1</td:property>
<td:property xmlns:td="urn:ibm.com/td"
key="document_createdToday">0</td:property> <td:property
xmlns:td="urn:ibm.com/td"
key="document_modifiedToday">0</td:property>
<td:property xmlns:td="urn:ibm.com/td"
key="document_webdoc">0</td:property> <td:property
xmlns:td="urn:ibm.com/td"
key="document_webdocCreatedToday">0</td:property>
<td:property xmlns:td="urn:ibm.com/td"
key="document_webdocModifiedToday">0</td:property>
<td:property xmlns:td="urn:ibm.com/td"
key="document_libdoc">1</td:property> <td:property
xmlns:td="urn:ibm.com/td"
key="document_libdocCreatedToday">0</td:property>
<td:property xmlns:td="urn:ibm.com/td"
key="document_libdocModifiedToday">0</td:property>
<td:property xmlns:td="urn:ibm.com/td"
key="document_blog_totalNum">0</td:property>
<td:property xmlns:td="urn:ibm.com/td"
key="document_wiki_totalNum">0</td:property>
<td:property xmlns:td="urn:ibm.com/td"
key="document_comment_totalNum">0</td:property>
</td:statistics> </entry> </feed> |
Apêndice 2: arquivo CSV para os gráficos
Place level statistic data. Place Name: test1 ,"Total number of contents","Total size of contents (KB)","Total number of contents added today","Total number of contents updated today","Total number of web contents (blog post, wiki page, comment)","Total number of documents","Total number of web contents added today","Total number of web contents updated today","Total number of documents added today","Total number of documents updated today","Total number of blog posts","Total number of wiki pagess","Total number of comments" 2010-06-25,17443,1666,4640,2653,8896,8547,424,4881,4216,2430,1240,4371,2861 2010-06-26,17865,3198,8101,3065,11472,6393,4334,3291,3767,1663,1673,4977,488 2010-06-27,17529,4311,6957,4239,11471,6058,3002,4720,3955,1499,162,4389,3918 2010-06-28,14208,4323,5054,3620,10080,4128,2581,1121,2473,702,4201,746,2552 2010-06-29,12443,1301,3867,981,7597,4846,2371,2501,1496,749,217,2540,2469 2010-06-30,15494,2366,2938,1801,10809,4685,2701,2903,237,4286,4566,3290,252 2010-07-01,16620,4674,6849,627,8317,8303,2249,4931,4600,2813,3562,397,2109 2010-07-02,9927,1950,1054,3002,7314,2613,607,2125,447,4642,145,2428,4134 2010-07-03,8095,2436,3233,4363,3595,4500,1293,2074,1940,3416,93,20,2189 2010-07-04,19311,4066,3796,1185,14135,5176,3450,4040,346,1976,4446,2514,3725 2010-07-05,19913,2261,9272,3160,11316,8597,4403,1798,4869,1574,894,1877,4142 2010-07-06,12321,1792,5029,2556,8998,3323,3262,1967,1767,1133,3963,814,959 2010-07-07,16604,2194,5726,371,12048,4556,2828,4418,2898,1580,2932,2919,3369 2010-07-08,12897,2147,6183,2345,7288,5609,2505,703,3678,2593,2136,668,1979 2010-07-09,12351,3222,5878,38,8290,4061,4402,1953,1476,1439,488,3182,218 2010-07-10,12801,2088,7208,4206,7752,5049,2606,2225,4602,1547,3584,1414,148 |
| Nome | Tamanho | Método de download |
|---|---|---|
| place.zip | 3.51MB | HTTP |
Informações sobre métodos de download
- Participar do fórum de discussão.
- Consulte a documentação do Lotus Quickr 8.5 para WebSphere Portal.
- Consulte o wiki do Lotus Quickr.
- Consulte o Centro de Informações do WebSphere Portal V6.1.5.
- Confira o Dojo
Campus , um site que contém vários exemplos de Dojo.
- Saiba mais sobre o Dojo Toolkit, incluindo documentação e
exemplos de Dojo.
- Saiba mais sobre o projeto Apache Abdera.

Jim Antill é desenvolvedor de software e trabalha com softwares sociais e de colaboração em equipe. Jim contribuiu para o release do Lotus Quickr 8.5, trabalhando principalmente nos aspectos de gerenciamento de membros do produto. É possível entrar em contato com ele pelo e-mail ANTILLJI@ie.ibm.com.
Nan Shi é engenheira consultora de software e trabalha com softwares sociais e de colaboração em equipe. Nan tem mais de 10 anos de experiência em consultoria de soluções de TI e desenvolvimento de software. Ela contribuiu para o componente Lotus Quickr Admin Console como líder técnica e desenvolvedora do Lotus Quickr 8.5. É possível entrar em contato com ela pelo e-mail nanshi@cn.ibm.com.
