001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.html; 014 015import static org.apache.juneau.collections.JsonMap.*; 016import static org.apache.juneau.common.internal.ThrowableUtils.*; 017import static org.apache.juneau.internal.CollectionUtils.*; 018 019import java.lang.annotation.*; 020import java.lang.reflect.*; 021import java.nio.charset.*; 022import java.util.*; 023import java.util.function.*; 024import java.util.regex.*; 025 026import org.apache.juneau.*; 027import org.apache.juneau.collections.*; 028import org.apache.juneau.internal.*; 029import org.apache.juneau.svl.*; 030import org.apache.juneau.utils.*; 031import org.apache.juneau.xml.*; 032 033/** 034 * Serializes POJOs to HTTP responses as HTML documents. 035 * 036 * <h5 class='topic'>Media types</h5> 037 * <p> 038 * Handles <c>Accept</c> types: <bc>text/html</bc> 039 * <p> 040 * Produces <c>Content-Type</c> types: <bc>text/html</bc> 041 * 042 * <h5 class='topic'>Description</h5> 043 * <p> 044 * Same as {@link HtmlSerializer}, except wraps the response in <code><xt><html></code>, 045 * <code><xt><head></code>, and <code><xt><body></code> tags so that it can be rendered in a browser. 046 * 047 * <p> 048 * Configurable properties are typically specified via <ja>@HtmlDocConfig</ja>. 049 * 050 * <h5 class='section'>Example:</h5> 051 * <p class='bjava'> 052 * <ja>@Rest</ja>( 053 * messages=<js>"nls/AddressBookResource"</js>, 054 * title=<js>"$L{title}"</js>, 055 * description=<js>"$L{description}"</js> 056 * ) 057 * <ja>@HtmlDocConfig</ja>( 058 * navlinks={ 059 * <js>"api: servlet:/api"</js>, 060 * <js>"doc: doc"</js> 061 * } 062 * ) 063 * <jk>public class</jk> AddressBookResource <jk>extends</jk> BasicRestServlet { 064 * </p> 065 * 066 * <p> 067 * The <c>$L{...}</c> variable represent localized strings pulled from the resource bundle identified by the 068 * <c>messages</c> annotation. 069 * <br>These variables are replaced at runtime based on the HTTP request locale. 070 * <br>Several built-in runtime variable types are defined, and the API can be extended to include user-defined variables. 071 * 072 * <h5 class='section'>Notes:</h5><ul> 073 * <li class='note'>This class is thread safe and reusable. 074 * </ul> 075 * 076 * <h5 class='section'>See Also:</h5><ul> 077 * <li class='link'><a class="doclink" href="../../../../index.html#jm.HtmlDetails">HTML Details</a> 078 079 * </ul> 080 */ 081public class HtmlDocSerializer extends HtmlStrippedDocSerializer { 082 083 //------------------------------------------------------------------------------------------------------------------- 084 // Static 085 //------------------------------------------------------------------------------------------------------------------- 086 087 private static final String[] EMPTY_ARRAY = new String[0]; 088 089 /** Default serializer, all default settings. */ 090 public static final HtmlDocSerializer DEFAULT = new HtmlDocSerializer(create()); 091 092 /** 093 * Creates a new builder for this object. 094 * 095 * @return A new builder. 096 */ 097 public static Builder create() { 098 return new Builder(); 099 } 100 101 //------------------------------------------------------------------------------------------------------------------- 102 // Builder 103 //------------------------------------------------------------------------------------------------------------------- 104 105 /** 106 * Builder class. 107 */ 108 @FluentSetters 109 public static class Builder extends HtmlStrippedDocSerializer.Builder { 110 111 private static final Cache<HashKey,HtmlDocSerializer> CACHE = Cache.of(HashKey.class, HtmlDocSerializer.class).build(); 112 113 List<String> aside, footer, head, header, nav, navlinks, script, style, stylesheet; 114 AsideFloat asideFloat; 115 String noResultsMessage; 116 boolean nowrap; 117 Class<? extends HtmlDocTemplate> template; 118 List<Class<? extends HtmlWidget>> widgets; 119 120 /** 121 * Constructor, default settings. 122 */ 123 protected Builder() { 124 super(); 125 produces("text/html"); 126 accept("text/html"); 127 asideFloat = AsideFloat.RIGHT; 128 noResultsMessage = "<p>no results</p>"; 129 template = BasicHtmlDocTemplate.class; 130 } 131 132 /** 133 * Copy constructor. 134 * 135 * @param copyFrom The bean to copy from. 136 */ 137 protected Builder(HtmlDocSerializer copyFrom) { 138 super(copyFrom); 139 aside = copy(copyFrom.aside); 140 footer = copy(copyFrom.footer); 141 head = copy(copyFrom.head); 142 header = copy(copyFrom.header); 143 nav = copy(copyFrom.nav); 144 navlinks = copy(copyFrom.navlinks); 145 script = copy(copyFrom.script); 146 style = copy(copyFrom.style); 147 stylesheet = copy(copyFrom.stylesheet); 148 asideFloat = copyFrom.asideFloat; 149 noResultsMessage = copyFrom.noResultsMessage; 150 nowrap = copyFrom.nowrap; 151 template = copyFrom.template; 152 widgets = copy(copyFrom.widgets); 153 } 154 155 /** 156 * Copy constructor. 157 * 158 * @param copyFrom The builder to copy from. 159 */ 160 protected Builder(Builder copyFrom) { 161 super(copyFrom); 162 aside = copy(copyFrom.aside); 163 footer = copy(copyFrom.footer); 164 head = copy(copyFrom.head); 165 header = copy(copyFrom.header); 166 nav = copy(copyFrom.nav); 167 navlinks = copy(copyFrom.navlinks); 168 script = copy(copyFrom.script); 169 style = copy(copyFrom.style); 170 stylesheet = copy(copyFrom.stylesheet); 171 asideFloat = copyFrom.asideFloat; 172 noResultsMessage = copyFrom.noResultsMessage; 173 nowrap = copyFrom.nowrap; 174 template = copyFrom.template; 175 widgets = copy(copyFrom.widgets); 176 } 177 178 @Override /* Context.Builder */ 179 public Builder copy() { 180 return new Builder(this); 181 } 182 183 @Override /* Context.Builder */ 184 public HtmlDocSerializer build() { 185 return cache(CACHE).build(HtmlDocSerializer.class); 186 } 187 188 @Override /* Context.Builder */ 189 public HashKey hashKey() { 190 return HashKey.of( 191 super.hashKey(), 192 aside, 193 footer, 194 head, 195 header, 196 nav, 197 navlinks, 198 script, 199 style, 200 stylesheet, 201 asideFloat, 202 noResultsMessage, 203 nowrap, 204 template, 205 widgets 206 ); 207 } 208 209 //----------------------------------------------------------------------------------------------------------------- 210 // Properties 211 //----------------------------------------------------------------------------------------------------------------- 212 213 /** 214 * Aside section contents. 215 * 216 * <p> 217 * Allows you to specify the contents of the aside section on the HTML page. 218 * The aside section floats on the right of the page for providing content supporting the serialized content of 219 * the page. 220 * 221 * <p> 222 * By default, the aside section is empty. 223 * 224 * <h5 class='section'>Example:</h5> 225 * <p class='bjava'> 226 * WriterSerializer <jv>serializer</jv> = HtmlDocSerializer 227 * .<jsm>create</jsm>() 228 * .aside( 229 * <js>"<ul>"</js>, 230 * <js>" <li>Item 1"</js>, 231 * <js>" <li>Item 2"</js>, 232 * <js>" <li>Item 3"</js>, 233 * <js>"</ul>"</js> 234 * ) 235 * .build(); 236 * </p> 237 * 238 * <h5 class='section'>Notes:</h5><ul> 239 * <li class='note'> 240 * Format: HTML 241 * <li class='note'> 242 * Supports <a class="doclink" href="../../../../index.html#jrs.SvlVariables">SVL Variables</a> 243 * (e.g. <js>"$L{my.localized.variable}"</js>). 244 * <li class='note'> 245 * A value of <js>"NONE"</js> can be used to force no value. 246 * <li class='note'> 247 * The parent value can be included by adding the literal <js>"INHERIT"</js> as a value. 248 * <li class='note'> 249 * Multiple values are combined with newlines into a single string. 250 * <li class='note'> 251 * On methods, this value is inherited from the <ja>@HtmlDocConfig</ja> annotation on the servlet/resource class. 252 * <li class='note'> 253 * On servlet/resource classes, this value is inherited from the <ja>@HtmlDocConfig</ja> annotation on the 254 * parent class. 255 * </ul> 256 * 257 * @param value 258 * The new value for this property. 259 * @return This object. 260 */ 261 @FluentSetter 262 public Builder aside(String...value) { 263 aside = merge(aside, value); 264 return this; 265 } 266 267 /** 268 * Returns the list of aside section contents. 269 * 270 * <p> 271 * Gives access to the inner list if you need to make more than simple additions via {@link #aside(String...)}. 272 * 273 * @return The list of aside section contents. 274 * @see #aside(String...) 275 */ 276 public List<String> aside() { 277 if (aside == null) 278 aside = list(); 279 return aside; 280 } 281 282 /** 283 * Float aside section contents. 284 * 285 * <p> 286 * Allows you to position the aside contents of the page around the main contents. 287 * 288 * <p> 289 * By default, the aside section is floated to the right. 290 * 291 * <h5 class='section'>Example:</h5> 292 * <p class='bjava'> 293 * WriterSerializer <jv>serializer</jv> = HtmlDocSerializer 294 * .<jsm>create</jsm>() 295 * .aside( 296 * <js>"<ul>"</js>, 297 * <js>" <li>Item 1"</js>, 298 * <js>" <li>Item 2"</js>, 299 * <js>" <li>Item 3"</js>, 300 * <js>"</ul>"</js> 301 * ) 302 * .asideFloat(<jsf>RIGHT</jsf>) 303 * .build(); 304 * </p> 305 * 306 * @param value 307 * The new value for this property. 308 * @return This object. 309 */ 310 @FluentSetter 311 public Builder asideFloat(AsideFloat value) { 312 asideFloat = value; 313 return this; 314 } 315 316 /** 317 * Footer section contents. 318 * 319 * <p> 320 * Allows you to specify the contents of the footer section on the HTML page. 321 * 322 * <p> 323 * By default, the footer section is empty. 324 * 325 * <h5 class='section'>Example:</h5> 326 * <p class='bjava'> 327 * WriterSerializer <jv>serializer</jv> = HtmlDocSerializer 328 * .<jsm>create</jsm>() 329 * .footer( 330 * <js>"<b>This interface is great!</b>"</js> 331 * ) 332 * .build(); 333 * </p> 334 * 335 * @param value 336 * The new value for this property. 337 * @return This object. 338 */ 339 @FluentSetter 340 public Builder footer(String...value) { 341 footer = merge(footer, value); 342 return this; 343 } 344 345 /** 346 * Returns the list of footer section contents. 347 * 348 * <p> 349 * Gives access to the inner list if you need to make more than simple additions via {@link #footer(String...)}. 350 * 351 * @return The list of footer section contents. 352 * @see #footer(String...) 353 */ 354 public List<String> footer() { 355 if (footer == null) 356 footer = list(); 357 return footer; 358 } 359 360 /** 361 * Additional head section content. 362 * 363 * <p> 364 * Adds the specified HTML content to the head section of the page. 365 * 366 * <h5 class='section'>Example:</h5> 367 * <p class='bjava'> 368 * WriterSerializer <jv>serializer</jv> = HtmlDocSerializer 369 * .<jsm>create</jsm>() 370 * .head( 371 * <js>"<link rel='icon' href='$U{servlet:/htdocs/mypageicon.ico}'>"</js> 372 * ) 373 * .build(); 374 * </p> 375 * 376 * @param value 377 * The new value for this property. 378 * @return This object. 379 */ 380 @FluentSetter 381 public Builder head(String...value) { 382 head = merge(head, value); 383 return this; 384 } 385 386 /** 387 * Returns the list of head section contents. 388 * 389 * <p> 390 * Gives access to the inner list if you need to make more than simple additions via {@link #head(String...)}. 391 * 392 * @return The list of head section contents. 393 * @see #head(String...) 394 */ 395 public List<String> head() { 396 if (head == null) 397 head = list(); 398 return head; 399 } 400 401 /** 402 * Header section contents. 403 * 404 * <p> 405 * Allows you to override the contents of the header section on the HTML page. 406 * The header section normally contains the title and description at the top of the page. 407 * 408 * <h5 class='section'>Example:</h5> 409 * <p class='bjava'> 410 * WriterSerializer <jv>serializer</jv> = HtmlDocSerializer 411 * .<jsm>create</jsm>() 412 * .header( 413 * <js>"<h1>My own header</h1>"</js> 414 * ) 415 * .build() 416 * </p> 417 * 418 * @param value 419 * The new value for this property. 420 * @return This object. 421 */ 422 @FluentSetter 423 public Builder header(String...value) { 424 header = merge(header, value); 425 return this; 426 } 427 428 /** 429 * Returns the list of header section contents. 430 * 431 * <p> 432 * Gives access to the inner list if you need to make more than simple additions via {@link #header(String...)}. 433 * 434 * @return The list of header section contents. 435 * @see #header(String...) 436 */ 437 public List<String> header() { 438 if (header == null) 439 header = list(); 440 return header; 441 } 442 443 /** 444 * Nav section contents. 445 * 446 * <p> 447 * Allows you to override the contents of the nav section on the HTML page. 448 * The nav section normally contains the page links at the top of the page. 449 * 450 * <h5 class='section'>Example:</h5> 451 * <p class='bjava'> 452 * WriterSerializer <jv>serializer</jv> = HtmlDocSerializer 453 * .<jsm>create</jsm>() 454 * .nav( 455 * <js>"<p class='special-navigation'>This is my special navigation content</p>"</js> 456 * ) 457 * .build() 458 * </p> 459 * 460 * <p> 461 * When this property is specified, the {@link Builder#navlinks(String...)} property is ignored. 462 * 463 * @param value 464 * The new value for this property. 465 * @return This object. 466 */ 467 @FluentSetter 468 public Builder nav(String...value) { 469 nav = merge(nav, value); 470 return this; 471 } 472 473 /** 474 * Returns the list of nav section contents. 475 * 476 * <p> 477 * Gives access to the inner list if you need to make more than simple additions via {@link #nav(String...)}. 478 * 479 * @return The list of nav section contents. 480 * @see #nav(String...) 481 */ 482 public List<String> nav() { 483 if (nav == null) 484 nav = list(); 485 return nav; 486 } 487 488 /** 489 * Page navigation links. 490 * 491 * <p> 492 * Adds a list of hyperlinks immediately under the title and description but above the content of the page. 493 * 494 * <p> 495 * This can be used to provide convenient hyperlinks when viewing the REST interface from a browser. 496 * 497 * <p> 498 * The value is an array of strings with two possible values: 499 * <ul> 500 * <li>A key-value pair representing a hyperlink label and href: 501 * <br><js>"google: http://google.com"</js> 502 * <li>Arbitrary HTML. 503 * </ul> 504 * 505 * <p> 506 * Relative URLs are considered relative to the servlet path. 507 * For example, if the servlet path is <js>"http://localhost/myContext/myServlet"</js>, and the 508 * URL is <js>"foo"</js>, the link becomes <js>"http://localhost/myContext/myServlet/foo"</js>. 509 * Absolute (<js>"/myOtherContext/foo"</js>) and fully-qualified (<js>"http://localhost2/foo"</js>) URLs 510 * can also be used in addition to various other protocols specified by {@link UriResolver} such as 511 * <js>"servlet:/..."</js>. 512 * 513 * <h5 class='section'>Example:</h5> 514 * <p class='bjava'> 515 * WriterSerializer <jv>serializer</jv> = HtmlDocSerializer 516 * .<jsm>create</jsm>() 517 * .navlinks( 518 * <js>"api: servlet:/api"</js>, 519 * <js>"stats: servlet:/stats"</js>, 520 * <js>"doc: doc"</js> 521 * ) 522 * .build(); 523 * </p> 524 * 525 * @param value 526 * The new value for this property. 527 * @return This object. 528 */ 529 @FluentSetter 530 public Builder navlinks(String...value) { 531 navlinks = mergeNavLinks(navlinks, value); 532 return this; 533 } 534 535 /** 536 * Returns the list of navlinks section contents. 537 * 538 * <p> 539 * Gives access to the inner list if you need to make more than simple additions via {@link #navlinks(String...)}. 540 * 541 * @return The list of navlinks section contents. 542 * @see #navlinks(String...) 543 */ 544 public List<String> navlinks() { 545 if (navlinks == null) 546 navlinks = list(); 547 return navlinks; 548 } 549 550 /** 551 * No-results message. 552 * 553 * <p> 554 * Allows you to specify the string message used when trying to serialize an empty array or empty list. 555 * 556 * <h5 class='section'>Example:</h5> 557 * <p class='bjava'> 558 * WriterSerializer <jv>serializer</jv> = HtmlDocSerializer 559 * .<jsm>create</jsm>() 560 * .noResultsMessage(<js>"<b>This interface is great!</b>"</js>) 561 * .build(); 562 * </p> 563 * 564 * <p> 565 * A value of <js>"NONE"</js> can be used to represent no value to differentiate it from an empty string. 566 * 567 * @param value 568 * The new value for this property. 569 * @return This object. 570 */ 571 @FluentSetter 572 public Builder noResultsMessage(String value) { 573 noResultsMessage = value; 574 return this; 575 } 576 577 /** 578 * Prevent word wrap on page. 579 * 580 * <p> 581 * Adds <js>"* {white-space:nowrap}"</js> to the CSS instructions on the page to prevent word wrapping. 582 * 583 * @return This object. 584 */ 585 @FluentSetter 586 public Builder nowrap() { 587 return nowrap(true); 588 } 589 590 /** 591 * Same as {@link #nowrap()} but allows you to explicitly specify the boolean value. 592 * 593 * @param value 594 * The new value for this property. 595 * @return This object. 596 * @see #nowrap() 597 */ 598 @FluentSetter 599 public Builder nowrap(boolean value) { 600 nowrap = value; 601 return this; 602 } 603 604 /** 605 * Adds the specified Javascript code to the HTML page. 606 * 607 * <p> 608 * A shortcut on <ja>@Rest</ja> is also provided for this setting: 609 * <p class='bjava'> 610 * WriterSerializer <jv>serializer</jv> = HtmlDocSerializer 611 * .<jsm>create</jsm>() 612 * .script(<js>"alert('hello!');"</js>) 613 * .build(); 614 * </p> 615 * 616 * @param value 617 * The value to add to this property. 618 * @return This object. 619 */ 620 @FluentSetter 621 public Builder script(String...value) { 622 script = merge(script, value); 623 return this; 624 } 625 626 /** 627 * Returns the list of page script contents. 628 * 629 * <p> 630 * Gives access to the inner list if you need to make more than simple additions via {@link #script(String...)}. 631 * 632 * @return The list of page script contents. 633 * @see #script(String...) 634 */ 635 public List<String> script() { 636 if (script == null) 637 script = list(); 638 return script; 639 } 640 641 /** 642 * Adds the specified CSS instructions to the HTML page. 643 * 644 * <p class='bjava'> 645 * WriterSerializer <jv>serializer</jv> = HtmlDocSerializer 646 * .<jsm>create</jsm>() 647 * .style( 648 * <js>"h3 { color: red; }"</js>, 649 * <js>"h5 { font-weight: bold; }"</js> 650 * ) 651 * .build(); 652 * </p> 653 * 654 * @param value 655 * The value to add to this property. 656 * @return This object. 657 */ 658 @FluentSetter 659 public Builder style(String...value) { 660 style = merge(style, value); 661 return this; 662 } 663 664 /** 665 * Returns the list of page style contents. 666 * 667 * <p> 668 * Gives access to the inner list if you need to make more than simple additions via {@link #style(String...)}. 669 * 670 * @return The list of page style contents. 671 * @see #style(String...) 672 */ 673 public List<String> style() { 674 if (style == null) 675 style = list(); 676 return style; 677 } 678 679 /** 680 * Adds to the list of stylesheet URLs. 681 * 682 * <p> 683 * Note that this stylesheet is controlled by the <code><ja>@Rest</ja>.stylesheet()</code> annotation. 684 * 685 * @param value 686 * The value to add to this property. 687 * @return This object. 688 */ 689 @FluentSetter 690 public Builder stylesheet(String...value) { 691 stylesheet = merge(stylesheet, value); 692 return this; 693 } 694 695 /** 696 * Returns the list of stylesheet URLs. 697 * 698 * <p> 699 * Gives access to the inner list if you need to make more than simple additions via {@link #stylesheet(String...)}. 700 * 701 * @return The list of stylesheet URLs. 702 * @see #stylesheet(String...) 703 */ 704 public List<String> stylesheet() { 705 if (stylesheet == null) 706 stylesheet = list(); 707 return stylesheet; 708 } 709 710 /** 711 * HTML document template. 712 * 713 * <p> 714 * Specifies the template to use for serializing the page. 715 * 716 * <p> 717 * By default, the {@link BasicHtmlDocTemplate} class is used to construct the contents of the HTML page, but 718 * can be overridden with your own custom implementation class. 719 * 720 * <h5 class='section'>Example:</h5> 721 * <p class='bjava'> 722 * WriterSerializer <jv>serializer</jv> = HtmlDocSerializer 723 * .<jsm>create</jsm>() 724 * .template(MySpecialDocTemplate.<jk>class</jk>) 725 * .build(); 726 * </p> 727 * 728 * @param value 729 * The new value for this property. 730 * @return This object. 731 */ 732 @FluentSetter 733 public Builder template(Class<? extends HtmlDocTemplate> value) { 734 template = value; 735 return this; 736 } 737 738 /** 739 * HTML Widgets. 740 * 741 * <p> 742 * Defines widgets that can be used in conjunction with string variables of the form <js>"$W{name}"</js>to quickly 743 * generate arbitrary replacement text. 744 * 745 * Widgets resolve the following variables: 746 * <ul class='spaced-list'> 747 * <li><js>"$W{name}"</js> - Contents returned by {@link HtmlWidget#getHtml(VarResolverSession)}. 748 * <li><js>"$W{name.script}"</js> - Contents returned by {@link HtmlWidget#getScript(VarResolverSession)}. 749 * <br>The script contents are automatically inserted into the <xt><head/script></xt> section 750 * in the HTML page. 751 * <li><js>"$W{name.style}"</js> - Contents returned by {@link HtmlWidget#getStyle(VarResolverSession)}. 752 * <br>The styles contents are automatically inserted into the <xt><head/style></xt> section 753 * in the HTML page. 754 * </ul> 755 * 756 * <p> 757 * The following examples shows how to associate a widget with a REST method and then have it rendered in the links 758 * and aside section of the page: 759 * 760 * <p class='bjava'> 761 * WriterSerializer <jv>serializer</jv> = HtmlDocSerializer 762 * .<jsm>create</jsm>() 763 * .widgets( 764 * MyWidget.<jk>class</jk> 765 * ) 766 * .navlinks( 767 * <js>"$W{MyWidget}"</js> 768 * ) 769 * .aside( 770 * <js>"Check out this widget: $W{MyWidget}"</js> 771 * ) 772 * .build(); 773 * </p> 774 * 775 * <h5 class='section'>Notes:</h5><ul> 776 * <li class='note'> 777 * Widgets are inherited from super classes, but can be overridden by reusing the widget name. 778 * </ul> 779 * 780 * <h5 class='section'>See Also:</h5><ul> 781 * <li class='link'><a class="doclink" href="../../../../index.html#jrs.HtmlWidgets">Widgets</a> 782 * </ul> 783 * 784 * @param values The values to add to this setting. 785 * @return This object. 786 */ 787 @FluentSetter 788 @SuppressWarnings("unchecked") 789 public Builder widgets(Class<? extends HtmlWidget>...values) { 790 addAll(widgets(), values); 791 return this; 792 } 793 794 /** 795 * Returns the list of page widgets. 796 * 797 * <p> 798 * Gives access to the inner list if you need to make more than simple additions via {@link #widgets(Class...)}. 799 * 800 * @return The list of page widgets. 801 * @see #widgets(Class...) 802 */ 803 public List<Class<? extends HtmlWidget>> widgets() { 804 if (widgets == null) 805 widgets = list(); 806 return widgets; 807 } 808 809 // <FluentSetters> 810 811 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 812 public Builder annotations(Annotation...values) { 813 super.annotations(values); 814 return this; 815 } 816 817 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 818 public Builder apply(AnnotationWorkList work) { 819 super.apply(work); 820 return this; 821 } 822 823 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 824 public Builder applyAnnotations(java.lang.Class<?>...fromClasses) { 825 super.applyAnnotations(fromClasses); 826 return this; 827 } 828 829 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 830 public Builder applyAnnotations(Method...fromMethods) { 831 super.applyAnnotations(fromMethods); 832 return this; 833 } 834 835 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 836 public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) { 837 super.cache(value); 838 return this; 839 } 840 841 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 842 public Builder debug() { 843 super.debug(); 844 return this; 845 } 846 847 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 848 public Builder debug(boolean value) { 849 super.debug(value); 850 return this; 851 } 852 853 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 854 public Builder impl(Context value) { 855 super.impl(value); 856 return this; 857 } 858 859 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 860 public Builder type(Class<? extends org.apache.juneau.Context> value) { 861 super.type(value); 862 return this; 863 } 864 865 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 866 public Builder beanClassVisibility(Visibility value) { 867 super.beanClassVisibility(value); 868 return this; 869 } 870 871 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 872 public Builder beanConstructorVisibility(Visibility value) { 873 super.beanConstructorVisibility(value); 874 return this; 875 } 876 877 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 878 public Builder beanContext(BeanContext value) { 879 super.beanContext(value); 880 return this; 881 } 882 883 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 884 public Builder beanContext(BeanContext.Builder value) { 885 super.beanContext(value); 886 return this; 887 } 888 889 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 890 public Builder beanDictionary(java.lang.Class<?>...values) { 891 super.beanDictionary(values); 892 return this; 893 } 894 895 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 896 public Builder beanFieldVisibility(Visibility value) { 897 super.beanFieldVisibility(value); 898 return this; 899 } 900 901 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 902 public Builder beanInterceptor(Class<?> on, Class<? extends org.apache.juneau.swap.BeanInterceptor<?>> value) { 903 super.beanInterceptor(on, value); 904 return this; 905 } 906 907 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 908 public Builder beanMapPutReturnsOldValue() { 909 super.beanMapPutReturnsOldValue(); 910 return this; 911 } 912 913 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 914 public Builder beanMethodVisibility(Visibility value) { 915 super.beanMethodVisibility(value); 916 return this; 917 } 918 919 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 920 public Builder beanProperties(Map<String,Object> values) { 921 super.beanProperties(values); 922 return this; 923 } 924 925 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 926 public Builder beanProperties(Class<?> beanClass, String properties) { 927 super.beanProperties(beanClass, properties); 928 return this; 929 } 930 931 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 932 public Builder beanProperties(String beanClassName, String properties) { 933 super.beanProperties(beanClassName, properties); 934 return this; 935 } 936 937 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 938 public Builder beanPropertiesExcludes(Map<String,Object> values) { 939 super.beanPropertiesExcludes(values); 940 return this; 941 } 942 943 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 944 public Builder beanPropertiesExcludes(Class<?> beanClass, String properties) { 945 super.beanPropertiesExcludes(beanClass, properties); 946 return this; 947 } 948 949 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 950 public Builder beanPropertiesExcludes(String beanClassName, String properties) { 951 super.beanPropertiesExcludes(beanClassName, properties); 952 return this; 953 } 954 955 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 956 public Builder beanPropertiesReadOnly(Map<String,Object> values) { 957 super.beanPropertiesReadOnly(values); 958 return this; 959 } 960 961 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 962 public Builder beanPropertiesReadOnly(Class<?> beanClass, String properties) { 963 super.beanPropertiesReadOnly(beanClass, properties); 964 return this; 965 } 966 967 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 968 public Builder beanPropertiesReadOnly(String beanClassName, String properties) { 969 super.beanPropertiesReadOnly(beanClassName, properties); 970 return this; 971 } 972 973 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 974 public Builder beanPropertiesWriteOnly(Map<String,Object> values) { 975 super.beanPropertiesWriteOnly(values); 976 return this; 977 } 978 979 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 980 public Builder beanPropertiesWriteOnly(Class<?> beanClass, String properties) { 981 super.beanPropertiesWriteOnly(beanClass, properties); 982 return this; 983 } 984 985 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 986 public Builder beanPropertiesWriteOnly(String beanClassName, String properties) { 987 super.beanPropertiesWriteOnly(beanClassName, properties); 988 return this; 989 } 990 991 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 992 public Builder beansRequireDefaultConstructor() { 993 super.beansRequireDefaultConstructor(); 994 return this; 995 } 996 997 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 998 public Builder beansRequireSerializable() { 999 super.beansRequireSerializable(); 1000 return this; 1001 } 1002 1003 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1004 public Builder beansRequireSettersForGetters() { 1005 super.beansRequireSettersForGetters(); 1006 return this; 1007 } 1008 1009 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1010 public Builder dictionaryOn(Class<?> on, java.lang.Class<?>...values) { 1011 super.dictionaryOn(on, values); 1012 return this; 1013 } 1014 1015 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1016 public Builder disableBeansRequireSomeProperties() { 1017 super.disableBeansRequireSomeProperties(); 1018 return this; 1019 } 1020 1021 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1022 public Builder disableIgnoreMissingSetters() { 1023 super.disableIgnoreMissingSetters(); 1024 return this; 1025 } 1026 1027 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1028 public Builder disableIgnoreTransientFields() { 1029 super.disableIgnoreTransientFields(); 1030 return this; 1031 } 1032 1033 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1034 public Builder disableIgnoreUnknownNullBeanProperties() { 1035 super.disableIgnoreUnknownNullBeanProperties(); 1036 return this; 1037 } 1038 1039 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1040 public Builder disableInterfaceProxies() { 1041 super.disableInterfaceProxies(); 1042 return this; 1043 } 1044 1045 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1046 public <T> Builder example(Class<T> pojoClass, T o) { 1047 super.example(pojoClass, o); 1048 return this; 1049 } 1050 1051 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1052 public <T> Builder example(Class<T> pojoClass, String json) { 1053 super.example(pojoClass, json); 1054 return this; 1055 } 1056 1057 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1058 public Builder findFluentSetters() { 1059 super.findFluentSetters(); 1060 return this; 1061 } 1062 1063 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1064 public Builder findFluentSetters(Class<?> on) { 1065 super.findFluentSetters(on); 1066 return this; 1067 } 1068 1069 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1070 public Builder ignoreInvocationExceptionsOnGetters() { 1071 super.ignoreInvocationExceptionsOnGetters(); 1072 return this; 1073 } 1074 1075 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1076 public Builder ignoreInvocationExceptionsOnSetters() { 1077 super.ignoreInvocationExceptionsOnSetters(); 1078 return this; 1079 } 1080 1081 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1082 public Builder ignoreUnknownBeanProperties() { 1083 super.ignoreUnknownBeanProperties(); 1084 return this; 1085 } 1086 1087 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1088 public Builder ignoreUnknownEnumValues() { 1089 super.ignoreUnknownEnumValues(); 1090 return this; 1091 } 1092 1093 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1094 public Builder implClass(Class<?> interfaceClass, Class<?> implClass) { 1095 super.implClass(interfaceClass, implClass); 1096 return this; 1097 } 1098 1099 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1100 public Builder implClasses(Map<Class<?>,Class<?>> values) { 1101 super.implClasses(values); 1102 return this; 1103 } 1104 1105 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1106 public Builder interfaceClass(Class<?> on, Class<?> value) { 1107 super.interfaceClass(on, value); 1108 return this; 1109 } 1110 1111 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1112 public Builder interfaces(java.lang.Class<?>...value) { 1113 super.interfaces(value); 1114 return this; 1115 } 1116 1117 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1118 public Builder locale(Locale value) { 1119 super.locale(value); 1120 return this; 1121 } 1122 1123 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1124 public Builder mediaType(MediaType value) { 1125 super.mediaType(value); 1126 return this; 1127 } 1128 1129 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1130 public Builder notBeanClasses(java.lang.Class<?>...values) { 1131 super.notBeanClasses(values); 1132 return this; 1133 } 1134 1135 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1136 public Builder notBeanPackages(String...values) { 1137 super.notBeanPackages(values); 1138 return this; 1139 } 1140 1141 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1142 public Builder propertyNamer(Class<? extends org.apache.juneau.PropertyNamer> value) { 1143 super.propertyNamer(value); 1144 return this; 1145 } 1146 1147 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1148 public Builder propertyNamer(Class<?> on, Class<? extends org.apache.juneau.PropertyNamer> value) { 1149 super.propertyNamer(on, value); 1150 return this; 1151 } 1152 1153 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1154 public Builder sortProperties() { 1155 super.sortProperties(); 1156 return this; 1157 } 1158 1159 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1160 public Builder sortProperties(java.lang.Class<?>...on) { 1161 super.sortProperties(on); 1162 return this; 1163 } 1164 1165 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1166 public Builder stopClass(Class<?> on, Class<?> value) { 1167 super.stopClass(on, value); 1168 return this; 1169 } 1170 1171 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1172 public <T, S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction) { 1173 super.swap(normalClass, swappedClass, swapFunction); 1174 return this; 1175 } 1176 1177 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1178 public <T, S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> unswapFunction) { 1179 super.swap(normalClass, swappedClass, swapFunction, unswapFunction); 1180 return this; 1181 } 1182 1183 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1184 public Builder swaps(java.lang.Class<?>...values) { 1185 super.swaps(values); 1186 return this; 1187 } 1188 1189 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1190 public Builder timeZone(TimeZone value) { 1191 super.timeZone(value); 1192 return this; 1193 } 1194 1195 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1196 public Builder typeName(Class<?> on, String value) { 1197 super.typeName(on, value); 1198 return this; 1199 } 1200 1201 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1202 public Builder typePropertyName(String value) { 1203 super.typePropertyName(value); 1204 return this; 1205 } 1206 1207 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1208 public Builder typePropertyName(Class<?> on, String value) { 1209 super.typePropertyName(on, value); 1210 return this; 1211 } 1212 1213 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1214 public Builder useEnumNames() { 1215 super.useEnumNames(); 1216 return this; 1217 } 1218 1219 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 1220 public Builder useJavaBeanIntrospector() { 1221 super.useJavaBeanIntrospector(); 1222 return this; 1223 } 1224 1225 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 1226 public Builder detectRecursions() { 1227 super.detectRecursions(); 1228 return this; 1229 } 1230 1231 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 1232 public Builder detectRecursions(boolean value) { 1233 super.detectRecursions(value); 1234 return this; 1235 } 1236 1237 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 1238 public Builder ignoreRecursions() { 1239 super.ignoreRecursions(); 1240 return this; 1241 } 1242 1243 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 1244 public Builder ignoreRecursions(boolean value) { 1245 super.ignoreRecursions(value); 1246 return this; 1247 } 1248 1249 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 1250 public Builder initialDepth(int value) { 1251 super.initialDepth(value); 1252 return this; 1253 } 1254 1255 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 1256 public Builder maxDepth(int value) { 1257 super.maxDepth(value); 1258 return this; 1259 } 1260 1261 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1262 public Builder accept(String value) { 1263 super.accept(value); 1264 return this; 1265 } 1266 1267 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1268 public Builder addBeanTypes() { 1269 super.addBeanTypes(); 1270 return this; 1271 } 1272 1273 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1274 public Builder addBeanTypes(boolean value) { 1275 super.addBeanTypes(value); 1276 return this; 1277 } 1278 1279 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1280 public Builder addRootType() { 1281 super.addRootType(); 1282 return this; 1283 } 1284 1285 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1286 public Builder addRootType(boolean value) { 1287 super.addRootType(value); 1288 return this; 1289 } 1290 1291 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1292 public Builder keepNullProperties() { 1293 super.keepNullProperties(); 1294 return this; 1295 } 1296 1297 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1298 public Builder keepNullProperties(boolean value) { 1299 super.keepNullProperties(value); 1300 return this; 1301 } 1302 1303 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1304 public Builder listener(Class<? extends org.apache.juneau.serializer.SerializerListener> value) { 1305 super.listener(value); 1306 return this; 1307 } 1308 1309 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1310 public Builder produces(String value) { 1311 super.produces(value); 1312 return this; 1313 } 1314 1315 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1316 public Builder sortCollections() { 1317 super.sortCollections(); 1318 return this; 1319 } 1320 1321 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1322 public Builder sortCollections(boolean value) { 1323 super.sortCollections(value); 1324 return this; 1325 } 1326 1327 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1328 public Builder sortMaps() { 1329 super.sortMaps(); 1330 return this; 1331 } 1332 1333 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1334 public Builder sortMaps(boolean value) { 1335 super.sortMaps(value); 1336 return this; 1337 } 1338 1339 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1340 public Builder trimEmptyCollections() { 1341 super.trimEmptyCollections(); 1342 return this; 1343 } 1344 1345 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1346 public Builder trimEmptyCollections(boolean value) { 1347 super.trimEmptyCollections(value); 1348 return this; 1349 } 1350 1351 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1352 public Builder trimEmptyMaps() { 1353 super.trimEmptyMaps(); 1354 return this; 1355 } 1356 1357 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1358 public Builder trimEmptyMaps(boolean value) { 1359 super.trimEmptyMaps(value); 1360 return this; 1361 } 1362 1363 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1364 public Builder trimStrings() { 1365 super.trimStrings(); 1366 return this; 1367 } 1368 1369 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1370 public Builder trimStrings(boolean value) { 1371 super.trimStrings(value); 1372 return this; 1373 } 1374 1375 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1376 public Builder uriContext(UriContext value) { 1377 super.uriContext(value); 1378 return this; 1379 } 1380 1381 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1382 public Builder uriRelativity(UriRelativity value) { 1383 super.uriRelativity(value); 1384 return this; 1385 } 1386 1387 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1388 public Builder uriResolution(UriResolution value) { 1389 super.uriResolution(value); 1390 return this; 1391 } 1392 1393 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1394 public Builder fileCharset(Charset value) { 1395 super.fileCharset(value); 1396 return this; 1397 } 1398 1399 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1400 public Builder maxIndent(int value) { 1401 super.maxIndent(value); 1402 return this; 1403 } 1404 1405 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1406 public Builder quoteChar(char value) { 1407 super.quoteChar(value); 1408 return this; 1409 } 1410 1411 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1412 public Builder quoteCharOverride(char value) { 1413 super.quoteCharOverride(value); 1414 return this; 1415 } 1416 1417 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1418 public Builder sq() { 1419 super.sq(); 1420 return this; 1421 } 1422 1423 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1424 public Builder streamCharset(Charset value) { 1425 super.streamCharset(value); 1426 return this; 1427 } 1428 1429 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1430 public Builder useWhitespace() { 1431 super.useWhitespace(); 1432 return this; 1433 } 1434 1435 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1436 public Builder useWhitespace(boolean value) { 1437 super.useWhitespace(value); 1438 return this; 1439 } 1440 1441 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1442 public Builder ws() { 1443 super.ws(); 1444 return this; 1445 } 1446 1447 @Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */ 1448 public Builder addBeanTypesXml() { 1449 super.addBeanTypesXml(); 1450 return this; 1451 } 1452 1453 @Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */ 1454 public Builder addBeanTypesXml(boolean value) { 1455 super.addBeanTypesXml(value); 1456 return this; 1457 } 1458 1459 @Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */ 1460 public Builder addNamespaceUrisToRoot() { 1461 super.addNamespaceUrisToRoot(); 1462 return this; 1463 } 1464 1465 @Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */ 1466 public Builder addNamespaceUrisToRoot(boolean value) { 1467 super.addNamespaceUrisToRoot(value); 1468 return this; 1469 } 1470 1471 @Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */ 1472 public Builder defaultNamespace(Namespace value) { 1473 super.defaultNamespace(value); 1474 return this; 1475 } 1476 1477 @Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */ 1478 public Builder disableAutoDetectNamespaces() { 1479 super.disableAutoDetectNamespaces(); 1480 return this; 1481 } 1482 1483 @Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */ 1484 public Builder disableAutoDetectNamespaces(boolean value) { 1485 super.disableAutoDetectNamespaces(value); 1486 return this; 1487 } 1488 1489 @Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */ 1490 public Builder enableNamespaces() { 1491 super.enableNamespaces(); 1492 return this; 1493 } 1494 1495 @Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */ 1496 public Builder enableNamespaces(boolean value) { 1497 super.enableNamespaces(value); 1498 return this; 1499 } 1500 1501 @Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */ 1502 public Builder namespaces(Namespace...values) { 1503 super.namespaces(values); 1504 return this; 1505 } 1506 1507 @Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */ 1508 public Builder ns() { 1509 super.ns(); 1510 return this; 1511 } 1512 1513 @Override /* GENERATED - org.apache.juneau.html.HtmlSerializer.Builder */ 1514 public Builder addBeanTypesHtml() { 1515 super.addBeanTypesHtml(); 1516 return this; 1517 } 1518 1519 @Override /* GENERATED - org.apache.juneau.html.HtmlSerializer.Builder */ 1520 public Builder addBeanTypesHtml(boolean value) { 1521 super.addBeanTypesHtml(value); 1522 return this; 1523 } 1524 1525 @Override /* GENERATED - org.apache.juneau.html.HtmlSerializer.Builder */ 1526 public Builder addKeyValueTableHeaders() { 1527 super.addKeyValueTableHeaders(); 1528 return this; 1529 } 1530 1531 @Override /* GENERATED - org.apache.juneau.html.HtmlSerializer.Builder */ 1532 public Builder addKeyValueTableHeaders(boolean value) { 1533 super.addKeyValueTableHeaders(value); 1534 return this; 1535 } 1536 1537 @Override /* GENERATED - org.apache.juneau.html.HtmlSerializer.Builder */ 1538 public Builder disableDetectLabelParameters() { 1539 super.disableDetectLabelParameters(); 1540 return this; 1541 } 1542 1543 @Override /* GENERATED - org.apache.juneau.html.HtmlSerializer.Builder */ 1544 public Builder disableDetectLabelParameters(boolean value) { 1545 super.disableDetectLabelParameters(value); 1546 return this; 1547 } 1548 1549 @Override /* GENERATED - org.apache.juneau.html.HtmlSerializer.Builder */ 1550 public Builder disableDetectLinksInStrings() { 1551 super.disableDetectLinksInStrings(); 1552 return this; 1553 } 1554 1555 @Override /* GENERATED - org.apache.juneau.html.HtmlSerializer.Builder */ 1556 public Builder disableDetectLinksInStrings(boolean value) { 1557 super.disableDetectLinksInStrings(value); 1558 return this; 1559 } 1560 1561 @Override /* GENERATED - org.apache.juneau.html.HtmlSerializer.Builder */ 1562 public Builder labelParameter(String value) { 1563 super.labelParameter(value); 1564 return this; 1565 } 1566 1567 @Override /* GENERATED - org.apache.juneau.html.HtmlSerializer.Builder */ 1568 public Builder uriAnchorText(AnchorText value) { 1569 super.uriAnchorText(value); 1570 return this; 1571 } 1572 1573 // </FluentSetters> 1574 1575 //----------------------------------------------------------------------------------------------------------------- 1576 // Helpers 1577 //----------------------------------------------------------------------------------------------------------------- 1578 1579 private static <T> List<T> copy(List<T> s) { 1580 return s == null || s.isEmpty() ? null : copyOf(s); 1581 } 1582 1583 private static <T> List<T> copy(T[] s) { 1584 return s.length == 0 ? null : list(s); 1585 } 1586 1587 private List<String> merge(List<String> old, String[] newValues) { 1588 List<String> x = list(newValues.length); 1589 for (String s : newValues) { 1590 if ("NONE".equals(s)) { 1591 if (old != null) 1592 old.clear(); 1593 } else if ("INHERIT".equals(s)) { 1594 if (old != null) 1595 x.addAll(old); 1596 } else { 1597 x.add(s); 1598 } 1599 } 1600 return x; 1601 } 1602 1603 private List<String> mergeNavLinks(List<String> old, String[] newValues) { 1604 List<String> x = list(newValues.length); 1605 for (String s : newValues) { 1606 if ("NONE".equals(s)) { 1607 if (old != null) 1608 old.clear(); 1609 } else if ("INHERIT".equals(s)) { 1610 if (old != null) 1611 x.addAll(old); 1612 } else if (s.indexOf('[') != -1 && INDEXED_LINK_PATTERN.matcher(s).matches()) { 1613 Matcher lm = INDEXED_LINK_PATTERN.matcher(s); 1614 lm.matches(); 1615 String key = lm.group(1); 1616 int index = Math.min(x.size(), Integer.parseInt(lm.group(2))); 1617 String remainder = lm.group(3); 1618 x.add(index, key.isEmpty() ? remainder : key + ":" + remainder); 1619 } else { 1620 x.add(s); 1621 } 1622 } 1623 return x; 1624 } 1625 1626 private static final Pattern INDEXED_LINK_PATTERN = Pattern.compile("(?s)(\\S*)\\[(\\d+)\\]\\:(.*)"); 1627 } 1628 1629 //------------------------------------------------------------------------------------------------------------------- 1630 // Instance 1631 //------------------------------------------------------------------------------------------------------------------- 1632 1633 final String[] style, stylesheet, script, navlinks, head, header, nav, aside, footer; 1634 final AsideFloat asideFloat; 1635 final String noResultsMessage; 1636 final boolean nowrap; 1637 final Class<? extends HtmlDocTemplate> template; 1638 final List<Class<? extends HtmlWidget>> widgets; 1639 1640 private final HtmlWidgetMap widgetMap; 1641 private final HtmlWidget[] widgetArray; 1642 private final HtmlDocTemplate templateBean; 1643 1644 private volatile HtmlSchemaDocSerializer schemaSerializer; 1645 1646 /** 1647 * Constructor. 1648 * 1649 * @param builder The builder for this object. 1650 */ 1651 public HtmlDocSerializer(Builder builder) { 1652 super(builder); 1653 style = builder.style != null ? toArray(builder.style) : EMPTY_ARRAY; 1654 stylesheet = builder.stylesheet != null ? toArray(builder.stylesheet) : EMPTY_ARRAY; 1655 script = builder.script != null ? toArray(builder.script) : EMPTY_ARRAY; 1656 head = builder.head != null ? toArray(builder.head) : EMPTY_ARRAY; 1657 header = builder.header != null ? toArray(builder.header) : EMPTY_ARRAY; 1658 nav = builder.nav != null ? toArray(builder.nav) : EMPTY_ARRAY; 1659 aside = builder.aside != null ? toArray(builder.aside) : EMPTY_ARRAY; 1660 footer = builder.footer != null ? toArray(builder.footer) : EMPTY_ARRAY; 1661 navlinks = builder.navlinks != null ? toArray(builder.navlinks) : EMPTY_ARRAY; 1662 asideFloat = builder.asideFloat; 1663 noResultsMessage = builder.noResultsMessage; 1664 nowrap = builder.nowrap; 1665 template = builder.template; 1666 widgets = builder.widgets == null ? emptyList() : copyOf(builder.widgets); 1667 1668 templateBean = newInstance(template); 1669 widgetMap = new HtmlWidgetMap(); 1670 widgets.stream().map(x -> newInstance(x)).forEach(x -> widgetMap.append(x)); 1671 widgetArray = array(widgetMap.values(), HtmlWidget.class); 1672 } 1673 1674 @Override /* Context */ 1675 public Builder copy() { 1676 return new Builder(this); 1677 } 1678 1679 @Override /* Context */ 1680 public HtmlDocSerializerSession.Builder createSession() { 1681 return HtmlDocSerializerSession.create(this); 1682 } 1683 1684 @Override /* Context */ 1685 public HtmlDocSerializerSession getSession() { 1686 return createSession().build(); 1687 } 1688 1689 @Override /* XmlSerializer */ 1690 public HtmlSerializer getSchemaSerializer() { 1691 if (schemaSerializer == null) 1692 schemaSerializer = HtmlSchemaDocSerializer.create().beanContext(getBeanContext()).build(); 1693 return schemaSerializer; 1694 } 1695 1696 //----------------------------------------------------------------------------------------------------------------- 1697 // Properties 1698 //----------------------------------------------------------------------------------------------------------------- 1699 1700 /** 1701 * Aside section contents. 1702 * 1703 * @see Builder#aside(String...) 1704 * @return 1705 * The overridden contents of the aside section on the HTML page. 1706 */ 1707 protected final String[] getAside() { 1708 return aside; 1709 } 1710 1711 /** 1712 * Float side section contents. 1713 * 1714 * @see Builder#asideFloat(AsideFloat) 1715 * @return 1716 * How to float the aside contents on the page. 1717 */ 1718 protected final AsideFloat getAsideFloat() { 1719 return asideFloat; 1720 } 1721 1722 /** 1723 * Footer section contents. 1724 * 1725 * @see Builder#footer(String...) 1726 * @return 1727 * The overridden contents of the footer section on the HTML page. 1728 */ 1729 protected final String[] getFooter() { 1730 return footer; 1731 } 1732 1733 /** 1734 * Additional head section content. 1735 * 1736 * @see Builder#head(String...) 1737 * @return 1738 * HTML content to add to the head section of the HTML page. 1739 */ 1740 protected final String[] getHead() { 1741 return head; 1742 } 1743 1744 /** 1745 * Header section contents. 1746 * 1747 * @see Builder#header(String...) 1748 * @return 1749 * The overridden contents of the header section on the HTML page. 1750 */ 1751 protected final String[] getHeader() { 1752 return header; 1753 } 1754 1755 /** 1756 * Nav section contents. 1757 * 1758 * @see Builder#nav(String...) 1759 * @return 1760 * The overridden contents of the nav section on the HTML page. 1761 */ 1762 protected final String[] getNav() { 1763 return nav; 1764 } 1765 1766 /** 1767 * Page navigation links. 1768 * 1769 * @see Builder#navlinks(String...) 1770 * @return 1771 * Navigation links to add to the HTML page. 1772 */ 1773 protected final String[] getNavlinks() { 1774 return navlinks; 1775 } 1776 1777 /** 1778 * No-results message. 1779 * 1780 * @see Builder#noResultsMessage(String) 1781 * @return 1782 * The message used when serializing an empty array or empty list. 1783 */ 1784 protected final String getNoResultsMessage() { 1785 return noResultsMessage; 1786 } 1787 1788 /** 1789 * Prevent word wrap on page. 1790 * 1791 * @see Builder#nowrap() 1792 * @return 1793 * <jk>true</jk> if <js>"* {white-space:nowrap}"</js> shoudl be added to the CSS instructions on the page to prevent word wrapping. 1794 */ 1795 protected final boolean isNowrap() { 1796 return nowrap; 1797 } 1798 1799 /** 1800 * Javascript code. 1801 * 1802 * @see Builder#script(String...) 1803 * @return 1804 * Arbitrary Javascript to add to the HTML page. 1805 */ 1806 protected final String[] getScript() { 1807 return script; 1808 } 1809 1810 /** 1811 * CSS style code. 1812 * 1813 * @see Builder#style(String...) 1814 * @return 1815 * The CSS instructions to add to the HTML page. 1816 */ 1817 protected final String[] getStyle() { 1818 return style; 1819 } 1820 1821 /** 1822 * Stylesheet import URLs. 1823 * 1824 * @see Builder#stylesheet(String...) 1825 * @return 1826 * The link to the stylesheet of the HTML page. 1827 */ 1828 protected final String[] getStylesheet() { 1829 return stylesheet; 1830 } 1831 1832 /** 1833 * HTML document template. 1834 * 1835 * @see Builder#template(Class) 1836 * @return 1837 * The template to use for serializing the page. 1838 */ 1839 protected final HtmlDocTemplate getTemplate() { 1840 return templateBean; 1841 } 1842 1843 /** 1844 * HTML widgets. 1845 * 1846 * @see Builder#widgets(Class...) 1847 * @return 1848 * Widgets defined on this serializers. 1849 */ 1850 protected final HtmlWidgetMap getWidgets() { 1851 return widgetMap; 1852 } 1853 1854 /** 1855 * Performs an action on all widgets defined on this serializer. 1856 * 1857 * @param action The action to perform. 1858 * @return This object. 1859 */ 1860 protected final HtmlDocSerializer forEachWidget(Consumer<HtmlWidget> action) { 1861 for (HtmlWidget w : widgetArray) 1862 action.accept(w); 1863 return this; 1864 } 1865 1866 //----------------------------------------------------------------------------------------------------------------- 1867 // Other methods 1868 //----------------------------------------------------------------------------------------------------------------- 1869 1870 private String[] toArray(List<String> x) { 1871 return x.toArray(new String[x.size()]); 1872 } 1873 1874 private <T> T newInstance(Class<T> c) { 1875 try { 1876 return c.getDeclaredConstructor().newInstance(); 1877 } catch (Exception e) { 1878 throw asRuntimeException(e); 1879 } 1880 } 1881 1882 @Override /* Context */ 1883 protected JsonMap properties() { 1884 return filteredMap() 1885 .append("header", header) 1886 .append("nav", nav) 1887 .append("navlinks", navlinks) 1888 .append("aside", aside) 1889 .append("asideFloat", asideFloat) 1890 .append("footer", footer) 1891 .append("style", style) 1892 .append("head", head) 1893 .append("stylesheet", stylesheet) 1894 .append("nowrap", nowrap) 1895 .append("template", template) 1896 .append("noResultsMessage", noResultsMessage) 1897 .append("widgets", widgets); 1898 } 1899}