1 51 package org.apache.fop.fo; 52 53 import org.apache.fop.apps.FOPException; 55 import org.apache.fop.apps.StreamRenderer; 56 import org.apache.fop.fo.pagination.PageSequence; 57 import org.apache.fop.extensions.ExtensionObj; 58 59 import org.apache.avalon.framework.logger.Logger; 61 62 import org.xml.sax.helpers.DefaultHandler ; 64 import org.xml.sax.SAXException ; 65 import org.xml.sax.Attributes ; 66 import org.xml.sax.Locator ; 67 68 import java.util.HashMap ; 70 import java.util.ArrayList ; 71 72 83 public class FOTreeBuilder extends DefaultHandler implements TreeBuilder { 84 85 89 protected HashMap fobjTable = new HashMap (); 90 91 protected ArrayList namespaces = new ArrayList (); 92 93 96 protected HashMap propertylistTable = new HashMap (); 97 98 101 protected FObj currentFObj = null; 102 103 106 protected FObj rootFObj = null; 107 108 111 protected HashMap unknownFOs = new HashMap (); 112 113 118 private StreamRenderer streamRenderer; 119 120 private Logger log; 121 122 private Locator locator; 123 124 private int errorCount = 0; 125 126 public FOTreeBuilder() {} 127 128 public void setLogger(Logger logger) { 129 log = logger; 130 } 131 132 133 134 public void setStreamRenderer(StreamRenderer streamRenderer) { 135 this.streamRenderer = streamRenderer; 136 } 137 138 public StreamRenderer getStreamRenderer() { 139 return this.streamRenderer; 140 } 141 142 148 public void addMapping(String namespaceURI, HashMap table) { 149 this.fobjTable.put(namespaceURI, table); 150 this.namespaces.add(namespaceURI.intern()); 151 } 152 153 159 public void addPropertyList(String namespaceURI, HashMap list) { 160 PropertyListBuilder plb; 161 plb = (PropertyListBuilder)this.propertylistTable.get(namespaceURI); 162 if (plb == null) { 163 plb = new PropertyListBuilder(); 164 plb.addList(list); 165 this.propertylistTable.put(namespaceURI, plb); 166 } else { 167 plb.addList(list); 168 } 169 } 170 171 178 public void addElementPropertyList(String namespaceURI, String localName, 179 HashMap list) { 180 PropertyListBuilder plb; 181 plb = (PropertyListBuilder)this.propertylistTable.get(namespaceURI); 182 if (plb == null) { 183 plb = new PropertyListBuilder(); 184 plb.addElementList(localName, list); 185 this.propertylistTable.put(namespaceURI, plb); 186 } else { 187 plb.addElementList(localName, list); 188 } 189 } 190 191 public void addPropertyListBuilder(String namespaceURI, 192 PropertyListBuilder propbuilder) { 193 PropertyListBuilder plb; 194 plb = (PropertyListBuilder)this.propertylistTable.get(namespaceURI); 195 if (plb == null) { 196 this.propertylistTable.put(namespaceURI, propbuilder); 197 } else { 198 } 200 } 201 202 205 public void characters(char data[], int start, int length) { 206 if(currentFObj != null) { 207 currentFObj.addCharacters(data, start, length); 208 } 209 } 210 211 214 public void endElement(String uri, String localName, String rawName) 215 throws SAXException { 216 currentFObj.end(); 217 218 if(currentFObj instanceof PageSequence) { 223 streamRenderer.render((PageSequence) currentFObj); 224 } else if(currentFObj instanceof ExtensionObj) { 225 if(!(currentFObj.getParent() instanceof ExtensionObj)) { 226 streamRenderer.addExtension((ExtensionObj)currentFObj); 227 } 228 } 229 230 currentFObj = (FObj)currentFObj.getParent(); 231 } 232 233 236 public void startDocument() 237 throws SAXException { 238 rootFObj = null; log.info("building formatting object tree"); 240 streamRenderer.startRenderer(); 241 } 242 243 public void endDocument() 244 throws SAXException { 245 log.info("Parsing of document complete, stopping renderer"); 246 streamRenderer.stopRenderer(); 247 } 248 249 public void setDocumentLocator(Locator locator) { 250 this.locator = locator; 251 } 252 253 private String formatLocator(Locator locator) { 254 if (locator == null) { 255 return ""; 256 } else { 257 StringBuffer sb = new StringBuffer (); 258 if (locator.getSystemId() != null) { 259 sb.append(locator.getSystemId()); 260 } else if (locator.getPublicId() != null) { 261 sb.append(locator.getPublicId()); 262 } else { 263 sb.append("Unknown source"); 264 } 265 sb.append(" (line: "); 266 sb.append(locator.getLineNumber()); 267 sb.append(", col: "); 268 sb.append(locator.getColumnNumber()); 269 sb.append(")"); 270 return sb.toString(); 271 } 272 } 273 274 277 public void startElement(String uri, String localName, String rawName, 278 Attributes attlist) throws SAXException { 279 280 FObj fobj; 281 282 283 FObj.Maker fobjMaker = null; 284 285 286 HashMap table = (HashMap )fobjTable.get(uri); 287 if(table != null) { 288 fobjMaker = (FObj.Maker)table.get(localName); 289 } 290 291 PropertyListBuilder currentListBuilder = 292 (PropertyListBuilder)this.propertylistTable.get(uri); 293 294 boolean foreignXML = false; 295 String systemId=null; 296 int line = -1; 297 int column = -1; 298 if (locator!=null) { 299 systemId = locator.getSystemId(); 300 line = locator.getLineNumber(); 301 column = locator.getColumnNumber(); 302 } 303 if (fobjMaker == null) { 304 String fullName = uri + "^" + localName; 305 if (!this.unknownFOs.containsKey(fullName)) { 306 this.unknownFOs.put(fullName, ""); 307 StringBuffer sb = new StringBuffer (128); 308 sb.append("Unsupported element encountered: "); 309 sb.append(localName); 310 sb.append(" (Namespace: "); 311 sb.append("".equals(uri) ? "default" : uri); 312 sb.append("). "); 313 sb.append("Source context: "); 314 if (locator != null) { 315 sb.append(formatLocator(locator)); 316 } else { 317 sb.append("unavailable"); 318 } 319 log.error(sb.toString()); 320 if (this.errorCount == 0) { 321 log.error("Expected XSL-FO (root, page-sequence, etc.), " 322 + "SVG (svg, rect, etc.) or elements from another " 323 + "supported language."); 324 } 325 this.errorCount++; 326 } 327 if(namespaces.contains(uri.intern())) { 328 fobjMaker = new Unknown.Maker(); 330 } else { 331 fobjMaker = new UnknownXMLObj.Maker(uri, localName); 332 foreignXML = true; 333 } 334 } 335 336 try { 337 PropertyList list = null; 338 if (currentListBuilder != null) { 339 list = 340 currentListBuilder.makeList(uri, localName, attlist, 341 (currentFObj == null) ? null 342 : currentFObj.properties, currentFObj); 343 } else if(foreignXML) { 344 list = new DirectPropertyListBuilder.AttrPropertyList(attlist); 345 } else { 346 if(currentFObj == null) { 347 throw new FOPException("Invalid XML or missing namespace", 348 systemId, line, column); 349 } 350 list = currentFObj.properties; 351 } 352 fobj = fobjMaker.make(currentFObj, list, systemId, line, column); 353 fobj.setLogger(log); 354 } catch (FOPException e) { 355 throw new SAXException (e); 356 } 357 358 if (rootFObj == null) { 359 rootFObj = fobj; 360 if (!fobj.getName().equals("fo:root")) { 361 if (fobj.getName().equals("root")) { 362 throw new SAXException (new FOPException( 363 "Root element is missing the namespace declaration: " 364 + "http://www.w3.org/1999/XSL/Format", 365 systemId, line, column)); 366 } else { 367 throw new SAXException (new FOPException( 368 "Root element must be root, not " 369 + fobj.getName(), systemId, line, column)); 370 } 371 } 372 } else if(!(fobj instanceof org.apache.fop.fo.pagination.PageSequence)) { 373 currentFObj.addChild(fobj); 374 } 375 376 currentFObj = fobj; 377 } 378 379 public void reset() { 380 currentFObj = null; 381 rootFObj = null; 382 streamRenderer = null; 383 this.errorCount = 0; 384 } 385 386 public boolean hasData() { 387 return (rootFObj != null); 388 } 389 390 } 391 | Popular Tags |