Package org.pirkaengine.core.template

Source Code of org.pirkaengine.core.template.XhtmlTemplate

package org.pirkaengine.core.template;

import static org.pirkaengine.core.util.Logger.*;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.pirkaengine.core.KeyNotContainsException;
import org.pirkaengine.core.PrkComponent;
import org.pirkaengine.core.Renderer;
import org.pirkaengine.core.Template;
import org.pirkaengine.core.expression.Function;
import org.pirkaengine.core.expression.JavaFunction;


/**
* XHMLテンプレート.
* <p>
* TemplateはフラットなNodeのListを保持する。
* また、各NodeはそれぞれネストしたNodeを子に持つ事ができる。<br />
* つまり、テンプレートはこのクラスをルートとしたNodeのツリー構造となるが、
* 完全なComposite構造とはなっていない(ルートが特殊な為)。
* </p>
* @author shuji.w6e
* @since 0.1.0
*/
public class XhtmlTemplate implements Template, Serializable {

    private static final long serialVersionUID = 1L;
    /** Null Value */
    public static final Object NULL_VALUE = new Object();

    /** node list */
    final LinkedList<Node> nodeList = new LinkedList<Node>();
    /** 配列1ist */
    final HashMap<String, LoopNode> loopNodes = new HashMap<String, LoopNode>();
    /** 項目名Set */
    final HashSet<String> itemNames = new HashSet<String>();
    /** function map, key = name  */
    final Map<String, Function> functions = new HashMap<String, Function>();
    /** name of template */
    final String templateName;
    /** timeStamp */
    private long timeStamp = -1;
    /** components */
    final ArrayList<PrkComponent> components = new ArrayList<PrkComponent>();

    /**
    * コンストラクタ.
     * @param templateName テンプレート名
    */
    public XhtmlTemplate(String templateName) {
        this.templateName = templateName;
    }

    /*
     * (non-Javadoc)
     *
     * @see org.pirkaengine.core.Template#generate()
     */
    @Override
    public Renderer generate() {
        return this.generate(new HashMap<String, Object>());
    }

    /*
     * (non-Javadoc)
     *
     * @see org.pirkaengine.core.Template#generate(java.util.Map)
     */
    @Override
    public Renderer generate(Map<String, Object> viewModel) {
        if (isDebugEnabled()) debug("generate: viewModel=" + viewModel);
        try {
            return new BindTemplate(this, viewModel, this.functions);
        } catch (RuntimeException e) {
            error("Rendering Error: " + this.templateName, e);
            throw e;
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see org.pirkaengine.core.Template#getTimeStamp()
     */
    @Override
    public long getTimeStamp() {
        return this.timeStamp;
    }

    /*
     * (non-Javadoc)
     *
     * @see org.pirkaengine.core.Template#setTimeStamp(long)
     */
    @Override
    public void setTimeStamp(long timeStamp) {
        this.timeStamp = timeStamp;
    }

    /*
     * (non-Javadoc)
     *
     * @see org.pirkaengine.core.Template#getName()
     */
    @Override
    public String getName() {
        return templateName;
    }

    /**
     * ノードリストの先頭にノードを追加する.
     * @param node 追加するノード
     */
    public void stack(Node node) {
        this.nodeList.addFirst(node);
        if (LoopNode.class.isInstance(node)) {
            LoopNode loopNode = (LoopNode) node;
            this.itemNames.add(loopNode.getItemName());
            this.loopNodes.put(loopNode.getItemsName(), loopNode);
        }
    }

    /**
     * スクリプトの追加
     * @param node ScriptNode
     */
    public void addScript(ScriptNode node) {
        if (node == null) throw new IllegalArgumentException("node is null.");
        if (node.function == null) throw new IllegalArgumentException("node.function is null: " + node);
        if (node.function.name == null) throw new IllegalArgumentException("node.function.name is null: " + node);
        if (isDebugEnabled()) debug("addScript: " + node);
        functions.put(node.function.name, node.function);
    }

    /**
     * 関数の追加
     * @param node FunctionsNode
     */
    public void addFunction(FunctionsNode node) {
        if (node == null) throw new IllegalArgumentException("node is null.");
        if (node.javaFunctions == null) throw new IllegalArgumentException("node.javaFunctions is null: " + node);
        if (isDebugEnabled()) debug("addFunction: " + node);
        for (JavaFunction func : node.javaFunctions) {
            this.functions.put(func.name, func);
            if (func.aliasName != null) this.functions.put(func.aliasName, func);
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see org.pirkaengine.core.Template#createViewModel()
     */
    @Override
    public Map<String, Object> createViewModel() {
        HashMap<String, Object> model = new HashMap<String, Object>();
        for (Node node : this.nodeList) {
            for (String nodeExpression : node.getExpressions()) {
                String[] keys = nodeExpression.split("\\.");
                if (this.itemNames.contains(keys[0])) continue; // Loop Items
                setNullValue(model, keys, 0);
            }
            if (LoopNode.class.isInstance(node)) {
                LoopNode loopNode = (LoopNode) node;
                String key = loopNode.getItemsName();
                if (!model.containsKey(key)) model.put(key, new ArrayList<Map<String, Object>>());
            }
        }
        return model;
    }

    private void setNullValue(HashMap<String, Object> model, String[] keys, int index) {
        String key = keys[index];
        Object value = model.get(keys[index]);
        if (index + 1 < keys.length) {
            @SuppressWarnings("unchecked")
            HashMap<String, Object> valueModel =
                HashMap.class.isInstance(value) ? (HashMap<String, Object>) value : new HashMap<String, Object>();
            if (value == null) model.put(key, valueModel);
            this.setNullValue(valueModel, keys, index + 1);
        } else {
            if (value == null) model.put(key, NULL_VALUE);
            // END
        }
    }

    @Override
    public Map<String, Object> createArrayItemModel(String arrayKey) throws KeyNotContainsException {
        HashMap<String, Object> model = new HashMap<String, Object>();
        LoopNode node = loopNodes.get(arrayKey);
        if (node == null) throw new KeyNotContainsException("arrayKey: " + arrayKey);
        for (String nodeExpression : node.getExpressions()) {
            String[] keys = nodeExpression.split("\\.");
            if (!node.getItemName().equals(keys[0])) continue; // Loop Items
            if (keys.length == 1) {
                model.put("toString", NULL_VALUE);
            } else {
                setNullValue(model, keys, 1);
            }
        }
        return model;
    }

    /**
     * PrkComponentを追加する
     * @param component PrkComponent
     */
    public void add(PrkComponent component) {
        this.components.add(component);
    }

    /**
     * PrkComponentを取得する
     * @return PrkComponentリスト
     */
    @Override
    public List<PrkComponent> getPrkComponents() {
        return components;
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof XhtmlTemplate)) return false;
        XhtmlTemplate tmpl = XhtmlTemplate.class.cast(obj);
        if (this.timeStamp != tmpl.timeStamp) return false;
        if (!this.components.equals(tmpl.components)) return false;
        if (!this.nodeList.equals(tmpl.nodeList)) return false;
        return functions.equals(tmpl.functions);
    }

    @Override
    public int hashCode() {
        int hash = 17;
        hash = hash * 13 + (int) (timeStamp ^ timeStamp >>> 32);
        hash = hash * 13 + this.nodeList.hashCode();
        hash = hash * 13 + this.components.hashCode();
        hash = hash * 13 + this.functions.hashCode();
        return hash;
    }

    @Override
    public String toString() {
        StringBuilder str = new StringBuilder();
        str.append("nodes=[");
        for (Node node : nodeList) {
            str.append(node).append(", ");
        }
        str.setLength(str.length() - 2);
        str.append("]\n");
        str.append("functions=[").append(functions.keySet()).append("\n");
        str.append("plugins=[").append(components).append("]");
        return str.toString();
    }

}
TOP

Related Classes of org.pirkaengine.core.template.XhtmlTemplate

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.