/** * 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 org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringUtils; import br.gov.camara.edemocracia.portlets.wikilegis.NoSuchArtigoException; import br.gov.camara.edemocracia.portlets.wikilegis.NoSuchEstruturaException; import br.gov.camara.edemocracia.portlets.wikilegis.util.HtmlStripperDiscussion; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.exception.SystemException; public class XMLCodigoComercialWikilegisImporter { private HtmlStripperDiscussion htmlStripper; public XMLCodigoComercialWikilegisImporter() { 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<EstruturaDTO, List<String>> artigosPorNivel; private HashMap<String, String> textoArtigo; private HashMap<String, String> legislacaoVigente; public EstruturaDTO processXML(InputStream input) throws PortalException, SystemException, IOException { HashMap<String, EstruturaDTO> estruturas = new HashMap<String, EstruturaDTO>(); artigosPorNivel = new HashMap<EstruturaDTO, List<String>>(); textoArtigo = new HashMap<String, String>(); legislacaoVigente = new HashMap<String, String>(); // Estrutura raiz EstruturaDTO raiz = new EstruturaDTO(null, null); // Estrutura atual EstruturaDTO estruturaAtual = raiz; String xml; xml = convertInputStreamToString(input); xml = htmlStripper.strip(xml); BufferedReader reader = new BufferedReader(new StringReader(xml)); String linha; StringBuilder sbArtigo = new StringBuilder(); boolean adicionar = false; try { while ((linha = reader.readLine()) != null) { linha = StringEscapeUtils.unescapeHtml(linha.trim()); if (linha.isEmpty()) continue; int pos = linha.indexOf("<a"); if (pos != -1) { // Estrutura Matcher m = REMOVE_ANCHOR.matcher(linha); if (m.matches()) { String codigoEstrutura = m.group(1); String titulo = m.group(2); // Verifica se o código da estrutura é apenas um número // Se for, então ignora if (!StringUtils.containsOnly(codigoEstrutura, "0123456789")) { sbArtigo.append(linha, 0, pos); processaArtigo(estruturaAtual, sbArtigo); adicionar = false; // Obtém a estrutura pai EstruturaDTO estruturaPai; int posEstrutura = codigoEstrutura.lastIndexOf('/'); if (posEstrutura != -1) { estruturaPai = estruturas.get(codigoEstrutura .substring(0, posEstrutura)); if (estruturaPai == null) throw new NoSuchEstruturaException( "Estrutura " + codigoEstrutura + " filha criada antes da estrutura pai"); } else { estruturaPai = raiz; } estruturaAtual = new EstruturaDTO(estruturaPai, titulo.trim()); estruturas.put(codigoEstrutura, estruturaAtual); continue; } else { linha = m.group(2); // Pega após o link inválido } } } // 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 (EstruturaDTO estruturaPai : artigosPorNivel.keySet()) { List<String> artigoIds = artigosPorNivel.get(estruturaPai); for (String artigoId : artigoIds) { String texto = textoArtigo.get(artigoId); String vigente = legislacaoVigente.get(artigoId); if (vigente == null) vigente = ""; estruturaPai.adiconaArtigo(new ArtigoDTO(texto, vigente)); } } return raiz; } /** * Armazena os dados de um artigo * * @param estrutura * @param sb * @throws IOException * @throws NoSuchArtigoException */ private void processaArtigo(EstruturaDTO estrutura, StringBuilder sb) throws IOException, NoSuchArtigoException { if (sb.length() == 0) return; Matcher m = PATTERN.matcher(sb); if (m.matches()) { String texto = m.group(4).trim(); // 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); if ("commentable".equals(m.group(2))) { List<String> artigos = artigosPorNivel.get(estrutura); if (artigos == null) { artigos = new ArrayList<String>(); artigosPorNivel.put(estrutura, artigos); } if (!artigos.contains(nodeId)) artigos.add(nodeId); if (textoArtigo.containsKey(nodeId)) throw new NoSuchArtigoException("Artigo " + nodeId + " 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 ""; } } }