/** * Copyright (c) 2009-2014 Câmara dos Deputados. Todos os direitos reservados. * * e-Democracia é um software livre; você pode redistribuí-lo e/ou modificá-lo dentro * dos termos da Licença Pública Geral Menor GNU como publicada pela Fundação do * Software Livre (FSF); na versão 2.1 da Licença, ou (na sua opinião) qualquer versão. * * Este programa é distribuído na esperança de que possa ser útil, mas SEM NENHUMA GARANTIA; * sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou APLICAÇÃO EM PARTICULAR. * Veja a Licença Pública Geral Menor GNU para maiores detalhes. */ package br.gov.camara.edemocracia.portlets.wikilegis.importer; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.exception.SystemException; import br.gov.camara.edemocracia.portlets.wikilegis.NoSuchArtigoException; import br.gov.camara.edemocracia.portlets.wikilegis.NoSuchEstruturaException; import br.gov.camara.edemocracia.portlets.wikilegis.model.Artigo; import br.gov.camara.edemocracia.portlets.wikilegis.model.Estrutura; import br.gov.camara.edemocracia.portlets.wikilegis.service.ArtigoLocalServiceUtil; import br.gov.camara.edemocracia.portlets.wikilegis.service.EstruturaLocalServiceUtil; import br.gov.camara.edemocracia.portlets.wikilegis.util.HtmlStripperDiscussion; public class XMLWikilegisImporter { private HtmlStripperDiscussion htmlStripper; public XMLWikilegisImporter() { htmlStripper = new HtmlStripperDiscussion(); } private static final Pattern REMOVE_ANCHOR = Pattern.compile("<a name=\"(.+?)\">(.+?)</a>(.+)"); private static final Pattern PATTERN = Pattern.compile("\\[((commentable|original_version) name=\"(.+?)\")\\](.+?)\\[/\\2\\]", Pattern.DOTALL); private static final Pattern REMOVE_EMPTY_LINES = Pattern.compile("^[\r\n]*(.+?)[\r\n]*$", Pattern.DOTALL); private HashMap<String, Long> estruturas; private HashMap<Long, Long> ultimaEstruturaPorNivel; private HashMap<Long, List<String>> artigosPorNivel; private HashMap<String, String> textoArtigo; private HashMap<String, String> legislacaoVigente; public void processXML(long groupId, InputStream input) throws PortalException, SystemException, IOException { estruturas = new HashMap<String, Long>(); ultimaEstruturaPorNivel = new HashMap<Long, Long>(); artigosPorNivel = new HashMap<Long, List<String>>(); textoArtigo = new HashMap<String, String>(); legislacaoVigente = new HashMap<String, String>(); // Estrutura raiz estruturas.put("", 0l); String xml; xml = convertInputStreamToString(input); xml = htmlStripper.strip(xml); BufferedReader reader = new BufferedReader(new StringReader(xml)); String linha; String estruturaAtual = ""; StringBuilder sbArtigo = new StringBuilder(); boolean adicionar = false; try { while ((linha = reader.readLine()) != null) { linha = linha.trim(); if (linha.isEmpty()) continue; int pos = linha.indexOf("<a"); if (pos != -1) { sbArtigo.append(linha, 0, pos); processaArtigo(estruturaAtual, sbArtigo); adicionar = false; // Estrutura Matcher m = REMOVE_ANCHOR.matcher(linha); if (m.matches()) { estruturaAtual = m.group(1); String titulo = m.group(2) + " - " + m.group(3); // Obtém a estrutura pai Long paiEstruturaId; int posEstrutura = estruturaAtual.lastIndexOf('/'); if (posEstrutura != -1) { paiEstruturaId = estruturas.get(estruturaAtual.substring(0, posEstrutura)); if (paiEstruturaId == null) throw new NoSuchEstruturaException("Estrutura filha criada antes da estrutura pai"); } else { paiEstruturaId = 0l; } // Obtém a ordem Long ultimoId = ultimaEstruturaPorNivel.get(paiEstruturaId); if (ultimoId == null) ultimoId = 0l; Estrutura novo = EstruturaLocalServiceUtil.criaEstrutura(groupId, paiEstruturaId, ultimoId, titulo); ultimaEstruturaPorNivel.put(paiEstruturaId, novo.getEstruturaId()); estruturas.put(estruturaAtual, novo.getEstruturaId()); continue; } } // Ok, é trecho de texto pos = linha.indexOf("[commentable name="); if (pos == -1) pos = linha.indexOf("[original_version name="); if (pos != -1) { // Processa o artigo anterior sbArtigo.append(linha.subSequence(0, pos)); processaArtigo(estruturaAtual, sbArtigo); // Dados do artigo atual int end = linha.indexOf("[/commentable]"); if (end == -1) { end = linha.indexOf("[/original_version]"); if (end != -1) end = end + ("[/original_version]".length()); } else { end = end + "[/commentable]".length(); } if (end == -1) { // O artigo não termina nesta linha sbArtigo.append(linha.subSequence(pos, linha.length())).append("\n"); adicionar = true; } else { sbArtigo.append(linha.subSequence(pos, end)); processaArtigo(estruturaAtual, sbArtigo); adicionar = false; } } else { if (adicionar) { int end = linha.indexOf("[/commentable]"); if (end == -1) { end = linha.indexOf("[/original_version]"); if (end != -1) end = end + ("[/original_version]".length()); } else { end = end + "[/commentable]".length(); } if (end == -1) sbArtigo.append(linha).append("\n"); else { sbArtigo.append(linha.subSequence(0, end)); processaArtigo(estruturaAtual, sbArtigo); adicionar = false; } } } } processaArtigo(estruturaAtual, sbArtigo); } finally { try { reader.close(); } catch (IOException e) { } } // Acrescenta os artigos for (Long estruturaPai : artigosPorNivel.keySet()) { List<String> artigos = artigosPorNivel.get(estruturaPai); long anteriorArtigoId = 0l; for (String artigoId : artigos) { String texto = textoArtigo.get(artigoId); String vigente = legislacaoVigente.get(artigoId); if (vigente == null) vigente = ""; Artigo artigo = ArtigoLocalServiceUtil.criaArtigo(groupId, estruturaPai.longValue(), anteriorArtigoId, texto, vigente); anteriorArtigoId = artigo.getArtigoId(); } } } /** * Armazena os dados de um artigo * * @param estrutura * @param sb * @throws IOException * @throws NoSuchArtigoException */ private void processaArtigo(String estrutura, StringBuilder sb) throws IOException, NoSuchArtigoException { if (sb.length() == 0) return; Matcher m = PATTERN.matcher(sb); if (m.matches()) { String texto = m.group(4); // Retira linhas em branco ao final Matcher cleaner = REMOVE_EMPTY_LINES.matcher(texto); if (cleaner.matches()) { texto = cleaner.group(1); } else { throw new RuntimeException("Error in regexp"); } String nodeId = m.group(3); Long estruturaId = estruturas.get(estrutura); List<String> artigos = artigosPorNivel.get(estruturaId); if (artigos == null) { artigos = new ArrayList<String>(); artigosPorNivel.put(estruturaId, artigos); } if (!artigos.contains(nodeId)) artigos.add(nodeId); if ("commentable".equals(m.group(2))) { if (textoArtigo.containsKey(nodeId)) throw new NoSuchArtigoException("Artigo já acrescentado"); textoArtigo.put(nodeId, texto); } else { if (legislacaoVigente.containsKey(nodeId)) throw new NoSuchArtigoException("Legislação vigente já acrescentada"); legislacaoVigente.put(nodeId, texto); } } else { throw new RuntimeException("Erro ao importar: " + sb.toString()); } sb.setLength(0); } private static String convertInputStreamToString(InputStream inputStream) throws IOException { if (inputStream != null) { StringBuilder sb = new StringBuilder(); String line; try { BufferedReader r1 = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); while ((line = r1.readLine()) != null) { sb.append(line).append("\n"); } } finally { inputStream.close(); } return sb.toString(); } else { return ""; } } }