Package httl.spi.filters

Source Code of httl.spi.filters.AttributeSyntaxFilter

/*
* Copyright 2011-2013 HTTL Team.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*      http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package httl.spi.filters;

import httl.spi.Filter;
import httl.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

import net.htmlparser.jericho.Attribute;
import net.htmlparser.jericho.Attributes;
import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.OutputDocument;
import net.htmlparser.jericho.Segment;
import net.htmlparser.jericho.Source;

/**
* AttributeSyntaxFilter. (SPI, Singleton, ThreadSafe)
*
* @see httl.spi.translators.CompiledTranslator#setTemplateFilter(Filter)
* @see httl.spi.translators.InterpretedTranslator#setTemplateFilter(Filter)
*
* @author Liang Fei (liangfei0201 AT gmail DOT com)
*/
public class AttributeSyntaxFilter extends AbstractFilter {

    private String ifattr = "ifattr";

    private String setattr = "setattr";

    private String[] setDirective = new String[]{"var"};

    private String[] ifDirective = new String[]{"if"};

    private String[] elseifDirective = new String[]{"elseif"};

    private String[] elseDirective = new String[]{"else"};

    private String[] forDirective = new String[]{"for"};

    private String[] breakifDirective = new String[]{"breakif"};

    private String[] macroDirective = new String[]{"macro"};

    private String[] endDirective = new String[]{"end"};

    private String attributeNamespace;

    /**
     * httl.properties: set.directive=set
     */
    public void setSetDirective(String[] setDirective) {
        this.setDirective = setDirective;
    }

    /**
     * httl.properties: if.directive=if
     */
    public void setIfDirective(String[] ifDirective) {
        this.ifDirective = ifDirective;
    }

    /**
     * httl.properties: elseif.directive=elseif
     */
    public void setElseifDirective(String[] elseifDirective) {
        this.elseifDirective = elseifDirective;
    }

    /**
     * httl.properties: else.directive=else
     */
    public void setElseDirective(String[] elseDirective) {
        this.elseDirective = elseDirective;
    }

    /**
     * httl.properties: for.directive=for
     */
    public void setForDirective(String[] forDirective) {
        this.forDirective = forDirective;
    }

    /**
     * httl.properties: breakif.directive=breakif
     */
    public void setBreakifDirective(String[] breakifDirective) {
        this.breakifDirective = breakifDirective;
    }

    /**
     * httl.properties: macro.directive=macro
     */
    public void setMacroDirective(String[] macroDirective) {
        this.macroDirective = macroDirective;
    }

    /**
     * httl.properties: end.directive=end
     */
    public void setEndDirective(String[] endDirective) {
        this.endDirective = endDirective;
    }

    /**
     * httl.properties: attribute.namespace=httl
     */
    public void setAttributeNamespace(String attributeNamespace) {
        if (!attributeNamespace.endsWith(":")) {
            attributeNamespace = attributeNamespace + ":";
        }
        this.attributeNamespace = attributeNamespace;
    }

    private boolean isDirective(String name) {
        return StringUtils.inArray(name, setDirective)
                || StringUtils.inArray(name, ifDirective) || StringUtils.inArray(name, elseifDirective)
                || StringUtils.inArray(name, elseDirective) || StringUtils.inArray(name, forDirective)
                || StringUtils.inArray(name, breakifDirective) || StringUtils.inArray(name, macroDirective)
                || StringUtils.inArray(name, endDirective);
    }

    private boolean isBlockDirective(String name) {
        return StringUtils.inArray(name, ifDirective) || StringUtils.inArray(name, elseifDirective)
                || StringUtils.inArray(name, elseDirective) || StringUtils.inArray(name, forDirective)
                || StringUtils.inArray(name, macroDirective);
    }

    public String filter(String key, String value) {
        Source source = new Source(value);
        OutputDocument document = new OutputDocument(source);
        replaceChildren(source, source, document);
        return document.toString();
    }

