blob: ea13c814445276e8c71552f2148e23dd500a38cc [file] [log] [blame]
/*
* Copyright 2008 Google Inc.
*
* Licensed 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 com.google.gwt.uibinder.rebind.messages;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.uibinder.rebind.Tokenator;
import com.google.gwt.uibinder.rebind.UiBinderWriter;
import com.google.gwt.uibinder.rebind.XMLElement;
import com.google.gwt.uibinder.rebind.Tokenator.Resolver;
import com.google.gwt.uibinder.rebind.XMLElement.PostProcessingInterpreter;
/**
* Abstract class performs the heavy lifting for processing ph children of a msg
* element.
*/
public abstract class PlaceholderInterpreter implements
PostProcessingInterpreter<String> {
protected final UiBinderWriter uiWriter;
protected final MessageWriter message;
protected final Tokenator tokenator = new Tokenator();
public PlaceholderInterpreter(UiBinderWriter writer, MessageWriter message) {
this.uiWriter = writer;
this.message = message;
}
public String interpretElement(XMLElement elem)
throws UnableToCompleteException {
if (isPlaceholderElement(elem)) {
/*
* The innerHTML or innerText of the <ui:ph> will be provided as the value
* of the appropriate parameter when the Messages method is called.
*
* E.g.
*
* <ui:msg>Able <ui:ph name="foo" example"baz">baker</ui:ph> charlie</ui:msg>
*
* becomes
*
* @Default("Able {0} charlie)
* String message1(@Example("baz") String foo)
*
* and in the generated innerHTML is invoked
*
* message1("baker")
*/
MessagesWriter mw = getMessagesWriter();
String name = mw.consumeRequiredMessageElementAttribute("name", elem);
String example = mw.consumeMessageElementAttribute("example", elem);
String value = consumePlaceholderInnards(elem);
// Use the value as the example if none is provided
if ("".equals(example)) {
/*
* The value may contain tokens vended by the TemplateWriter, which will
* be substituted for runtime-computed values (like unique dom ids). We
* don't want those in the example text shown to the translator, so snip
* them
*/
example = stripTokens(value);
}
/*
* Likewise, if there are tokens from the UiWriter in the value string, we
* need it to replace them with the real expresions.
*/
value = uiWriter.detokenate(value);
return nextPlaceholder(name, example, value);
}
if (uiWriter.isWidgetElement(elem)) {
uiWriter.die(elem, "Found widget in a message that cannot contain widgets");
}
return null;
}
/**
* Called by various {@link XMLElement} consumeInner*() methods after all
* elements have been handed to {@link #interpretElement}.
* <p>
* Performs escaping on the consumed text to make it safe for use as a
* Messages {@literal @}Default value
*/
public String postProcess(String consumed) throws UnableToCompleteException {
return tokenator.detokenate(MessageWriter.escapeMessageFormat(consumed));
}
protected abstract String consumePlaceholderInnards(XMLElement elem)
throws UnableToCompleteException;
/**
* To be called from {@link #interpretElement(XMLElement)}. Creates the next
* placeholder in the {@link MessageWriter} we're building, and returns the
* text to stand in its place.
*
* @param name
* @param example
* @param value
* @return
*/
protected String nextPlaceholder(String name, String example, String value) {
message.addPlaceholder(new PlaceholderWriter(name, example, value));
/*
* We can't just return the {0} placeholder text, because it will be
* clobbered by the escaping performed in postProcess. We use a tokenator to
* hide the placeholder from the escaping step, and postProcess resolves the
* tokens when the escaping is done.
*/
String placeholder = String.format("{%d}",
message.getPlaceholderCount() - 1);
return tokenator.nextToken(placeholder);
}
protected String stripTokens(String value) {
String rtn = Tokenator.detokenate(value, new Resolver() {
public String resolveToken(String token) {
return "";
}
});
return rtn;
}
private MessagesWriter getMessagesWriter() {
return uiWriter.getMessages();
}
private boolean isPlaceholderElement(XMLElement elem) {
return getMessagesWriter().isMessagePrefixed(elem)
&& "ph".equals(elem.getLocalName());
}
}