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.

LayoutEngineTester.java 7.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. /*
  2. * Copyright 2005 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /* $Id$ */
  17. package org.apache.fop.layoutengine;
  18. import java.io.File;
  19. import java.lang.reflect.Constructor;
  20. import java.net.MalformedURLException;
  21. import java.util.Iterator;
  22. import java.util.List;
  23. import java.util.Map;
  24. import javax.xml.transform.Result;
  25. import javax.xml.transform.Source;
  26. import javax.xml.transform.Templates;
  27. import javax.xml.transform.Transformer;
  28. import javax.xml.transform.TransformerConfigurationException;
  29. import javax.xml.transform.TransformerException;
  30. import javax.xml.transform.dom.DOMResult;
  31. import javax.xml.transform.dom.DOMSource;
  32. import javax.xml.transform.sax.SAXResult;
  33. import javax.xml.transform.sax.SAXTransformerFactory;
  34. import javax.xml.transform.sax.TransformerHandler;
  35. import javax.xml.transform.stream.StreamResult;
  36. import javax.xml.transform.stream.StreamSource;
  37. import org.apache.fop.apps.FOPException;
  38. import org.apache.fop.apps.FOUserAgent;
  39. import org.apache.fop.apps.Fop;
  40. import org.apache.fop.apps.MimeConstants;
  41. import org.apache.fop.layoutmgr.ElementListObserver;
  42. import org.apache.fop.render.xml.XMLRenderer;
  43. import org.w3c.dom.Document;
  44. import org.w3c.dom.Element;
  45. import org.w3c.dom.Node;
  46. import org.w3c.dom.NodeList;
  47. /**
  48. * Class for testing the FOP's layout engine using testcases specified in XML
  49. * files.
  50. */
  51. public class LayoutEngineTester {
  52. private static final Map CHECK_CLASSES = new java.util.HashMap();
  53. private SAXTransformerFactory tfactory
  54. = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
  55. private Templates testcase2fo;
  56. private Templates testcase2checks;
  57. private File areaTreeBackupDir;
  58. static {
  59. CHECK_CLASSES.put("true", TrueCheck.class);
  60. CHECK_CLASSES.put("eval", EvalCheck.class);
  61. CHECK_CLASSES.put("element-list", ElementListCheck.class);
  62. }
  63. /**
  64. * Constructs a new instance.
  65. * @param areaTreeBackupDir Optional directory that receives the generated
  66. * area tree XML files. May be null.
  67. */
  68. public LayoutEngineTester(File areaTreeBackupDir) {
  69. this.areaTreeBackupDir = areaTreeBackupDir;
  70. }
  71. private Templates getTestcase2FOStylesheet() throws TransformerConfigurationException {
  72. if (testcase2fo == null) {
  73. //Load and cache stylesheet
  74. Source src = new StreamSource(new File("test/layoutengine/testcase2fo.xsl"));
  75. testcase2fo = tfactory.newTemplates(src);
  76. }
  77. return testcase2fo;
  78. }
  79. private Templates getTestcase2ChecksStylesheet() throws TransformerConfigurationException {
  80. if (testcase2checks == null) {
  81. //Load and cache stylesheet
  82. Source src = new StreamSource(new File("test/layoutengine/testcase2checks.xsl"));
  83. testcase2checks = tfactory.newTemplates(src);
  84. }
  85. return testcase2checks;
  86. }
  87. /**
  88. * Runs a single layout engine test case.
  89. * @param testFile Test case to run
  90. * @throws TransformerException In case of an XSLT/JAXP problem
  91. * @throws FOPException In case of a FOP problem
  92. * @throws MalformedURLException if the base URL cannot be set
  93. */
  94. public void runTest(File testFile)
  95. throws TransformerException, FOPException, MalformedURLException {
  96. DOMResult domres = new DOMResult();
  97. ElementListCollector elCollector = new ElementListCollector();
  98. ElementListObserver.addObserver(elCollector);
  99. try {
  100. //Setup Transformer to convert the testcase XML to XSL-FO
  101. Transformer transformer = getTestcase2FOStylesheet().newTransformer();
  102. Source src = new StreamSource(testFile);
  103. //Setup Transformer to convert the area tree to a DOM
  104. TransformerHandler athandler = tfactory.newTransformerHandler();
  105. athandler.setResult(domres);
  106. //Setup FOP for area tree rendering
  107. FOUserAgent ua = new FOUserAgent();
  108. ua.setBaseURL(testFile.getParentFile().toURL().toString());
  109. XMLRenderer atrenderer = new XMLRenderer();
  110. atrenderer.setUserAgent(ua);
  111. atrenderer.setTransformerHandler(athandler);
  112. ua.setRendererOverride(atrenderer);
  113. Fop fop = new Fop(MimeConstants.MIME_FOP_AREA_TREE, ua);
  114. SAXResult fores = new SAXResult(fop.getDefaultHandler());
  115. transformer.transform(src, fores);
  116. } finally {
  117. ElementListObserver.removeObserver(elCollector);
  118. }
  119. Document doc = (Document)domres.getNode();
  120. if (this.areaTreeBackupDir != null) {
  121. saveAreaTreeXML(doc, new File(this.areaTreeBackupDir, testFile.getName() + ".at.xml"));
  122. }
  123. LayoutResult result = new LayoutResult(doc, elCollector);
  124. checkAll(testFile, result);
  125. }
  126. /**
  127. * Factory method to create checks from DOM elements.
  128. * @param el DOM element to create the check from
  129. * @return The newly create check
  130. */
  131. protected LayoutEngineCheck createCheck(Element el) {
  132. String name = el.getTagName();
  133. Class clazz = (Class)CHECK_CLASSES.get(name);
  134. if (clazz != null) {
  135. try {
  136. Constructor c = clazz.getDeclaredConstructor(new Class[] {Node.class});
  137. LayoutEngineCheck instance = (LayoutEngineCheck)c.newInstance(new Object[] {el});
  138. return instance;
  139. } catch (Exception e) {
  140. throw new RuntimeException("Error while instantiating check '"
  141. + name + "': " + e.getMessage());
  142. }
  143. } else {
  144. throw new IllegalArgumentException("No check class found: " + name);
  145. }
  146. }
  147. /**
  148. * Perform all checks on the area tree.
  149. * @param testFile Test case XML file
  150. * @param result The layout results
  151. * @throws TransformerException if a problem occurs in XSLT/JAXP
  152. */
  153. protected void checkAll(File testFile, LayoutResult result) throws TransformerException {
  154. Transformer transformer = getTestcase2ChecksStylesheet().newTransformer();
  155. Source src = new StreamSource(testFile);
  156. DOMResult res = new DOMResult();
  157. transformer.transform(src, res);
  158. List checks = new java.util.ArrayList();
  159. Document doc = (Document)res.getNode();
  160. NodeList nodes = doc.getDocumentElement().getChildNodes();
  161. for (int i = 0; i < nodes.getLength(); i++) {
  162. Node node = nodes.item(i);
  163. if (node instanceof Element) {
  164. checks.add(createCheck((Element)node));
  165. }
  166. }
  167. if (checks.size() == 0) {
  168. throw new RuntimeException("No checks are available!");
  169. }
  170. Iterator i = checks.iterator();
  171. while (i.hasNext()) {
  172. LayoutEngineCheck check = (LayoutEngineCheck)i.next();
  173. check.check(result);
  174. }
  175. }
  176. /**
  177. * Save the area tree XML for later inspection.
  178. * @param doc area tree as a DOM document
  179. * @param target target file
  180. * @throws TransformerException if a problem occurs during serialization
  181. */
  182. protected void saveAreaTreeXML(Document doc, File target) throws TransformerException {
  183. Transformer transformer = tfactory.newTransformer();
  184. Source src = new DOMSource(doc);
  185. Result res = new StreamResult(target);
  186. transformer.transform(src, res);
  187. }
  188. }