/** * Renders head for embedded component, i.e. those who are not added directly to this container * but have the markup inside it. * * @param container The HtmlHeaderContainer */ private void renderHeadForInnerSiblings(HtmlHeaderContainer container) { MarkupStream stream = new MarkupStream(getMarkup()); while (stream.hasMore()) { MarkupElement childOpenTag = stream.nextOpenTag(); if ((childOpenTag instanceof ComponentTag) && !stream.atCloseTag()) { // Get element as tag final ComponentTag tag = (ComponentTag) childOpenTag; // Get component id final String id = tag.getId(); Component component = null; if (get(id) == null) { component = ComponentResolvers.resolveByComponentHierarchy(this, stream, tag); } if (component != null) { component.internalRenderHead(container); } // consider just direct children stream.skipToMatchingCloseTag(tag); } } }
@Override public void onComponentTagBody(MarkupStream markup, ComponentTag tag) { // We assume the body of the component is raw HTML // (i.e. not nested wicket components or wicket tags). RawMarkup raw = (RawMarkup) markup.get(); getResponse().write(getTruncateHelper().truncate(raw.toString(), this.length)); markup.next(); }
/** * @param container * @param markupStream * @return The header id */ private String getHeaderId(final Component container, final MarkupStream markupStream) { Class<?> markupClass = markupStream.getTag().getMarkupClass(); if (markupClass == null) { markupClass = markupStream.getContainerClass(); } // create a unique id for the HtmlHeaderContainer StringBuilder builder = new StringBuilder(100); builder.append('_'); builder.append(Classes.simpleName(markupClass)); if (container.getVariation() != null) { builder.append(container.getVariation()); } builder.append("Header"); builder.append(markupStream.getCurrentIndex()); return builder.toString(); }
/** * Search the child's markup in the header section of the markup * * @param container * @param child * @return Null, if not found */ public IMarkupFragment findMarkupInAssociatedFileHeader( final MarkupContainer container, final Component child) { // Get the associated markup IMarkupFragment markup = container.getAssociatedMarkup(); IMarkupFragment childMarkup = null; // MarkupStream is good at searching markup MarkupStream stream = new MarkupStream(markup); while (stream.skipUntil(ComponentTag.class) && (childMarkup == null)) { ComponentTag tag = stream.getTag(); if (TagUtils.isWicketHeadTag(tag)) { if (tag.getMarkupClass() == null) { // find() can still fail an return null => continue the search childMarkup = stream.getMarkupFragment().find(child.getId()); } } else if (TagUtils.isHeadTag(tag)) { // find() can still fail an return null => continue the search childMarkup = stream.getMarkupFragment().find(child.getId()); } // Must be a direct child. We are not interested in grand children if (tag.isOpen() && !tag.hasNoCloseTag()) { stream.skipToMatchingCloseTag(tag); } stream.next(); } return childMarkup; }
/** * Process next header markup fragment. * * @param associatedMarkupStream * @return index or -1 when done */ private int nextHeaderMarkup(final MarkupStream associatedMarkupStream) { // No associated markup => no header section if (associatedMarkupStream == null) { return -1; } // Scan the markup for <wicket:head>. MarkupElement elem = associatedMarkupStream.get(); while (elem != null) { if (elem instanceof WicketTag) { WicketTag tag = (WicketTag) elem; if (tag.isOpen() && tag.isHeadTag()) { if (noMoreWicketHeadTagsAllowed == true) { throw new MarkupException( "<wicket:head> tags are only allowed before <body>, </head>, <wicket:panel> etc. tag"); } return associatedMarkupStream.getCurrentIndex(); } // wicket:head must be before border, panel or extend // @TODO why is that? Why can't it be anywhere? (except inside wicket:fragment) else if (tag.isOpen() && (tag.isPanelTag() || tag.isBorderTag() || tag.isExtendTag())) { noMoreWicketHeadTagsAllowed = true; } } else if (elem instanceof ComponentTag) { ComponentTag tag = (ComponentTag) elem; // wicket:head must be before </head> // @TODO why?? if (tag.isClose() && TagUtils.isHeadTag(tag)) { noMoreWicketHeadTagsAllowed = true; } // wicket:head must be before <body> // @TODO why?? else if (tag.isOpen() && TagUtils.isBodyTag(tag)) { noMoreWicketHeadTagsAllowed = true; } } elem = associatedMarkupStream.next(); } // No (more) wicket:head found return -1; }
/** * Called by components like Panel and Border which have associated Markup and which may have a * <wicket:head> tag. * * <p>Whereas 'this' might be a Panel or Border, the HtmlHeaderContainer parameter has been added * to the Page as a container for all headers any of its components might wish to contribute to. * * <p>The headers contributed are rendered in the standard way. * * @param container * @param htmlContainer The HtmlHeaderContainer added to the Page */ public final void renderHeadFromAssociatedMarkupFile( final WebMarkupContainer container, final HtmlHeaderContainer htmlContainer) { // reset for each render in case the strategy is re-used noMoreWicketHeadTagsAllowed = false; // Gracefully getAssociateMarkupStream. Throws no exception in case // markup is not found final MarkupStream markupStream = container.getAssociatedMarkupStream(false); if (markupStream == null) { return; } // Position pointer at current (first) header noMoreWicketHeadTagsAllowed = false; while (nextHeaderMarkup(markupStream) != -1) { // found <wicket:head> String headerId = getHeaderId(container, markupStream); // Create a HeaderPartContainer and associate the markup HeaderPartContainer headerPart = getHeaderPart(container, headerId, markupStream.getMarkupFragment()); if (headerPart != null) { // A component's header section must only be added once, // no matter how often the same Component has been added // to the page or any other container in the hierarchy. if (htmlContainer.okToRenderComponent(headerPart.getScope(), headerPart.getId())) { // make sure the Page is accessible headerPart.setParent(htmlContainer); headerPart.render(); } } // Position the stream after <wicket:head> markupStream.skipComponent(); } }
/** * Resolves the child component which is the controller of this Enclosure * * @param markupStream the markup stream of this Enclosure * @param enclosureParent the non-auto parent component of this Enclosure * @return The component associated with the {@linkplain #childId} */ private Component getChildComponent( final MarkupStream markupStream, MarkupContainer enclosureParent) { String fullChildId = getChildId(); Component controller = enclosureParent.get(fullChildId); if (controller == null) { int orgIndex = markupStream.getCurrentIndex(); try { while (markupStream.hasMore()) { markupStream.next(); if (markupStream.skipUntil(ComponentTag.class)) { ComponentTag tag = markupStream.getTag(); if ((tag != null) && (tag.isOpen() || tag.isOpenClose())) { String tagId = tag.getId(); if (fullChildId.equals(tagId)) { ComponentTag fullComponentTag = new ComponentTag(tag); fullComponentTag.setId(childId.toString()); controller = ComponentResolvers.resolve( enclosureParent, markupStream, fullComponentTag, new ResolverFilter() { @Override public boolean ignoreResolver(final IComponentResolver resolver) { return resolver instanceof EnclosureHandler; } }); break; } else if (fullChildId.startsWith(tagId + PATH_SEPARATOR)) { fullChildId = Strings.afterFirst(fullChildId, PATH_SEPARATOR); } } } } } finally { markupStream.setCurrentIndex(orgIndex); } } checkChildComponent(controller); return controller; }
/** * Search for <wicket:panel ...> on the same level. * * @param markup * @return null, if not found */ private final IMarkupFragment findStartTag(final IMarkupFragment markup) { MarkupStream stream = new MarkupStream(markup); while (stream.skipUntil(ComponentTag.class)) { ComponentTag tag = stream.getTag(); if (tag.isOpen() || tag.isOpenClose()) { if (tag instanceof WicketTag) { WicketTag wtag = (WicketTag) tag; if (tagName.equalsIgnoreCase(wtag.getName())) { return stream.getMarkupFragment(); } } stream.skipToMatchingCloseTag(tag); } stream.next(); } return null; }
@Override public IMarkupFragment getMarkup() { if (getParent() == null) { throw new WicketRuntimeException( "Bug: The Wicket internal instance of HtmlHeaderContainer is not connected to a parent"); } // Get the page markup IMarkupFragment markup = getPage().getMarkup(); if (markup == null) { throw new MarkupException("Unable to get page markup: " + getPage().toString()); } // Find the markup fragment MarkupStream stream = new MarkupStream(markup); IMarkupFragment headerMarkup = null; while (stream.skipUntil(ComponentTag.class) && (headerMarkup == null)) { ComponentTag tag = stream.getTag(); if (tag.isOpen() || tag.isOpenClose()) { if (tag instanceof WicketTag) { WicketTag wtag = (WicketTag) tag; if (wtag.isHeadTag()) { if (tag.getMarkupClass() == null) { headerMarkup = stream.getMarkupFragment(); } } } else if (tag.getName().equalsIgnoreCase("head")) { headerMarkup = stream.getMarkupFragment(); } } stream.next(); } setMarkup(headerMarkup); return headerMarkup; }
/** {@inheritDoc} */ @Override public ComponentTag getComponentTag(Component c) { IMarkupFragment markup = c.getMarkup(); MarkupStream stream = new MarkupStream(markup); return stream.getTag(); }
/** Scans the given markup and extracts balancing tags. */ private void parseMarkup() { try { // always remember the latest index (size) int size = markup.size(); // Loop through tags MarkupElement elem; while (null != (elem = getNextTag())) { if (elem instanceof HtmlSpecialTag) { elem = new ComponentTag(((HtmlSpecialTag) elem).getXmlTag()); } if (elem instanceof ComponentTag) { ComponentTag tag = (ComponentTag) elem; boolean add = (tag.getId() != null); if (!add && tag.isClose()) { add = ((tag.getOpenTag() != null) && (tag.getOpenTag().getId() != null)); } // Add tag to list? if (add || /*tag.isModified() ||*/ (markup.size() != size)) { // Add text from last position to the current tag position CharSequence text = xmlParser.getInputFromPositionMarker(tag.getPos()); if (text.length() > 0) { text = handleRawText(text.toString()); // Make sure you add it at the correct location. // IMarkupFilters might have added elements as well. markup.addMarkupElement(size, new RawMarkup(text)); } xmlParser.setPositionMarker(); if (add) { // Add to the markup unless the tag has been flagged as // to be removed from the markup. (e.g. <wicket:remove> if (tag.isIgnore() == false) { markup.addMarkupElement(tag); } } /*else if (tag.isModified()) { markup.addMarkupElement(new RawMarkup(tag.toCharSequence())); }*/ else { xmlParser.setPositionMarker(tag.getPos()); } } // always remember the latest index (size) size = markup.size(); } } } catch (final ParseException ex) { // Add remaining input string final CharSequence text = xmlParser.getInputFromPositionMarker(-1); if (text.length() > 0) { markup.addMarkupElement(new RawMarkup(text)); } // markup.getMarkupResourceStream().setEncoding(xmlParser.getEncoding()); markup.getMarkupResourceStream().setDoctype(xmlParser.getDoctype()); final MarkupStream markupStream = new MarkupStream(markup); markupStream.setCurrentIndex(markup.size() - 1); throw new MarkupException(markupStream, ex.getMessage(), ex); } // Add tail? CharSequence text = xmlParser.getInputFromPositionMarker(-1); if (text.length() > 0) { text = handleRawText(text.toString()); // Make sure you add it at the correct location. // IMarkupFilters might have added elements as well. markup.addMarkupElement(new RawMarkup(text)); } postProcess(markup); // Make all tags immutable and the list of elements unmodifiable markup.makeImmutable(); }
private static void render(BootstrapRadioChoice<String> choice, String initialMarkup) { MarkupStream stream = new MarkupStream(Markup.of(initialMarkup)); stream.setCurrentIndex(1); choice.onComponentTagBody(stream, new ComponentTag("div", TagType.OPEN)); }