001: /*
002: * $Id: TagTypeHandler.java 461655 2006-07-30 12:37:49Z jdonnerstag $ $Revision:
003: * 1.5 $ $Date: 2006-07-30 14:37:49 +0200 (Sun, 30 Jul 2006) $
004: *
005: * ==============================================================================
006: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
007: * use this file except in compliance with the License. You may obtain a copy of
008: * the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
014: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
015: * License for the specific language governing permissions and limitations under
016: * the License.
017: */
018: package wicket.markup.parser.filter;
019:
020: import java.text.ParseException;
021: import java.util.HashMap;
022: import java.util.Map;
023:
024: import wicket.markup.ComponentTag;
025: import wicket.markup.MarkupElement;
026: import wicket.markup.parser.AbstractMarkupFilter;
027: import wicket.markup.parser.XmlTag;
028: import wicket.util.collections.ArrayListStack;
029:
030: /**
031: * This is a markup inline filter. It identifies tags which are allowed
032: * open-close in the markup, but which for Wicket to be processed correctly
033: * must be open-body-close.
034: *
035: * @author Juergen Donnerstag
036: */
037: public final class TagTypeHandler extends AbstractMarkupFilter {
038: /** Tag stack to find balancing tags */
039: final private ArrayListStack stack = new ArrayListStack();
040:
041: /** Map of simple tags. */
042: private static final Map requireOpenBodyCloseTag = new HashMap();
043:
044: static {
045: // Tags which require open-body-close
046: requireOpenBodyCloseTag.put("select", Boolean.TRUE);
047: }
048:
049: /**
050: * Construct.
051: */
052: public TagTypeHandler() {
053: }
054:
055: /**
056: * Get the next MarkupElement from the parent MarkupFilter and handle it if
057: * the specific filter criteria are met. Depending on the filter, it may
058: * return the MarkupElement unchanged, modified or it remove by asking the
059: * parent handler for the next tag.
060: *
061: * @see wicket.markup.parser.IMarkupFilter#nextTag()
062: * @return Return the next eligible MarkupElement
063: */
064: public MarkupElement nextTag() throws ParseException {
065: // If there is something in the stack, ...
066: while (stack.size() > 0) {
067: final ComponentTag top = (ComponentTag) stack.pop();
068: return top;
069: }
070:
071: // Get the next tag. If null, no more tags are available
072: // in the markup
073: final ComponentTag tag = (ComponentTag) getParent().nextTag();
074: if (tag == null) {
075: return tag;
076: }
077:
078: if (tag.isOpenClose()) {
079: String name = tag.getName();
080: if (tag.getNamespace() != null) {
081: name = tag.getNamespace() + ":" + tag.getName();
082: }
083:
084: // Pop any simple tags off the top of the stack
085: if (requiresOpenBodyCloseTag(name)) {
086: tag.setType(XmlTag.OPEN);
087: XmlTag closeTag = new XmlTag();
088: closeTag.setType(XmlTag.CLOSE);
089: closeTag.setName(tag.getName());
090: closeTag.setNamespace(tag.getNamespace());
091: closeTag.closes(tag);
092:
093: stack.push(new ComponentTag(closeTag));
094: }
095: }
096:
097: return tag;
098: }
099:
100: /**
101: * Gets whether this tag does not require open-body-close tags.
102: *
103: * @param name
104: * The tag's name, e.g. a, br, div, etc.
105: * @return True if this tag must be converted into open-body-close if openClose
106: */
107: public static boolean requiresOpenBodyCloseTag(final String name) {
108: return requireOpenBodyCloseTag.get(name) != null;
109: }
110: }
|