    // 替换子元素中的指令属性
    private void replaceChildren(Source source, Segment segment, OutputDocument document) {
        // 迭代子元素,逐个查找
        List<Element> elements = segment.getChildElements();
        if (elements != null) {
            for (Element element : elements) {
                if (element != null) {
                    // ---- 标签属性处理 ----
                    List<String> directiveNames = new ArrayList<String>();
                    List<String> directiveValues = new ArrayList<String>();
                    List<Attribute> directiveAttributes = new ArrayList<Attribute>();
                    // 迭代标签属性,查找指令属性
                    Attributes attributes = element.getAttributes();
                    if (attributes != null) {
                        for (Attribute attribute : attributes) {
                            if (attribute != null) {
                                String name = attribute.getName();
                                if (name != null && (isDirective(name) || (attributeNamespace != null && name.startsWith(attributeNamespace)) && isDirective(name.substring(attributeNamespace.length())))) { // 识别名称空间
                                    String directiveName = attributeNamespace != null ? name.substring(attributeNamespace.length()) : name;
                                    String value = attribute.getValue();
                                    directiveNames.add(directiveName);
                                    directiveValues.add(value);
                                    directiveAttributes.add(attribute);
                                }
                            }
                        }
                    }
                    // ---- 指令处理 ----
                    if (directiveNames.size() > 0) {
                        StringBuffer buf = new StringBuffer();
                        for (int i = 0; i < directiveNames.size(); i++) { // 按顺序添加块指令
                            String directiveName = (String) directiveNames.get(i);
                            String directiveValue = (String) directiveValues.get(i);
                            buf.append("#");
                            buf.append(directiveName);
                            buf.append("(");
                            buf.append(directiveValue);
                            buf.append(")");
                        }
                        document.insert(element.getBegin(), buf.toString()); // 插入块指令
                    }
                    // ---- 指令属性处理 ----
                    for (int i = 0; i < directiveAttributes.size(); i++) {
                        Attribute attribute = (Attribute) directiveAttributes.get(i);
                        document.remove(new Segment(source, attribute.getBegin() - 1, attribute.getEnd())); // 移除属性
                    }

                    if (attributes != null) {
                        //检查扩展的ifattr指令
                        for (Attribute attribute : attributes) {
                            if (attribute != null) {
                                String name = attribute.getName();
                                if (ifattr.equals(name)) {
                                    String val = attribute.getValue();
                                    String[] arr = val.split(",");
                                    String attrName = arr[0].trim();
                                    String expression = arr[1].trim();

                                    //修改原attribute
                                    Attribute oriattr = attributes.get(attrName);
                                    if (oriattr != null) {
                                        String buf = String.format("#if(%s)%s=\"%s\"#end()", expression, oriattr.getName(), oriattr.getValue());
                                        document.replace(new Segment(source, oriattr.getBegin(), oriattr.getEnd()), buf);
                                        document.remove(new Segment(source, attribute.getBegin(), attribute.getEnd())); // 移除ifattr控制属性
                                    }
                                }
                            }
                        }

                        //检查扩展的setattr指令
                        for (Attribute attribute : attributes) {
                            if (attribute != null) {
                                String name = attribute.getName();
                                if (setattr.equals(name)) {
                                    String val = attribute.getValue();
                                    String[] arr = val.split(",");
                                    String attrName = arr[0].trim();
                                    String expression = arr[1].trim();

                                    //将控制指令直接替换为动态属性赋值
                                    Attribute oriattr = attributes.get(attrName);
                                    String buf = String.format("%s=\"%s\"", attrName, expression);
                                    document.replace(new Segment(source, attribute.getBegin(), attribute.getEnd()), buf);

                                    //如果有已经存在的静态属性,直接删去即可
                                    if (oriattr != null) {
                                        document.remove(new Segment(source, attribute.getBegin(), attribute.getEnd())); // 移除setattr控制属性
                                    }
                                }
                            }
                        }
                    }

                    replaceChildren(source, element, document); // 递归处理子标签
                    // ---- 结束指令处理 ----
                    if (directiveNames.size() > 0) {
                        StringBuffer buf = new StringBuffer();
                        for (int i = directiveNames.size() - 1; i >= 0; i--) { // 倒序添加结束指令
                            String directiveName = (String) directiveNames.get(i);
                            if (isBlockDirective(directiveName)) {
                                buf.append("#");
                                buf.append(endDirective[0]);
                                buf.append("(");
                                buf.append(directiveName);
                                buf.append(")");
                            }
                        }
                        document.insert(element.getEnd(), buf.toString()); // 插入结束指令
                    }
                    // 清理临时容器
                    directiveNames.clear();
                    directiveValues.clear();
                    directiveAttributes.clear();
                }
            }
        }
    }

}
TOP

Related Classes of httl.spi.filters.AttributeSyntaxFilter

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.