org.paxml.control.IterateTag.java Source code

Java tutorial

Introduction

Here is the source code for org.paxml.control.IterateTag.java

Source

/**
 * This file is part of PaxmlCore.
 *
 * PaxmlCore is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * PaxmlCore is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with PaxmlCore.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.paxml.control;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.jxpath.Pointer;
import org.paxml.annotation.Tag;
import org.paxml.core.Context;
import org.paxml.core.PaxmlRuntimeException;
import org.paxml.el.IExpression;
import org.paxml.file.FileHelper;
import org.paxml.tag.AbstractTag.ChildrenResultList;
import org.paxml.tag.IPropertyVisitor;
import org.paxml.util.PaxmlUtils;
import org.paxml.util.ReflectUtils;
import org.paxml.util.ReflectUtils.PropertyDescriptorType;
import org.springframework.core.io.Resource;

/**
 * Iterate tag impl.
 * 
 * @author Xuetao Niu
 * 
 */
@Tag(name = "iterate", factory = IterateTagFactory.class)
public class IterateTag extends AbstractControlTag implements IPropertyVisitor<Context, ChildrenResultList> {
    /**
     * The default const name of var.
     */
    public static final String DEFAULT_VAR = "var";
    /**
     * The default const name of the var name.
     */
    public static final String DEFAULT_VAR_NAME = "name";
    /**
     * The default const name of index.
     */
    public static final String DEFAULT_INDEX = "index";

    private IExpression list;
    private IExpression map;
    private IExpression xpath;
    private IExpression times;
    private IExpression bean;
    private IExpression values;
    private IExpression file;
    private String varName = DEFAULT_VAR;
    private String indexVarName = DEFAULT_INDEX;
    private String varNameText = DEFAULT_VAR_NAME;

    private ChildrenResultList visitIterator(Context context, Iterator<?> it) {
        if (it == null) {
            return null;
        }
        ChildrenResultList list = null;
        int i = 0;
        while (it.hasNext()) {
            Object value = it.next();
            if (value instanceof Pointer) {
                value = ((Pointer) value).getValue();
            }
            if (value != null) {
                list = addAll(list, visit(context, it, i + "", i, value));
                i++;
            }
        }
        return list;
    }

    private ChildrenResultList visitIterable(Context context, Iterable<?> it) {
        return visitIterator(context, it.iterator());
    }

    private ChildrenResultList visitEnumeration(Context context, Enumeration<?> e) {
        if (e == null) {
            return null;
        }
        ChildrenResultList list = null;
        int i = 0;
        while (e.hasMoreElements()) {
            list = addAll(list, visit(context, e, i + "", i, e.nextElement()));
            i++;
        }
        return list;
    }

    private ChildrenResultList visitBean(Context context, Object bean, boolean readValue) {
        if (bean == null) {
            return null;
        }
        ChildrenResultList list = null;
        int i = 0;
        for (PropertyDescriptor d : ReflectUtils.getPropertyDescriptors(bean.getClass(),
                PropertyDescriptorType.GETTER)) {
            Method method = d.getReadMethod();
            Object value = null;
            if (readValue) {
                try {
                    value = method.invoke(bean);
                } catch (Exception e) {
                    throw new PaxmlRuntimeException(
                            "Cannot read property '" + d.getName() + "' from class: " + bean.getClass().getName(),
                            e);
                }
            }

            list = addAll(list, visit(context, bean, d.getName(), i++, value));
        }
        return list;
    }

    private ChildrenResultList visitMap(Context context, Map<?, ?> map) {
        if (map == null) {
            return null;
        }
        ChildrenResultList list = null;
        int i = 0;
        for (Map.Entry<?, ?> entry : map.entrySet()) {
            list = addAll(list, visit(context, map, entry.getKey(), i++, entry.getValue()));
        }
        return list;
    }

