Elo perdido - Linux Magazine

Propaganda
Apache Jena | TUTORIAL
Apache Jena
TUTORIAL
Elo perdido
Conheça um novo método para processar,
combinar, analisar e apresentar informações
ocultas em dados brutos usando a
plataforma Jena: web semântica e dados
vinculados (linked data) para Java.
por Ian Dickinson
O
compartilhamento de dados é
um dos tópicos mais quentes
atualmente na computação.
As fontes podem ser desde APIs do Facebook, dados científicos abertos e até
dados públicos gerados pelo governo
e disponibilizados gratuitamente. Por
todos os lados, há alguém liberando
novos dados para serem explorados
por desenvolvedores e cientistas de
dados [1]. Nesse cenário, espera-se
que projetistas, exploradores de dados
e desenvolvedores criem aplicativos
de valor para usuários finais, com recursos novos e interessantes.
Sendo um desenvolvedor, como
abordar essa montanha de informações? Que ferramentas e técnicas
serão úteis? Muitas abordagens estão
disponíveis, variando desde de simples análise de arquivos com valores
separados por vírgulas (CSV) em planilhas de dados, consulta em bancos
de dados relacionais, chegando a ferramentas de larga escala e distribuídas
de análise de informações na nuvem.
Como cada técnica possui vantagens e desvantagens, e ao invés de
fazer um levantamento completo de
todas elas, vamos focar apenas em
dados semânticos vinculados, mais
especificamente na plataforma Jena.
é autor do artigo123, sobre Jena” poderia ser escrito com a seguinte linha
de código, podendo ser representado
graficamente como na figura 1.
A web semântica
<ian> <autor-do> <artigo123>.
<artigo123> <tem-o-assunto> “Jena”.
Não por acaso, as técnicas e ideias da
web semântica acabaram ganhando
uma reputação de complexidade e
dificuldade. O modelo de XML padrão do RDF (Resource Description
Framework) é grosseiro, razão pela qual
modelar o mundo real pode revelar nuances conflituosas. No entanto, em seu
núcleo estão duas ideias importantes.
A primeira é a de que estruturas ricas
e expressivas de dados, descrevendo informações sobre determinado assunto,
podem ser construídas a partir de um
conjunto de informações simples sobre o relacionamento entre pares de
elementos: duas entidades nomeadas
ou uma entidade nomeada e um valor,
como um número.
Um exemplo simples: suponhamos
que o identificador para o artigo que
você está lendo é artigo123 (voltaremos
a isso em breve); então, a sentença “Ian
Figura 1: Uma representação gráfica da sentença.
Linux Magazine #80 | Julho de 2011
Matematicamente, a estrutura exemplificada na figura é um gráfico direcionado, que rotula os dois nós e suas
extremidades. Para ser simples, irei me
referir a ele apenas como um gráfico.
Uma vez que cada declaração contém
tipicamente três elementos – o assunto,
o objeto e o nome do predicado que
os liga –, o termo triple é usado para
denotar tal declaração. Isso leva a outras
expressões como triplestore, para um
banco de dados constituído de triples.
A segunda das duas ideias importantes é o nome das coisas que não
são valores, que é representado por
URIs. Um URI (Uniform Resource
Identifier, ou Identificador de Recursos
Uniforme) refere-se a um conjunto
de identificadores definidos pela RFC
2396. O mais importante desse conjunto é que ele inclui identificadores
http:// para websites familiares. O uso
de URIs por identificadores tem duas
consequências importantes: primeiro, todos os identificadores formam
eficazmente um grande namespace,
minimizando as chances de usar acidentalmente um mesmo nome para
63
TUTORIAL | Apache Jena
se referir a coisas diferentes. Segundo, a maioria dos URIs podem ser
“resolvidos” ou procurados com um
navegador de Internet, de forma que
dê informações sobre o termo que
está sendo identificado.
Além das consequências óbvias
de ter o significado, ou a semântica,
declarado explicitamente, isso significa também que o responsável pela
manutenção do domínio web que
hospeda o identificador tem alguma
autoridade sobre o uso ou significado pretendido do termo. Além disso, qualquer um pode reutilizar um
termo publicado em um domínio.
Aliás, a web semântica acaba encorajando esse tipo de ação. No entanto, somente pessoas com direitos de
escrita direta sobre aquele domínio
podem atualizar o significado mais
diretamente associado aos termos.
Então, para atualizar o exemplo com
o uso de URIs, precisamos considerar
quais identificadores usar. Sempre
que possível, deve-se tentar reutilizar
vocabulários existentes. O vocabulário
Dublin Core Metadata Initiative [2]
possui um conjunto bem estabelecido
de vocábulos para “metadados conhecidos”, como o autor de uma matéria.
O próprio artigo, aliás, eventualmente
ganhará uma identidade no espaço
web de quem publica.
Por enquanto, isso é um rascunho. Imagine portanto o URI padrão
http://epimorphics.com/documents/
draft#jena-1. O URI para dar cré-
Listagem 1: Código gerado pelo Schemagen no Doap.Java
01 /** URL de uma homepage de um projeto, associada com exatamente
um projeto. */
02 public static final Property homepage =
m_model.createProperty( "http://usefulinc.com/ns/doap#homepage" )
Listagem 2: O núcleo do Init.java
01 public void run() {
02 if (noTDB() || hasOption( "f" )) {
03
// (re)criar a imagem TDB
04
FileUtils.deleteQuietly( getTDBFile() );
05
FileUtils.forceMkdir( getTDBFile() );
06
Dataset dataset = TDBFactory.createDataset( getTdbLocation() );
07
08
// o nome do projeto é um argumento requisitado
09
String projectName = getArgs()[0];
10
String projectURI = projectNamespace() + projectName;
11
Resource project = dataset.getDefaultModel().
createResource( projectURI );
12
13
project.addProperty( RDF.type, DOAP.Project );
14
project.addProperty( DOAP.name, projectName );
15
16
// adicione descrições a partir de opções de linhas de
comando
17
addOptionalProperty( project, DOAP.shortdesc, "s" );
18
addOptionalProperty( project, DOAP.description, "d" );
19
20
System.out.println( String.format( "Criada nova descrição
DOAP para %s projetos com %s triples", projectName,
dataset.getDefaultModel().size() ) );
21 }
22 else {
23
System.out.println( "Logbook já existe, nenhuma ação sendo
tomada" );
24 }
25 }
64
ditos ao autor deve ser tratado com
cuidado, porque uma pessoa não é
um recurso de informação na web.
Essa questão, amplamente debatida,
tem uma série de soluções que vão
além do escopo deste artigo. Um
URI elaborado com a classe Person
do vocabulário Friend of a Friend
(FOAF, ou amigo do amigo) [3], será
suficiente. Com essas mudanças, o
exemplo fica assim:
<http://epimorphics.com/rdf/
staff#ian> rdf:type foaf:Person.
<http://epimorphics.com/rdf/
staff#ian> dcterms:creator.
<http://epimorphics.com/documents/
drafts/jena-1>.
<http://epimorphics.com/documents/
drafts/jena-1> dcterms:subject
“Jena”.
<http://epimorphics.com/documents/
drafts/jena-1> rdf:type
foaf:Document.
Claro que poderíamos entrar em
muitos detalhes sobre as várias tecnologias de web semântica: linguagens
de consulta, armazenamento persistente, vocabulários específicos e assim
por diante. Para focar na prática, no
entanto, falareremos apenas sobre
como os triples podem ser manipulados com código Java usando o Jena.
Apache Jena
O Jena é um framework Java de código
aberto para criar, armazenar, manipular
e consultar dados semânticos na web.
Foi desenvolvido originalmente por pesquisadores dos laboratórios da HP no
Reino Unido e tem sido amplamente
utilizado desde seu primeiro lançamento
em 2001. Em 2008, o time do Jena deixou a HP e, em 2009, o Jena se tornou
um projeto incubado na Apache [4].
Ao invés de listar os recursos técnicos do Jena, vamos introduzir a
abordagem de algumas partes do
framework enquanto trabalhamos
por meio de exemplos. Algumas
linhas de terminologia básica, no
entanto, ajudarão.
O gráfico descrito previamente é
gerenciado no código Jena como um
www.linuxmagazine.com.br
Apache Jena | TUTORIAL
objeto Model. O objeto é, nos termos do
Java, uma interface ou especificação abstrata que permite ao Jena fornecer vários
tipos de objetos Model (armazenado na
memória, no disco, sem interferência
de disco etc.) com uma API comum.
O Model é uma das abstrações chaves
do Jena para lidar com RDF.
Um recurso no modelo, denotado
por uma URI, é representado por um
objeto Resource, enquanto um valor,
como um número, é um Literal. O
predicado que liga os nós do gráfico
são objetos Property, e Property é uma
subclasse de Resource. Finalmente,
um objeto Statement representa um
triple. Um determinado Statement terá
um assunto Resource, um predicado
Property e um objeto, que pode ser
tanto um Resource quanto um Literal.
Chega de teoria. Vamos ver um
pouco de código.
Exemplo de aplicativo
Suponhamos que você queira compartilhar detalhes com outros desenvolvedores de código aberto, como, por
exemplo, o nome do projeto, a localização do repositório fonte, quem está
trabalhando nele e assim por diante.
Felizmente, um vocabulário já existe
para gravar esse tipo de informação:
DOAP (Description of a Project, ou
descrição de um projeto) [5] [6].
Coincidentemente, os projetos da
Apache são encorajados a usar arquivos DOAP. Embora o DOAP forme o
núcleo de um caderno de notas de um
aplicativo, você deve ter a possibilidade
de adicionar outras informações que
pareçam relevantes sem ser restringido
por esquemas rígidos de dados.
Projetar uma ferramenta visual rica
em recursos para criar e editar arquivos DOAP está além do escopo deste
artigo. Em vez disso, tenho a meta de
criar um conjunto de ferramentas de
linhas de comando e atualizar um diário de bordo, imprimir um relatório e
enriquecê-lo ao mesclar informações
a partir de uma fonte externa.
O objetivo deste miniprojeto é gerar
e manter dados DOAP para um projeto em particular; assim, eu presumirei
Listagem 3: Consultar o ref:type
01 /** O recurso com URI tem rdf:type t? */
02 public boolean hasType( String u, Resource t ) {
03 return getModel().getResource( u ).hasProperty( RDF.type, t );
04 }
Listagem 4: Acumular documentos RDF descobertos por
meio do sindice.com
01 // fase de leitura: adicione os documentos em um modelo combinado
02 Model m = ModelFactory.createDefaultModel();
03 for (ResIterator i = sIndex.listSubjectsWithProperty( RDF.type,
Sindice.Result ); i.hasNext(); ) {
04 String docURL = i.next().getPropertyResourceValue(
Sindice.link ).getURI();
05
06 // poderíamos ser mais sofisticados sobre a proveniência dos recursos
07 try {
08 m.read( docURL );
09 }
10 catch (RuntimeException e) {
11 // alerte sobre falha de leitura, mas siga na leitura de
outros documentos
12 log.warn( String.format( “Failed to retrieve from %s
because: %s”, docURL, e.getMessage() ) );
13 }
14 }
Linux Magazine #80 | Julho de 2011
que os dados DOAP estão armazenados
no diretório do próprio projeto. Com
o tempo, meu objetivo poderá ser o
de desenvolver a ferramenta para armazenar mais do que simples dados
DOAP, talvez até incluir controle de
tempo, entre outras informações. Por
essa razão, vou generalizar o nome e
chamá-lo simplesmente de “Projeto
Diário de Bordo”, representado pelo
termo plb. Para brincar com o código,
veja o quadro 1.
Uma escolha razoável para o projeto
seria armazenar os dados em um simples arquivo RDF. No entanto, como
meu o objetivo é ilustrar os vários recursos do Jena, vamos armazenar o RDF
gerado em um triplestore persistente.
O Jena tem uma série de soluções de
armazenamento RDF persistentes.
Vamos usar o TDB, customizado para
triplestore, com a capacidade de armazenar um grande números de triples
com eficiência sem requerer um banco
de dados relacional adicional, como o
MySQL, por exemplo.
O TDB pode suportar ordens de
magnitude muito maior que aquelas
que eu vou gerar agora, mas ele torna bem direta a tarefa de atualizar o
banco de dados persistente.
Quadro 1: Teste o código
Para o projeto, você precisará de
um compilador Java que suporte
Java 1.6. Eu estou usando também o Maven para gerenciar o
Jena e outras bibliotecas dependentes. Então, você precisará da
versão mais recente do mvn. Finalmente, o código está no repositório Git e o exemplo também lida
com metadata Git, de modo que
você precisará do Git instalado. O
pom.xml, no diretório raiz do projeto, lista as dependências de software. O Maven instalará todos automaticamente como necessário.
Para clonar o projeto do repositório
Git, use o seguinte comando:
git clone [email protected]:
epimorphics/epimorphics-open/
jena-plb-tutorial.git
65
TUTORIAL | Apache Jena
Início do projeto
O problema tem quatro componentes: inicializar o projeto, atualizar a
descrição DOAP manualmente, aumentar a descrição automaticamente e reportar o perfil DOAP. Cada
componente é chamado pela linha
de comando (quadro 2).
Inicializar o projeto é algo direto:
você precisará criar o elemento de
armazenamento TDB (ou recriar se
o usuário quiser forçar a criação de
um novo elemento de armazenamento) e adicionar um recurso root para
representar o projeto DOAP que estou descrevendo. Criar um elemento de armazenamento TDB requer
um diretório para os dados – vamos
usar o ./.plb/tdb por padrão – e um
chamado Java. O chamado é uma
linha getTdbLocation(), método que
retorna uma string especificamente
no diretório TDB.
Dataset dataset = TDBFactory.
createDataset( getTdbLocation() );
Criar o recurso root para o projeto é
conceitualmente simples: é preciso somente um URI para denotar o projeto e
esse deve ser atribuído ao doap:Project.
Aqui, doap: é o componente namespace
do URI e se expande para http://usefulinc.com/ns/doap#, enquanto Project é o
nome de uma classe RDFS. Matematicamente, classes RDFS (RDF Schema
ou Esquema RDF) correspondem a
conjuntos de coisas que compartilham
características semelhantes – o conjunto
de todas as coisas que são descrições de
projetos, por exemplo.
Para desenvolvedores, é interessante pensar nas classes RDFS como
análogas aos types na linguagem Java
ou outras linguagens de programação. Tenha em mente, no entanto,
que as classes Java e as classes RDFS
têm diferenças importantes. Em particular, à medida que você descobre
mais informações sobre um recurso,
você poderá achar que se trata de um
membro de uma classe que você não
sabia de que fazia parte. Além disso,
66
um recurso pode ser membro de muitas classes ao mesmo tempo.
Obter o código Java para fazer com
que o recém criado projeto seja membro
da classe doap:Project vai requerer um
novo triple, com o projeto como assunto, o predicado especial rdf:type como
propriedade e um recurso denotando
a classe doap:Project como um objeto.
O URI doap:Project não muda (a não
ser que o esquema mude), então este
será definido como constante. Embora
seja possível escrever manualmente a
declaração de uma constante no código, correríamos o risco de fazer erros de
transcrição e criar problemas de manutenção com a mudança de esquema.
Felizmente, o Jena oferece uma
ferramenta que gera um código Java
automaticamente a partir de um arquivo RDFS, o schemagen. A classe Java
gerada define constantes para cada uma
das classes, propriedades e recursos in-
dividuais definidos no arquivo. A ferramenta Schemagen pode ser executada
a partir da linha de comando ou como
um plugin Maven [7]. Uma amostra
do código gerado aparece na listagem
1. Os vocabulários completos estão
incluídos no projeto para download.
Considerando que eu tenho acesso às
propriedades e classes DOAP por meio
da classe DOAP.java, o início do projeto
é direto, como mostrado na listagem 2.
Inclusão manual no
diário de bordo
Muitos bits de informação útil sobre
um projeto devem ser capturados,
inclusive as várias propriedades diferentes utilizadas pelo DOAP. Assim,
eu quero que meus usuários possam
adicionar informações de forma incremental. No entanto, é necessário
atingir um balanço na interface apre-
Listagem 4: Acumular documentos RDF descobertos por
meio do sindice.com
01 // fase de leitura: adicione os documentos em um modelo combinado
02 Model m = ModelFactory.createDefaultModel();
03 for (ResIterator i = sIndex.listSubjectsWithProperty(
RDF.type, Sindice.Result ); i.hasNext(); ) {
04 String docURL = i.next().getPropertyResourceValue(
Sindice.link ).getURI();
05
06 // poderíamos ser mais sofisticados sobre a proveniência dos recursos
07 try {
08 m.read( docURL );
09 }
10 catch (RuntimeException e) {
11 // alerte sobre falha de leitura, mas siga na leitura de
outros documentos
12 log.warn( String.format( "Failed to retrieve from %s
because: %s", docURL, e.getMessage() ) );
13 }
14 }
Listagem 5: Modelo de consulta
01 String queryString = String.format( "describe ?s where
{?s <%s> \"%s\"}", FOAF.mbox_sha1sum.getURI(), mboxSha1 );
02 // analise a consulta
03 Query query = QueryFactory.create( queryString ) ;
04 // vincule ao modelo
05 QueryExecution qexec = QueryExecutionFactory.create(
query, collected );
06 // faça a consulta
07 dev.getModel().add( qexec.execDescribe() );
www.linuxmagazine.com.br
Apache Jena | TUTORIAL
sentada aos usuários. Como não há
modelo de dados fixo, o RDF permite
que qualquer predicado seja anexado
a qualquer recurso, algumas vezes declarado como “qualquer um pode dizer
qualquer coisa sobre qualquer coisa”.
Esse modelo pode ser muito poderoso, mas tanta abertura pode dificultar as coisas. Por exemplo, há algumas
restrições na estruturação da interação
do usuário. Nesse caso, não espero que
os usuários digitem uma propriedade
URI completa ou linha de comando só
para adicionar um triple para a descrição do projeto; então, permitirei que
qualquer propriedade no vocabulário
do DOAP seja abreviada somente com
seu nome de local, menos o namespace. Os usuários digitarão algo como:
$> plb set language Java
$> plb set -r release 1.0.1
Esses dois comandos adicionam valores para doap:language e
doap:release; a bandeira -r substitui um valor existente armazenado.
O código RDF específico na classe
de ação Set é pequeno: a maior parte
do código é ocupada com checagem
de rotina e manipulação de argumen-
tos. A definição da classe completa
pode ser encontrada no download.
Com Jena, toda informação de
estado é mantida no objeto Model.
No entanto, um objeto Resource
contém referência para o Model que
o contém. Então, eu posso perguntar ao Resource pelos seus triples relacionados, ou seja, pergunto se um
determinado URI corresponde ao
recurso com um rdf:type em particular (aqui atribuído ao parâmetro
type; listagem 3).
Dado um Resource denotando o
projeto, posso adicionar um novo
triple com esse recurso como um
assunto, usando o método addProperty. Já que eu optei por usar um
modelo baseado em TDB persistente,
eu não preciso fazer uma chamada
separada para salvar os triples atualizados no disco.
Dados automáticos
no diário de bordo
Até então, eu criei um novo diário
de bordo usando TDB e uma armazenagem triple, defini um recurso
para representar o projeto e permiti
que os usuários anexassem algumas
propriedades à linha de comando.
É um começo sólido, mas não fez
muito ainda pela web semântica e
os princípios de dados ligados.
Meu projeto tem alguns desenvolvedores. Deste modo, vamos assumir
que eu quero anotar no meu diário
de bordo quaisquer informações que
possam ser coletadas sobre eles para
ter a visão mais fiel possível sobre
o projeto. Para evitar questões de
privacidade, vamos usar somente
informações públicas.
Qual seria a estratégia? Se o projeto
está usando um sistema de gerenciamento de recursos, posso listar todos
eles facilmente. Nesse tutorial, vou
presumir que o código é gerenciado
por um repositório Git. Algum processamento simples do log do Git
listará os desenvolvedores por nome
e e-mail e podemos usar o endereço de e-mail como uma chave para
reunir mais dados.
Amigo do amigo (Friend of a
Friend ou FOAF [8]) é outro vocabulário RDF usado amplamente. As pessoas utilizam FOAF para
publicar dados pessoais, como
Listagem 6: Listar todos os desenvolvedores do projeto
01 $ sp="prefix foaf: <http://xmlns.com/foaf/0.1/> prefix doap: <http://usefulinc.com/ns/doap#> prefix
plb: <http://www.epimorphics.com/tutorial/plb#> prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
02 $ tdbquery --loc=.plb/tdb "$sp select ?p ?e ?w {?p a doap:Project . ?p doap:developer ?d. optional
{?d foaf:mbox ?e ; foaf:homepage ?w}}"
03 -------------------------------------------------------------------------------04 | p
| e
| w
|
05 ================================================================================
06 | plb:plb | "mailto:[email protected]" | <http://www.iandickinson.me.uk> |
07 | plb:plb | "mailto:[email protected]"
| <http://www.iandickinson.me.uk> |
08 --------------------------------------------------------------------------------
Listagem 7: Listar todas as propriedades do projeto
01
02
03
04
05
06
07
08
09
10
$ tdbquery --loc=.plb/tdb "$sp select ?p ?o where {?proj a plb:root . ?proj ?p ?o} order by ?p"
---------------------------------------------------------------------------------------| p
| o
|
========================================================================================
| doap:description | "A Jena tutorial showing how to create DOAP project descriptions" |
| doap:developer | <http://www.iandickinson.me.uk/rdf/foaf#ian>
|
| doap:name
| "plb"
|
| doap:shortdesc | "Jena PLB tutorial"
|
| rdf:type
| doap:Project
|
----------------------------------------------------------------------------------------
Linux Magazine #80 | Julho de 2011
67
TUTORIAL | Apache Jena
websites, detalhes de contato, interesses e amigos que conhecem
por referência de perfis de outros
amigos. A princípio, eu poderia
usar esses detalhes do log inicial
para procurar informações públicas
dos membros e adicionar automaticamente ao diário de bordo. Na
história inicial do FOAF, a prática
de disfarçar endereços de e-mail
para evitar spams era uma medida
comum contra estes; assim, precisamos buscar pela soma SHA1 dos
endereços de e-mail dos meus desenvolvedores. Um algoritmo ideal
para obter essa informação seria:
for each unique committer C
let m be the email address of C
let s be sha1( m )
run the sparql query:
describe ?person where
{?person foaf:mbox_sha1sum
“value of s”}
A linguagem SPARQL é a padrão
para fazer consultas em armazenagens triple RDF e é totalmente suportada pelo Jena. Ela tem quatro
verbos de consulta:
Quadro 2: Empacotador de
linhas de comando
Uma variedade de comandos pode
ser executada de um shell. Em vez
de um script Bash para cada um
deles, um script empacotado, plb,
pode chamar um conjunto de comandos diferentes. Veja o exemplo:
plb init test-project
O script Bash plb chama um programa Java para desempenhar o
comando predefinido no primeiro
argumento, com a convenção de
que um comando cmd corresponde
a classe Java com.epimorphics.plb.
Cmd. Para ter dependências no caminho da classe, o script empacotador
executa o programa com mvn:exec,
que, por sua vez, executa um programa Java arbitrário com todas as
dependências do pom.xml, baixando
as dependências que faltam antes,
se necessário. O script Bash está no
diretório bin do projeto plb.
68
➧ select: entrega linha de valores
correspondentes, semelhante às armazenagens relacionais SQL;
➧ ask: confirma se um padrão de
consulta pode ser correspondido;
➧ construct: cria um novo gráfico
com o uso de templates e padrões e
consultas;
➧ describe: transfere a responsabilidade de retornar uma descrição
útil de um recurso para um servidor,
suportando especificamente o caso
no qual o cliente não sabe a estrutura do gráfico contendo um recurso
em particular.
Tipicamente, o servidor retorna
algum tipo de descrição vinculada [9].
O ponto chave, aqui, é que o cliente – meu programa – não sabe os esquemas que podem ser usados para
anotar um recurso particular, razão
pela qual os verbos descritos são úteis
para obter um conjunto de dados que
podem ser processados localmente.
O único problema com meu algoritmo, é que, no momento da escrita,
um serviço disponível publicamente
que agregava dados FOAF de múltiplos pontos de publicação ficou
indisponível. No entanto, o projeto
de serviço de pesquisa Sindice [10]
proporciona um índice navegável
para todos os documentos RDF que
possam ser detectados. Posso emendar
meu algoritmo da seguinte maneira:
for each unique committer C
let m be the email address of C
let s be sha1( m )
query sindice.com for docs
mentioning s
for each found document
accumulate the doc
into local model L
run the sparql query against model L:
describe ?person where
{?person foaf:mbox_sha1sum
“valor do s”}
A princípio, o programa poderia
obter uma lista de desenvolvedores de
qualquer fonte de sistema de gerenciamento, no entanto o tutorial somente
lida com o repositório Git. O retorno
daquela parte de código é um Model do
Jena, contendo recursos denotando os
desenvolvedores no projeto, cada um
com um foaf:mbox denotando seu endereço de e-mail como dado ao Git.
O que são esses recursos, no entanto?
Uma vez que eu não sei as reais identidades dos desenvolvedores, apenas um
dos endereços de e-mail, que recurso
URI deve ser usado para denotar cada
desenvolvedor? Eu poderia criar um
identificador, porém o RDF também
permite um tipo especial de recurso
chamado recurso anônimo (anonymous
resource). Esse recurso age como qualquer outro, exceto pelo fato de não ter
identidade conhecida. Por razões históricas, é normalmente chamado de
bNode, que pode ser usado como um
alocador de recurso, sobre o qual conheço a existência e propriedades, mas
não conheço a identidade. No exemplo
plb, eu crio bNodes para denotar os
desenvolvedores antes de reunir informações sobre eles de fontes públicas.
A API Sindice é muito fácil: é só
chamar http://sindice.com/search?q=
com o termo de busca depois do sinal de igual (=). Esse endereço usa
negociação de conteúdo HTTP
para determinar o formato no qual
deve retornar resultados, o que faz
da busca algo muito natural para o
Jena, uma vez que o método Model.
read() faz com que o tipo favorito de
conteúdo vá ao RDF. Para procurar
por todos os documentos que mencionam uma caixa de correio SHA1
em particular, mboxSha1, tudo o que
eu tenho de fazer é digitar:
Model sIndex = ModelFactory.
createDefaultModel();
sIndex.read( “http://api.sindice.
com/v2/search?q=” + mboxSha1 );
O Model resultante contém um
conjunto de recursos sindice:Result
denotando as buscas. Para cada uma
das buscas, eu tento executar o link
para o documento original, tendo
em mente que isso pode falhar se o
documento foi indexado há algum
tempo. A listagem 4 mostra o processo.
www.linuxmagazine.com.br
Apache Jena | TUTORIAL
Dado um modelo que contenha
triples potencialmente relevantes
e acumuladas, eu posso executar
a consulta descrita (listagem 5).
Aqui, collected (linha 5) é o modelo
contendo os triples dos documentos que foram coletados da web e
dev (linha 7) são os recursos para o
desenvolvedor sendo adicionados à
descrição do projeto.
Resta um passo. Eu utilizei muitas informações da web. O modelo
inclui uma série de fontes denotando a mesma pessoa, alguma delas
sendo bNodes; e eu gostaria de simplificar o gráfico, mesclando essas
fontes redundantes.
O Jena não tem uma ferramenta
interna para fazer isso, mas não é
difícil com a propriedade foaf:mbox_
sha1sum, que é uma boa chave de
desambiguação. Em geral, esse
tipo de mesclagem de informação pode ser bem complexo, mas
não com essa simples abordagem.
Finalmente, adicionei os resultados da consulta describe para meu
modelo TDB persistente.
Relatórios
A SPARQL é útil também quando
quero produzir relatórios simples a
partir do diário de bordo. O comando tdbquery está disponível na instalação completa do Jena e executa
uma consulta contra um modelo
TDB da linha de comando. Por
exemplo, eu poderia listar todos os
desenvolvedores no projeto com os
seus sites, se conhecidos (listagem
6), ou listar cada propriedade do
projeto (listagem 7). Obviamente,
eu poderia escrever relatórios muito
mais abrangentes, mas precisaria de
tutoriais separados para isso.
Conclusão
Meu objetivo com este artigo foi introduzir os recursos Jena para uma tarefa
prática. Não pretendo, com isso, oferecer a melhor forma de gerar perfis
DOAP. Na verdade, o plugin Maven
Linux Magazine #80 | Julho de 2011
faz esse trabalho. No entanto, a combinação de um formato flexível de dados
e a habilidade de mesclar informações
de múltiplas fontes na web mostra as
possibilidades tanto do Jena em relação à abordagem de web semântica e
dados vinculados em geral.
O Jena está, atualmente, incubado
na Apache, e contribuições são bem
vindas: bugs, sugestões, correções etc.
Mais informações estão disponíveis
no site do Jena. ■
Gostou do artigo?
tigo?
Queremos ouvir sua
ua opinião.
Fale conosco em
m
[email protected]
gazine.com br
Este artigo no nosso
osso site:
te:
http://lnm.com.br/article/5494
br/art /549
Mais informações
[1] “What is Data Science?”
por Mike Loukides,
O’Reilly Radar, junho de
2010: http://radar.
oreilly.com/2010/06/
what-is-data-science.html
[2] Dublin Core Metadata
Initiative: http://
dublincore.org/
[3] Vocabulário FOAF: http://
xmlns.com/foaf/spec/
[4] Projeto Apache Jena: http://
incubator.apache.org/jena
[5] Vocabulário DOAP: http://
usefulinc.com/ns/doap#
[6] Página DOAP: http://
trac.usefulinc.com/doap
[7] Código-fonte Jena: http://
jena.sourceforge.
net/downloads.html
[8] Projeto Friend of a
Friend: http://www.
foaf-project.org/
[9] Descrição vinculada:
http://goo.gl/rOjmt
[10] Serviço Sindice: http://
www.sindice.com/
69
Download