
com.google.sitebricks.rendering.control.XmlWidget Maven / Gradle / Ivy
The newest version!
package com.google.sitebricks.rendering.control;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.sitebricks.Renderable;
import com.google.sitebricks.Respond;
import com.google.sitebricks.compiler.EvaluatorCompiler;
import com.google.sitebricks.compiler.ExpressionCompileException;
import com.google.sitebricks.compiler.Token;
import com.google.sitebricks.headless.Request;
import com.google.sitebricks.rendering.Attributes;
import com.google.sitebricks.rendering.SelfRendering;
import net.jcip.annotations.ThreadSafe;
import java.util.*;
/**
* Widget renders an XML-like tag
*
* @author Dhanji R. Prasanna ([email protected])
*/
@ThreadSafe
@SelfRendering
class XmlWidget implements Renderable {
private final WidgetChain widgetChain;
private final boolean selfClosed;
private final String name;
private final Map> attributes;
// HACK Extremely ouch! Replace with Assisted inject.
private static volatile Provider request;
private static final Set CONTEXTUAL_ATTRIBS;
static {
Set set = new HashSet();
set.add("href");
set.add("action");
set.add("src");
CONTEXTUAL_ATTRIBS = Collections.unmodifiableSet(set);
}
XmlWidget(WidgetChain widgetChain, String name, EvaluatorCompiler compiler,
@Attributes Map attributes) throws ExpressionCompileException {
this.widgetChain = widgetChain;
this.name = name;
this.attributes = Collections.unmodifiableMap(compile(attributes, compiler));
//hacky. Script tags should not be self-closed due to IE insanity.
this.selfClosed =
widgetChain instanceof TerminalWidgetChain && !"script".equalsIgnoreCase(name);
}
//compiles a map of name:value attrs into a map of name:token renderables
static Map> compile(Map attributes,
EvaluatorCompiler compiler)
throws ExpressionCompileException {
Map> map = new LinkedHashMap>();
for (Map.Entry attribute : attributes.entrySet()) {
map.put(attribute.getKey(), compiler.tokenizeAndCompile(attribute.getValue()));
}
return map;
}
public void render(Object bound, Respond respond) {
writeOpenTag(bound, respond, name, attributes);
//write children
if (selfClosed) {
respond.write("/>"); //write self-closed tag
} else {
respond.write('>');
widgetChain.render(bound, respond);
//close tag
respond.write("");
respond.write(name);
respond.write('>');
}
}
static void writeOpenTag(Object bound, Respond respond, String name,
Map> attributes) {
respond.write('<');
respond.write(name);
respond.write(' ');
//write attributes
for (Map.Entry> attribute : attributes.entrySet()) {
respond.write(attribute.getKey());
respond.write("=\"");
final List tokenList = attribute.getValue();
for (int i = 0; i < tokenList.size(); i++) {
Token token = tokenList.get(i);
if (token.isExpression()) {
respond.write(token.render(bound));
} else {
respond.write(
contextualizeIfNeeded(attribute.getKey(), (0 == i), token.render(bound)));
}
}
respond.write("\" ");
}
respond.chew();
}
private static String contextualizeIfNeeded(String attribute, boolean isFirstToken, String raw) {
if (isFirstToken && CONTEXTUAL_ATTRIBS.contains(attribute)) {
//add context to path if needed
if (raw.startsWith("/"))
raw = request.get().context() + raw;
}
return raw;
}
public Set collect(Class clazz) {
return widgetChain.collect(clazz);
}
@Inject
public void setRequestProvider(Provider requestProvider) {
XmlWidget.request = requestProvider;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy