You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

IFStructureTreeBuilderTestCase.java 9.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /* $Id$ */
  18. package org.apache.fop.render.intermediate;
  19. import java.io.ByteArrayInputStream;
  20. import java.io.ByteArrayOutputStream;
  21. import java.io.File;
  22. import javax.xml.transform.Result;
  23. import javax.xml.transform.Source;
  24. import javax.xml.transform.Transformer;
  25. import javax.xml.transform.TransformerException;
  26. import javax.xml.transform.TransformerFactory;
  27. import javax.xml.transform.sax.SAXResult;
  28. import javax.xml.transform.stream.StreamSource;
  29. import org.junit.Assert;
  30. import org.junit.Before;
  31. import org.junit.Test;
  32. import org.mockito.ArgumentMatcher;
  33. import org.mockito.InOrder;
  34. import org.xml.sax.Attributes;
  35. import org.xml.sax.ContentHandler;
  36. import org.xml.sax.SAXException;
  37. import org.xml.sax.helpers.AttributesImpl;
  38. import static org.junit.Assert.fail;
  39. import static org.mockito.Matchers.any;
  40. import static org.mockito.Matchers.argThat;
  41. import static org.mockito.Matchers.eq;
  42. import static org.mockito.Mockito.inOrder;
  43. import static org.mockito.Mockito.mock;
  44. import static org.mockito.Mockito.verify;
  45. import org.apache.fop.apps.FOUserAgent;
  46. import org.apache.fop.apps.Fop;
  47. import org.apache.fop.apps.FopFactory;
  48. import org.apache.fop.apps.MimeConstants;
  49. import org.apache.fop.fo.FOElementMapping;
  50. import org.apache.fop.fo.extensions.ExtensionElementMapping;
  51. import org.apache.fop.fo.extensions.InternalElementMapping;
  52. import org.apache.fop.util.XMLUtil;
  53. public class IFStructureTreeBuilderTestCase {
  54. private IFStructureTreeBuilder sut;
  55. @Before
  56. public void setUp() {
  57. sut = new IFStructureTreeBuilder();
  58. }
  59. @Test
  60. public void startAndEndPageSequence() throws SAXException {
  61. final ContentHandler handler = mock(ContentHandler.class);
  62. try {
  63. sut.replayEventsForPageSequence(handler, 0);
  64. fail("No page sequences created");
  65. } catch (IndexOutOfBoundsException e) {
  66. // Expected
  67. }
  68. sut.startPageSequence(null, null);
  69. sut.endPageSequence();
  70. sut.replayEventsForPageSequence(handler, 0);
  71. InOrder inOrder = inOrder(handler);
  72. inOrder.verify(handler).startPrefixMapping(
  73. InternalElementMapping.STANDARD_PREFIX, InternalElementMapping.URI);
  74. inOrder.verify(handler).startPrefixMapping(
  75. ExtensionElementMapping.STANDARD_PREFIX, ExtensionElementMapping.URI);
  76. inOrder.verify(handler).startElement(eq(IFConstants.NAMESPACE),
  77. eq(IFConstants.EL_STRUCTURE_TREE),
  78. eq(IFConstants.EL_STRUCTURE_TREE),
  79. any(Attributes.class));
  80. inOrder.verify(handler).endElement(eq(IFConstants.NAMESPACE),
  81. eq(IFConstants.EL_STRUCTURE_TREE),
  82. eq(IFConstants.EL_STRUCTURE_TREE));
  83. inOrder.verify(handler).endPrefixMapping(ExtensionElementMapping.STANDARD_PREFIX);
  84. inOrder.verify(handler).endPrefixMapping(InternalElementMapping.STANDARD_PREFIX);
  85. }
  86. @Test
  87. public void startNode() throws Exception {
  88. final String[] attributes = {"struct-id", "1"};
  89. final String nodeName = "block";
  90. final ContentHandler handler = mock(ContentHandler.class);
  91. sut.startPageSequence(null, null);
  92. sut.startNode(nodeName, createSimpleAttributes(attributes), null);
  93. sut.endPageSequence();
  94. sut.replayEventsForPageSequence(handler, 0);
  95. verify(handler).startElement(eq(FOElementMapping.URI), eq(nodeName),
  96. eq(FOElementMapping.STANDARD_PREFIX + ":" + nodeName),
  97. AttributesMatcher.match(createSimpleAttributes(attributes)));
  98. }
  99. @Test
  100. public void endNode() throws Exception {
  101. final String nodeName = "block";
  102. final ContentHandler handler = mock(ContentHandler.class);
  103. sut.startPageSequence(null, null);
  104. sut.endNode(nodeName);
  105. sut.endPageSequence();
  106. sut.replayEventsForPageSequence(handler, 0);
  107. verify(handler).endElement(eq(FOElementMapping.URI), eq(nodeName),
  108. eq(FOElementMapping.STANDARD_PREFIX + ":" + nodeName));
  109. }
  110. private static Attributes createSimpleAttributes(String... attributes) {
  111. assert (attributes.length % 2 == 0);
  112. final AttributesImpl atts = new AttributesImpl();
  113. for (int i = 0; i < attributes.length; i += 2) {
  114. String key = attributes[i];
  115. String value = attributes[i + 1];
  116. atts.addAttribute("", key, key, XMLUtil.CDATA, value);
  117. }
  118. return atts;
  119. }
  120. private static final class AttributesMatcher extends ArgumentMatcher<Attributes> {
  121. private final Attributes expected;
  122. private AttributesMatcher(Attributes expected) {
  123. this.expected = expected;
  124. }
  125. public static Attributes match(Attributes expected) {
  126. return argThat(new AttributesMatcher(expected));
  127. }
  128. public boolean matches(Object attributes) {
  129. return attributesEqual(expected, (Attributes) attributes);
  130. }
  131. private static boolean attributesEqual(Attributes attributes1, Attributes attributes2) {
  132. if (attributes1.getLength() != attributes2.getLength()) {
  133. return false;
  134. }
  135. for (int i = 0; i < attributes1.getLength(); i++) {
  136. if (attributes1.getLocalName(i) != attributes2.getLocalName(i)) {
  137. return false;
  138. }
  139. if (attributes1.getQName(i) != attributes2.getQName(i)) {
  140. return false;
  141. }
  142. if (attributes1.getType(i) != attributes2.getType(i)) {
  143. return false;
  144. }
  145. if (attributes1.getURI(i) != attributes2.getURI(i)) {
  146. return false;
  147. }
  148. if (attributes1.getValue(i) != attributes2.getValue(i)) {
  149. return false;
  150. }
  151. }
  152. return true;
  153. }
  154. }
  155. @Test
  156. public void checkLinkStructRef() throws TransformerException, SAXException {
  157. String fo = "<fo:root xmlns:fo=\"http://www.w3.org/1999/XSL/Format\">\n"
  158. + " <fo:layout-master-set>\n"
  159. + " <fo:simple-page-master master-name=\"all\" page-width=\"8.5in\" page-height=\"11in\">\n"
  160. + " <fo:region-body/>\n"
  161. + " </fo:simple-page-master>\n"
  162. + " </fo:layout-master-set>\n"
  163. + " <fo:page-sequence format=\"1\" id=\"th_default_sequence1\" master-reference=\"all\">\n"
  164. + " <fo:flow flow-name=\"xsl-region-body\">\n"
  165. + " <fo:block>\n"
  166. + " <fo:block>1 <fo:basic-link external-destination=\"http://a.net\">www.a.net</fo:basic-link>"
  167. + "</fo:block>\n"
  168. + " <fo:block>2 <fo:basic-link external-destination=\"http://a.net\">www.a.net</fo:basic-link>"
  169. + "</fo:block>\n"
  170. + " </fo:block>\n"
  171. + " </fo:flow>\n"
  172. + " </fo:page-sequence>\n"
  173. + "</fo:root>";
  174. String ifXML = foToIF(fo);
  175. Assert.assertTrue(ifXML, ifXML.contains("<nav:link rect=\"10008 1650 56016 11100\" foi:struct-ref=\"2\">"));
  176. Assert.assertTrue(ifXML, ifXML.contains("<nav:link rect=\"10008 16050 56016 11100\" foi:struct-ref=\"6\">"));
  177. }
  178. private String foToIF(String fo) throws SAXException, TransformerException {
  179. FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
  180. FOUserAgent userAgent = fopFactory.newFOUserAgent();
  181. userAgent.setAccessibility(true);
  182. IFSerializer serializer = new IFSerializer(new IFContext(userAgent));
  183. IFDocumentHandler targetHandler
  184. = userAgent.getRendererFactory().createDocumentHandler(userAgent, MimeConstants.MIME_PDF);
  185. serializer.mimicDocumentHandler(targetHandler);
  186. userAgent.setDocumentHandlerOverride(serializer);
  187. ByteArrayOutputStream out = new ByteArrayOutputStream();
  188. Fop fop = fopFactory.newFop(MimeConstants.MIME_FOP_IF, userAgent, out);
  189. Transformer transformer = TransformerFactory.newInstance().newTransformer();
  190. Source src = new StreamSource(new ByteArrayInputStream(fo.getBytes()));
  191. Result res = new SAXResult(fop.getDefaultHandler());
  192. transformer.transform(src, res);
  193. return out.toString();
  194. }
  195. }