-
Notifications
You must be signed in to change notification settings - Fork 44
Conversão de contexto em URN LEX
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.
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.
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.
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?