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.

Markers.java 8.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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.fo.flow;
  19. import java.util.HashMap;
  20. import java.util.Map;
  21. import java.util.Set;
  22. import org.apache.commons.logging.Log;
  23. import org.apache.commons.logging.LogFactory;
  24. import org.apache.fop.fo.Constants;
  25. /**
  26. * A class to register and resolve markers.
  27. */
  28. public final class Markers {
  29. // IsAny means either IsFirst or IsLast
  30. private Map<String, Marker> firstQualifyingIsFirst;
  31. private Map<String, Marker> firstQualifyingIsAny;
  32. private Map<String, Marker> lastQualifyingIsFirst;
  33. private Map<String, Marker> lastQualifyingIsLast;
  34. private Map<String, Marker> lastQualifyingIsAny;
  35. private static Log log = LogFactory.getLog(Markers.class);
  36. /**
  37. * Registers a marker with the position traits set.
  38. * Only the required markers are kept.
  39. * For "first-starting-within-page" it adds the markers
  40. * that are starting only if the marker class name is not
  41. * already added.
  42. * For "first-including-carryover" it adds any starting marker
  43. * if the marker class name is not already added.
  44. * For "last-starting-within-page" it adds all marks that
  45. * are starting, replacing earlier markers.
  46. * For "last-ending-within-page" it adds all markers that
  47. * are ending, replacing earlier markers.
  48. *
  49. * @param marks a map of markers to register
  50. * @param starting whether the registration happens at the start (true) or end (false) the the area
  51. * @param isfirst whether it is the first area of the parent LM
  52. * @param islast whether it is the last area of the parent LM
  53. */
  54. public void register(Map<String, Marker> marks, boolean starting, boolean isfirst, boolean islast) {
  55. // TODO: find way to put the page number in the log tracing
  56. if (marks == null) {
  57. return;
  58. }
  59. if (log.isDebugEnabled()) {
  60. log.debug("--" + marks.keySet() + ": " + (starting ? "starting" : "ending")
  61. + (isfirst ? ", first" : "") + (islast ? ", last" : ""));
  62. }
  63. if (starting) {
  64. // at the start of the area, register is-first and any areas
  65. if (firstQualifyingIsAny == null) {
  66. firstQualifyingIsAny = new HashMap<String, Marker>();
  67. }
  68. if (isfirst) {
  69. if (firstQualifyingIsFirst == null) {
  70. firstQualifyingIsFirst = new HashMap<String, Marker>();
  71. }
  72. // first on scope: only put in new values, leave current
  73. Set<Map.Entry<String, Marker>> entries = marks.entrySet();
  74. for (Map.Entry<String, Marker> entry : entries) {
  75. String key = entry.getKey();
  76. Marker marker = entry.getValue();
  77. if (!firstQualifyingIsFirst.containsKey(key)) {
  78. firstQualifyingIsFirst.put(key, marker);
  79. if (log.isTraceEnabled()) {
  80. log.trace("Adding marker " + key + " to firstQualifyingIsFirst");
  81. }
  82. }
  83. if (!firstQualifyingIsAny.containsKey(key)) {
  84. firstQualifyingIsAny.put(key, marker);
  85. if (log.isTraceEnabled()) {
  86. log.trace("Adding marker " + key + " to firstQualifyingIsAny");
  87. }
  88. }
  89. }
  90. if (lastQualifyingIsFirst == null) {
  91. lastQualifyingIsFirst = new HashMap<String, Marker>();
  92. }
  93. // last on scope: replace all
  94. lastQualifyingIsFirst.putAll(marks);
  95. if (log.isTraceEnabled()) {
  96. log.trace("Adding all markers to LastStart");
  97. }
  98. } else {
  99. // first on scope: only put in new values, leave current
  100. Set<Map.Entry<String, Marker>> entries = marks.entrySet();
  101. for (Map.Entry<String, Marker> entry : entries) {
  102. String key = entry.getKey();
  103. Marker marker = entry.getValue();
  104. if (!firstQualifyingIsAny.containsKey(key)) {
  105. firstQualifyingIsAny.put(key, marker);
  106. if (log.isTraceEnabled()) {
  107. log.trace("Adding marker " + key + " to firstQualifyingIsAny");
  108. }
  109. }
  110. }
  111. }
  112. } else {
  113. // at the end of the area, register is-last and any areas
  114. if (islast) {
  115. if (lastQualifyingIsLast == null) {
  116. lastQualifyingIsLast = new HashMap<String, Marker>();
  117. }
  118. // last on page: replace all
  119. lastQualifyingIsLast.putAll(marks);
  120. if (log.isTraceEnabled()) {
  121. log.trace("Adding all markers to lastQualifyingIsLast");
  122. }
  123. }
  124. if (lastQualifyingIsAny == null) {
  125. lastQualifyingIsAny = new HashMap<String, Marker>();
  126. }
  127. // last on page: replace all
  128. lastQualifyingIsAny.putAll(marks);
  129. if (log.isTraceEnabled()) {
  130. log.trace("Adding all markers to lastQualifyingIsAny");
  131. }
  132. }
  133. }
  134. /**
  135. * Retrieves the best candidate marker for the given position.
  136. * @param name the key used to register the marker
  137. * @param pos the retrieval scope position
  138. * @return a Marker instance
  139. */
  140. public Marker resolve(AbstractRetrieveMarker arm) {
  141. Marker mark = null;
  142. int pos = arm.getPosition();
  143. String name = arm.getRetrieveClassName();
  144. String posName = arm.getPositionLabel();
  145. String localName = arm.getLocalName();
  146. switch (pos) {
  147. case Constants.EN_FSWP: // retrieve-marker
  148. case Constants.EN_FIRST_STARTING: // retrieve-table-marker
  149. if (firstQualifyingIsFirst != null) {
  150. mark = firstQualifyingIsFirst.get(name);
  151. }
  152. if (mark == null && firstQualifyingIsAny != null) {
  153. mark = firstQualifyingIsAny.get(name);
  154. posName = "FirstAny after " + posName;
  155. }
  156. break;
  157. case Constants.EN_FIC: // retrieve-marker
  158. case Constants.EN_FIRST_INCLUDING_CARRYOVER: // retrieve-table-marker
  159. if (firstQualifyingIsAny != null) {
  160. mark = firstQualifyingIsAny.get(name);
  161. }
  162. break;
  163. case Constants.EN_LSWP: // retrieve-marker
  164. case Constants.EN_LAST_STARTING: // retrieve-table-marker
  165. if (lastQualifyingIsFirst != null) {
  166. mark = lastQualifyingIsFirst.get(name);
  167. }
  168. if (mark == null && lastQualifyingIsAny != null) {
  169. mark = lastQualifyingIsAny.get(name);
  170. posName = "LastAny after " + posName;
  171. }
  172. break;
  173. case Constants.EN_LEWP: // retrieve-marker
  174. case Constants.EN_LAST_ENDING: // retrieve-table-marker
  175. if (lastQualifyingIsLast != null) {
  176. mark = lastQualifyingIsLast.get(name);
  177. }
  178. if (mark == null && lastQualifyingIsAny != null) {
  179. mark = lastQualifyingIsAny.get(name);
  180. posName = "LastAny after " + posName;
  181. }
  182. break;
  183. default:
  184. throw new RuntimeException("Invalid position attribute in " + localName + ".");
  185. }
  186. if (log.isTraceEnabled()) {
  187. // TODO: find way to put the page number here
  188. log.trace(localName + ": name[" + name + "]; position [" + posName + "]");
  189. }
  190. return mark;
  191. }
  192. /** Dumps the current marker data to the logger. */
  193. public void dump() {
  194. if (log.isTraceEnabled()) {
  195. log.trace("FirstAny: " + this.firstQualifyingIsAny);
  196. log.trace("FirstStart: " + this.firstQualifyingIsFirst);
  197. log.trace("LastAny: " + this.lastQualifyingIsAny);
  198. log.trace("LastEnd: " + this.lastQualifyingIsLast);
  199. log.trace("LastStart: " + this.lastQualifyingIsFirst);
  200. }
  201. }
  202. }