001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.wicket.markup.parser.filter;
018:
019: import java.text.ParseException;
020: import java.util.ArrayList;
021: import java.util.Iterator;
022: import java.util.List;
023:
024: import org.apache.wicket.markup.ComponentTag;
025: import org.apache.wicket.markup.MarkupResourceData;
026: import org.apache.wicket.markup.MarkupElement;
027: import org.apache.wicket.markup.WicketTag;
028: import org.apache.wicket.markup.parser.AbstractMarkupFilter;
029: import org.apache.wicket.markup.parser.XmlTag;
030:
031: /**
032: * This is a markup inline filter. It identifies xml tags which have a special
033: * meaning for Wicket. There are two type of tags which have a special meaning
034: * for Wicket.
035: * <p>
036: * <ul>
037: * <li>All tags with Wicket namespace, e.g. <wicket:remove></li>
038: * <li>All tags with an attribute like wicket:id="myLabel" </li>
039: * </ul>
040: *
041: * @author Juergen Donnerstag
042: */
043: public final class WicketTagIdentifier extends AbstractMarkupFilter {
044: /** List of well known wicket tag names */
045: private static List wellKnownTagNames;
046:
047: /** The current markup needed to get the markups namespace */
048: private final MarkupResourceData markup;
049:
050: /**
051: * Construct.
052: *
053: * @param markup
054: * The markup as known by now
055: */
056: public WicketTagIdentifier(final MarkupResourceData markup) {
057: this .markup = markup;
058: }
059:
060: /**
061: * Get the next tag from the next MarkupFilter in the chain and search for
062: * Wicket specific tags.
063: * <p>
064: * Note: The xml parser - the next MarkupFilter in the chain - returns
065: * XmlTags which are a subclass of MarkupElement. The implementation of this
066: * filter will return either ComponentTags or ComponentWicketTags. Both are
067: * subclasses of MarkupElement as well and both maintain a reference to the
068: * XmlTag. But no XmlTag is returned.
069: *
070: * @see org.apache.wicket.markup.parser.IMarkupFilter#nextTag()
071: * @return The next tag from markup to be processed. If null, no more tags
072: * are available
073: */
074: public MarkupElement nextTag() throws ParseException {
075: // Get the next tag from the markup.
076: // If null, no more tags are available
077: XmlTag xmlTag = (XmlTag) getParent().nextTag();
078: if (xmlTag == null) {
079: return xmlTag;
080: }
081:
082: final String namespace = markup.getWicketNamespace();
083:
084: // Identify tags with Wicket namespace
085: ComponentTag tag;
086: if (namespace.equalsIgnoreCase(xmlTag.getNamespace())) {
087: // It is <wicket:...>
088: tag = new WicketTag(xmlTag);
089:
090: // Make it a Wicket component. Otherwise it would be RawMarkup
091: tag.setId("_" + tag.getName());
092: tag.setAutoComponentTag(true);
093: tag.setModified(true);
094:
095: // If the tag is not a well-known wicket namespace tag
096: if (!isWellKnown(xmlTag)) {
097: // give up
098: throw new ParseException(
099: "Unknown tag name with Wicket namespace: '"
100: + xmlTag.getName()
101: + "'. Might be you haven't installed the appropriate resolver?",
102: tag.getPos());
103: }
104: } else {
105: // Everything else, except tags with Wicket namespace
106: tag = new ComponentTag(xmlTag);
107: }
108:
109: // If the form <tag wicket:id = "value"> is used
110: final String value = tag.getAttributes().getString(
111: namespace + ":id");
112: if (value != null) {
113: if (value.trim().length() == 0) {
114: throw new ParseException(
115: "The wicket:id attribute value must not be empty. May be unmatched quotes?!?",
116: tag.getPos());
117: }
118: // Make it a wicket component. Otherwise it would be RawMarkup
119: tag.setId(value);
120: }
121:
122: return tag;
123: }
124:
125: /**
126: * Register a new well known wicket tag name (e.g. panel)
127: *
128: * @param name
129: */
130: public final static void registerWellKnownTagName(final String name) {
131: if (wellKnownTagNames == null) {
132: wellKnownTagNames = new ArrayList();
133: }
134:
135: if (wellKnownTagNames.contains(name) == false) {
136: wellKnownTagNames.add(name);
137: }
138: }
139:
140: private boolean isWellKnown(final XmlTag xmlTag) {
141: final Iterator iterator = wellKnownTagNames.iterator();
142: while (iterator.hasNext()) {
143: final String name = (String) iterator.next();
144: if (xmlTag.getName().equalsIgnoreCase(name)) {
145: return true;
146: }
147: }
148: return false;
149: }
150: }
|