/* * Copyright (C) 2011 Laurent Caillette * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.novelang.rendering.multipage; import java.io.File; import java.io.StringReader; import java.util.concurrent.Executors; import javax.xml.transform.URIResolver; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import org.apache.commons.io.FileUtils; import org.fest.assertions.Assertions; import org.junit.Rule; import org.junit.Test; import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; import org.xml.sax.helpers.XMLReaderFactory; import static org.fest.assertions.Assertions.assertThat; import static org.novelang.ResourcesForTests.initialize; import org.novelang.ResourcesForTests; import org.novelang.common.filefixture.Resource; import org.novelang.common.filefixture.ResourceInstaller; import org.novelang.common.metadata.PageIdentifier; import org.novelang.designator.Tag; import org.novelang.logger.Logger; import org.novelang.logger.LoggerFactory; import org.novelang.opus.Opus; import org.novelang.outfit.DefaultCharset; import org.novelang.outfit.loader.ClasspathResourceLoader; import org.novelang.outfit.xml.EntityEscapeSelector; import org.novelang.outfit.xml.LocalEntityResolver; import org.novelang.outfit.xml.LocalUriResolver; import org.novelang.outfit.xml.SaxRecorder; import org.novelang.outfit.xml.TransformerCompositeException; import org.novelang.testing.junit.MethodSupport; /** * Tests for {@link org.novelang.rendering.multipage.XslMultipageStylesheetCapture}. * * @author Laurent Caillette */ public class XslPageIdentifierExtractorTest { @Test public void extractPageIdentifiers() throws Exception { verify( ResourcesForTests.Multipage.MULTIPAGE_NOVELLA, ImmutableMap.of( new PageIdentifier( "Level-0" ), "/opus/level[1]", new PageIdentifier( "Level-1" ), "/opus/level[2]" ) ) ; } /** * The {@link ResourcesForTests.Multipage#MULTIPAGE_XSL} use level title as it is, * so it may produce an invalid {@link PageIdentifier}, like when using * {@link ResourcesForTests.Multipage#MULTIPAGE_HAZARDOUS_NOVELLA}. * This test guarantees the exception makes its way out. * <p> * Maybe this test should take a more general form because it's about a wider mechanism * that takes place in {@link org.novelang.outfit.xml.TransformerErrorListener} and what's * installing it. */ @Test( expected = TransformerCompositeException.class ) public void rethrowExceptionFromXslTransformer() throws Exception { try { verify( ResourcesForTests.Multipage.MULTIPAGE_HAZARDOUS_NOVELLA, ImmutableMap.of( new PageIdentifier( "Level-0" ), "/opus/level[1]", new PageIdentifier( "Level-1" ), "/opus/level[2]" ) ) ; } catch( TransformerCompositeException e ) { LOGGER.info( e, "Caught expected exception" ) ; Assertions.assertThat( e.getMessage() ).contains( "line=19; column=16 - java.lang.IllegalArgumentException: Name '' doesn't match " ) ; throw e ; } } // ======= // Fixture // ======= private static final Logger LOGGER = LoggerFactory.getLogger( XslPageIdentifierExtractorTest.class ) ; static { initialize() ; } @Rule public final MethodSupport methodSupport = new MethodSupport() ; private final ResourceInstaller resourceInstaller = new ResourceInstaller( methodSupport ) ; private void verify( final Resource novellaDocument, final ImmutableMap< PageIdentifier, String > expectedPages ) throws Exception { final File stylesheetFile = resourceInstaller.copy( ResourcesForTests.Multipage.MULTIPAGE_XSL ) ; resourceInstaller.copy( novellaDocument ) ; final ClasspathResourceLoader resourceLoader = new ClasspathResourceLoader() ; final EntityResolver entityResolver = new LocalEntityResolver( resourceLoader, NO_ENTITY_ESCAPE ) ; final URIResolver uriResolver = new LocalUriResolver( resourceLoader, entityResolver ) ; final SaxRecorder.Player[] stylesheetPlayerReference = new SaxRecorder.Player[ 1 ] ; final XslMultipageStylesheetCapture stylesheetCapture = new XslMultipageStylesheetCapture( entityResolver ) { @Override protected void onStylesheetDocumentBuilt( final SaxRecorder.Player freshStylesheetPlayer ) { stylesheetPlayerReference[ 0 ] = freshStylesheetPlayer ; } } ; final XMLReader reader = XMLReaderFactory.createXMLReader() ; reader.setContentHandler( stylesheetCapture ) ; reader.parse( new InputSource( new StringReader( FileUtils.readFileToString( stylesheetFile ) ) ) ) ; final SaxRecorder.Player stylesheetPlayer = stylesheetPlayerReference[ 0 ] ; LOGGER.info( "Got stylesheet:\n", stylesheetPlayer == null ? "null" : SaxRecorder.asXml( stylesheetPlayer ) ) ; final PagesExtractor pageIdentifierExtractor = new XslPageIdentifierExtractor( entityResolver, uriResolver, stylesheetPlayer ) ; final Opus opus = new Opus( resourceInstaller.getTargetDirectory(), resourceInstaller.getTargetDirectory(), Executors.newSingleThreadExecutor(), "insert file:" + novellaDocument.getName(), DefaultCharset.SOURCE, DefaultCharset.RENDERING, ImmutableSet.<Tag>of() ) ; final ImmutableMap<PageIdentifier,String > pages = pageIdentifierExtractor.extractPages( opus.getDocumentTree() ) ; assertThat( pages ).isEqualTo( expectedPages ) ; } private static final EntityEscapeSelector NO_ENTITY_ESCAPE = new EntityEscapeSelector() { @Override public boolean shouldEscape( final String publicId, final String systemId ) { return false ; } } ; }