Skip to content
This repository has been archived by the owner on Aug 7, 2018. It is now read-only.

Conversão de contexto em URN LEX

Peter edited this page May 2, 2015 · 3 revisions

A URN LEX é o padrão adotado pelo LexML-Brasil e outras autoridades pelo mundo, para identificar univocamente e de forma transparente documentos legislativos e jurídicos. Quanto à URN LEX ser um nome transparente, ver o mini-tutorial.

Sintaticamente, conforme lembrado neste resumo, a URN LEX deve estar toda em letras minúsculas (sem acentos e com pontos no lugar de espaços) e deve iniciar com urn:lex:<localidade>:<autoridade>:<tipo-documento>
podendo ser seguida por :<descritor>.

Na issue #273 foi proposto o uso das URN LEX para poder expressar links na interface final com o usuário, e para garantir a interoperabilidade do banco de dados do Radar com outros Dados Abertos.

##O problema que a URN LEX resolve ## No Radar temos tabelas com metadados das proposições legislativas (título, data, código, etc.), e para designar uma proposição específica, basta chamá-la pelo seu id,

SELECT * FROM modelagem_proposicao WHERE id=123

retorna tudo o que queremos saber da proposição de ID 123. Mas o público não vai referir o ID 123, ele vai referir a "Proposição legislativa 00029, de 2011, do tipo PLV do Senado Federal Brasileiro", que é de fato uma das alternativas de se referir ao documento, ou seja, o seu nome ou apelido "completo". Quais os campos (ano, tipo, autoridade, etc.) em uma cláusula SQL WHERE garantem unicidade? quais são mais importantes para o público? e para trocar dados com sistemas externos?

Tudo isso já foi estudado e resolvido pela equipe do LexML, e pelo fato deles poderem impor certas convenções que vem sendo adotados, inclusive pelo E-PING. Qualquer sistema vai conversar com o Radar se os registros da tabela modelagem_proposicao apresentarem mais um campo, contendo a sua URN LEX. Como o registro (em JOIN com a tabela modelagem_casalegislativa) oferece todas as informações de "contexto", o problema aqui se resume à conversão de contexto em URN LEX. É um problema típico de mapeamento "de para".

O problema não é grande, a consulta abaixo mostra exatamente quantos registros precisam ser mapeados,

SELECT DISTINCT esfera,nome,sigla
FROM 
  modelagem_casalegislativa c INNER JOIN  modelagem_proposicao p
  ON p.casa_legislativa_id = c.id
ORDER BY 1,2,3;  -- menos de 30 itens no DUMP de 2015-04

A primeira alternativa que se coloca é realizar manualmente o mapeamento... Mas é interessante para escalabilidade e confiabilidade automatizar o tanto quanto for possível.

Metodologia para construir o mapeamento

Apesar de existirem glossários razoáveis, a melhor fonte para obter os descritores que precisamos aqui no Radar, está no Git do LexML. Justamente o mapeamento das siglas para <autoridade> e <tipo-documento> já foi realizado por eles, e está bem estruturado em XML (ex. nos dados abertos do Senado), sendo o melhor já pegar tudo junto num XML só, que é o lexcomp/configuracao.xml.

Solução, parte 1

Como já indicado na issue #273, uma VIEW SQL para as proposições é a solução,

CREATE VIEW modelagem_proposicao_lex AS
SELECT 
  modelagem_radar2lex(c.esfera,c.nome,sigla) || ':' || p.ano || ';'|| p.numero as urnlex,
  p.*,  
  c.nome,  c.nome_curto,    -- autoridade
  c.esfera,   c.local        -- jurisdição
FROM 
  modelagem_casalegislativa c INNER JOIN  modelagem_proposicao p
  ON p.casa_legislativa_id = c.id;

CREATE TABLE modelagem_prefixoLexml (
   chave_radar text,
   prefixolex text,
   UNIQUE (chave_radar),
   UNIQUE (prefixolex)
   );

CREATE FUNCTION modelagem_radar2lex(text,text,text) RETURNS text AS
$func$
  SELECT prefixolex FROM modelagem_prefixoLexml WHERE chave_radar=$1||':'||$2||':'||$3;
$func$ LANGUAGE sql IMMUTABLE;

A função radar2lex() pode ser utilizada de outras formas. Ela é simples porque recupera dados de uma tabela faz papel de cache dos mapeamentos.

Solução, parte 2

A URN LEX dá preferência à expressão de <tipo-documento> por extenso, ao invés do uso de siglas. O padrão LexML oferece vocabulários de apoio, que permitem o mapeamento das siglas. No configuracao.xml são listados primeiramente os termos completos (ex. "Lei Complementar" por extenso), deixando a interpretação das abreviações restritas ao contexto (ex. "PL" significa "Lei Complementar" apenas no contexto camara.deputados).

