1 package com.nwalsh.saxon; 2 3 import java.util.Stack ; 4 import java.util.StringTokenizer ; 5 import org.xml.sax.*; 6 import org.w3c.dom.*; 7 import javax.xml.transform.TransformerException ; 8 import com.icl.saxon.Controller; 9 import com.icl.saxon.om.NamePool; 10 import com.icl.saxon.output.Emitter; 11 import com.icl.saxon.tree.AttributeCollection; 12 13 47 public class CalloutEmitter extends CopyEmitter { 48 49 protected Stack elementStack = null; 50 51 52 protected Stack tempStack = null; 53 54 55 protected boolean firstElement = false; 56 57 58 protected static String foURI = "http://www.w3.org/1999/XSL/Format"; 59 60 61 protected static String xhURI = "http://www.w3.org/1999/xhtml"; 62 63 64 protected int defaultColumn = 60; 65 66 67 protected boolean foStylesheet = false; 68 69 70 private static int lineNumber = 0; 71 72 73 private static int colNumber = 0; 74 75 76 private static Callout callout[] = null; 77 78 79 private static int calloutCount = 0; 80 81 82 private static int calloutPos = 0; 83 84 85 private static FormatCallout fCallout = null; 86 87 96 public CalloutEmitter(Controller controller, 97 NamePool namePool, 98 int defaultColumn, 99 boolean foStylesheet, 100 FormatCallout fCallout) { 101 super(controller, namePool); 102 elementStack = new Stack (); 103 firstElement = true; 104 105 this.defaultColumn = defaultColumn; 106 this.foStylesheet = foStylesheet; 107 this.fCallout = fCallout; 108 } 109 110 123 public void setupCallouts (NodeList areaspecNodeList) { 124 callout = new Callout[10]; 125 calloutCount = 0; 126 calloutPos = 0; 127 lineNumber = 1; 128 colNumber = 1; 129 130 int pos = 0; 141 int coNum = 0; 142 boolean inAreaSet = false; 143 Node areaspec = areaspecNodeList.item(0); 144 NodeList children = areaspec.getChildNodes(); 145 146 for (int count = 0; count < children.getLength(); count++) { 147 Node node = children.item(count); 148 if (node.getNodeType() == Node.ELEMENT_NODE) { 149 if (node.getNodeName().equalsIgnoreCase("areaset")) { 150 coNum++; 151 NodeList areas = node.getChildNodes(); 152 for (int acount = 0; acount < areas.getLength(); acount++) { 153 Node area = areas.item(acount); 154 if (area.getNodeType() == Node.ELEMENT_NODE) { 155 if (area.getNodeName().equalsIgnoreCase("area")) { 156 addCallout(coNum, area, defaultColumn); 157 } else { 158 System.out.println("Unexpected element in areaset: " 159 + area.getNodeName()); 160 } 161 } 162 } 163 } else if (node.getNodeName().equalsIgnoreCase("area")) { 164 coNum++; 165 addCallout(coNum, node, defaultColumn); 166 } else { 167 System.out.println("Unexpected element in areaspec: " 168 + node.getNodeName()); 169 } 170 } 171 } 172 173 java.util.Arrays.sort(callout, 0, calloutCount); 175 } 176 177 178 public void characters(char[] chars, int start, int len) 179 throws TransformerException { 180 181 firstElement = false; 183 184 if (lineNumber == 0) { 185 lineNumber++; 187 colNumber = 1; 188 } 189 190 char[] newChars = new char[len]; 192 int pos = 0; 193 for (int count = start; count < start+len; count++) { 194 if (calloutPos < calloutCount 195 && callout[calloutPos].getLine() == lineNumber 196 && callout[calloutPos].getColumn() == colNumber) { 197 if (pos > 0) { 198 rtfEmitter.characters(newChars, 0, pos); 199 pos = 0; 200 } 201 202 closeOpenElements(rtfEmitter); 203 204 while (calloutPos < calloutCount 205 && callout[calloutPos].getLine() == lineNumber 206 && callout[calloutPos].getColumn() == colNumber) { 207 fCallout.formatCallout(rtfEmitter, callout[calloutPos]); 208 calloutPos++; 209 } 210 211 openClosedElements(rtfEmitter); 212 } 213 214 if (chars[count] == '\n') { 215 if (calloutPos < calloutCount 217 && callout[calloutPos].getLine() == lineNumber 218 && callout[calloutPos].getColumn() > colNumber) { 219 220 if (pos > 0) { 221 rtfEmitter.characters(newChars, 0, pos); 222 pos = 0; 223 } 224 225 closeOpenElements(rtfEmitter); 226 227 while (calloutPos < calloutCount 228 && callout[calloutPos].getLine() == lineNumber 229 && callout[calloutPos].getColumn() > colNumber) { 230 formatPad(callout[calloutPos].getColumn() - colNumber); 231 colNumber = callout[calloutPos].getColumn(); 232 while (calloutPos < calloutCount 233 && callout[calloutPos].getLine() == lineNumber 234 && callout[calloutPos].getColumn() == colNumber) { 235 fCallout.formatCallout(rtfEmitter, callout[calloutPos]); 236 calloutPos++; 237 } 238 } 239 240 openClosedElements(rtfEmitter); 241 } 242 243 lineNumber++; 244 colNumber = 1; 245 } else { 246 colNumber++; 247 } 248 newChars[pos++] = chars[count]; 249 } 250 251 if (pos > 0) { 252 rtfEmitter.characters(newChars, 0, pos); 253 } 254 } 255 256 265 protected void formatPad(int numBlanks) { 266 char chars[] = new char[numBlanks]; 267 for (int count = 0; count < numBlanks; count++) { 268 chars[count] = ' '; 269 } 270 271 try { 272 rtfEmitter.characters(chars, 0, numBlanks); 273 } catch (TransformerException e) { 274 System.out.println("Transformer Exception in formatPad"); 275 } 276 } 277 278 293 protected void addCallout (int coNum, 294 Node node, 295 int defaultColumn) { 296 297 Element area = (Element) node; 298 String units = null; 299 String coords = null; 300 301 if (area.hasAttribute("units")) { 302 units = area.getAttribute("units"); 303 } 304 305 if (area.hasAttribute("coords")) { 306 coords = area.getAttribute("coords"); 307 } 308 309 if (units != null 310 && !units.equalsIgnoreCase("linecolumn") 311 && !units.equalsIgnoreCase("linerange")) { 312 System.out.println("Only linecolumn and linerange units are supported"); 313 return; 314 } 315 316 if (coords == null) { 317 System.out.println("Coords must be specified"); 318 return; 319 } 320 321 StringTokenizer st = new StringTokenizer (coords); 323 int tokenCount = 0; 324 int c1 = 0; 325 int c2 = 0; 326 while (st.hasMoreTokens()) { 327 tokenCount++; 328 if (tokenCount > 2) { 329 System.out.println("Unparseable coordinates"); 330 return; 331 } 332 try { 333 String token = st.nextToken(); 334 int coord = Integer.parseInt(token); 335 c2 = coord; 336 if (tokenCount == 1) { 337 c1 = coord; 338 } 339 } catch (NumberFormatException e) { 340 System.out.println("Unparseable coordinate"); 341 return; 342 } 343 } 344 345 if (calloutCount == callout.length) { 347 Callout bigger[] = new Callout[calloutCount+10]; 348 for (int count = 0; count < callout.length; count++) { 349 bigger[count] = callout[count]; 350 } 351 callout = bigger; 352 } 353 354 if (tokenCount == 2) { 356 if (units != null && units.equalsIgnoreCase("linerange")) { 357 for (int count = c1; count <= c2; count++) { 358 callout[calloutCount++] = new Callout(coNum, area, 359 count, defaultColumn); 360 } 361 } else { 362 callout[calloutCount++] = new Callout(coNum, area, c1, c2); 364 } 365 } else { 366 callout[calloutCount++] = new Callout(coNum, area, c1, defaultColumn); 368 } 369 } 370 371 372 public void endElement(int nameCode) 373 throws TransformerException { 374 375 if (!elementStack.empty()) { 376 elementStack.pop(); 380 } 381 rtfEmitter.endElement(nameCode); 382 } 383 384 385 public void startElement(int nameCode, 386 org.xml.sax.Attributes attributes, 387 int[] namespaces, 388 int nscount) 389 throws TransformerException { 390 391 if (!skipThisElement(nameCode)) { 392 StartElementInfo sei = new StartElementInfo(nameCode, attributes, 393 namespaces, nscount); 394 elementStack.push(sei); 395 } 396 397 firstElement = false; 398 399 rtfEmitter.startElement(nameCode, attributes, namespaces, nscount); 400 } 401 402 418 protected boolean skipThisElement(int nameCode) { 419 if (firstElement) { 421 int thisFingerprint = namePool.getFingerprint(nameCode); 422 int foBlockFingerprint = namePool.getFingerprint(foURI, "block"); 423 int htmlPreFingerprint = namePool.getFingerprint("", "pre"); 424 int htmlDivFingerprint = namePool.getFingerprint("", "div"); 425 int xhtmlPreFingerprint = namePool.getFingerprint(xhURI, "pre"); 426 int xhtmlDivFingerprint = namePool.getFingerprint(xhURI, "div"); 427 428 if ((foStylesheet && thisFingerprint == foBlockFingerprint) 429 || (!foStylesheet && (thisFingerprint == htmlPreFingerprint 430 || thisFingerprint == htmlDivFingerprint 431 || thisFingerprint == xhtmlPreFingerprint 432 || thisFingerprint == xhtmlDivFingerprint))) { 433 return true; 435 } 436 } 437 438 return false; 439 } 440 441 private void closeOpenElements(Emitter rtfEmitter) 442 throws TransformerException { 443 tempStack = new Stack (); 445 while (!elementStack.empty()) { 446 StartElementInfo elem = (StartElementInfo) elementStack.pop(); 447 rtfEmitter.endElement(elem.getNameCode()); 448 tempStack.push(elem); 449 } 450 } 451 452 private void openClosedElements(Emitter rtfEmitter) 453 throws TransformerException { 454 while (!tempStack.empty()) { 456 StartElementInfo elem = (StartElementInfo) tempStack.pop(); 457 AttributeCollection attr = (AttributeCollection) elem.getAttributes(); 458 AttributeCollection newAttr = new AttributeCollection(namePool); 459 460 for (int acount = 0; acount < attr.getLength(); acount++) { 461 String localName = attr.getLocalName(acount); 462 int nameCode = attr.getNameCode(acount); 463 String type = attr.getType(acount); 464 String value = attr.getValue(acount); 465 String uri = attr.getURI(acount); 466 String prefix = ""; 467 468 if (localName.indexOf(':') > 0) { 469 prefix = localName.substring(0, localName.indexOf(':')); 470 localName = localName.substring(localName.indexOf(':')+1); 471 } 472 473 if (uri.equals("") 474 && ((foStylesheet 475 && localName.equals("id")) 476 || (!foStylesheet 477 && (localName.equals("id") 478 || localName.equals("name"))))) { 479 } else { 481 newAttr.addAttribute(prefix, uri, localName, type, value); 482 } 483 } 484 485 rtfEmitter.startElement(elem.getNameCode(), 486 newAttr, 487 elem.getNamespaces(), 488 elem.getNSCount()); 489 490 elementStack.push(elem); 491 } 492 } 493 494 502 private class StartElementInfo { 503 private int _nameCode; 504 org.xml.sax.Attributes _attributes; 505 int[] _namespaces; 506 int _nscount; 507 508 public StartElementInfo(int nameCode, 509 org.xml.sax.Attributes attributes, 510 int[] namespaces, 511 int nscount) { 512 _nameCode = nameCode; 513 _attributes = attributes; 514 _namespaces = namespaces; 515 _nscount = nscount; 516 } 517 518 public int getNameCode() { 519 return _nameCode; 520 } 521 522 public org.xml.sax.Attributes getAttributes() { 523 return _attributes; 524 } 525 526 public int[] getNamespaces() { 527 return _namespaces; 528 } 529 530 public int getNSCount() { 531 return _nscount; 532 } 533 } 534 } 535 | Popular Tags |