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 18 /* $Id: RepeatablePageMasterAlternatives.java 1733431 2016-03-03 09:40:50Z gadams $ */ 19 20 package org.apache.fop.fo.pagination; 21 22 // Java 23 import java.util.ArrayList; 24 import java.util.List; 25 26 import org.xml.sax.Locator; 27 28 import org.apache.fop.apps.FOPException; 29 import org.apache.fop.fo.FONode; 30 import org.apache.fop.fo.FObj; 31 import org.apache.fop.fo.PropertyList; 32 import org.apache.fop.fo.ValidationException; 33 import org.apache.fop.fo.properties.Property; 34 import org.apache.fop.layoutmgr.BlockLevelEventProducer; 35 36 /** 37 * Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_repeatable-page-master-alternatives"> 38 * <code>fo:repeatable-page-master-alternatives</code></a> object. 39 * This contains a list of conditional-page-master-reference 40 * and the page master is found from the reference that 41 * matches the page number and emptyness. 42 */ 43 public class RepeatablePageMasterAlternatives extends FObj 44 implements SubSequenceSpecifier { 45 // The value of properties relevant for fo:repeatable-page-master-alternatives. 46 private Property maximumRepeats; 47 // End of property values 48 49 private static final int INFINITE = -1; 50 51 private int numberConsumed; 52 53 private List<ConditionalPageMasterReference> conditionalPageMasterRefs; 54 private boolean hasPagePositionLast; 55 private boolean hasPagePositionOnly; 56 57 /** 58 * Base constructor 59 * 60 * @param parent {@link FONode} that is the parent of this object 61 */ RepeatablePageMasterAlternatives(FONode parent)62 public RepeatablePageMasterAlternatives(FONode parent) { 63 super(parent); 64 } 65 66 /** {@inheritDoc} */ bind(PropertyList pList)67 public void bind(PropertyList pList) throws FOPException { 68 maximumRepeats = pList.get(PR_MAXIMUM_REPEATS); 69 } 70 71 /** {@inheritDoc} */ startOfNode()72 public void startOfNode() throws FOPException { 73 conditionalPageMasterRefs = new java.util.ArrayList<ConditionalPageMasterReference>(); 74 75 assert parent.getName().equals("fo:page-sequence-master"); //Validation by the parent 76 PageSequenceMaster pageSequenceMaster = (PageSequenceMaster)parent; 77 pageSequenceMaster.addSubsequenceSpecifier(this); 78 } 79 80 /** {@inheritDoc} */ endOfNode()81 public void endOfNode() throws FOPException { 82 if (firstChild == null) { 83 missingChildElementError("(conditional-page-master-reference+)"); 84 } 85 } 86 87 /** 88 * {@inheritDoc} 89 * <br>XSL/FOP: (conditional-page-master-reference+) 90 */ validateChildNode(Locator loc, String nsURI, String localName)91 protected void validateChildNode(Locator loc, String nsURI, String localName) 92 throws ValidationException { 93 if (FO_URI.equals(nsURI)) { 94 if (!localName.equals("conditional-page-master-reference")) { 95 invalidChildError(loc, nsURI, localName); 96 } 97 } 98 } 99 100 /** 101 * Get the value of the <code>maximum-repeats</code> property? 102 * @return the "maximum-repeats" property 103 */ getMaximumRepeats()104 public int getMaximumRepeats() { 105 if (maximumRepeats.getEnum() == EN_NO_LIMIT) { 106 return INFINITE; 107 } else { 108 int mr = maximumRepeats.getNumeric().getValue(); 109 if (mr < 0) { 110 log.debug("negative maximum-repeats: " 111 + this.maximumRepeats); 112 mr = 0; 113 } 114 return mr; 115 } 116 } 117 118 /** {@inheritDoc} */ getNextPageMaster(boolean isOddPage, boolean isFirstPage, boolean isLastPage, boolean isBlankPage)119 public SimplePageMaster getNextPageMaster(boolean isOddPage, 120 boolean isFirstPage, 121 boolean isLastPage, 122 boolean isBlankPage) { 123 124 if (!isInfinite() && numberConsumed >= getMaximumRepeats()) { 125 return null; 126 } 127 128 numberConsumed++; 129 130 for (ConditionalPageMasterReference cpmr : conditionalPageMasterRefs) { 131 if (cpmr.isValid(isOddPage, isFirstPage, isLastPage, isBlankPage)) { 132 return cpmr.getMaster(); 133 } 134 } 135 136 137 return null; 138 } 139 getLastPageMaster(boolean isOddPage, boolean isFirstPage, boolean isBlankPage, BlockLevelEventProducer blockLevelEventProducer)140 public SimplePageMaster getLastPageMaster(boolean isOddPage, boolean isFirstPage, boolean isBlankPage, 141 BlockLevelEventProducer blockLevelEventProducer) { 142 for (ConditionalPageMasterReference cpmr : conditionalPageMasterRefs) { 143 if (cpmr.isValid(isOddPage, isFirstPage, true, isBlankPage)) { 144 return cpmr.getMaster(); 145 } 146 } 147 blockLevelEventProducer.lastPageMasterReferenceMissing(this, getLocator()); 148 for (ConditionalPageMasterReference cpmr : conditionalPageMasterRefs) { 149 if (cpmr.isValid(isOddPage, isFirstPage, false, isBlankPage)) { 150 return cpmr.getMaster(); 151 } 152 } 153 throw new PageProductionException("Last page master not found: oddpage=" + isOddPage 154 + " firstpage=" + isFirstPage + " blankpage=" + isBlankPage); 155 } 156 157 /** 158 * Adds a new conditional page master reference. 159 * @param cpmr the new conditional reference 160 */ addConditionalPageMasterReference(ConditionalPageMasterReference cpmr)161 public void addConditionalPageMasterReference(ConditionalPageMasterReference cpmr) { 162 this.conditionalPageMasterRefs.add(cpmr); 163 if (cpmr.getPagePosition() == EN_LAST) { 164 this.hasPagePositionLast = true; 165 } 166 if (cpmr.getPagePosition() == EN_ONLY) { 167 this.hasPagePositionOnly = true; 168 } 169 } 170 171 /** {@inheritDoc} */ reset()172 public void reset() { 173 this.numberConsumed = 0; 174 } 175 176 /** {@inheritDoc} */ goToPrevious()177 public boolean goToPrevious() { 178 if (numberConsumed == 0) { 179 return false; 180 } else { 181 numberConsumed--; 182 return true; 183 } 184 } 185 186 /** {@inheritDoc} */ hasPagePositionLast()187 public boolean hasPagePositionLast() { 188 return this.hasPagePositionLast; 189 } 190 191 /** {@inheritDoc} */ hasPagePositionOnly()192 public boolean hasPagePositionOnly() { 193 return this.hasPagePositionOnly; 194 } 195 196 /** {@inheritDoc} */ getLocalName()197 public String getLocalName() { 198 return "repeatable-page-master-alternatives"; 199 } 200 201 /** 202 * {@inheritDoc} 203 * @return {@link org.apache.fop.fo.Constants#FO_REPEATABLE_PAGE_MASTER_ALTERNATIVES} 204 */ getNameId()205 public int getNameId() { 206 return FO_REPEATABLE_PAGE_MASTER_ALTERNATIVES; 207 } 208 209 210 211 /** {@inheritDoc} */ resolveReferences(LayoutMasterSet layoutMasterSet)212 public void resolveReferences(LayoutMasterSet layoutMasterSet) throws ValidationException { 213 for (ConditionalPageMasterReference conditionalPageMasterReference 214 : conditionalPageMasterRefs) { 215 conditionalPageMasterReference.resolveReferences(layoutMasterSet); 216 } 217 218 } 219 220 /** {@inheritDoc} */ canProcess(String flowName)221 public boolean canProcess(String flowName) { 222 223 boolean willTerminate = true; 224 225 226 //Look for rest spm that cannot terminate 227 ArrayList<ConditionalPageMasterReference> rest 228 = new ArrayList<ConditionalPageMasterReference>(); 229 for (ConditionalPageMasterReference cpmr 230 : conditionalPageMasterRefs) { 231 if (cpmr.isValid(true, false, false, false) 232 || cpmr.isValid(false, false, false, false)) { 233 rest.add(cpmr); 234 } 235 } 236 if (!rest.isEmpty()) { 237 willTerminate = false; 238 for (ConditionalPageMasterReference cpmr : rest) { 239 willTerminate |= cpmr.getMaster().getRegion(FO_REGION_BODY).getRegionName() 240 .equals(flowName); 241 } 242 } 243 244 245 return willTerminate; 246 } 247 248 /** {@inheritDoc} */ isInfinite()249 public boolean isInfinite() { 250 return getMaximumRepeats() == INFINITE; 251 } 252 253 /** {@inheritDoc} */ isReusable()254 public boolean isReusable() { 255 return false; 256 } 257 258 } 259