package jj.document.servable;
import static jj.server.ServerLocation.Virtual;
import java.util.Locale;
import javax.inject.Inject;
import javax.inject.Singleton;
import jj.execution.CurrentTask;
import jj.i18n.MessagesResource;
import jj.resource.ResourceFinder;
import jj.resource.ResourceTask;
import org.jsoup.nodes.Attribute;
import org.jsoup.nodes.Element;
/**
* Performs properties substitutions in place based on attribute values.
* for example, given a properties file like
* <pre>
* hi=Why, hello there
* goodbye=http://www.google.com/
* </pre>
* and html like
* <pre>
* <a data-i18n-href="goodbye" data-i18n="hi">HI MESSAGE HERE</a>
* </pre>
*
* you get back
* <pre>
* <a href="http://www.google.com/">Why, hello there</a>
* </pre>
* <p>
* At some point in the future, this should also perform internal
* substitutions but i'm not yet sure how
* </p>
* @author jason
*
*/
@Singleton
class InlineMessagesDocumentFilter implements DocumentFilter {
static final String MISSING_KEY = "??? MISSING KEY (%s) ???";
private static final String TEXT_KEY = "data-i18n";
private static final String ATTRIBUTE_KEY = TEXT_KEY + "-";
private final ResourceFinder resourceFinder;
private final CurrentTask currentTask;
@Inject
InlineMessagesDocumentFilter(
final ResourceFinder resourceFinder,
final CurrentTask currentTask
) {
this.resourceFinder = resourceFinder;
this.currentTask = currentTask;
}
private String findValue(String key, MessagesResource resource) {
return resource.containsKey(key) ? resource.message(key) : String.format(MISSING_KEY, key);
}
@Override
public void filter(final DocumentRequestProcessor documentRequestProcessor) {
String baseName = documentRequestProcessor.baseName();
MessagesResource resource = resource(baseName, Locale.US);
if (resource != null) {
resource.addDependent(documentRequestProcessor.documentScriptEnvironment());
for (final Element el : documentRequestProcessor.document().select("[" + TEXT_KEY + "]")) {
String key = el.attr(TEXT_KEY);
String value = findValue(key, resource);
el.html(value).removeAttr(TEXT_KEY);
}
for (final Element el : documentRequestProcessor.document().select("[^" + ATTRIBUTE_KEY + "]")) {
for (final Attribute attr : el.attributes()) {
if (attr.getKey().startsWith(ATTRIBUTE_KEY)) {
String key = attr.getValue();
String value = findValue(key, resource);
String newAttr = attr.getKey().substring(ATTRIBUTE_KEY.length());
el.attr(newAttr, value).removeAttr(attr.getKey());
}
}
}
}
}
@Override
public boolean needsIO(final DocumentRequestProcessor documentRequestProcessor) {
return resourceFinder.findResource(
MessagesResource.class,
Virtual,
documentRequestProcessor.baseName(),
Locale.US
) == null;
}
private MessagesResource resource(String baseName, Locale locale) {
return currentTask.currentIs(ResourceTask.class) ?
resourceFinder.loadResource(MessagesResource.class, Virtual, baseName, locale) :
resourceFinder.findResource(MessagesResource.class, Virtual, baseName, locale);
}
}