001: /*
002: * $Id: WicketMessageTagHandler.java 462303 2006-09-18 05:11:58Z ehillenius $
003: * $Revision: 462303 $ $Date: 2006-09-18 07:11:58 +0200 (Mon, 18 Sep 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.ArrayList;
022: import java.util.List;
023: import java.util.StringTokenizer;
024:
025: import wicket.Application;
026: import wicket.markup.ComponentTag;
027: import wicket.markup.ContainerInfo;
028: import wicket.markup.MarkupElement;
029: import wicket.markup.parser.AbstractMarkupFilter;
030: import wicket.settings.IResourceSettings;
031:
032: /**
033: * THIS IS EXPERIMENTAL ONLY AND DISABLED BY DEFAULT
034: * <p>
035: * This is a markup inline filter. It identifies wicket:message attributes and
036: * replaces the attributes referenced. E.g. wicket:message="value=key" would
037: * replace or add the attribute "value" with the message associated with "key".
038: *
039: * @author Juergen Donnerstag
040: */
041: public final class WicketMessageTagHandler extends AbstractMarkupFilter {
042: /** Logging */
043: // private final static Log log = LogFactory.getLog(WicketMessageTagHandler.class);
044: /** TODO Post 1.2: General: Namespace should not be a constant */
045: private final static String WICKET_MESSAGE_ATTRIBUTE_NAME = "wicket:message";
046:
047: /**
048: * globally enable wicket:message; If accepted by user, we should use an
049: * apps setting
050: */
051: public static boolean enable = false;
052:
053: /**
054: * The MarkupContainer requesting the information incl. class, locale and
055: * style
056: */
057: private final ContainerInfo containerInfo;
058:
059: /** temporary storage unomdified while the object instance exists */
060: private final List searchStack;
061:
062: /**
063: * The application settings required. Note: you can rely on
064: * Application.get().getResourceSettings() as reading the markup happens in
065: * another thread due to ModificationWatcher.
066: */
067: private IResourceSettings settings;
068:
069: /**
070: * Construct.
071: *
072: * @param containerInfo
073: * The container requesting the current markup incl class, style
074: * and locale
075: */
076: public WicketMessageTagHandler(final ContainerInfo containerInfo) {
077: this .containerInfo = containerInfo;
078: this .settings = Application.get().getResourceSettings();
079:
080: this .searchStack = new ArrayList();
081: searchStack.add(containerInfo.getContainerClass());
082: }
083:
084: /**
085: *
086: * @see wicket.markup.parser.IMarkupFilter#nextTag()
087: * @return The next tag to be processed. Null, if not more tags are
088: * available
089: */
090: public final MarkupElement nextTag() throws ParseException {
091: // Get the next tag from the next MarkupFilter in the chain
092: // If null, no more tags are available
093: final ComponentTag tag = (ComponentTag) getParent().nextTag();
094: if (tag == null) {
095: return tag;
096: }
097:
098: final String wicketMessageAttribute = tag.getAttributes()
099: .getString(WICKET_MESSAGE_ATTRIBUTE_NAME);
100: if ((wicketMessageAttribute != null)
101: && (wicketMessageAttribute.trim().length() > 0)) {
102: if (this .containerInfo == null) {
103: throw new ParseException(
104: "Found "
105: + WICKET_MESSAGE_ATTRIBUTE_NAME
106: + " but the message can not be resolved, because the associated Page is not known."
107: + " This might be caused by using the wrong MarkupParser constructor",
108: tag.getPos());
109: }
110:
111: StringTokenizer attrTokenizer = new StringTokenizer(
112: wicketMessageAttribute, ",");
113: while (attrTokenizer.hasMoreTokens()) {
114: String text = attrTokenizer.nextToken().trim();
115: if (text == null) {
116: text = wicketMessageAttribute;
117: }
118:
119: StringTokenizer valueTokenizer = new StringTokenizer(
120: text, "=");
121: if (valueTokenizer.countTokens() != 2) {
122: throw new ParseException(
123: "Wrong format of wicket:message attribute value. "
124: + text
125: + "; Must be: key=value[, key=value]",
126: tag.getPos());
127: }
128:
129: String attrName = valueTokenizer.nextToken();
130: String messageKey = valueTokenizer.nextToken();
131: if ((attrName == null)
132: || (attrName.trim().length() == 0)
133: || (messageKey == null)
134: || (messageKey.trim().length() == 0)) {
135: throw new ParseException(
136: "Wrong format of wicket:message attribute value. "
137: + text
138: + "; Must be: key=value[, key=value]",
139: tag.getPos());
140: }
141:
142: String value = settings.getLocalizer().getString(
143: messageKey, null, searchStack,
144: containerInfo.getLocale(),
145: containerInfo.getStyle());
146:
147: if (value != null && (value.length() > 0)) {
148: tag.getAttributes().put(attrName, value);
149: tag.setModified(true);
150: } else if (tag.getAttributes().get(attrName) == null) {
151: tag.getAttributes().put(attrName, value);
152: tag.setModified(true);
153: } else {
154: // Do not modify the existing value
155: }
156: }
157: }
158:
159: return tag;
160: }
161: }
|