package http.resource;
import http.resource.template.LoadDataMethod;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import nebula.data.DataRepos;
import nebula.data.DataStore;
import nebula.data.Entity;
import nebula.lang.Code;
import nebula.lang.Field;
import nebula.lang.Flow.Step;
import nebula.lang.JsCallCompiler;
import nebula.lang.JsCompiler;
import nebula.lang.Type;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateMethodModel;
public class TypeTemplateResouce extends AbstractResouce {
final Configuration cfg;
// private final String templateName;
TemplateMethodModel dataWareHouseModel;
final Map<String, Object> root = new HashMap<String, Object>();
final DataRepos dataWareHouse;
final DataStore<Entity> attributes;
final String path;
// final TypeLoader typeLoader;
final String theme;
final String skin;
final Type type;
// final String actionName;
final String name;
public TypeTemplateResouce(Configuration cfg, DataRepos dataWareHouse, DataStore<Entity> attributes, String path, String theme, String skin, Type type,
String specName, String layoutName, String actionName) {
this(cfg, dataWareHouse, attributes, path, theme, skin, type, makeName(type, specName, layoutName, actionName));
}
private static String makeName(Type type, String specName, String layout, String actionName) {
String entityType = (String) type.getStandalone().name().toLowerCase();
layout = layout != null ? layout : (String) type.getAttrs().get("Layout");
String name = entityType + "_" + layout.toLowerCase() + "_" + actionName.toLowerCase() + ".ftl";
name = specName != null ? specName + "_" + name : name;
return name;
}
public TypeTemplateResouce(Configuration cfg, DataRepos dataWareHouse, DataStore<Entity> attributes, String path, String theme, String skin, Type type,
String name) {
super("text/template", 0, 0);// TODO Not realized TypeTemplateResouce
// super("text/template", 0, 0)
this.cfg = cfg;
this.dataWareHouse = dataWareHouse;
this.dataWareHouseModel = new LoadDataMethod(dataWareHouse);
this.attributes = attributes;
this.path = path;
this.theme = theme;
this.skin = skin;
this.type = type;
this.name = name;
root.put("alldatas", dataWareHouseModel);
root.put("_path", path);
root.put("_theme", this.theme);
root.put("_skin", this.skin);
root.put("_spec", "admin");
}
protected void fillData() {
root.put("type", layout(type));
DataStore<Entity> attrs = attributes;
root.put("attrs", attrs);
}
protected void get(HttpServletRequest req) throws IOException {
try {
TemplateLoader loader = cfg.getTemplateLoader();
String templateName = null;
if (loader.findTemplateSource(theme + "/" + skin + "/" + name) != null) {
templateName = theme + "/" + skin + "/" + name;
} else if (loader.findTemplateSource(theme + "/" + name) != null) {
templateName = theme + "/" + name;
} else if (loader.findTemplateSource(name) != null) {
templateName = name;
} else {
throw new IOException(name + " can not find!");
}
ByteArrayOutputStream bout = new ByteArrayOutputStream();
Writer w = new OutputStreamWriter(bout);
fillData();
Template template = cfg.getTemplate(templateName);
template.process(root, w);
w.flush();
w.close();
super.lastModified = System.currentTimeMillis();
super.cache = bout.toByteArray();
} catch (TemplateException e) {
log.error("Template prase error", e);
throw new IOException(e);
}
}
public static final String HasFollowing = "HasFollowing";
private Type layout(Type type) {
List<Field> fields = type.getFields();
Field lastField = null;
for (int i = 0; i < fields.size(); i++) {
Field field = fields.get(i);
if (field.getAttrs().containsKey(Field.SingleLine)) {
if (lastField != null) {
lastField.getAttrs().remove(HasFollowing);
}
lastField = null;
} else {
if (lastField != null) {
if (field.getAttrs().containsKey(Field.ShouldBeLeader)) {
lastField.getAttrs().remove(HasFollowing);
} else {
lastField.getAttrs().put(HasFollowing, HasFollowing);
}
}
lastField = field;
}
if (field.isDerived() && !field.getAttrs().containsKey(Field.ComputeBackend)) {
field.getAttrs().put("DerivedExpression", JsCompiler.compiler(field.getCode(), "this", "data"));
}
if (field.isDefaultValue() && !field.getAttrs().containsKey(Field.ComputeBackend)) {
field.getAttrs().put("DefaultExpression", JsCompiler.compiler(field.getCode(), "this", "data"));
}
if (field.getAttrs().containsKey(Field.DisplayOn)) {
field.getAttrs().put(Field.DisplayOn + "Expression", JsCompiler.compiler((Code)field.getAttrs().get(Field.DisplayOn), "this", "data"));
}
if (field.getAttrs().containsKey(Field.RequiredOn)) {
field.getAttrs().put(Field.RequiredOn + "Expression", JsCompiler.compiler((Code)field.getAttrs().get(Field.RequiredOn), "this", "data"));
}
}
// if (!type.getAttrs().containsKey("AjaxExpressionName")) {
StringBuilder sb = new StringBuilder();
String ctrlName = type.getName() + "_OnChangeCtrl";
sb.append("<script>function " + ctrlName + "($scope){var doCall = function( $scope ){");
for (int i = 0; i < fields.size(); i++) {
Field field = fields.get(i);
if (field.getOnChangeCode() != null) {
sb.append(JsCallCompiler.compiler("data." + field.getName(), field.getOnChangeCode(), "this", "data"));
}
}
sb.append("};doCall( $scope.$parent );}</script>");
type.getAttrs().put("AjaxExpressionName", ctrlName);
type.getAttrs().put("AjaxExpression", sb.toString());
// }
List<Step> steps = type.getSteps();
if(steps!=null){
for (Step step : steps) {
layout(step.getType());
}
}
return type;
}
}