All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.wicket.markup.MarkupStream Maven / Gradle / Ivy

Go to download

Pax Wicket Service is an OSGi extension of the Wicket framework, allowing for dynamic loading and unloading of Wicket components and pageSources.

There is a newer version: 5.0.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.wicket.markup;

import org.apache.wicket.Component;
import org.apache.wicket.util.resource.IResourceStream;
import org.apache.wicket.util.string.Strings;


/**
 * A stream of {@link org.apache.wicket.markup.MarkupElement}s, subclasses of which are
 * {@link org.apache.wicket.markup.ComponentTag} and {@link org.apache.wicket.markup.RawMarkup}. A
 * markup stream has a current index in the list of markup elements. The next markup element can be
 * retrieved and the index advanced by calling next(). If the index hits the end, hasMore() will
 * return false.
 * 

* The current markup element can be accessed with get() and as a ComponentTag with getTag(). *

* The stream can be sought to a particular location with setCurrentIndex(). *

* Convenience methods also exist to skip component tags (and any potentially nested markup) or raw * markup. *

* Several boolean methods of the form at*() return true if the markup stream is positioned at a tag * with a given set of characteristics. *

* The resource from which the markup was loaded can be retrieved with getResource(). * * @author Jonathan Locke */ public final class MarkupStream { /** Element at currentIndex */ private MarkupElement current; /** Current index in markup stream */ private int currentIndex = 0; /** The markup element list */ private final Markup markup; /** * Constructor * * @param markup * List of markup elements */ public MarkupStream(final Markup markup) { this.markup = markup; if (markup.size() > 0) { current = get(currentIndex); } } /** * @return True if current markup element is a close tag */ public boolean atCloseTag() { return atTag() && getTag().isClose(); } /** * @return True if current markup element is an openclose tag */ public boolean atOpenCloseTag() { return atTag() && getTag().isOpenClose(); } /** * @param componentId * Required component name attribute * @return True if the current markup element is an openclose tag with the given component name */ public boolean atOpenCloseTag(final String componentId) { return atOpenCloseTag() && componentId.equals(getTag().getId()); } /** * @return True if current markup element is an open tag */ public boolean atOpenTag() { return atTag() && getTag().isOpen(); } /** * @param id * Required component id attribute * @return True if the current markup element is an open tag with the given component name */ public boolean atOpenTag(final String id) { return atOpenTag() && id.equals(getTag().getId()); } /** * @return True if current markup element is a tag */ public boolean atTag() { return current instanceof ComponentTag; } /** * Compare this markup stream with another one * * @param that * The other markup stream * @return True if each MarkupElement in this matches each element in that */ public boolean equalTo(final MarkupStream that) { // While a has more markup elements while (hasMore()) { // Get an element from each final MarkupElement thisElement = this.get(); final MarkupElement thatElement = that.get(); // and if the elements are not equal if (thisElement != null && thatElement != null) { if (!thisElement.equalTo(thatElement)) { // fail the comparison return false; } } else { // If one element is null, if (!(thisElement == null && thatElement == null)) { // fail the comparison return false; } } next(); that.next(); } // If we've run out of markup elements in b if (!that.hasMore()) { // then the two streams match perfectly return true; } // Stream b had extra elements return false; } /** * True, if associate markup is the same. It will change e.g. if the markup file has been * re-loaded or the locale has been changed. * * @param markupStream * The markup stream to compare with. * @return true, if markup has not changed */ public final boolean equalMarkup(final MarkupStream markupStream) { if (markupStream == null) { return false; } return markup == markupStream.markup; } /** * Find the markup element index of the component with 'path' * * @param path * The component path expression * @param id * The component's id to search for * @return -1, if not found */ public final int findComponentIndex(final String path, final String id) { return markup.findComponentIndex(path, id); } /** * @return The current markup element */ public MarkupElement get() { return current; } /** * @param index * The index of a markup element * @return The MarkupElement element */ public MarkupElement get(final int index) { return markup.get(index); } /** * Get the component/container's Class which is directly associated with the stream. * * @return The component's class */ public final Class getContainerClass() { return markup.getMarkupResourceData().getResource().getMarkupClass(); } /** * @return Current index in markup stream */ public int getCurrentIndex() { return currentIndex; } /** * Gets the markup encoding. A markup encoding may be specified in a markup file with an XML * encoding specifier of the form <?xml ... encoding="..." ?>. * * @return The encoding, or null if not found */ public final String getEncoding() { return markup.getMarkupResourceData().getEncoding(); } /** * @return The resource where this markup stream came from */ public IResourceStream getResource() { return markup.getMarkupResourceData().getResource(); } /** * @return The current markup element as a markup tag */ public ComponentTag getTag() { if (current instanceof ComponentTag) { return (ComponentTag)current; } throwMarkupException("Tag expected"); return null; } /** * Get the wicket namespace valid for this specific markup * * @return wicket namespace */ public final String getWicketNamespace() { return markup.getMarkupResourceData().getWicketNamespace(); } /** * Return the XML declaration string, in case if found in the markup. * * @return Null, if not found. */ public String getXmlDeclaration() { return markup.getMarkupResourceData().getXmlDeclaration(); } /** * @return True if this markup stream has more MarkupElement elements */ public boolean hasMore() { return currentIndex < markup.size(); } /** * * @return true, if underlying markup has been merged (inheritance) */ public final boolean isMergedMarkup() { return markup instanceof MergedMarkup; } /** * The correct way of using MarkupStream is like: * *

	 * while (markupStream.hasMore())
	 * {
	 *    final MarkupElement cursor = markupStream.get();
	 *    ...
	 *    markupStream.next();
	 * }
	 * 
* * @return The next markup element in the stream */ public MarkupElement next() { if (++currentIndex < markup.size()) { return current = get(currentIndex); } return null; } /** * @param currentIndex * New current index in the stream */ public void setCurrentIndex(final int currentIndex) { current = get(currentIndex); this.currentIndex = currentIndex; } /** * Skips this component and all nested components */ public final void skipComponent() { // Get start tag final ComponentTag startTag = getTag(); if (startTag.isOpen()) { // With HTML not all tags require a close tag which // must have been detected by the HtmlHandler earlier on. if (startTag.hasNoCloseTag() == false) { // Skip next(); // Skip nested components skipToMatchingCloseTag(startTag); } // Skip next(); } else if (startTag.isOpenClose()) { // Skip next(); } else { // We were something other than or throwMarkupException("Skip component called on bad markup element " + startTag); } } /** * Skips any raw markup at the current position */ public void skipRawMarkup() { while (true) { if (current instanceof RawMarkup) { if (next() != null) { continue; } } else if ((current instanceof ComponentTag) && !(current instanceof WicketTag)) { ComponentTag tag = (ComponentTag)current; if (tag.isAutoComponentTag()) { if (next() != null) { continue; } } else if (tag.isClose() && tag.getOpenTag().isAutoComponentTag()) { if (next() != null) { continue; } } } break; } } /** * Skips any markup at the current position until the wicket tag name is found. * * @param wicketTagName * wicket tag name to seek */ public void skipUntil(final String wicketTagName) { while (true) { if ((current instanceof WicketTag) && ((WicketTag)current).getName().equals(wicketTagName)) { return; } // go on until we reach the end if (next() == null) { return; } } } /** * Renders markup until a closing tag for openTag is reached. * * @param openTag * The open tag */ public void skipToMatchingCloseTag(final ComponentTag openTag) { // Loop through the markup in this container while (hasMore()) { // If the current markup tag closes the openTag if (get().closes(openTag)) { // Done! return; } // Skip element next(); } throwMarkupException("Expected close tag for " + openTag); } /** * Throws a new markup exception * * @param message * The exception message * @throws MarkupException */ public void throwMarkupException(final String message) { throw new MarkupException(this, message); } /** * @return An HTML string highlighting the current position in the markup stream */ public String toHtmlDebugString() { final StringBuffer buffer = new StringBuffer(); for (int i = 0; i < markup.size(); i++) { if (i == currentIndex) { buffer.append(""); } final MarkupElement element = markup.get(i); buffer.append(Strings.escapeMarkup(element.toString(), true).toString()); if (i == currentIndex) { buffer.append(""); } } return buffer.toString(); } /** * @return String representation of markup stream */ @Override public String toString() { return "[markup = " + String.valueOf(markup) + ", index = " + currentIndex + ", current = " + ((current == null) ? "null" : current.toUserDebugString()) + "]"; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy