xapi.dev.ui.html.AbstractHtmlGenerator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xapi-dev Show documentation
Show all versions of xapi-dev Show documentation
Everything needed to run a comprehensive dev environment.
Just type X_ and pick a service from autocomplete;
new dev modules will be added as they are built.
The only dev service not included in the uber jar is xapi-dev-maven,
as it includes all runtime dependencies of maven, adding ~4 seconds to build time,
and 6 megabytes to the final output jar size (without xapi-dev-maven, it's ~1MB).
The newest version!
package xapi.dev.ui.html;
import static xapi.collect.X_Collect.newStringMap;
import static xapi.ui.html.api.HtmlSnippet.appendTo;
import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.dev.javac.StandardGeneratorContext;
import com.google.gwt.dev.jjs.UnifyAstView;
import com.google.gwt.user.server.Base64Utils;
import com.google.gwt.util.tools.shared.Md5Utils;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import javax.inject.Provider;
import xapi.annotation.compile.Generated;
import xapi.annotation.compile.Import;
import xapi.collect.X_Collect;
import xapi.collect.api.IntTo;
import xapi.collect.api.StringTo;
import xapi.dev.source.SourceBuilder;
import xapi.except.NotYetImplemented;
import xapi.source.X_Source;
import xapi.source.write.MappedTemplate;
import xapi.source.write.ToStringer;
import xapi.ui.html.api.Css;
import xapi.ui.html.api.El;
import xapi.ui.html.api.Html;
import xapi.ui.html.api.HtmlTemplate;
import xapi.ui.html.api.Style;
import xapi.util.api.ConvertsValue;
import xapi.util.impl.LazyProvider;
public abstract class AbstractHtmlGenerator implements CreatesContextObject {
protected static final String KEY_FROM = "from";
private static final Provider isDev = new LazyProvider<>(new Provider() {
@Override
public Boolean get() {
return true;
}
});
protected static Ctx existingTypesUnchanged(final TreeLogger logger,
final UnifyAstView ast, final Ctx result, final String verify) {
if (isDev.get()) {
// During development, never reuse existing types, as we're likely changing generators
return null;
}
try {
if (result.getSourceType() == null) {
return null;
}
final Generated gen = result.getSourceType().getAnnotation(Generated.class);
if (gen == null) {
return null;
}
final String hash = gen.value()[gen.value().length-1];
if (verify.equals(hash)) {
return result;
}
} catch (final Exception e) {
logger.log(Type.WARN, "Unknown error calculating change hashes", e);
}
return null;
}
protected static String toHash(final UnifyAstView ast, final String ... types) throws UnableToCompleteException {
final StringBuilder b = new StringBuilder();
for (final String type : types) {
b.append(ast.searchForTypeBySource(type).toSource());
}
return Base64Utils.toBase64(Md5Utils.getMd5Digest(b.toString().getBytes()));
}
protected String clsName;
protected String documentType;
protected final HtmlGeneratorContext htmlGen;
protected final SourceBuilder out;
protected boolean renderAllChildren;
protected String[] renderOrder;
public AbstractHtmlGenerator(final String clsName, final JClassType templateType, final UnifyAstView ast) {
this.clsName = clsName;
htmlGen = new HtmlGeneratorContext(templateType);
this.out = new SourceBuilder("public class "+clsName)
.setPackage(templateType.getPackage().getName())
.setPayload(ast);
}
protected void addEl(final String name, final El el) {
htmlGen.addEl(name, el);
}
protected void addHtml(final String name, final Html html, final IntTo elOrder) {
if (html == null) {
return;
}
elOrder.add(name);
}
public void addImport(final Import importType) {
if (importType.staticImport().length()==0) {
out.getImports().addImport(importType.value());
} else {
out.getImports().addStatic(importType.value(), importType.staticImport());
}
}
protected void clear() {
htmlGen.clear();
}
/**
* @param key
* @param accessor
* @param template
* @return
*/
protected ConvertsValue createProvider(final String key,
final String accessor, final HtmlTemplate template) {
switch (key) {
case HtmlTemplate.KEY_VALUE:
return new ConvertsValue() {
@Override
public String convert(final String from) {
if (accessor.equals(El.DEFAULT_ACCESSOR)) {
return "".equals(key) ? KEY_FROM :
KEY_FROM+"."+key+(key.endsWith("()") ? "" : "()");
} else {
return accessor;
}
}
};
default:
return new ConvertsValue() {
@Override
public String convert(final String from) {
return from.startsWith(key) ?
from.substring(key.length()) :
from;
}
};
case HtmlTemplate.KEY_CHILDREN:
case HtmlTemplate.KEY_PARENT:
case HtmlTemplate.KEY_CONTEXT:
throw new NotYetImplemented("Key "+key+" not yet implemented in "+getClass()+".createProvider()");
}
}
/**
* @param text
* @return
*/
protected String escape(final String text) {
return Generator.escape(text);
}
@SuppressWarnings("unchecked")
protected String escape(String text, final String key, final String accessor) {
if (text.length() == 0) {
return "";
}
final HtmlGeneratorNode node = htmlGen.allNodes.get(key);
if (node.hasTemplates()) {
final StringTo