/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* $Id$ */ package org.apache.fop.layoutengine; import java.util.List; import org.w3c.dom.CDATASection; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthGlue; import org.apache.fop.layoutmgr.KnuthPenalty; import org.apache.fop.layoutmgr.ListElement; /** * Check implementation that checks a Knuth element list. */ public class ElementListCheck implements LayoutEngineCheck { private String category; private String id; private int index = -1; private Element checkElement; /** * Creates a new instance from a DOM node. * @param node DOM node that defines this check */ public ElementListCheck(Node node) { this.category = node.getAttributes().getNamedItem("category").getNodeValue(); if (node.getAttributes().getNamedItem("id") != null) { this.id = node.getAttributes().getNamedItem("id").getNodeValue(); } if (!haveID()) { if (node.getAttributes().getNamedItem("index") != null) { String s = node.getAttributes().getNamedItem("index").getNodeValue(); this.index = Integer.parseInt(s); } } this.checkElement = (Element)node; } /** * @see org.apache.fop.layoutengine.LayoutEngineCheck */ public void check(LayoutResult result) { ElementListCollector.ElementList elementList = findElementList(result); NodeList children = checkElement.getChildNodes(); int pos = -1; for (int i = 0; i < children.getLength(); i++) { Node node = children.item(i); if (node instanceof Element) { pos++; Element domEl = (Element)node; ListElement knuthEl = (ListElement) elementList.getElementList().get(pos); if ("skip".equals(domEl.getLocalName())) { pos += Integer.parseInt(getElementText(domEl)) - 1; } else if ("box".equals(domEl.getLocalName())) { if (!(knuthEl instanceof KnuthBox)) { fail("Expected KnuthBox" + " at position " + pos + " but got: " + knuthEl.getClass().getName()); } KnuthBox box = (KnuthBox) knuthEl; if (domEl.getAttribute("w").length() > 0) { int w = Integer.parseInt(domEl.getAttribute("w")); if (w != box.getWidth()) { fail("Expected w=" + w + " at position " + pos + " but got: " + box.getWidth()); } } if ("true".equals(domEl.getAttribute("aux"))) { if (!box.isAuxiliary()) { fail("Expected auxiliary box" + " at position " + pos); } } if ("false".equals(domEl.getAttribute("aux"))) { if (box.isAuxiliary()) { fail("Expected a normal, not an auxiliary box" + " at position " + pos); } } } else if ("penalty".equals(domEl.getLocalName())) { if (!(knuthEl instanceof KnuthPenalty)) { fail("Expected KnuthPenalty " + " at position " + pos + " but got: " + knuthEl.getClass().getName()); } KnuthPenalty pen = (KnuthPenalty)knuthEl; if (domEl.getAttribute("w").length() > 0) { int w = Integer.parseInt(domEl.getAttribute("w")); if (w != pen.getWidth()) { fail("Expected w=" + w + " at position " + pos + " but got: " + pen.getWidth()); } } if (domEl.getAttribute("p").length() > 0) { if ("<0".equals(domEl.getAttribute("p"))) { if (pen.getPenalty() >= 0) { fail("Expected p<0" + " at position " + pos + " but got: " + pen.getPenalty()); } } else if (">0".equals(domEl.getAttribute("p"))) { if (pen.getPenalty() <= 0) { fail("Expected p>0" + " at position " + pos + " but got: " + pen.getPenalty()); } } else { int p; if ("INF".equalsIgnoreCase(domEl.getAttribute("p"))) { p = KnuthPenalty.INFINITE; } else if ("INFINITE".equalsIgnoreCase(domEl.getAttribute("p"))) { p = KnuthPenalty.INFINITE; } else if ("-INF".equalsIgnoreCase(domEl.getAttribute("p"))) { p = -KnuthPenalty.INFINITE; } else if ("-INFINITE".equalsIgnoreCase(domEl.getAttribute("p"))) { p = -KnuthPenalty.INFINITE; } else { p = Integer.parseInt(domEl.getAttribute("p")); } if (p != pen.getPenalty()) { fail("Expected p=" + p + " at position " + pos + " but got: " + pen.getPenalty()); } } } if ("true".equals(domEl.getAttribute("flagged"))) { if (!pen.isPenaltyFlagged()) { fail("Expected flagged penalty" + " at position " + pos); } } else if ("false".equals(domEl.getAttribute("flagged"))) { if (pen.isPenaltyFlagged()) { fail("Expected non-flagged penalty" + " at position " + pos); } } if ("true".equals(domEl.getAttribute("aux"))) { if (!pen.isAuxiliary()) { fail("Expected auxiliary penalty" + " at position " + pos); } } else if ("false".equals(domEl.getAttribute("aux"))) { if (pen.isAuxiliary()) { fail("Expected non-auxiliary penalty" + " at position " + pos); } } } else if ("glue".equals(domEl.getLocalName())) { if (!(knuthEl instanceof KnuthGlue)) { fail("Expected KnuthGlue" + " at position " + pos + " but got: " + knuthEl.getClass().getName()); } KnuthGlue glue = (KnuthGlue)knuthEl; if (domEl.getAttribute("w").length() > 0) { int w = Integer.parseInt(domEl.getAttribute("w")); if (w != glue.getWidth()) { fail("Expected w=" + w + " at position " + pos + " but got: " + glue.getWidth()); } } if (domEl.getAttribute("y").length() > 0) { int stretch = Integer.parseInt(domEl.getAttribute("y")); if (stretch != glue.getStretch()) { fail("Expected y=" + stretch + " (stretch) at position " + pos + " but got: " + glue.getStretch()); } } if (domEl.getAttribute("z").length() > 0) { int shrink = Integer.parseInt(domEl.getAttribute("z")); if (shrink != glue.getShrink()) { fail("Expected z=" + shrink + " (shrink) at position " + pos + " but got: " + glue.getShrink()); } } } else { throw new IllegalArgumentException("Invalid child node for 'element-list': " + domEl.getLocalName() + " at position " + pos + " (" + this + ")"); } } } pos++; if (elementList.getElementList().size() > pos) { fail("There are " + (elementList.getElementList().size() - pos) + " unchecked elements at the end of the list"); } } private void fail(String msg) { throw new AssertionError(msg + " (" + this + ")"); } private boolean haveID() { return (this.id != null && this.id.length() > 0); } private ElementListCollector.ElementList findElementList(LayoutResult result) { List candidates = new java.util.ArrayList(); for (Object o : result.getElementListCollector().getElementLists()) { ElementListCollector.ElementList el = (ElementListCollector.ElementList) o; if (el.getCategory().equals(category)) { if (haveID() && this.id.equals(el.getID())) { candidates.add(el); break; } else if (!haveID()) { candidates.add(el); } } } if (candidates.size() == 0) { throw new ArrayIndexOutOfBoundsException("Requested element list not found"); } else if (index >= 0) { return (ElementListCollector.ElementList)candidates.get(index); } else { return (ElementListCollector.ElementList)candidates.get(0); } } private static String getElementText(Element el) { StringBuffer sb = new StringBuffer(); NodeList children = el.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node node = children.item(i); if (node instanceof Text) { sb.append(((Text)node).getData()); } else if (node instanceof CDATASection) { sb.append(((CDATASection)node).getData()); } } return sb.toString(); } /** @see java.lang.Object#toString() */ public String toString() { StringBuffer sb = new StringBuffer("element-list"); sb.append(" category=").append(category); if (haveID()) { sb.append(" id=").append(id); } else if (index >= 0) { sb.append(" index=").append(index); } return sb.toString(); } }