1 16 package org.apache.cocoon.transformation.pagination; 17 18 import org.apache.avalon.framework.activity.Disposable; 19 import org.apache.avalon.framework.parameters.Parameters; 20 import org.apache.avalon.framework.service.ServiceException; 21 import org.apache.avalon.framework.service.ServiceManager; 22 import org.apache.avalon.framework.service.Serviceable; 23 import org.apache.cocoon.ProcessingException; 24 import org.apache.cocoon.caching.CacheableProcessingComponent; 25 import org.apache.cocoon.environment.ObjectModelHelper; 26 import org.apache.cocoon.environment.Request; 27 import org.apache.cocoon.environment.SourceResolver; 28 import org.apache.cocoon.transformation.AbstractTransformer; 29 import org.apache.excalibur.source.Source; 30 import org.apache.excalibur.source.SourceException; 31 import org.apache.excalibur.source.SourceValidity; 32 import org.apache.excalibur.source.impl.validity.AggregatedValidity; 33 import org.apache.excalibur.source.impl.validity.TimeStampValidity; 34 import org.apache.excalibur.store.Store; 35 import org.apache.excalibur.xml.sax.SAXParser; 36 import org.xml.sax.Attributes ; 37 import org.xml.sax.InputSource ; 38 import org.xml.sax.SAXException ; 39 import org.xml.sax.helpers.AttributesImpl ; 40 41 import java.io.IOException ; 42 import java.io.Serializable ; 43 import java.util.Map ; 44 45 53 public class Paginator extends AbstractTransformer 54 implements Serviceable, Disposable, CacheableProcessingComponent { 55 56 public static final String PAGINATE_URI = "http://apache.org/cocoon/paginate/1.0"; 57 public static final String PAGINATE_PREFIX = "page"; 58 public static final String PAGINATE_PREFIX_TOKEN = PAGINATE_PREFIX + ":"; 59 60 private ServiceManager manager; 61 private SAXParser parser; 62 private Store store; 63 private SourceResolver resolver; 64 private Source inputSource; 65 private int page; 66 private int item; 67 private String itemGroup; 68 private String requestURI; 69 private Request request; 70 private Pagesheet pagesheet; 71 private int level; 72 private boolean prefixMapping; 73 74 80 public void service(ServiceManager manager) throws ServiceException { 81 try { 82 this.manager = manager; 83 getLogger().debug("Looking up "+SAXParser.ROLE); 84 this.parser = (SAXParser) manager.lookup(SAXParser.ROLE); 85 86 getLogger().debug("Looking up " + Store.TRANSIENT_STORE); 87 this.store = (Store) manager.lookup(Store.TRANSIENT_STORE); 88 } catch (Exception e) { 89 getLogger().error("Could not find component", e); 90 } 91 } 92 93 96 public void dispose() { 97 if (this.parser!=null) { 98 this.manager.release(this.parser); 99 } else { 100 this.parser = null; 101 } 102 if (this.store!=null) { 103 this.manager.release(this.store); 104 } else { 105 this.store = null; 106 } 107 } 108 109 112 public void setup(SourceResolver resolver, Map objectModel, String src, 113 Parameters par) 114 throws ProcessingException, SAXException , 115 IOException { 116 117 if (src == null) { 118 throw new ProcessingException("I need the paginate instructions (pagesheet) to continue. Set the 'src' attribute."); 119 } 120 121 try { 122 this.level = 0; 123 this.prefixMapping = false; 124 this.resolver = resolver; 125 this.inputSource = resolver.resolveURI(src); 126 if (getLogger().isDebugEnabled()) { 127 getLogger().debug("Using pagesheet: '"+ 128 this.inputSource.getURI()+"' in "+this+ 129 ", last modified: "+ 130 this.inputSource.getLastModified()); 131 } 132 this.page = par.getParameterAsInteger("page", 1); 133 this.item = par.getParameterAsInteger("item", 0); 134 this.itemGroup = par.getParameter("item-group", ""); 135 if (getLogger().isDebugEnabled()) { 136 getLogger().debug("Paginating with [page = "+this.page+ 137 ", item = "+this.item+", item-group = "+ 138 this.itemGroup+"]"); 139 } 140 141 this.request = ObjectModelHelper.getRequest(objectModel); 142 this.requestURI = request.getRequestURI(); 143 144 if (store!=null) { 147 pagesheet = (Pagesheet) store.get(src); 148 } 149 150 if ((pagesheet==null) || 152 pagesheet.modifiedSince(inputSource.getLastModified())) { 153 pagesheet = new Pagesheet(); 154 pagesheet.setLastModified(inputSource.getLastModified()); 155 parser.parse(new InputSource (inputSource.getInputStream()), 156 pagesheet); 157 if (store!=null) { 158 store.store(src, pagesheet); 159 } 160 } 161 162 this.pagesheet = (Pagesheet) this.pagesheet.clone(); 165 } catch (SourceException se) { 166 throw new ProcessingException("Could not retrieve source '" + 167 src + "'", se); 168 } 169 } 170 171 public void recycle() { 172 if (null != this.inputSource) { 173 this.resolver.release(this.inputSource); 174 this.inputSource = null; 175 } 176 this.resolver = null; 177 super.recycle(); 178 } 179 180 188 public Serializable getKey() { 189 if (this.inputSource.getLastModified()!=0) { 190 return this.inputSource.getURI()+page; 191 } else { 192 return null; 193 } 194 } 195 196 203 public SourceValidity getValidity() { 204 if (this.inputSource.getLastModified()!=0) { 205 AggregatedValidity validity = new AggregatedValidity(); 206 207 validity.add(new TimeStampValidity(page)); 208 validity.add(this.inputSource.getValidity()); 209 return validity; 210 } else { 211 return null; 212 } 213 } 214 215 228 public void startElement(String uri, String loc, String raw, 229 Attributes a) throws SAXException { 230 if ( !prefixMapping) { 231 super.startPrefixMapping(PAGINATE_PREFIX, PAGINATE_URI); 232 this.prefixMapping = true; 233 } 234 level++; 235 pagesheet.processStartElement(uri, loc); 236 if (pagesheet.isInPage(page, item, itemGroup)) { 237 int itemCount = pagesheet.itemCount(uri, loc); 238 239 if (itemCount>0) { 240 String itemGroup = pagesheet.getItemGroupName(uri, loc); 241 AttributesImpl atts = new AttributesImpl (a); 242 243 atts.addAttribute(PAGINATE_URI, "item", 244 PAGINATE_PREFIX_TOKEN+"item", "CDATA", 245 String.valueOf(itemCount)); 246 atts.addAttribute(PAGINATE_URI, "item-group", 247 PAGINATE_PREFIX_TOKEN+"item-group", 248 "CDATA", itemGroup); 249 super.startElement(uri, loc, raw, atts); 250 } else { 251 super.startElement(uri, loc, raw, a); 252 } 253 } 254 } 255 256 267 public void endElement(String uri, String loc, 268 String raw) throws SAXException { 269 level--; 270 271 if (PAGINATE_URI.equals(uri)) { 273 super.endElement(uri, loc, raw); 274 return; 275 } 276 277 if (pagesheet.isInPage(page, item, itemGroup)) { 278 if (level==0) { 279 if (item==0) { 280 int totalPages = pagesheet.getTotalPages(); 281 PageRules rules = pagesheet.getPageRules(page); 282 283 Integer [] rangeLinks = rules.getRangeLinks(); 284 int unitLinks = rules.unitLinks; 285 int currentPage = page; 286 287 addPaginateTags(rangeLinks, unitLinks, currentPage, 289 totalPages, requestURI, this); 290 291 } else { 292 int totalItems = pagesheet.getTotalItems(itemGroup); 293 AttributesImpl atts = new AttributesImpl (); 294 295 atts.addAttribute("", "current", "current", "CDATA", 296 String.valueOf(item)); 297 atts.addAttribute("", "total", "total", "CDATA", 298 String.valueOf(totalItems)); 299 atts.addAttribute("", "current-uri", "current-uri", 300 "CDATA", requestURI); 301 atts.addAttribute("", "clean-uri", "clean-uri", 302 "CDATA", cleanURI(requestURI, item)); 303 atts.addAttribute("", "page", "page", "CDATA", 304 String.valueOf(pagesheet.getPageForItem(item, 305 itemGroup))); 306 super.startElement(PAGINATE_URI, "item", 307 PAGINATE_PREFIX_TOKEN+"item", atts); 308 if (item>1) { 309 atts.clear(); 310 atts.addAttribute("", "type", "type", "CDATA", 311 "prev"); 312 atts.addAttribute("", "uri", "uri", "CDATA", 313 encodeURI(requestURI, item, 314 item-1)); 315 super.startElement(PAGINATE_URI, "link", 316 PAGINATE_PREFIX_TOKEN+"link", 317 atts); 318 super.endElement(PAGINATE_URI, "link", 319 PAGINATE_PREFIX_TOKEN+"link"); 320 } 321 if (item<=totalItems) { 322 atts.clear(); 323 atts.addAttribute("", "type", "type", "CDATA", 324 "next"); 325 atts.addAttribute("", "uri", "uri", "CDATA", 326 encodeURI(requestURI, item, 327 item+1)); 328 super.startElement(PAGINATE_URI, "link", 329 PAGINATE_PREFIX_TOKEN+"link", 330 atts); 331 super.endElement(PAGINATE_URI, "link", 332 PAGINATE_PREFIX_TOKEN+"link"); 333 } 334 super.endElement(PAGINATE_URI, "item", 335 PAGINATE_PREFIX_TOKEN+"item"); 336 } 337 338 super.endPrefixMapping(PAGINATE_PREFIX); 339 } 340 341 super.endElement(uri, loc, raw); 342 } 343 344 pagesheet.processEndElement(uri, loc); 345 } 346 347 public static void addPaginateTags(Integer [] rangeLinks, int unitLinks, 348 int currentPage, int totalPages, 349 String requestURI, 350 AbstractTransformer saxTransformer) 351 throws SAXException { 352 AttributesImpl atts = new AttributesImpl (); 353 354 atts.addAttribute("", "current", "current", "CDATA", 355 String.valueOf(currentPage)); 356 atts.addAttribute("", "total", "total", "CDATA", 357 String.valueOf(totalPages)); 358 atts.addAttribute("", "current-uri", "current-uri", "CDATA", 359 requestURI); 360 atts.addAttribute("", "clean-uri", "clean-uri", "CDATA", 361 Paginator.cleanURI(requestURI, currentPage)); 362 saxTransformer.startElement(Paginator.PAGINATE_URI, "page", 363 Paginator.PAGINATE_PREFIX_TOKEN+"page", 364 atts); 365 366 for (int i = rangeLinks.length-1; i>-1; i--) { 367 int rangeLink = rangeLinks[i].intValue(); 368 369 if ((rangeLink>0) && (currentPage-rangeLink>=1)) { 370 atts.clear(); 371 atts.addAttribute("", "type", "type", "CDATA", "prev"); 372 atts.addAttribute("", "range", "range", "CDATA", 373 rangeLinks[i].toString()); 374 atts.addAttribute("", "uri", "uri", "CDATA", 375 Paginator.encodeURI(requestURI, 376 currentPage, 377 currentPage-rangeLink)); 378 atts.addAttribute("", "page", "page", "CDATA", 379 String.valueOf(currentPage-rangeLink)); 380 saxTransformer.startElement(Paginator.PAGINATE_URI, 381 "range-link", 382 Paginator.PAGINATE_PREFIX_TOKEN+ 383 "range-link", atts); 384 saxTransformer.endElement(Paginator.PAGINATE_URI, 385 "range-link", 386 Paginator.PAGINATE_PREFIX_TOKEN+ 387 "range-link"); 388 } 389 } 390 391 for (int i = currentPage-unitLinks; i<currentPage; i++) { 392 if (i>0) { 393 atts.clear(); 394 atts.addAttribute("", "type", "type", "CDATA", "prev"); 395 atts.addAttribute("", "uri", "uri", "CDATA", 396 Paginator.encodeURI(requestURI, 397 currentPage, i)); 398 atts.addAttribute("", "page", "page", "CDATA", 399 String.valueOf(i)); 400 saxTransformer.startElement(Paginator.PAGINATE_URI, "link", 401 Paginator.PAGINATE_PREFIX_TOKEN+ 402 "link", atts); 403 saxTransformer.endElement(Paginator.PAGINATE_URI, "link", 404 Paginator.PAGINATE_PREFIX_TOKEN+ 405 "link"); 406 } 407 } 408 for (int i = currentPage+1; i<=currentPage+unitLinks; i++) { 409 if (i<=totalPages) { 410 atts.clear(); 411 atts.addAttribute("", "type", "type", "CDATA", "next"); 412 atts.addAttribute("", "uri", "uri", "CDATA", 413 Paginator.encodeURI(requestURI, 414 currentPage, i)); 415 atts.addAttribute("", "page", "page", "CDATA", 416 String.valueOf(i)); 417 saxTransformer.startElement(Paginator.PAGINATE_URI, "link", 418 Paginator.PAGINATE_PREFIX_TOKEN+ 419 "link", atts); 420 saxTransformer.endElement(Paginator.PAGINATE_URI, "link", 421 Paginator.PAGINATE_PREFIX_TOKEN+ 422 "link"); 423 } 424 } 425 426 for (int i = 0; i<rangeLinks.length; i++) { 427 int rangeLink = rangeLinks[i].intValue(); 428 429 if ((rangeLink>0) && (currentPage+rangeLink<=totalPages)) { 430 atts.clear(); 431 atts.addAttribute("", "type", "type", "CDATA", "next"); 432 atts.addAttribute("", "range", "range", "CDATA", 433 rangeLinks[i].toString()); 434 atts.addAttribute("", "uri", "uri", "CDATA", 435 Paginator.encodeURI(requestURI, 436 currentPage, 437 currentPage+rangeLink)); 438 atts.addAttribute("", "page", "page", "CDATA", 439 String.valueOf(currentPage+rangeLink)); 440 saxTransformer.startElement(Paginator.PAGINATE_URI, 441 "range-link", 442 Paginator.PAGINATE_PREFIX_TOKEN+ 443 "range-link", atts); 444 saxTransformer.endElement(Paginator.PAGINATE_URI, 445 "range-link", 446 Paginator.PAGINATE_PREFIX_TOKEN+ 447 "range-link"); 448 } 449 } 450 451 saxTransformer.endElement(Paginator.PAGINATE_URI, "page", 452 Paginator.PAGINATE_PREFIX_TOKEN+"page"); 453 } 454 455 462 public void characters(char c[], int start, int len) throws SAXException { 463 pagesheet.processCharacters(c, start, len); 464 if (pagesheet.isInPage(page, item, itemGroup)) { 465 super.characters(c, start, len); 466 } 467 } 468 469 476 public void ignorableWhitespace(char c[], int start, 477 int len) throws SAXException { 478 if (pagesheet.isInPage(page, item, itemGroup)) { 479 super.ignorableWhitespace(c, start, len); 480 } 481 } 482 483 490 public void processingInstruction(String target, 491 String data) throws SAXException { 492 if (pagesheet.isInPage(page, item, itemGroup)) { 493 super.processingInstruction(target, data); 494 } 495 } 496 497 503 public void skippedEntity(String name) throws SAXException { 504 if (pagesheet.isInPage(page, item, itemGroup)) { 505 super.skippedEntity(name); 506 } 507 } 508 509 518 public void startDTD(String name, String publicId, 519 String systemId) throws SAXException { 520 if (pagesheet.isInPage(page, item, itemGroup)) { 521 super.startDTD(name, publicId, systemId); 522 } else { 523 throw new SAXException ("Recieved startDTD not in page."); 524 } 525 } 526 527 530 public void endDTD() throws SAXException { 531 if (pagesheet.isInPage(page, item, itemGroup)) { 532 super.endDTD(); 533 } else { 534 throw new SAXException ("Recieved endDTD not in page."); 535 } 536 } 537 538 544 public void startEntity(String name) throws SAXException { 545 if (pagesheet.isInPage(page, item, itemGroup)) { 546 super.startEntity(name); 547 } 548 } 549 550 555 public void endEntity(String name) throws SAXException { 556 if (pagesheet.isInPage(page, item, itemGroup)) { 557 super.endEntity(name); 558 } 559 } 560 561 564 public void startCDATA() throws SAXException { 565 if (pagesheet.isInPage(page, item, itemGroup)) { 566 super.startCDATA(); 567 } 568 } 569 570 573 public void endCDATA() throws SAXException { 574 if (pagesheet.isInPage(page, item, itemGroup)) { 575 super.endCDATA(); 576 } 577 } 578 579 586 public void comment(char ch[], int start, int len) throws SAXException { 587 if (pagesheet.isInPage(page, item, itemGroup)) { 588 super.comment(ch, start, len); 589 } 590 } 591 592 596 public static String cleanURI(String uri, int current) { 597 String currentS = String.valueOf(current); 598 int index = uri.lastIndexOf(currentS); 599 600 if (index==-1) { 601 return uri; 602 } else { 603 return uri.substring(0, index-1)+ 604 uri.substring(index+currentS.length()+1); 605 } 606 } 607 608 614 public static String encodeURI(String uri, int current, int next) { 615 String currentS = String.valueOf(current); 616 String nextS = String.valueOf(next); 617 int index = uri.lastIndexOf(currentS); 618 619 if (index==-1) { 620 index = uri.lastIndexOf('.'); 621 if (index==-1) { 622 return uri+"("+nextS+")"; 623 } else { 624 return uri.substring(0, index)+"("+nextS+")."+ 625 uri.substring(index+1); 626 } 627 } else { 628 return uri.substring(0, index)+nextS+ 629 uri.substring(index+currentS.length()); 630 } 631 } 632 } 633 | Popular Tags |