    private ChildrenResultList visitArray(Context context, Object array) {
        if (array == null) {
            return null;
        }
        ChildrenResultList list = null;
        final int len = Array.getLength(array);
        for (int i = 0; i < len; i++) {
            Object value = Array.get(array, i);
            list = addAll(list, visit(context, array, i + "", i, value));

        }
        return list;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected Object doExecute(Context context) {
        try {

            if (list != null) {
                return iterateList(context, list.evaluate(context));
            } else if (map != null) {
                Object value = map.evaluate(context);
                if (value instanceof Map) {
                    return visitMap(context, (Map) value);
                } else if (value != null) {
                    return visit(context, value, null, 0, value);
                }
            } else if (bean != null) {
                Object overValue = bean.evaluate(context);
                return visitBean(context, overValue, true);
            } else if (xpath != null) {
                String exp = xpath.evaluateString(context);
                List<?> list = (List<?>) context.xpathSelect(exp, true);
                return iterateList(context, list);
            } else if (times != null) {
                String num = times.evaluateString(context);
                final long rounds;
                try {
                    rounds = (long) Double.parseDouble(num);
                } catch (Exception e) {
                    throw new PaxmlRuntimeException("The @" + IterateTagFactory.ATTR_TIMES + " attribute of tag <"
                            + getTagName() + "> is not a number: " + num);
                }
                ChildrenResultList list = null;
                for (int i = 0; i < rounds; i++) {
                    list = addAll(list, visit(context, rounds, null, i, i));
                }
                return list;
            } else if (values != null) {
                return iterateValues(context, values.evaluate(context));
            } else if (file != null) {
                Resource res = PaxmlUtils.getResource(file.evaluateString(context),
                        getEntity().getResource().getSpringResource());
                return iterateValues(context, FileHelper.load(res));
            } else {
                throw new PaxmlRuntimeException("Nothing to iterate on!!!");
            }
        } finally {
            context.setConstOverwritable(false);
        }
        return null;
    }

    private Object iterateValues(Context context, Object overValue) {

        if (overValue == null) {
            // do nothing
            return null;
        } else if (overValue instanceof Iterable) {
            return visitIterable(context, (Iterable<?>) overValue);
        } else if (overValue instanceof Iterator) {
            return visitIterator(context, (Iterator<?>) overValue);
        } else if (overValue instanceof Enumeration) {
            return visitEnumeration(context, (Enumeration<?>) overValue);
        } else if (overValue instanceof Map) {
            // iterate over the values of the map
            return visitMap(context, (Map<?, ?>) overValue);
        } else if (overValue.getClass().isArray()) {
            // iterate over the items of the array
            return visitArray(context, overValue);
        } else {
            return visit(context, overValue, null, 0, overValue);
        }
    }

    private Object iterateList(Context context, Object overValue) {

        if (overValue == null) {
            // do nothing
            return null;
        } else if (overValue instanceof Iterable) {
            return visitIterable(context, (Iterable<?>) overValue);
        } else if (overValue instanceof Iterator) {
            return visitIterator(context, (Iterator<?>) overValue);
        } else if (overValue instanceof Enumeration) {
            return visitEnumeration(context, (Enumeration<?>) overValue);
        } else if (overValue.getClass().isArray()) {
            // iterate over the items of the array
            return visitArray(context, overValue);
        } else {
            return visit(context, overValue, null, 0, overValue);
        }
    }

    /**
     * {@inheritDoc}
     */
    public ChildrenResultList visit(Context context, Object obj, Object propertyName, int index,
            Object propertyValue) {
        // set the loop vars and remember the previous status
        final boolean varExists = context.hasConstId(varName, false);
        final Object oldVar = varExists ? context.removeConst(varName) : null;
        context.addConst(varName, varName, propertyValue, true);

        final boolean indexExists = context.hasConstId(indexVarName, false);
        final Object oldIndex = indexExists ? context.removeConst(indexVarName) : null;
        context.addConst(indexVarName, indexVarName, index, true);

        final boolean varNameExists = context.hasConstId(varNameText, false);
        final Object oldVarName = varNameExists ? context.removeConst(varNameText) : null;
        context.addConst(varNameText, varNameText, propertyName, true);

        ChildrenResultList list = executeChildren(context);

        // restore the previous status
        context.removeConst(varName);
        if (varExists) {
            context.addConst(varName, varName, oldVar, true);
        }

        context.removeConst(indexVarName);
        if (indexExists) {
            context.addConst(indexVarName, indexVarName, oldIndex, true);
        }

        context.removeConst(varNameText);
        if (varNameExists) {
            context.addConst(varNameText, varNameText, oldVarName, true);
        }
        return list;
    }

    private static ChildrenResultList addAll(ChildrenResultList to, Collection<Object> from) {

        if (from != null) {
            if (to == null) {
                to = new ChildrenResultList(from.size());
            }
            to.addAll(from);
        }
        return to;
    }

    public IExpression getList() {
        return list;
    }

    public void setList(IExpression list) {
        this.list = list;
    }

    public IExpression getMap() {
        return map;
    }

    public void setMap(IExpression map) {
        this.map = map;
    }

    public IExpression getXpath() {
        return xpath;
    }

    public void setXpath(IExpression xpath) {
        this.xpath = xpath;
    }

    public IExpression getTimes() {
        return times;
    }

    public void setTimes(IExpression times) {
        this.times = times;
    }

    public String getVarName() {
        return varName;
    }

    public void setVarName(String varName) {
        this.varName = varName;
    }

    public String getIndexVarName() {
        return indexVarName;
    }

    public void setIndexVarName(String indexVarName) {
        this.indexVarName = indexVarName;
    }

    public String getVarNameText() {
        return varNameText;
    }

    public void setVarNameText(String varNameText) {
        this.varNameText = varNameText;
    }

    public IExpression getBean() {
        return bean;
    }

    public void setBean(IExpression bean) {
        this.bean = bean;
    }

    public IExpression getValues() {
        return values;
    }

    public void setValues(IExpression values) {
        this.values = values;
    }

    public IExpression getFile() {
        return file;
    }

    public void setFile(IExpression file) {
        this.file = file;
    }

}