Como não há acoplamento entre autoridade e tipo, pode-se primeiro resolver o mapeamento de autoridades, na mesma tabela,

 INSERT INTO modelagem_prefixoLexml (chave_radar,prefixolex) VALUES
  ('FEDERAL:Senado:', 'br:senado.federal:'),
  ('FEDERAL:Câmara dos Deputados:', 'br:camara.deputados:'),
  ('MUNICIPAL:Câmara Municipal de São Paulo:', 'br;sao.paulo;sao.paulo:camara.municipal:');

Com isso podemos explorar todos as siglas e urns do configuracao.xml... Supondo que o XML tenha sido transferido para uma tabela tmp_lexml_configuracao (elemento TipoDocumento), temos:

SELECT DISTINCT esfera ||':'||nome||':'||sigla as prefix_radar, t.xmlid
FROM   modelagem_casalegislativa c INNER JOIN  modelagem_proposicao p
       ON p.casa_legislativa_id = c.id,
       tmp_lexml_configuracao t 
WHERE t.SiglaDocumento=sigla AND t.xmlid LIKE modelagem_radar2lex(esfera,nome,'') || '%'
ORDER BY 1,2;

que gera os dados abaixo,

 INSERT INTO modelagem_prefixoLexml (chave_radar,prefixolex) VALUES
  ('FEDERAL:Câmara dos Deputados:PDC', 'br:camara.deputados:projeto.decreto.legislativo;pdc'),
  -- ('FEDERAL:Câmara dos Deputados:PDC', 'br:camara.deputados:projeto.resolucao;pdc'),
  ('FEDERAL:Câmara dos Deputados:PEC', 'br:camara.deputados:proposta.emenda.constituicao;pec'),
  ('FEDERAL:Câmara dos Deputados:PL', 'br:camara.deputados:projeto.lei;pl'),
  ('FEDERAL:Câmara dos Deputados:PLP', 'br:camara.deputados:projeto.lei.complementar;plp'),
  ('FEDERAL:Senado:PDS', 'br:senado.federal:projeto.decreto.legislativo;pds'),
  ('FEDERAL:Senado:PEC', 'br:senado.federal:proposta.emenda.constituicao;pec'),
  ('FEDERAL:Senado:PLC', 'br:senado.federal:projeto.lei;plc'),
  --('FEDERAL:Senado:PLC', 'br:senado.federal:projeto.lei;pln'),  
  ('FEDERAL:Senado:PLS', 'br:senado.federal:projeto.lei;pls'),
  ('FEDERAL:Senado:PRS', 'br:senado.federal:projeto.resolucao;prs'),
  ('FEDERAL:Senado:SCD', 'br:senado.federal:substitutivo.camara.deputados.projeto.lei.senado;scd');

São Paulo não faz parte desse arquivo XML, mas está presente nas localidades fixadas pelos dados abertos e pelos antigos dados de vocabulário.

 INSERT INTO modelagem_prefixoLexml (chave_radar,prefixolex) VALUES
  ('MUNICIPAL:Câmara Municipal de São Paulo:PDL', 'br;sao.paulo;sao.paulo:camara.municipal:projeto.decreto.legislativo;pdl'),
  ('MUNICIPAL:Câmara Municipal de São Paulo:PL', 'br;sao.paulo;sao.paulo:camara.municipal:projeto.lei;pl'),
  ('MUNICIPAL:Câmara Municipal de São Paulo:PLO', 'br;sao.paulo;sao.paulo:camara.municipal:projeto.lei.organica;plo');

#NOTAS E CURIOSIDADES# Olhando esse Projeto de Lei 5.883 da Câmara vão perceber que um Projeto de Lei é considerado evolutivamente um objeto só, mas como conteúdo pode ser considerado dois, pois corre o risco de mostrar duas caras diferentes...

  • urn:lex:br:camara.deputados:projeto.lei;pl:2009;5883 (dá o título por ser origem)
  • urn:lex:br:senado.federal:projeto.lei;plc:2010;6 (vira outro processo)

... É como uma segunda edição de livro, daquelas "melhorada e ampliada", ou uma obra que o pai morre e o filho termina. Enfim, o rigor técnico assusta de ver dois IDs para o mesmo conteúdo, mas o rigor semântico exige essa separação.

NOTA: para o Radar, se os dois documentos (Senado e Câmara) são "mesmo conteúdo", deveriam gerar mesma semelhança partidária nas votações (!)... Que tal buscar correlação nisso? Ou seja, quando o comportamento do partido na Câmara e no Senado foi mantido e quando não?